summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2>2005-10-20 19:20:38 +0000
committerpeter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2>2005-10-20 19:20:38 +0000
commit5ed980d600661e3e77f429a510f093f4a001dee9 (patch)
tree40d655e7921c1019d039da654a9df550de3cd249
parent907c764cb881dab769452696fc5e6bee076c2656 (diff)
downloadfpc-unitrw.tar.gz
* retag for unitrwunitrw
git-svn-id: http://svn.freepascal.org/svn/fpc/branches/unitrw@1551 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--compiler/COPYING340
-rw-r--r--compiler/MPWMake1
-rw-r--r--compiler/Makefile2785
-rw-r--r--compiler/Makefile.fpc563
-rw-r--r--compiler/README58
-rw-r--r--compiler/aasmbase.pas952
-rw-r--r--compiler/aasmtai.pas2349
-rw-r--r--compiler/aggas.pas870
-rw-r--r--compiler/alpha/aasmcpu.pas281
-rw-r--r--compiler/alpha/agaxpgas.pas126
-rw-r--r--compiler/alpha/aoptcpu.pas38
-rw-r--r--compiler/alpha/aoptcpub.pas115
-rw-r--r--compiler/alpha/aoptcpuc.pas38
-rw-r--r--compiler/alpha/aoptcpud.pas39
-rw-r--r--compiler/alpha/cgcpu.pas160
-rw-r--r--compiler/alpha/cpubase.pas457
-rw-r--r--compiler/alpha/cpuinfo.pas68
-rw-r--r--compiler/alpha/cpunode.pas54
-rw-r--r--compiler/alpha/cpupara.pas290
-rw-r--r--compiler/alpha/cpupi.pas43
-rw-r--r--compiler/alpha/cpuswtch.pas121
-rw-r--r--compiler/alpha/cputarg.pas51
-rw-r--r--compiler/alpha/radirect.pas313
-rw-r--r--compiler/alpha/rasm.pas65
-rw-r--r--compiler/alpha/rgcpu.pas69
-rw-r--r--compiler/alpha/tgcpu.pas42
-rw-r--r--compiler/aopt.pas267
-rw-r--r--compiler/aoptbase.pas257
-rw-r--r--compiler/aoptcs.pas848
-rw-r--r--compiler/aoptda.pas183
-rw-r--r--compiler/aoptobj.pas1125
-rw-r--r--compiler/arm/aasmcpu.pas2399
-rw-r--r--compiler/arm/agarmgas.pas237
-rw-r--r--compiler/arm/aoptcpu.pas42
-rw-r--r--compiler/arm/aoptcpub.pas120
-rw-r--r--compiler/arm/aoptcpuc.pas38
-rw-r--r--compiler/arm/aoptcpud.pas40
-rw-r--r--compiler/arm/armatt.inc90
-rw-r--r--compiler/arm/armatts.inc90
-rw-r--r--compiler/arm/armins.dat394
-rw-r--r--compiler/arm/armnop.inc2
-rw-r--r--compiler/arm/armop.inc90
-rw-r--r--compiler/arm/armreg.dat84
-rw-r--r--compiler/arm/armtab.inc759
-rw-r--r--compiler/arm/cgcpu.pas1712
-rw-r--r--compiler/arm/cpubase.pas520
-rw-r--r--compiler/arm/cpuinfo.pas88
-rw-r--r--compiler/arm/cpunode.pas46
-rw-r--r--compiler/arm/cpupara.pas496
-rw-r--r--compiler/arm/cpupi.pas105
-rw-r--r--compiler/arm/cpuswtch.pas118
-rw-r--r--compiler/arm/cputarg.pas78
-rw-r--r--compiler/arm/itcpugas.pas93
-rw-r--r--compiler/arm/narmadd.pas336
-rw-r--r--compiler/arm/narmcal.pas50
-rw-r--r--compiler/arm/narmcnv.pas265
-rw-r--r--compiler/arm/narmcon.pas141
-rw-r--r--compiler/arm/narminl.pas216
-rw-r--r--compiler/arm/narmmat.pas121
-rw-r--r--compiler/arm/raarm.pas54
-rw-r--r--compiler/arm/raarmgas.pas797
-rw-r--r--compiler/arm/rarmcon.inc74
-rw-r--r--compiler/arm/rarmdwa.inc74
-rw-r--r--compiler/arm/rarmnor.inc2
-rw-r--r--compiler/arm/rarmnum.inc74
-rw-r--r--compiler/arm/rarmrni.inc74
-rw-r--r--compiler/arm/rarmsri.inc74
-rw-r--r--compiler/arm/rarmsta.inc74
-rw-r--r--compiler/arm/rarmstd.inc74
-rw-r--r--compiler/arm/rarmsup.inc74
-rw-r--r--compiler/arm/rgcpu.pas168
-rw-r--r--compiler/assemble.pas1482
-rw-r--r--compiler/browcol.pas2143
-rw-r--r--compiler/browlog.pas515
-rw-r--r--compiler/bsdcompile3
-rw-r--r--compiler/catch.pas92
-rw-r--r--compiler/cclasses.pas2352
-rw-r--r--compiler/cg64f32.pas791
-rw-r--r--compiler/cgbase.pas605
-rw-r--r--compiler/cgobj.pas2090
-rw-r--r--compiler/cgutils.pas186
-rw-r--r--compiler/charset.pas252
-rw-r--r--compiler/cmsgs.pas413
-rw-r--r--compiler/comphook.pas413
-rw-r--r--compiler/compiler.pas450
-rw-r--r--compiler/compinnr.inc107
-rw-r--r--compiler/comprsrc.pas185
-rw-r--r--compiler/cp437.pas281
-rw-r--r--compiler/cp850.pas281
-rw-r--r--compiler/cp8859_1.pas281
-rw-r--r--compiler/crc.pas100
-rw-r--r--compiler/cresstr.pas294
-rw-r--r--compiler/cstreams.pas613
-rw-r--r--compiler/cutils.pas1081
-rw-r--r--compiler/dbgbase.pas128
-rw-r--r--compiler/dbgdwarf.pas49
-rw-r--r--compiler/dbgstabs.pas1589
-rw-r--r--compiler/defcmp.pas1489
-rw-r--r--compiler/defutil.pas921
-rw-r--r--compiler/dwarf.pas419
-rw-r--r--compiler/export.pas179
-rw-r--r--compiler/finput.pas740
-rw-r--r--compiler/fmodule.pas831
-rw-r--r--compiler/fpcdefs.inc93
-rw-r--r--compiler/fppu.pas1605
-rw-r--r--compiler/gendef.pas159
-rw-r--r--compiler/globals.pas2245
-rw-r--r--compiler/globtype.pas316
-rw-r--r--compiler/html/i386/readme.txt5
-rw-r--r--compiler/html/powerpc/readme.txt5
-rw-r--r--compiler/htypechk.pas2150
-rw-r--r--compiler/i386/ag386nsm.pas906
-rw-r--r--compiler/i386/aopt386.pas119
-rw-r--r--compiler/i386/cgcpu.pas750
-rw-r--r--compiler/i386/cpubase.inc171
-rw-r--r--compiler/i386/cpuinfo.pas94
-rw-r--r--compiler/i386/cpunode.pas59
-rw-r--r--compiler/i386/cpupara.pas623
-rw-r--r--compiler/i386/cpupi.pas69
-rw-r--r--compiler/i386/cpuswtch.pas115
-rw-r--r--compiler/i386/cputarg.pas116
-rw-r--r--compiler/i386/csopt386.pas2218
-rw-r--r--compiler/i386/daopt386.pas2796
-rw-r--r--compiler/i386/i386att.inc569
-rw-r--r--compiler/i386/i386atts.inc569
-rw-r--r--compiler/i386/i386int.inc569
-rw-r--r--compiler/i386/i386nop.inc2
-rw-r--r--compiler/i386/i386op.inc569
-rw-r--r--compiler/i386/i386prop.inc569
-rw-r--r--compiler/i386/i386tab.inc11553
-rw-r--r--compiler/i386/n386add.pas385
-rw-r--r--compiler/i386/n386cal.pas95
-rw-r--r--compiler/i386/n386inl.pas42
-rw-r--r--compiler/i386/n386mat.pas324
-rw-r--r--compiler/i386/n386mem.pas140
-rw-r--r--compiler/i386/n386set.pas218
-rw-r--r--compiler/i386/optbase.pas34
-rw-r--r--compiler/i386/popt386.pas2033
-rw-r--r--compiler/i386/r386ari.inc73
-rw-r--r--compiler/i386/r386att.inc73
-rw-r--r--compiler/i386/r386con.inc73
-rw-r--r--compiler/i386/r386dwrf.inc73
-rw-r--r--compiler/i386/r386int.inc73
-rw-r--r--compiler/i386/r386iri.inc73
-rw-r--r--compiler/i386/r386nasm.inc73
-rw-r--r--compiler/i386/r386nor.inc2
-rw-r--r--compiler/i386/r386nri.inc73
-rw-r--r--compiler/i386/r386num.inc73
-rw-r--r--compiler/i386/r386op.inc73
-rw-r--r--compiler/i386/r386ot.inc73
-rw-r--r--compiler/i386/r386rni.inc73
-rw-r--r--compiler/i386/r386sri.inc73
-rw-r--r--compiler/i386/r386stab.inc73
-rw-r--r--compiler/i386/r386std.inc73
-rw-r--r--compiler/i386/ra386att.pas59
-rw-r--r--compiler/i386/ra386int.pas2107
-rw-r--r--compiler/i386/rgcpu.pas71
-rw-r--r--compiler/i386/rropt386.pas364
-rw-r--r--compiler/ia64/cpuasm.pas296
-rw-r--r--compiler/ia64/cpubase.pas282
-rw-r--r--compiler/ia64/cpuinfo.pas60
-rw-r--r--compiler/impdef.pas483
-rw-r--r--compiler/import.pas237
-rw-r--r--compiler/link.pas705
-rw-r--r--compiler/m68k/aasmcpu.pas539
-rw-r--r--compiler/m68k/agcpugas.pas354
-rw-r--r--compiler/m68k/aoptcpu.pas41
-rw-r--r--compiler/m68k/aoptcpub.pas120
-rw-r--r--compiler/m68k/aoptcpud.pas36
-rw-r--r--compiler/m68k/cgcpu.pas1321
-rw-r--r--compiler/m68k/cpuasm.pas26
-rw-r--r--compiler/m68k/cpubase.pas464
-rw-r--r--compiler/m68k/cpuinfo.pas74
-rw-r--r--compiler/m68k/cpunode.pas52
-rw-r--r--compiler/m68k/cpupara.pas477
-rw-r--r--compiler/m68k/cpupi.pas41
-rw-r--r--compiler/m68k/cpuswtch.pas106
-rw-r--r--compiler/m68k/cputarg.pas56
-rw-r--r--compiler/m68k/itcpugas.pas138
-rw-r--r--compiler/m68k/m68kreg.dat44
-rw-r--r--compiler/m68k/n68kcnv.pas239
-rw-r--r--compiler/m68k/n68kmat.pas248
-rw-r--r--compiler/m68k/ncpuadd.pas424
-rw-r--r--compiler/m68k/r68kcon.inc35
-rw-r--r--compiler/m68k/r68kgas.inc35
-rw-r--r--compiler/m68k/r68kgri.inc35
-rw-r--r--compiler/m68k/r68knor.inc2
-rw-r--r--compiler/m68k/r68knum.inc35
-rw-r--r--compiler/m68k/r68krni.inc35
-rw-r--r--compiler/m68k/r68ksri.inc35
-rw-r--r--compiler/m68k/r68ksta.inc35
-rw-r--r--compiler/m68k/r68kstd.inc35
-rw-r--r--compiler/m68k/r68ksup.inc35
-rwxr-xr-xcompiler/m68k/ra68k.pas363
-rw-r--r--compiler/m68k/ra68kmot.pas1790
-rw-r--r--compiler/m68k/rgcpu.pas40
-rw-r--r--compiler/make_old.cmd65
-rw-r--r--compiler/mdppc386.bat2
-rw-r--r--compiler/mips/aasmcpu.pas339
-rw-r--r--compiler/mips/cpubase.pas491
-rw-r--r--compiler/mips/cpuinfo.pas72
-rw-r--r--compiler/mips/itcpugas.pas116
-rw-r--r--compiler/mips/mipsreg.dat83
-rw-r--r--compiler/mips/rmipscon.inc75
-rw-r--r--compiler/mips/rmipsdwf.inc75
-rw-r--r--compiler/mips/rmipsgas.inc75
-rw-r--r--compiler/mips/rmipsgri.inc75
-rw-r--r--compiler/mips/rmipsgss.inc75
-rw-r--r--compiler/mips/rmipsmot.inc75
-rw-r--r--compiler/mips/rmipsmri.inc75
-rw-r--r--compiler/mips/rmipsnor.inc2
-rw-r--r--compiler/mips/rmipsnum.inc75
-rw-r--r--compiler/mips/rmipsrni.inc75
-rw-r--r--compiler/mips/rmipssri.inc75
-rw-r--r--compiler/mips/rmipssta.inc75
-rw-r--r--compiler/mips/rmipsstd.inc75
-rw-r--r--compiler/mips/rmipssup.inc75
-rw-r--r--compiler/mppc386.bat6
-rw-r--r--compiler/mppc68k.bat2
-rw-r--r--compiler/mppcsparc42
-rw-r--r--compiler/msg/errorct.msg2356
-rw-r--r--compiler/msg/errord.msg2574
-rw-r--r--compiler/msg/errore.msg2403
-rw-r--r--compiler/msg/errores.msg2374
-rw-r--r--compiler/msg/errorf.msg1899
-rw-r--r--compiler/msg/errorhe.msg2362
-rw-r--r--compiler/msg/errorn.msg2454
-rw-r--r--compiler/msg/errorpl.msg2385
-rw-r--r--compiler/msg/errorpli.msg2385
-rw-r--r--compiler/msg/errorptd.msg2337
-rw-r--r--compiler/msg/errorptw.msg2335
-rw-r--r--compiler/msg/errorr.msg2015
-rw-r--r--compiler/msg/errorrw.msg2015
-rw-r--r--compiler/msg/errorues.msg2368
-rw-r--r--compiler/msgidx.inc671
-rw-r--r--compiler/msgtxt.inc958
-rw-r--r--compiler/nadd.pas2290
-rw-r--r--compiler/nbas.pas1042
-rw-r--r--compiler/ncal.pas2560
-rw-r--r--compiler/ncgadd.pas792
-rw-r--r--compiler/ncgbas.pas512
-rw-r--r--compiler/ncgcal.pas1030
-rw-r--r--compiler/ncgcnv.pas566
-rw-r--r--compiler/ncgcon.pas617
-rw-r--r--compiler/ncgflw.pas1469
-rw-r--r--compiler/ncginl.pas688
-rw-r--r--compiler/ncgld.pas940
-rw-r--r--compiler/ncgmat.pas472
-rw-r--r--compiler/ncgmem.pas768
-rw-r--r--compiler/ncgopt.pas194
-rw-r--r--compiler/ncgset.pas869
-rw-r--r--compiler/ncgutil.pas2205
-rw-r--r--compiler/ncnv.pas2687
-rw-r--r--compiler/ncon.pas917
-rw-r--r--compiler/nflw.pas1444
-rw-r--r--compiler/ninl.pas2526
-rw-r--r--compiler/nld.pas1209
-rw-r--r--compiler/nmat.pas950
-rw-r--r--compiler/nmem.pas965
-rw-r--r--compiler/nobj.pas1353
-rw-r--r--compiler/node.pas1157
-rw-r--r--compiler/nopt.pas288
-rw-r--r--compiler/nset.pas808
-rw-r--r--compiler/nstate.pas123
-rw-r--r--compiler/nutils.pas619
-rw-r--r--compiler/ogbase.pas572
-rw-r--r--compiler/ogcoff.pas1767
-rw-r--r--compiler/ogelf.pas886
-rw-r--r--compiler/oglx.pas394
-rw-r--r--compiler/ogmap.pas137
-rw-r--r--compiler/optcse.pas79
-rw-r--r--compiler/options.pas2138
-rw-r--r--compiler/optunrol.pas170
-rw-r--r--compiler/owar.pas282
-rw-r--r--compiler/owbase.pas320
-rw-r--r--compiler/parabase.pas250
-rw-r--r--compiler/paramgr.pas385
-rw-r--r--compiler/parser.pas613
-rw-r--r--compiler/pass_1.pas220
-rw-r--r--compiler/pass_2.pas210
-rw-r--r--compiler/pbase.pas272
-rw-r--r--compiler/pdecl.pas659
-rw-r--r--compiler/pdecobj.pas788
-rw-r--r--compiler/pdecsub.pas2467
-rw-r--r--compiler/pdecvar.pas1318
-rw-r--r--compiler/pexports.pas182
-rw-r--r--compiler/pexpr.pas2674
-rw-r--r--compiler/pinline.pas796
-rw-r--r--compiler/pmodules.pas1564
-rw-r--r--compiler/powerpc/aasmcpu.pas508
-rw-r--r--compiler/powerpc/agppcgas.pas376
-rw-r--r--compiler/powerpc/agppcmpw.pas1295
-rw-r--r--compiler/powerpc/aoptcpu.pas451
-rw-r--r--compiler/powerpc/aoptcpub.pas121
-rw-r--r--compiler/powerpc/aoptcpuc.pas40
-rw-r--r--compiler/powerpc/aoptcpud.pas40
-rw-r--r--compiler/powerpc/cgcpu.pas2403
-rw-r--r--compiler/powerpc/cpubase.pas558
-rw-r--r--compiler/powerpc/cpuinfo.pas71
-rw-r--r--compiler/powerpc/cpunode.pas50
-rw-r--r--compiler/powerpc/cpupara.pas634
-rw-r--r--compiler/powerpc/cpupi.pas144
-rw-r--r--compiler/powerpc/cpuswtch.pas118
-rw-r--r--compiler/powerpc/cputarg.pas90
-rw-r--r--compiler/powerpc/itcpugas.pas143
-rw-r--r--compiler/powerpc/nppcadd.pas1462
-rw-r--r--compiler/powerpc/nppccal.pas142
-rw-r--r--compiler/powerpc/nppccnv.pas334
-rw-r--r--compiler/powerpc/nppcinl.pas146
-rw-r--r--compiler/powerpc/nppcld.pas126
-rw-r--r--compiler/powerpc/nppcmat.pas703
-rw-r--r--compiler/powerpc/nppcset.pas215
-rw-r--r--compiler/powerpc/ppcins.dat68
-rw-r--r--compiler/powerpc/ppcreg.dat120
-rw-r--r--compiler/powerpc/rappc.pas41
-rw-r--r--compiler/powerpc/rappcgas.pas733
-rw-r--r--compiler/powerpc/rgcpu.pas130
-rw-r--r--compiler/powerpc/rppccon.inc111
-rw-r--r--compiler/powerpc/rppcdwrf.inc111
-rw-r--r--compiler/powerpc/rppcgas.inc111
-rw-r--r--compiler/powerpc/rppcgri.inc111
-rw-r--r--compiler/powerpc/rppcgss.inc111
-rw-r--r--compiler/powerpc/rppcmot.inc111
-rw-r--r--compiler/powerpc/rppcmri.inc111
-rw-r--r--compiler/powerpc/rppcnor.inc2
-rw-r--r--compiler/powerpc/rppcnum.inc111
-rw-r--r--compiler/powerpc/rppcrni.inc111
-rw-r--r--compiler/powerpc/rppcsri.inc111
-rw-r--r--compiler/powerpc/rppcstab.inc111
-rw-r--r--compiler/powerpc/rppcstd.inc111
-rw-r--r--compiler/powerpc/rppcsup.inc111
-rw-r--r--compiler/powerpc64/aasmcpu.pas537
-rw-r--r--compiler/powerpc64/agppcgas.pas343
-rw-r--r--compiler/powerpc64/aoptcpu.pas41
-rw-r--r--compiler/powerpc64/aoptcpub.pas123
-rw-r--r--compiler/powerpc64/aoptcpuc.pas40
-rw-r--r--compiler/powerpc64/aoptcpud.pas40
-rw-r--r--compiler/powerpc64/cgcpu.pas1668
-rw-r--r--compiler/powerpc64/cpubase.pas541
-rw-r--r--compiler/powerpc64/cpuinfo.pas69
-rw-r--r--compiler/powerpc64/cpunode.pas51
-rw-r--r--compiler/powerpc64/cpupara.pas479
-rw-r--r--compiler/powerpc64/cpupi.pas111
-rw-r--r--compiler/powerpc64/cpuswtch.pas125
-rw-r--r--compiler/powerpc64/cputarg.pas78
-rw-r--r--compiler/powerpc64/itcpugas.pas158
-rw-r--r--compiler/powerpc64/nppcadd.pas851
-rw-r--r--compiler/powerpc64/nppccal.pas51
-rw-r--r--compiler/powerpc64/nppccnv.pas303
-rw-r--r--compiler/powerpc64/nppcinl.pas148
-rw-r--r--compiler/powerpc64/nppcld.pas62
-rw-r--r--compiler/powerpc64/nppcmat.pas376
-rw-r--r--compiler/powerpc64/nppcset.pas209
-rw-r--r--compiler/powerpc64/ppcins.dat75
-rw-r--r--compiler/powerpc64/ppcreg.dat143
-rw-r--r--compiler/powerpc64/rappc.pas42
-rw-r--r--compiler/powerpc64/rappcgas.pas731
-rw-r--r--compiler/powerpc64/rgcpu.pas46
-rw-r--r--compiler/powerpc64/rppccon.inc111
-rw-r--r--compiler/powerpc64/rppcdwrf.inc111
-rw-r--r--compiler/powerpc64/rppcgas.inc111
-rw-r--r--compiler/powerpc64/rppcgri.inc111
-rw-r--r--compiler/powerpc64/rppcgss.inc111
-rw-r--r--compiler/powerpc64/rppcmot.inc111
-rw-r--r--compiler/powerpc64/rppcmri.inc111
-rw-r--r--compiler/powerpc64/rppcnor.inc2
-rw-r--r--compiler/powerpc64/rppcnum.inc111
-rw-r--r--compiler/powerpc64/rppcrni.inc111
-rw-r--r--compiler/powerpc64/rppcsri.inc111
-rw-r--r--compiler/powerpc64/rppcstab.inc111
-rw-r--r--compiler/powerpc64/rppcstd.inc111
-rw-r--r--compiler/powerpc64/rppcsup.inc111
-rw-r--r--compiler/pp.lpi136
-rw-r--r--compiler/pp.pas207
-rw-r--r--compiler/ppc.cfg40
-rw-r--r--compiler/ppc.conf39
-rw-r--r--compiler/ppc.dof95
-rw-r--r--compiler/ppc.dpr157
-rw-r--r--compiler/ppheap.pas147
-rw-r--r--compiler/ppu.pas1068
-rw-r--r--compiler/procinfo.pas183
-rw-r--r--compiler/pstatmnt.pas1182
-rw-r--r--compiler/psub.pas1475
-rw-r--r--compiler/psystem.pas557
-rw-r--r--compiler/ptconst.pas1030
-rw-r--r--compiler/ptype.pas658
-rw-r--r--compiler/raatt.pas1534
-rw-r--r--compiler/rabase.pas105
-rw-r--r--compiler/rasm.pas68
-rw-r--r--compiler/rautils.pas1556
-rw-r--r--compiler/regvars.pas666
-rw-r--r--compiler/rgbase.pas80
-rw-r--r--compiler/rgobj.pas2022
-rw-r--r--compiler/scandir.pas1209
-rw-r--r--compiler/scanner.pas3760
-rw-r--r--compiler/script.pas502
-rw-r--r--compiler/sparc/aasmcpu.pas312
-rw-r--r--compiler/sparc/aoptcpu.pas41
-rw-r--r--compiler/sparc/aoptcpub.pas120
-rw-r--r--compiler/sparc/aoptcpud.pas36
-rw-r--r--compiler/sparc/cgcpu.pas1479
-rw-r--r--compiler/sparc/cpubase.pas462
-rw-r--r--compiler/sparc/cpugas.pas205
-rw-r--r--compiler/sparc/cpuinfo.pas68
-rw-r--r--compiler/sparc/cpunode.pas38
-rw-r--r--compiler/sparc/cpupara.pas325
-rw-r--r--compiler/sparc/cpupi.pas84
-rw-r--r--compiler/sparc/cpuswtch.pas125
-rw-r--r--compiler/sparc/cputarg.pas76
-rw-r--r--compiler/sparc/itcpugas.pas98
-rw-r--r--compiler/sparc/ncpuadd.pas376
-rw-r--r--compiler/sparc/ncpucall.pas56
-rw-r--r--compiler/sparc/ncpucnv.pas305
-rw-r--r--compiler/sparc/ncpuinln.pas149
-rw-r--r--compiler/sparc/ncpumat.pas324
-rw-r--r--compiler/sparc/ncpuset.pas126
-rw-r--r--compiler/sparc/opcode.inc73
-rw-r--r--compiler/sparc/racpu.pas53
-rw-r--r--compiler/sparc/racpugas.pas671
-rw-r--r--compiler/sparc/rgcpu.pas163
-rw-r--r--compiler/sparc/rspcon.inc140
-rw-r--r--compiler/sparc/rspdwrf.inc140
-rw-r--r--compiler/sparc/rspnor.inc2
-rw-r--r--compiler/sparc/rspnum.inc140
-rw-r--r--compiler/sparc/rsprni.inc140
-rw-r--r--compiler/sparc/rspsri.inc140
-rw-r--r--compiler/sparc/rspstab.inc140
-rw-r--r--compiler/sparc/rspstd.inc140
-rw-r--r--compiler/sparc/rspsup.inc140
-rw-r--r--compiler/sparc/spreg.dat154
-rw-r--r--compiler/sparc/strinst.inc69
-rw-r--r--compiler/switches.pas228
-rw-r--r--compiler/symbase.pas333
-rw-r--r--compiler/symconst.pas434
-rw-r--r--compiler/symdef.pas5485
-rw-r--r--compiler/symnot.pas63
-rw-r--r--compiler/symsym.pas2349
-rw-r--r--compiler/symtable.pas2303
-rw-r--r--compiler/symtype.pas1447
-rw-r--r--compiler/symutil.pas119
-rw-r--r--compiler/systems.pas801
-rw-r--r--compiler/systems/i_amiga.pas169
-rw-r--r--compiler/systems/i_atari.pas83
-rw-r--r--compiler/systems/i_beos.pas100
-rw-r--r--compiler/systems/i_bsd.pas572
-rw-r--r--compiler/systems/i_emx.pas114
-rw-r--r--compiler/systems/i_gba.pas101
-rw-r--r--compiler/systems/i_go32v2.pas100
-rw-r--r--compiler/systems/i_linux.pas658
-rw-r--r--compiler/systems/i_macos.pas100
-rw-r--r--compiler/systems/i_morph.pas101
-rw-r--r--compiler/systems/i_nwl.pas100
-rw-r--r--compiler/systems/i_nwm.pas100
-rw-r--r--compiler/systems/i_os2.pas114
-rw-r--r--compiler/systems/i_palmos.pas90
-rw-r--r--compiler/systems/i_sunos.pas168
-rw-r--r--compiler/systems/i_watcom.pas102
-rw-r--r--compiler/systems/i_wdosx.pas102
-rw-r--r--compiler/systems/i_win.pas306
-rw-r--r--compiler/systems/mac_crea.txt71
-rw-r--r--compiler/systems/t_amiga.pas43
-rw-r--r--compiler/systems/t_atari.pas43
-rw-r--r--compiler/systems/t_beos.pas495
-rw-r--r--compiler/systems/t_bsd.pas655
-rw-r--r--compiler/systems/t_emx.pas516
-rw-r--r--compiler/systems/t_gba.pas300
-rw-r--r--compiler/systems/t_go32v2.pas364
-rw-r--r--compiler/systems/t_linux.pas755
-rw-r--r--compiler/systems/t_macos.pas273
-rw-r--r--compiler/systems/t_morph.pas269
-rw-r--r--compiler/systems/t_nwl.pas645
-rw-r--r--compiler/systems/t_nwm.pas576
-rw-r--r--compiler/systems/t_os2.pas516
-rw-r--r--compiler/systems/t_palmos.pas212
-rw-r--r--compiler/systems/t_sunos.pas490
-rw-r--r--compiler/systems/t_watcom.pas178
-rw-r--r--compiler/systems/t_wdosx.pas84
-rw-r--r--compiler/systems/t_win.pas1673
-rw-r--r--compiler/tgobj.pas625
-rw-r--r--compiler/tokens.pas538
-rw-r--r--compiler/utils/Makefile2021
-rw-r--r--compiler/utils/Makefile.fpc52
-rw-r--r--compiler/utils/README20
-rw-r--r--compiler/utils/fixlog.pp174
-rw-r--r--compiler/utils/fixmsg.pp66
-rw-r--r--compiler/utils/fixnasm.pp99
-rw-r--r--compiler/utils/fixtab.pp367
-rw-r--r--compiler/utils/fpc.cft204
-rw-r--r--compiler/utils/fpc.mpw2
-rw-r--r--compiler/utils/fpc.pp205
-rw-r--r--compiler/utils/fpccfg.inc224
-rw-r--r--compiler/utils/fpcmkcfg.pp230
-rw-r--r--compiler/utils/fpcsubst.pp241
-rw-r--r--compiler/utils/fpimpdef.pp98
-rw-r--r--compiler/utils/fppkg.pp963
-rw-r--r--compiler/utils/gppc386.pp138
-rw-r--r--compiler/utils/mk68kreg.pp334
-rw-r--r--compiler/utils/mkarmins.pp432
-rw-r--r--compiler/utils/mkarmreg.pp298
-rw-r--r--compiler/utils/mkmpsreg.pp349
-rw-r--r--compiler/utils/mkppcreg.pp396
-rw-r--r--compiler/utils/mkspreg.pp301
-rw-r--r--compiler/utils/mkx86ins.pp454
-rw-r--r--compiler/utils/mkx86reg.pp467
-rw-r--r--compiler/utils/msg2inc.pp815
-rw-r--r--compiler/utils/msgdif.pp529
-rw-r--r--compiler/utils/msgused.pl42
-rw-r--r--compiler/utils/ppudump.pp2191
-rw-r--r--compiler/utils/ppufiles.pp252
-rw-r--r--compiler/utils/ppumove.pp613
-rw-r--r--compiler/utils/samplecfg267
-rw-r--r--compiler/utils/usubst.pp109
-rw-r--r--compiler/verbose.pas830
-rw-r--r--compiler/version.pas92
-rw-r--r--compiler/vis/aasmcpu.pas248
-rw-r--r--compiler/vis/cpubase.pas643
-rw-r--r--compiler/vis/cpuinfo.pas56
-rw-r--r--compiler/vis/cpunode.pas47
-rw-r--r--compiler/vis/cpupara.pas74
-rw-r--r--compiler/widestr.pas227
-rw-r--r--compiler/x86/aasmcpu.pas2155
-rw-r--r--compiler/x86/agx86att.pas284
-rw-r--r--compiler/x86/agx86int.pas965
-rw-r--r--compiler/x86/cga.pas128
-rw-r--r--compiler/x86/cgx86.pas1835
-rw-r--r--compiler/x86/cpubase.pas471
-rw-r--r--compiler/x86/itcpugas.pas138
-rw-r--r--compiler/x86/itx86int.pas97
-rw-r--r--compiler/x86/nx86add.pas1065
-rw-r--r--compiler/x86/nx86cnv.pas392
-rw-r--r--compiler/x86/nx86con.pas91
-rw-r--r--compiler/x86/nx86inl.pas403
-rw-r--r--compiler/x86/nx86mat.pas317
-rw-r--r--compiler/x86/nx86set.pas462
-rw-r--r--compiler/x86/rax86.pas715
-rw-r--r--compiler/x86/rax86att.pas808
-rw-r--r--compiler/x86/rgx86.pas346
-rw-r--r--compiler/x86/x86ins.dat3421
-rw-r--r--compiler/x86/x86reg.dat140
-rw-r--r--compiler/x86_64/aoptcpu.pas41
-rw-r--r--compiler/x86_64/aoptcpub.pas120
-rw-r--r--compiler/x86_64/aoptcpud.pas36
-rw-r--r--compiler/x86_64/cgcpu.pas139
-rw-r--r--compiler/x86_64/cpubase.inc148
-rw-r--r--compiler/x86_64/cpuinfo.pas84
-rw-r--r--compiler/x86_64/cpunode.pas58
-rw-r--r--compiler/x86_64/cpupara.pas493
-rw-r--r--compiler/x86_64/cpupi.pas64
-rw-r--r--compiler/x86_64/cpuswtch.pas97
-rw-r--r--compiler/x86_64/cputarg.pas84
-rw-r--r--compiler/x86_64/nx64add.pas87
-rw-r--r--compiler/x86_64/nx64cal.pas62
-rw-r--r--compiler/x86_64/nx64cnv.pas66
-rw-r--r--compiler/x86_64/nx64inl.pas42
-rw-r--r--compiler/x86_64/nx64mat.pas204
-rw-r--r--compiler/x86_64/r8664ari.inc126
-rw-r--r--compiler/x86_64/r8664att.inc126
-rw-r--r--compiler/x86_64/r8664con.inc126
-rw-r--r--compiler/x86_64/r8664dwrf.inc126
-rw-r--r--compiler/x86_64/r8664int.inc126
-rw-r--r--compiler/x86_64/r8664iri.inc126
-rw-r--r--compiler/x86_64/r8664nor.inc2
-rw-r--r--compiler/x86_64/r8664num.inc126
-rw-r--r--compiler/x86_64/r8664op.inc126
-rw-r--r--compiler/x86_64/r8664ot.inc126
-rw-r--r--compiler/x86_64/r8664rni.inc126
-rw-r--r--compiler/x86_64/r8664sri.inc126
-rw-r--r--compiler/x86_64/r8664stab.inc126
-rw-r--r--compiler/x86_64/r8664std.inc126
-rw-r--r--compiler/x86_64/rax64att.pas69
-rw-r--r--compiler/x86_64/rgcpu.pas53
-rw-r--r--compiler/x86_64/x8664ats.inc569
-rw-r--r--compiler/x86_64/x8664att.inc569
-rw-r--r--compiler/x86_64/x8664int.inc569
-rw-r--r--compiler/x86_64/x8664nop.inc2
-rw-r--r--compiler/x86_64/x8664op.inc569
-rw-r--r--compiler/x86_64/x8664pro.inc569
-rw-r--r--compiler/x86_64/x8664tab.inc11483
578 files changed, 297913 insertions, 0 deletions
diff --git a/compiler/COPYING b/compiler/COPYING
new file mode 100644
index 0000000000..5b6e7c66c2
--- /dev/null
+++ b/compiler/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/compiler/MPWMake b/compiler/MPWMake
new file mode 100644
index 0000000000..4ba478f4ca
--- /dev/null
+++ b/compiler/MPWMake
@@ -0,0 +1 @@
+# Make file for MPW make. # To run it, use: # Make <target> -f MPWMake > Makeout ; Makeout # where <target> should be replaced with actual make target. ############################################# # TIPS (TODO move to Wiki or something # # Defined variables: No quoting # Command lines: quote paths, dont quote option strings, since # they might contain several options, which must be separated. # Recursive call to Make: # - give options as -d XXX="{XXX}" # - in same dir, remember to ensure to have different Makeout files, # e g Makeout2. # # NOTE Currently cycle is stopped after three rounds, no diff is checked. FPC = {FPCDIR}bin:ppcppc # Default language for the compiler (english): FPCLANG = e MSGFILE = :msg:error{FPCLANG}.msg msg2inc Ä :utils:msg2inc.pp {FPC} -FE: -WT :utils:msg2inc.pp # The msgtxt.inc only depends on the error?.msg file, not on msg2inc, # because that one will be new almost everytime msgtxt.inc Ä {MSGFILE} Make msg2inc -f MPWMake > Makeout3 ; Makeout3 msg2inc {MSGFILE} msg msg msg Ä msgtxt.inc compiler Ä msg Set Exit 0 NewFolder :powerpc:units: ³ Dev:Null NewFolder :powerpc:units:powerpc-macos: ³ Dev:Null Set Exit 1 "{FPC}" {OPT} "-Fu{RTLDIR}" -Fu:systems: -Fu:powerpc: -dGDB -dBROWSERLOG -dNOOPT ¶ -dpowerpc -WT -FE: -FU:powerpc:units:powerpc-macos: pp.pas Rename -y pp ppcppc clean Ä utils_clean Set Exit 0 Delete -y :powerpc:units:powerpc-macos Delete -y ppcppc oldfpc msg2inc Delete -y Å.xcoff Set Exit 1 cycleclean Ä Set Exit 0 Delete -y :powerpc:units:powerpc-macos Set Exit 1 install Ä If {FPCDIR} == '' Set -e FPCDIR `GetFileName -wd -m 'Select where to install the FreePascal folder'`FreePascal: Set -e Commands "{Commands},{FPCDIR}bin:" Echo "Set -e FPCDIR ¶'{FPCDIR}¶'" > "{MPW}Startup Items:FPC Startup" Echo 'Set -e Commands "{Commands},{FPCDIR}bin:"' >> "{MPW}Startup Items:FPC Startup" End Set Exit 0 NewFolder "{FPCDIR}" ³ Dev:Null NewFolder "{FPCDIR}bin:" ³ Dev:Null Set Exit 1 Duplicate -y :ppcppc :utils:ppudump :utils:ppufiles :utils:ppumove ¶ :utils:fpc "{FPCDIR}bin:" Echo "# Configuration file for Free Pascal for MPW" > "{FPCDIR}bin:fpc.cfg" Echo "-Fu¶'{FPCDIR}units:rtl:¶'" >> "{FPCDIR}bin:fpc.cfg" Echo "-l" >> "{FPCDIR}bin:fpc.cfg" Echo "-vi" >> "{FPCDIR}bin:fpc.cfg" cycle Ä Directory ::rtl:macos Make clean -f MPWMake > Makeout ; Makeout Make all -d FPC="{FPC}" -d OPT="{OPT}" -f MPWMake > Makeout ; Makeout Directory :::compiler Make clean -f MPWMake > Makeout2 ; Makeout2 Make compiler -d FPC="{FPC}" -d OPT="{OPT}" -d RTLDIR=::rtl:units:powerpc-macos -f MPWMake > Makeout2 ; Makeout2 # Echo '******************** SECOND ROUND *********************' Rename -y ppcppc oldfpc Directory ::rtl:macos Make clean -f MPWMake > Makeout ; Makeout Make all -d FPC=:::compiler:oldfpc -d OPT="{OPT}" -f MPWMake > Makeout ; Makeout Directory :::compiler Make cycleclean -f MPWMake > Makeout2 ; Makeout2 Make compiler -d FPC=oldfpc -d OPT="{OPT}" -d RTLDIR=::rtl:units:powerpc-macos -f MPWMake > Makeout2 ; Makeout2 # Echo '********************* THIRD ROUND *********************' Rename -y ppcppc oldfpc Directory ::rtl:macos Make clean -f MPWMake > Makeout ; Makeout Make all -d FPC=:::compiler:oldfpc -d OPT="{OPT}" -f MPWMake > Makeout ; Makeout Directory :::compiler Make cycleclean -f MPWMake > Makeout2 ; Makeout2 Make compiler -d FPC=oldfpc -d OPT="{OPT}" -d RTLDIR=::rtl:units:powerpc-macos -f MPWMake > Makeout2 ; Makeout2 # Make utils_clean -f MPWMake > Makeout2 ; Makeout2 Make utils_all -d FPC=::oldfpc -d OPT="{OPT}" -d RTLDIR=:::rtl:units:powerpc-macos -f MPWMake > Makeout2 ; Makeout2 utils_all Ä Directory :utils Set Exit 0 NewFolder :units: ³ Dev:Null NewFolder :units:powerpc-macos: ³ Dev:Null Set Exit 1 "{FPC}" {OPT} "-Fu{RTLDIR}" -FE: -FU:units:powerpc-macos -Fu:: -WT ppudump.pp "{FPC}" {OPT} "-Fu{RTLDIR}" -FE: -FU:units:powerpc-macos -Fu:: -WT ppufiles.pp "{FPC}" {OPT} "-Fu{RTLDIR}" -FE: -FU:units:powerpc-macos -Fu:: -WT ppumove.pp Duplicate -y fpc.mpw fpc Directory :: utils_clean Ä Directory :utils Set Exit 0 Delete -y :units:powerpc-macos Delete -y fpc ppudump ppufiles ppumove msg2inc Delete -y Å.xcoff Set Exit 1 Directory :: \ No newline at end of file
diff --git a/compiler/Makefile b/compiler/Makefile
new file mode 100644
index 0000000000..b889d23a61
--- /dev/null
+++ b/compiler/Makefile
@@ -0,0 +1,2785 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2005/10/20]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-emx i386-watcom i386-netwlibc i386-wince m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd x86_64-win64 arm-linux arm-wince powerpc64-linux
+BSDs = freebsd netbsd openbsd darwin
+UNIXs = linux $(BSDs) solaris qnx
+LIMIT83fs = go32v2 os2 emx watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPC:=$(shell $(FPCPROG) -PB)
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifneq ($(words $(FPC_COMPILERINFO)),5)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSO)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTO)
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+export OS_TARGET OS_SOURCE CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+override PACKAGE_NAME=compiler
+override PACKAGE_VERSION=2.0.0
+unexport FPC_VERSION FPC_COMPILERINFO
+CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64
+ALLTARGETS=$(CYCLETARGETS) m68k
+ifdef ALPHA
+PPC_TARGET=alpha
+endif
+ifdef POWERPC
+PPC_TARGET=powerpc
+endif
+ifdef POWERPC64
+PPC_TARGET=powerpc64
+endif
+ifdef SPARC
+PPC_TARGET=sparc
+endif
+ifdef M68K
+PPC_TARGET=m68k
+endif
+ifdef I386
+PPC_TARGET=i386
+endif
+ifdef X86_64
+PPC_TARGET=x86_64
+endif
+ifdef ARM
+PPC_TARGET=arm
+endif
+ifndef PPC_TARGET
+PPC_TARGET=$(CPU_TARGET)
+endif
+ifndef PPC_OS
+PPC_OS=$(OS_TARGET)
+endif
+CPU_UNITDIR=$(PPC_TARGET)
+UTILSDIR=../utils
+COMPILERSOURCEDIR=$(PPC_TARGET) systems
+COMPILERUTILSDIR=utils
+ifndef FPCLANG
+FPCLANG=e
+endif
+ifndef LOCALOPT
+LOCALOPT:=$(OPT)
+endif
+ifndef RTLOPT
+RTLOPT:=$(OPT)
+endif
+override OPT=
+MSGFILES=$(wildcard msg/error*.msg)
+ifeq ($(PPC_TARGET),i386)
+CPUSUF=386
+endif
+ifeq ($(PPC_TARGET),alpha)
+CPUSUF=axp
+endif
+ifeq ($(PPC_TARGET),m68k)
+CPUSUF=68k
+endif
+ifeq ($(PPC_TARGET),powerpc)
+CPUSUF=ppc
+endif
+ifeq ($(PPC_TARGET),powerpc64)
+CPUSUF=ppc64
+endif
+ifeq ($(PPC_TARGET),sparc)
+CPUSUF=sparc
+endif
+ifeq ($(PPC_TARGET),x86_64)
+CPUSUF=x64
+endif
+ifeq ($(PPC_TARGET),arm)
+CPUSUF=arm
+endif
+NOCPUDEF=1
+MSGFILE=msg/error$(FPCLANG).msg
+ifeq ($(OS_TARGET),linux)
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+override LOCALOPT+=-dUNIX
+endif
+endif
+ifeq ($(OS_TARGET),freebsd)
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+override LOCALOPT+=-dUNIX
+endif
+endif
+override LOCALOPT+=-d$(PPC_TARGET) -dGDB -dBROWSERLOG
+ifeq ($(PPC_TARGET),i386)
+override LOCALOPT+=-Fux86
+endif
+ifeq ($(PPC_TARGET),x86_64)
+override LOCALOPT+=-Fux86
+endif
+ifeq ($(PPC_TARGET),powerpc)
+override LOCALOPT+=
+endif
+ifeq ($(PPC_TARGET),m68k)
+override LOCALOPT+=-dNOOPT
+endif
+ifeq ($(PPC_TARGET),sparc)
+override LOCALOPT+=
+endif
+ifeq ($(PPC_TARGET),m68k)
+ifeq ($(OS_TARGET),amiga)
+override LOCALOPT+=-Ct
+endif
+endif
+ifeq ($(PPC_TARGET),arm)
+override LOCALOPT+=-dNOOPT
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_PROGRAMS+=pp
+endif
+override INSTALL_FPCPACKAGE=y
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_INCLUDEDIR+=$(PPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+STATICLIBPREFIX=libp
+RSTEXT=.rst
+ifeq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+endif
+ifeq ($(OS_TARGET),darwin)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+endif
+else
+ifeq ($(OS_TARGET),go32v1)
+PPUEXT=.pp1
+OEXT=.o1
+ASMEXT=.s1
+SMARTEXT=.sl1
+STATICLIBEXT=.a1
+SHAREDLIBEXT=.so1
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+SHORTSUFFIX=wat
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+PPUEXT=.ppw
+OEXT=.ow
+ASMEXT=.sw
+SMARTEXT=.slw
+STATICLIBEXT=.aw
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+PPUEXT=.ppo
+ASMEXT=.so2
+OEXT=.oo2
+AOUTEXT=.out
+SMARTEXT=.sl2
+STATICLIBPREFIX=
+STATICLIBEXT=.ao2
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+PPUEXT=.ppu
+ASMEXT=.asm
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),atari)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nw
+endif
+ifeq ($(OS_TARGET),netwlibc)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nwl
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+endif
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),win32)
+ifeq ($(CROSSBINDIR),)
+ASNAME=asw
+LDNAME=ldw
+ARNAME=arw
+endif
+endif
+endif
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+PPAS=ppas$(SRCBATCHEXT)
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ifndef UPXPROG
+ifeq ($(OS_TARGET),go32v2)
+UPXPROG:=1
+endif
+ifeq ($(OS_TARGET),win32)
+UPXPROG:=1
+endif
+ifdef UPXPROG
+UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(UPXPROG),)
+UPXPROG=
+else
+UPXPROG:=$(firstword $(UPXPROG))
+endif
+else
+UPXPROG=
+endif
+endif
+export UPXPROG
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl rtl
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(CPU_TARGET)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX) -Xc
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+else
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+else
+FPCCPUOPT:=
+endif
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-OG2p3
+endif
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifeq ($(OS_TARGET),linux)
+ifeq ($(FPC_VERSION),1.0.6)
+override FPCOPTDEF+=HASUNIX
+endif
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+EXECPPAS:=@$(PPAS)
+endif
+endif
+.PHONY: fpc_exes
+ifndef CROSSINSTALL
+ifneq ($(TARGET_PROGRAMS),)
+override EXEFILES=$(addsuffix $(EXEEXT),$(TARGET_PROGRAMS))
+override EXEOFILES:=$(addsuffix $(OEXT),$(TARGET_PROGRAMS)) $(addprefix $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_PROGRAMS)))
+override ALLTARGET+=fpc_exes
+override INSTALLEXEFILES+=$(EXEFILES)
+override CLEANEXEFILES+=$(EXEFILES) $(EXEOFILES)
+ifeq ($(OS_TARGET),os2)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))
+endif
+ifeq ($(OS_TARGET),emx)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))
+endif
+endif
+endif
+fpc_exes: $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(EXEFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release
+$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)
+ @$(ECHOREDIR) Compiled > $(FPCMADE)
+fpc_all: $(FPCMADE)
+fpc_smart:
+ $(MAKE) all LINKSMART=1 CREATESMART=1
+fpc_debug:
+ $(MAKE) all DEBUG=1
+fpc_release:
+ $(MAKE) all RELEASE=1
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res
+$(COMPILER_UNITTARGETDIR):
+ $(MKDIRTREE) $(COMPILER_UNITTARGETDIR)
+$(COMPILER_TARGETDIR):
+ $(MKDIRTREE) $(COMPILER_TARGETDIR)
+%$(PPUEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(PPUEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.lpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.dpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%.res: %.rc
+ windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+ $(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILES)
+endif
+ $(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+ $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+ $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+ $(MKDIR) $(INSTALL_LIBDIR)
+ $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+ ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+ $(MKDIR) $(INSTALL_DATADIR)
+ $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+ $(MKDIR) $(INSTALL_SOURCEDIR)
+ $(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+ $(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+ $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_distinstall
+fpc_distinstall: install exampleinstall
+.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/../fpc-pack
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+ifndef ZIPNAME
+ifdef DIST_ZIPNAME
+ZIPNAME=$(DIST_ZIPNAME)
+else
+ZIPNAME=$(PACKAGE_NAME)
+endif
+endif
+ifndef FULLZIPNAME
+FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX)
+endif
+ifndef ZIPTARGET
+ifdef DIST_ZIPTARGET
+ZIPTARGET=DIST_ZIPTARGET
+else
+ZIPTARGET=install
+endif
+endif
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+ifndef inUnix
+USEZIPWRAPPER=1
+endif
+ifdef USEZIPWRAPPER
+ZIPPATHSEP=$(PATHSEP)
+ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT))
+else
+ZIPPATHSEP=/
+endif
+ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
+ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
+ifdef USETAR
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
+ZIPCMD_ZIP:=$(TARPROG) cf$(TAROPT) $(ZIPDESTFILE) *
+else
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
+ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
+endif
+fpc_zipinstall:
+ $(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1
+ $(MKDIR) $(DIST_DESTDIR)
+ $(DEL) $(ZIPDESTFILE)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER)
+else
+ echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)
+ echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)
+ echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)
+endif
+ifdef inUnix
+ /bin/sh $(ZIPWRAPPER)
+else
+ $(ZIPWRAPPER)
+endif
+ $(DEL) $(ZIPWRAPPER)
+else
+ $(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)
+endif
+ $(DELTREE) $(PACKDIR)
+fpc_zipsourceinstall:
+ $(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX)
+fpc_zipexampleinstall:
+ifdef HASEXAMPLES
+ $(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX)
+endif
+fpc_zipdistinstall:
+ $(MAKE) fpc_zipinstall ZIPTARGET=distinstall
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+ -$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+ -$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+ -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+ -$(DELTREE) units
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+ -$(DEL) *.o *.ppu *.a
+endif
+ -$(DELTREE) *$(SMARTEXT)
+ -$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+ -$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+ -$(DEL) *$(DEBUGSYMEXT)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+ @$(ECHO)
+ @$(ECHO) == Package info ==
+ @$(ECHO) Package Name..... $(PACKAGE_NAME)
+ @$(ECHO) Package Version.. $(PACKAGE_VERSION)
+ @$(ECHO)
+ @$(ECHO) == Configuration info ==
+ @$(ECHO)
+ @$(ECHO) FPC.......... $(FPC)
+ @$(ECHO) FPC Version.. $(FPC_VERSION)
+ @$(ECHO) Source CPU... $(CPU_SOURCE)
+ @$(ECHO) Target CPU... $(CPU_TARGET)
+ @$(ECHO) Source OS.... $(OS_SOURCE)
+ @$(ECHO) Target OS.... $(OS_TARGET)
+ @$(ECHO) Full Source.. $(FULL_SOURCE)
+ @$(ECHO) Full Target.. $(FULL_TARGET)
+ @$(ECHO) SourceSuffix. $(SOURCESUFFIX)
+ @$(ECHO) TargetSuffix. $(TARGETSUFFIX)
+ @$(ECHO)
+ @$(ECHO) == Directory info ==
+ @$(ECHO)
+ @$(ECHO) Required pkgs... $(REQUIRE_PACKAGES)
+ @$(ECHO)
+ @$(ECHO) Basedir......... $(BASEDIR)
+ @$(ECHO) FPCDir.......... $(FPCDIR)
+ @$(ECHO) CrossBinDir..... $(CROSSBINDIR)
+ @$(ECHO) UnitsDir........ $(UNITSDIR)
+ @$(ECHO) PackagesDir..... $(PACKAGESDIR)
+ @$(ECHO)
+ @$(ECHO) GCC library..... $(GCCLIBDIR)
+ @$(ECHO) Other library... $(OTHERLIBDIR)
+ @$(ECHO)
+ @$(ECHO) == Tools info ==
+ @$(ECHO)
+ @$(ECHO) As........ $(AS)
+ @$(ECHO) Ld........ $(LD)
+ @$(ECHO) Ar........ $(AR)
+ @$(ECHO) Rc........ $(RC)
+ @$(ECHO)
+ @$(ECHO) Mv........ $(MVPROG)
+ @$(ECHO) Cp........ $(CPPROG)
+ @$(ECHO) Rm........ $(RMPROG)
+ @$(ECHO) GInstall.. $(GINSTALL)
+ @$(ECHO) Echo...... $(ECHO)
+ @$(ECHO) Shell..... $(SHELL)
+ @$(ECHO) Date...... $(DATE)
+ @$(ECHO) FPCMake... $(FPCMAKE)
+ @$(ECHO) PPUMove... $(PPUMOVE)
+ @$(ECHO) Upx....... $(UPXPROG)
+ @$(ECHO) Zip....... $(ZIPPROG)
+ @$(ECHO)
+ @$(ECHO) == Object info ==
+ @$(ECHO)
+ @$(ECHO) Target Loaders........ $(TARGET_LOADERS)
+ @$(ECHO) Target Units.......... $(TARGET_UNITS)
+ @$(ECHO) Target Implicit Units. $(TARGET_IMPLICITUNITS)
+ @$(ECHO) Target Programs....... $(TARGET_PROGRAMS)
+ @$(ECHO) Target Dirs........... $(TARGET_DIRS)
+ @$(ECHO) Target Examples....... $(TARGET_EXAMPLES)
+ @$(ECHO) Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+ @$(ECHO)
+ @$(ECHO) Clean Units......... $(CLEAN_UNITS)
+ @$(ECHO) Clean Files......... $(CLEAN_FILES)
+ @$(ECHO)
+ @$(ECHO) Install Units....... $(INSTALL_UNITS)
+ @$(ECHO) Install Files....... $(INSTALL_FILES)
+ @$(ECHO)
+ @$(ECHO) == Install info ==
+ @$(ECHO)
+ @$(ECHO) DateStr.............. $(DATESTR)
+ @$(ECHO) ZipName.............. $(ZIPNAME)
+ @$(ECHO) ZipPrefix............ $(ZIPPREFIX)
+ @$(ECHO) ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+ @$(ECHO) ZipSuffix............ $(ZIPSUFFIX)
+ @$(ECHO) FullZipName.......... $(FULLZIPNAME)
+ @$(ECHO) Install FPC Package.. $(INSTALL_FPCPACKAGE)
+ @$(ECHO)
+ @$(ECHO) Install base dir..... $(INSTALL_BASEDIR)
+ @$(ECHO) Install binary dir... $(INSTALL_BINDIR)
+ @$(ECHO) Install library dir.. $(INSTALL_LIBDIR)
+ @$(ECHO) Install units dir.... $(INSTALL_UNITDIR)
+ @$(ECHO) Install source dir... $(INSTALL_SOURCEDIR)
+ @$(ECHO) Install doc dir...... $(INSTALL_DOCDIR)
+ @$(ECHO) Install example dir.. $(INSTALL_EXAMPLEDIR)
+ @$(ECHO) Install data dir..... $(INSTALL_DATADIR)
+ @$(ECHO)
+ @$(ECHO) Dist destination dir. $(DIST_DESTDIR)
+ @$(ECHO) Dist zip name........ $(DIST_ZIPNAME)
+ @$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+ fpc_makefile_dirs
+fpc_makefile:
+ $(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+ifeq ($(FULL_TARGET),i386-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifdef TARGET_DIRS_UTILS
+utils_all:
+ $(MAKE) -C utils all
+utils_debug:
+ $(MAKE) -C utils debug
+utils_smart:
+ $(MAKE) -C utils smart
+utils_release:
+ $(MAKE) -C utils release
+utils_units:
+ $(MAKE) -C utils units
+utils_examples:
+ $(MAKE) -C utils examples
+utils_shared:
+ $(MAKE) -C utils shared
+utils_install:
+ $(MAKE) -C utils install
+utils_sourceinstall:
+ $(MAKE) -C utils sourceinstall
+utils_exampleinstall:
+ $(MAKE) -C utils exampleinstall
+utils_distinstall:
+ $(MAKE) -C utils distinstall
+utils_zipinstall:
+ $(MAKE) -C utils zipinstall
+utils_zipsourceinstall:
+ $(MAKE) -C utils zipsourceinstall
+utils_zipexampleinstall:
+ $(MAKE) -C utils zipexampleinstall
+utils_zipdistinstall:
+ $(MAKE) -C utils zipdistinstall
+utils_clean:
+ $(MAKE) -C utils clean
+utils_distclean:
+ $(MAKE) -C utils distclean
+utils_cleanall:
+ $(MAKE) -C utils cleanall
+utils_info:
+ $(MAKE) -C utils info
+utils_makefiles:
+ $(MAKE) -C utils makefiles
+utils:
+ $(MAKE) -C utils all
+.PHONY: utils_all utils_debug utils_smart utils_release utils_units utils_examples utils_shared utils_install utils_sourceinstall utils_exampleinstall utils_distinstall utils_zipinstall utils_zipsourceinstall utils_zipexampleinstall utils_zipdistinstall utils_clean utils_distclean utils_cleanall utils_info utils_makefiles utils
+endif
+ifndef DIFF
+DIFF:=$(strip $(wildcard $(addsuffix /diff$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DIFF),)
+DIFF= __missing_command_DIFF
+else
+DIFF:=$(firstword $(DIFF))
+endif
+endif
+export DIFF
+ifndef CMP
+CMP:=$(strip $(wildcard $(addsuffix /cmp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CMP),)
+CMP= __missing_command_CMP
+else
+CMP:=$(firstword $(CMP))
+endif
+endif
+export CMP
+debug: fpc_debug
+smart: fpc_smart
+release: fpc_release
+units: fpc_units $(addsuffix _units,$(TARGET_DIRS))
+examples: $(addsuffix _examples,$(TARGET_DIRS))
+shared: $(addsuffix _shared,$(TARGET_DIRS))
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall $(addsuffix _exampleinstall,$(TARGET_DIRS))
+distinstall: fpc_distinstall
+zipinstall: fpc_zipinstall
+zipsourceinstall: fpc_zipsourceinstall
+zipexampleinstall: fpc_zipexampleinstall $(addsuffix _zipexampleinstall,$(TARGET_DIRS))
+zipdistinstall: fpc_zipdistinstall
+cleanall: fpc_cleanall $(addsuffix _cleanall,$(TARGET_DIRS))
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: debug smart release units examples shared sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+ifeq ($(OS_TARGET),win32)
+ifdef CMP
+override DIFF:=$(CMP) -i218
+endif
+endif
+override COMPILER+=$(LOCALOPT)
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+override COMPILER:=$(patsubst -O%,,$(COMPILER))
+endif
+PASDOC:=$(strip $(wildcard $(addsuffix /pasdoc.exe,$(SEARCHPATH))))
+ifeq ($(PASDOC),)
+PASDOC:=$(strip $(wildcard $(addsuffix /pasdoc,$(SEARCHPATH))))
+endif
+ifeq ($(PASDOC),)
+PASDOC:=../projects/pasdoc/bin/pasdoc
+else
+PASDOC:=$(firstword $(PASDOC))
+endif
+ifndef EXENAME
+EXENAME=ppc$(CPUSUF)$(EXEEXT)
+endif
+PPEXENAME=pp$(EXEEXT)
+TEMPNAME=ppc$(SRCEXEEXT)
+PPCROSSNAME=ppcross$(CPUSUF)$(SRCEXEEXT)
+TEMPNAME1=ppc1$(EXEEXT)
+TEMPNAME2=ppc2$(EXEEXT)
+TEMPNAME3=ppc3$(EXEEXT)
+MAKEDEP=ppdep$(EXEEXT)
+MSG2INC=./msg2inc$(EXEEXT)
+ifdef CROSSINSTALL
+INSTALLEXEFILE=$(PPCROSSNAME)
+else
+INSTALLEXEFILE=$(EXENAME)
+endif
+PPC_TARGETS=alpha i386 m68k powerpc sparc arm x86_64
+.PHONY: $(PPC_TARGETS)
+$(PPC_TARGETS):
+ $(MAKE) PPC_TARGET=$@ CPU_UNITDIR=$@ all
+.PHONY: all compiler echotime ppuclean execlean clean distclean
+all: compiler $(addsuffix _all,$(TARGET_DIRS))
+compiler: $(COMPILER_UNITTARGETDIR) $(COMPILER_TARGETDIR) $(EXENAME)
+ifeq ($(MAKELEVEL),0)
+ifndef STARTTIME
+ifdef DATE
+STARTTIME:=$(shell $(DATE) +%T)
+else
+STARTTIME:=unknown
+endif
+endif
+endif
+export STARTTIME
+ifdef DATE
+ENDTIME=$(shell $(DATE) +%T)
+else
+ENDTIME:=unknown
+endif
+echotime:
+ @echo Start $(STARTTIME) now $(ENDTIME)
+ppuclean:
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ -$(DEL) $(addsuffix /*$(PPUEXT),$(COMPILERSOURCEDIR))
+tempclean:
+ -$(DEL) $(PPCROSSNAME) $(TEMPNAME) $(TEMPNAME1) $(TEMPNAME2) $(TEMPNAME3) $(MSG2INC)
+execlean :
+ -$(DEL) ppc386$(EXEEXT) ppcaxp$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) $(EXENAME)
+$(addsuffix _clean,$(ALLTARGETS)):
+ -$(DELTREE) $(addprefix $(subst _clean,,$@),/units)
+ -$(DEL) $(addprefix $(subst _clean,,$@)/,*$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT))
+ -$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppcaxp$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcppc$(EXEEXT) $(EXENAME))
+cycleclean: cleanall $(addsuffix _clean,$(PPC_TARGET))
+ -$(DEL) $(EXENAME)
+clean: tempclean execlean cleanall $(addsuffix _clean,$(PPC_TARGET)) $(addsuffix _clean,$(TARGET_DIRS))
+distclean: tempclean execlean cleanall $(addsuffix _clean,$(ALLTARGETS)) $(addsuffix _distclean,$(TARGET_DIRS))
+$(MSG2INC): $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(COMPILERUTILSDIR)/msg2inc.pp
+ $(COMPILER) -FE. $(COMPILERUTILSDIR)/msg2inc.pp
+msgtxt.inc: $(MSGFILE)
+ $(MAKE) $(MSG2INC)
+ $(MSG2INC) $(MSGFILE) msg msg
+msg: msgtxt.inc
+$(EXENAME) : $(wildcard *.pas) $(wildcard *.inc) msg \
+ $(wildcard systems/*.pas) $(wilcard systems/*.inc) \
+ $(wildcard $(PPC_TARGET)/*.pas) $(wildcard $(PPC_TARGET)/*.inc)
+ $(COMPILER) pp.pas
+ $(EXECPPAS)
+ $(MOVE) $(COMPILER_TARGETDIR)/$(PPEXENAME) $(EXENAME)
+ifeq ($(CPU_SOURCE),$(PPC_TARGET))
+ifeq ($(OS_SOURCE),$(OS_TARGET))
+ifdef DIFF
+ifdef OLDFPC
+DIFFRESULT:=$(shell $(DIFF) $(OLDFPC) $(FPC))
+else
+DIFFRESULT=Not equal
+endif
+else
+DIFFRESULT=No diff program
+endif
+ifndef DIFFRESULT
+next :
+ @echo $(OLDFPC) and $(FPC) are equal
+ $(COPY) $(FPC) $(EXENAME)
+else
+next :
+ $(MAKE) rtlclean rtl
+ $(MAKE) cycleclean compiler
+ $(MAKE) echotime
+endif
+$(TEMPNAME1) :
+ $(MAKE) 'OLDFPC=' next
+ -$(DEL) $(TEMPNAME1)
+ $(MOVE) $(EXENAME) $(TEMPNAME1)
+$(TEMPNAME2) : $(TEMPNAME1)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME1)' 'OLDFPC=' next
+ -$(DEL) $(TEMPNAME2)
+ $(MOVE) $(EXENAME) $(TEMPNAME2)
+$(TEMPNAME3) : $(TEMPNAME2)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME2)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME1)' next
+ -$(DEL) $(TEMPNAME3)
+ $(MOVE) $(EXENAME) $(TEMPNAME3)
+cycle:
+ $(MAKE) tempclean $(TEMPNAME3)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next
+ $(DIFF) $(TEMPNAME3) $(EXENAME)
+ $(MAKE) $(addsuffix _all,$(TARGET_DIRS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+ $(MAKE) echotime
+else
+cycle:
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) OS_TARGET=$(OS_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) EXENAME=$(PPCROSSNAME) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+ifndef CROSSINSTALL
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler
+endif
+endif
+else
+cycle:
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) PPC_TARGET=$(CPU_TARGET) EXENAME=$(PPCROSSNAME) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+ifndef CROSSINSTALL
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler
+endif
+endif
+cycledep:
+ $(MAKE) cycle USEDEPEND=1
+extcycle:
+ $(MAKE) cycle OPT='-n -OG2p3 -gl -CRriot -dEXTDEBUG'
+cvstest:
+ $(MAKE) cycle 'LOCALOPT=-n -Se' 'RTLOPT=-n -Se'
+full: fullcycle
+fullcycle:
+ $(MAKE) cycle
+ $(MAKE) ppuclean
+ $(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+htmldocs:
+ $(PASDOC) -p -h -o html$(PATHSEP)$(PPC_TARGET) -d fpc -d gdb -d $(PPC_TARGET) -u $(PPC_TARGET) $(PPC_TARGET)$(PATHSEP)*.pas systems$(PATHSEP)*.pas *.pas
+.PHONY: quickinstall install installsym
+MSGINSTALLDIR=$(INSTALL_BASEDIR)/msg
+override PPEXEFILE:=$(wildcard $(EXENAME))
+ifdef UNIXHier
+PPCCPULOCATION=$(INSTALL_BASEDIR)
+else
+PPCCPULOCATION=$(INSTALL_BINDIR)
+endif
+quickinstall: $(addsuffix _install,$(TARGET_DIRS))
+ifneq ($(INSTALLEXEFILE),)
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILE)
+endif
+ $(MKDIR) $(PPCCPULOCATION)
+ $(INSTALLEXE) $(INSTALLEXEFILE) $(PPCCPULOCATION)/$(EXENAME)
+endif
+install: quickinstall
+ifndef CROSSINSTALL
+ifdef UNIXHier
+ $(MKDIR) $(INSTALL_BASEDIR)
+ $(INSTALLEXE) $(COMPILERUTILSDIR)/samplecfg $(INSTALL_BASEDIR)/samplecfg
+endif
+ $(MKDIR) $(MSGINSTALLDIR)
+ $(INSTALL) $(MSGFILES) $(MSGINSTALLDIR)
+endif
+installsymlink: install
+ifneq ($(PPCCPULOCATION),$(INSTALL_BINDIR))
+ $(MKDIR) $(INSTALL_BINDIR)
+ ln -sf $(INSTALL_BASEDIR)/$(EXENAME) $(INSTALL_BINDIR)/$(EXENAME)
+endif
+.PHONY: rtl rtlclean rtlinstall
+rtl:
+ $(MAKE) -C $(PACKAGEDIR_RTL) 'OPT=$(RTLOPT)' all
+rtlclean:
+ $(MAKE) -C $(PACKAGEDIR_RTL) clean
+rtlinstall:
+ $(MAKE) -C $(PACKAGEDIR_RTL) install
+localmake:=$(strip $(wildcard makefile.loc))
+ifdef localmake
+include ./$(localmake)
+endif
diff --git a/compiler/Makefile.fpc b/compiler/Makefile.fpc
new file mode 100644
index 0000000000..b9fd07e240
--- /dev/null
+++ b/compiler/Makefile.fpc
@@ -0,0 +1,563 @@
+#
+# Makefile.fpc for Free Pascal Compiler
+#
+
+[package]
+name=compiler
+version=2.0.0
+
+[target]
+programs=pp
+dirs=utils
+
+[compiler]
+targetdir=.
+unittargetdir=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+unitdir=$(COMPILERSOURCEDIR)
+includedir=$(PPC_TARGET)
+
+[require]
+packages=rtl
+tools=diff cmp
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=..
+
+
+[prerules]
+# Don't export version it can change after the first compile
+unexport FPC_VERSION FPC_COMPILERINFO
+
+# Which platforms are ready for inclusion in the cycle
+CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64
+
+# All supported targets used for clean
+ALLTARGETS=$(CYCLETARGETS) m68k
+
+# Allow ALPHA, POWERPC, POWERPC64, M68K, I386 defines for target cpu
+ifdef ALPHA
+PPC_TARGET=alpha
+endif
+ifdef POWERPC
+PPC_TARGET=powerpc
+endif
+ifdef POWERPC64
+PPC_TARGET=powerpc64
+endif
+ifdef SPARC
+PPC_TARGET=sparc
+endif
+ifdef M68K
+PPC_TARGET=m68k
+endif
+ifdef I386
+PPC_TARGET=i386
+endif
+ifdef X86_64
+PPC_TARGET=x86_64
+endif
+ifdef ARM
+PPC_TARGET=arm
+endif
+
+# Default is to generate a compiler for the same
+# platform as CPU_TARGET (a native compiler)
+ifndef PPC_TARGET
+PPC_TARGET=$(CPU_TARGET)
+endif
+
+# Default is to generate a compiler for the same
+# target as OS_TARGET (a native compiler)
+ifndef PPC_OS
+PPC_OS=$(OS_TARGET)
+endif
+
+# Where to place the unit files.
+CPU_UNITDIR=$(PPC_TARGET)
+
+# RTL
+UTILSDIR=../utils
+
+# Directories containing compiler sources
+COMPILERSOURCEDIR=$(PPC_TARGET) systems
+
+# Utils used by compiler development/installation
+COMPILERUTILSDIR=utils
+
+# Default language for the compiler
+ifndef FPCLANG
+FPCLANG=e
+endif
+
+# Local options for the compiler only
+ifndef LOCALOPT
+LOCALOPT:=$(OPT)
+endif
+
+# Options for the RTL only when cycling
+ifndef RTLOPT
+RTLOPT:=$(OPT)
+endif
+
+# Make OPT empty. It is copied to LOCALOPT and RTLOPT
+override OPT=
+
+# Message files
+MSGFILES=$(wildcard msg/error*.msg)
+
+# ppcSUFFIX
+ifeq ($(PPC_TARGET),i386)
+CPUSUF=386
+endif
+ifeq ($(PPC_TARGET),alpha)
+CPUSUF=axp
+endif
+ifeq ($(PPC_TARGET),m68k)
+CPUSUF=68k
+endif
+ifeq ($(PPC_TARGET),powerpc)
+CPUSUF=ppc
+endif
+ifeq ($(PPC_TARGET),powerpc64)
+CPUSUF=ppc64
+endif
+ifeq ($(PPC_TARGET),sparc)
+CPUSUF=sparc
+endif
+ifeq ($(PPC_TARGET),x86_64)
+CPUSUF=x64
+endif
+ifeq ($(PPC_TARGET),arm)
+CPUSUF=arm
+endif
+
+# Do not define the default -d$(CPU_TARGET) because that
+# will conflict with our -d$(PPC_TARGET)
+NOCPUDEF=1
+
+# Default message file
+MSGFILE=msg/error$(FPCLANG).msg
+
+# Define Unix also for Linux
+ifeq ($(OS_TARGET),linux)
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+override LOCALOPT+=-dUNIX
+endif
+endif
+
+ifeq ($(OS_TARGET),freebsd)
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+override LOCALOPT+=-dUNIX
+endif
+endif
+
+# set correct defines (-d$(CPU_TARGET) is automaticly added in makefile.fpc)
+override LOCALOPT+=-d$(PPC_TARGET) -dGDB -dBROWSERLOG
+
+# i386 specific
+ifeq ($(PPC_TARGET),i386)
+override LOCALOPT+=-Fux86
+endif
+
+# x86_64 specific
+ifeq ($(PPC_TARGET),x86_64)
+override LOCALOPT+=-Fux86
+endif
+
+# PowerPC specific
+ifeq ($(PPC_TARGET),powerpc)
+override LOCALOPT+=
+endif
+
+# m68k specific
+ifeq ($(PPC_TARGET),m68k)
+override LOCALOPT+=-dNOOPT
+endif
+
+# Sparc specific
+ifeq ($(PPC_TARGET),sparc)
+override LOCALOPT+=
+endif
+
+# m68k specific with low stack
+ifeq ($(PPC_TARGET),m68k)
+ifeq ($(OS_TARGET),amiga)
+override LOCALOPT+=-Ct
+endif
+endif
+
+# ARM specific
+ifeq ($(PPC_TARGET),arm)
+override LOCALOPT+=-dNOOPT
+endif
+
+[rules]
+#####################################################################
+# Setup Targets
+#####################################################################
+
+ifeq ($(OS_TARGET),win32)
+ifdef CMP
+override DIFF:=$(CMP) -i218
+endif
+endif
+
+# Add Local options
+override COMPILER+=$(LOCALOPT)
+
+# Disable optimizer when compiled with 1.0.x
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+override COMPILER:=$(patsubst -O%,,$(COMPILER))
+endif
+
+
+#####################################################################
+# PASDoc
+#####################################################################
+
+PASDOC:=$(strip $(wildcard $(addsuffix /pasdoc.exe,$(SEARCHPATH))))
+ifeq ($(PASDOC),)
+PASDOC:=$(strip $(wildcard $(addsuffix /pasdoc,$(SEARCHPATH))))
+endif
+ifeq ($(PASDOC),)
+PASDOC:=../projects/pasdoc/bin/pasdoc
+else
+PASDOC:=$(firstword $(PASDOC))
+endif
+
+
+#####################################################################
+# Setup os-independent filenames
+#####################################################################
+
+ifndef EXENAME
+EXENAME=ppc$(CPUSUF)$(EXEEXT)
+endif
+PPEXENAME=pp$(EXEEXT)
+TEMPNAME=ppc$(SRCEXEEXT)
+PPCROSSNAME=ppcross$(CPUSUF)$(SRCEXEEXT)
+TEMPNAME1=ppc1$(EXEEXT)
+TEMPNAME2=ppc2$(EXEEXT)
+TEMPNAME3=ppc3$(EXEEXT)
+MAKEDEP=ppdep$(EXEEXT)
+MSG2INC=./msg2inc$(EXEEXT)
+ifdef CROSSINSTALL
+INSTALLEXEFILE=$(PPCROSSNAME)
+else
+INSTALLEXEFILE=$(EXENAME)
+endif
+
+#####################################################################
+# CPU targets
+#####################################################################
+
+PPC_TARGETS=alpha i386 m68k powerpc sparc arm x86_64
+
+.PHONY: $(PPC_TARGETS)
+
+$(PPC_TARGETS):
+ $(MAKE) PPC_TARGET=$@ CPU_UNITDIR=$@ all
+
+
+#####################################################################
+# Default makefile
+#####################################################################
+
+.PHONY: all compiler echotime ppuclean execlean clean distclean
+
+all: compiler $(addsuffix _all,$(TARGET_DIRS))
+
+compiler: $(COMPILER_UNITTARGETDIR) $(COMPILER_TARGETDIR) $(EXENAME)
+
+ifeq ($(MAKELEVEL),0)
+ifndef STARTTIME
+ifdef DATE
+STARTTIME:=$(shell $(DATE) +%T)
+else
+STARTTIME:=unknown
+endif
+endif
+endif
+
+export STARTTIME
+
+ifdef DATE
+ENDTIME=$(shell $(DATE) +%T)
+else
+ENDTIME:=unknown
+endif
+
+echotime:
+ @echo Start $(STARTTIME) now $(ENDTIME)
+
+ppuclean:
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ -$(DEL) $(addsuffix /*$(PPUEXT),$(COMPILERSOURCEDIR))
+
+tempclean:
+ -$(DEL) $(PPCROSSNAME) $(TEMPNAME) $(TEMPNAME1) $(TEMPNAME2) $(TEMPNAME3) $(MSG2INC)
+
+execlean :
+ -$(DEL) ppc386$(EXEEXT) ppcaxp$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) $(EXENAME)
+
+$(addsuffix _clean,$(ALLTARGETS)):
+ -$(DELTREE) $(addprefix $(subst _clean,,$@),/units)
+ -$(DEL) $(addprefix $(subst _clean,,$@)/,*$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT))
+ -$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppcaxp$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcppc$(EXEEXT) $(EXENAME))
+
+cycleclean: cleanall $(addsuffix _clean,$(PPC_TARGET))
+ -$(DEL) $(EXENAME)
+
+clean: tempclean execlean cleanall $(addsuffix _clean,$(PPC_TARGET)) $(addsuffix _clean,$(TARGET_DIRS))
+
+distclean: tempclean execlean cleanall $(addsuffix _clean,$(ALLTARGETS)) $(addsuffix _distclean,$(TARGET_DIRS))
+
+
+#####################################################################
+# Make targets
+#####################################################################
+
+$(MSG2INC): $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(COMPILERUTILSDIR)/msg2inc.pp
+ $(COMPILER) -FE. $(COMPILERUTILSDIR)/msg2inc.pp
+
+# The msgtxt.inc only depends on the error?.msg file, not on msg2inc,
+# because that one will be new almost everytime
+msgtxt.inc: $(MSGFILE)
+ $(MAKE) $(MSG2INC)
+ $(MSG2INC) $(MSGFILE) msg msg
+
+msg: msgtxt.inc
+
+# Make only the compiler
+$(EXENAME) : $(wildcard *.pas) $(wildcard *.inc) msg \
+ $(wildcard systems/*.pas) $(wilcard systems/*.inc) \
+ $(wildcard $(PPC_TARGET)/*.pas) $(wildcard $(PPC_TARGET)/*.inc)
+ $(COMPILER) pp.pas
+ $(EXECPPAS)
+ $(MOVE) $(COMPILER_TARGETDIR)/$(PPEXENAME) $(EXENAME)
+
+
+#####################################################################
+# Cycle targets
+#
+# 1. Source CPU = Target CPU and Source OS = Target OS
+# Normal cycle
+#
+# 2. Source CPU = Target CPU and Source OS <> Target OS
+# First source native compiler
+# Second target native compiler (skipped for cross installation)
+#
+# 3. Source CPU <> Target CPU
+# First source native compiler
+# Second cross compiler
+# Third target native compiler (skipped for cross installation)
+#
+#####################################################################
+
+ifeq ($(CPU_SOURCE),$(PPC_TARGET))
+
+ifeq ($(OS_SOURCE),$(OS_TARGET))
+
+##########################
+# Normal cycle
+#
+
+# Used to avoid unnecessary steps
+ifdef DIFF
+ifdef OLDFPC
+DIFFRESULT:=$(shell $(DIFF) $(OLDFPC) $(FPC))
+else
+DIFFRESULT=Not equal
+endif
+else
+DIFFRESULT=No diff program
+endif
+
+ifndef DIFFRESULT
+next :
+ @echo $(OLDFPC) and $(FPC) are equal
+ $(COPY) $(FPC) $(EXENAME)
+else
+next :
+ $(MAKE) rtlclean rtl
+ $(MAKE) cycleclean compiler
+ $(MAKE) echotime
+endif
+
+$(TEMPNAME1) :
+ $(MAKE) 'OLDFPC=' next
+ -$(DEL) $(TEMPNAME1)
+ $(MOVE) $(EXENAME) $(TEMPNAME1)
+
+$(TEMPNAME2) : $(TEMPNAME1)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME1)' 'OLDFPC=' next
+ -$(DEL) $(TEMPNAME2)
+ $(MOVE) $(EXENAME) $(TEMPNAME2)
+
+$(TEMPNAME3) : $(TEMPNAME2)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME2)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME1)' next
+ -$(DEL) $(TEMPNAME3)
+ $(MOVE) $(EXENAME) $(TEMPNAME3)
+
+cycle:
+ $(MAKE) tempclean $(TEMPNAME3)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next
+ $(DIFF) $(TEMPNAME3) $(EXENAME)
+ $(MAKE) $(addsuffix _all,$(TARGET_DIRS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+ $(MAKE) echotime
+
+else
+
+##########################
+# Cross Target cycle
+#
+
+cycle:
+# ppc (source native)
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) OS_TARGET=$(OS_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+# ppcross<ARCH> (source native)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) EXENAME=$(PPCROSSNAME) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+# ppc<ARCH> (target native)
+ifndef CROSSINSTALL
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler
+endif
+
+endif
+
+else
+
+##########################
+# Cross CPU cycle
+#
+# ppc1 = native
+# ppc2 = cross running on this platform
+# ppc3/ppcXXX = native (skipped for cross installation)
+#
+
+cycle:
+# ppc (source native)
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+# ppcross<ARCH> (source native)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) PPC_TARGET=$(CPU_TARGET) EXENAME=$(PPCROSSNAME) CROSSBINDIR="" BINUTILSPREFIX="" CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+# ppc<ARCH> (target native)
+ifndef CROSSINSTALL
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler
+endif
+
+endif
+
+cycledep:
+ $(MAKE) cycle USEDEPEND=1
+
+extcycle:
+ $(MAKE) cycle OPT='-n -OG2p3 -gl -CRriot -dEXTDEBUG'
+
+cvstest:
+ $(MAKE) cycle 'LOCALOPT=-n -Se' 'RTLOPT=-n -Se'
+
+
+##########################
+# Full cycle
+#
+# 1. build a compiler using cycle
+# 2. remove all .ppufiles
+# 3. build all supported cross compilers except the
+# current PPC_TARGET which was already build
+#
+
+full: fullcycle
+
+fullcycle:
+ $(MAKE) cycle
+ $(MAKE) ppuclean
+ $(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+
+#####################################################################
+# Docs
+#####################################################################
+
+htmldocs:
+ $(PASDOC) -p -h -o html$(PATHSEP)$(PPC_TARGET) -d fpc -d gdb -d $(PPC_TARGET) -u $(PPC_TARGET) $(PPC_TARGET)$(PATHSEP)*.pas systems$(PATHSEP)*.pas *.pas
+
+#####################################################################
+# Installation
+#####################################################################
+
+.PHONY: quickinstall install installsym
+
+MSGINSTALLDIR=$(INSTALL_BASEDIR)/msg
+override PPEXEFILE:=$(wildcard $(EXENAME))
+
+ifdef UNIXHier
+PPCCPULOCATION=$(INSTALL_BASEDIR)
+else
+PPCCPULOCATION=$(INSTALL_BINDIR)
+endif
+
+# This will only install the ppcXXX executable, not the message files etc.
+quickinstall: $(addsuffix _install,$(TARGET_DIRS))
+# Install ppcXXX executable, for a cross installation we install
+# the ppcrossXXX as ppcXXX. The target native build ppcXXX is not used
+# for this installation type
+ifneq ($(INSTALLEXEFILE),)
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILE)
+endif
+ $(MKDIR) $(PPCCPULOCATION)
+ $(INSTALLEXE) $(INSTALLEXEFILE) $(PPCCPULOCATION)/$(EXENAME)
+endif
+
+install: quickinstall
+ifndef CROSSINSTALL
+ifdef UNIXHier
+ $(MKDIR) $(INSTALL_BASEDIR)
+ $(INSTALLEXE) $(COMPILERUTILSDIR)/samplecfg $(INSTALL_BASEDIR)/samplecfg
+endif
+ $(MKDIR) $(MSGINSTALLDIR)
+ $(INSTALL) $(MSGFILES) $(MSGINSTALLDIR)
+endif
+
+# This also installs a link from bin to the actual executable.
+# The .deb does that later.
+installsymlink: install
+ifneq ($(PPCCPULOCATION),$(INSTALL_BINDIR))
+ $(MKDIR) $(INSTALL_BINDIR)
+ ln -sf $(INSTALL_BASEDIR)/$(EXENAME) $(INSTALL_BINDIR)/$(EXENAME)
+endif
+
+
+#####################################################################
+# RTL
+#####################################################################
+
+.PHONY: rtl rtlclean rtlinstall
+
+rtl:
+ $(MAKE) -C $(PACKAGEDIR_RTL) 'OPT=$(RTLOPT)' all
+
+rtlclean:
+ $(MAKE) -C $(PACKAGEDIR_RTL) clean
+
+rtlinstall:
+ $(MAKE) -C $(PACKAGEDIR_RTL) install
+
+
+#####################################################################
+# local user configurable file
+# in makefile.loc you can add any desired target
+#####################################################################
+
+localmake:=$(strip $(wildcard makefile.loc))
+
+ifdef localmake
+include ./$(localmake)
+endif
diff --git a/compiler/README b/compiler/README
new file mode 100644
index 0000000000..32e54a36d1
--- /dev/null
+++ b/compiler/README
@@ -0,0 +1,58 @@
+This directory contains the sources of the Free Pascal Compiler
+
+If you want to compile/modify the compiler, please read first the
+programmers manual.
+
+To recompile the compiler, you can use the batch files :
+ + mppc386.bat if you want to build a cross compiler from i386 to m68k
+ + mppcsparc if you want to build a cross compiler from i386 to SPARC
+
+ or
+Use the make utility as following
+
+ make OS_TARGET="compiler OS target" \
+ CPU_TARGET="compiler CPU target" \
+ FPCCPUOPT="Optimization level" \
+ PP="compiler used to compile FPC" \
+ COMPILER_OPTIONS="Options passed to compiler" \
+
+
+If an option is omitted, then target CPU/OS will be same as current CPU/OS
+
+Possibles targets are : linux go32v2 win32 os2 freebsd beos netbsd amiga
+atari sunos qnx netware openbsd wdosx palmos macos macosx emx
+
+Possible compiler switches (* marks a currently required switch):
+ -----------------------------------------------------------------
+ GDB* support of the GNU Debugger
+ I386 generate a compiler for the Intel i386+
+ x86_64 generate a compiler for the AMD x86-64 architecture
+ M68K generate a compiler for the M68000
+ SPARC generate a compiler for SPARC
+ POWERPC generate a compiler for the PowerPC
+ VIS generate a compile for the VIS
+ DEBUG version with debug code is generated
+ EXTDEBUG some extra debug code is executed
+ SUPPORT_MMX only i386: releases the compiler switch
+ MMX which allows the compiler to generate
+ MMX instructions
+ EXTERN_MSG Don't compile the msgfiles in the compiler, always
+ use external messagefiles, default for TP
+ NOAG386INT no Intel Assembler output
+ NOAG386NSM no NASM output
+ NOAG386BIN leaves out the binary writer, default for TP
+ NORA386DIR No direct i386 assembler reader
+ TEST_GENERIC Test Generic version of code generator
+ (uses generic RTL calls)
+ -----------------------------------------------------------------
+ cpuflags The target processor has status flags (on by default)
+ cpufpemu The target compiler will also support emitting software
+ floating point operations
+ cpu64bit The target is a 64-bit processor
+ -----------------------------------------------------------------
+
+ Required switches for a i386 compiler be compiled by Free Pascal Compiler:
+ GDB;I386
+
+to build a compiler to SPARC target using a Win32/i386 you just use :
+ make CPU_TARGET=SPARC
diff --git a/compiler/aasmbase.pas b/compiler/aasmbase.pas
new file mode 100644
index 0000000000..26fd21a6e8
--- /dev/null
+++ b/compiler/aasmbase.pas
@@ -0,0 +1,952 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an abstract asmoutput class for all processor types
+
+ 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.
+
+ ****************************************************************************
+}
+{ @abstract(This unit implements an abstract asm output class for all processor types)
+ This unit implements an abstract assembler output class for all processors, these
+ are then overriden for each assembler writer to actually write the data in these
+ classes to an assembler file.
+}
+
+unit aasmbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,systems
+ ;
+
+ type
+ TAsmSection = class;
+ TAsmObjectData = class;
+
+ TAsmsymbind=(AB_NONE,AB_EXTERNAL,AB_COMMON,AB_LOCAL,AB_GLOBAL);
+
+ TAsmsymtype=(AT_NONE,AT_FUNCTION,AT_DATA,AT_SECTION,AT_LABEL);
+
+ TAsmRelocationType = (RELOC_ABSOLUTE,RELOC_RELATIVE,RELOC_RVA);
+
+ TAsmSectionType=(sec_none,
+ sec_code,sec_data,sec_rodata,sec_bss,sec_threadvar,
+ sec_common, { used for executable creation }
+ sec_custom, { custom section, no prefix }
+ sec_stub, { used for darwin import stubs }
+ { stabs }
+ sec_stab,sec_stabstr,
+ { win32 }
+ sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_edata,
+ { C++ exception handling unwinding (uses dwarf) }
+ sec_eh_frame,
+ { dwarf }
+ sec_debug_frame,
+ { ELF resources }
+ sec_fpc
+ );
+
+ TAsmSectionOption = (aso_alloconly,aso_executable);
+ TAsmSectionOptions = set of TAsmSectionOption;
+
+ TAsmSymbol = class(TNamedIndexItem)
+ private
+ { this need to be incremented with every symbol loading into the
+ paasmoutput, thus in loadsym/loadref/const_symbol (PFV) }
+ refs : longint;
+ public
+ defbind,
+ currbind : TAsmsymbind;
+ typ : TAsmsymtype;
+ { the next fields are filled in the binary writer }
+ section : TAsmSection;
+ address,
+ size : aint;
+ { Alternate symbol which can be used for 'renaming' needed for
+ inlining }
+ altsymbol : tasmsymbol;
+ { pointer to objectdata that is the owner of this symbol }
+ owner : tasmobjectdata;
+ { Is the symbol in the used list }
+ inusedlist : boolean;
+ { assembler pass label is set, used for detecting multiple labels }
+ pass : byte;
+ ppuidx : longint;
+ constructor create(const s:string;_bind:TAsmsymbind;_typ:Tasmsymtype);
+ procedure reset;
+ function is_used:boolean;
+ procedure increfs;
+ procedure decrefs;
+ function getrefs: longint;
+ procedure setaddress(_pass:byte;sec:TAsmSection;offset,len:aint);
+ end;
+
+ { is the label only there for getting an address (e.g. for i/o
+ checks -> alt_addr) or is it a jump target (alt_jump), for debug
+ info alt_dbgline and alt_dbgfile }
+ TAsmLabelType = (alt_jump,alt_addr,alt_data,alt_dbgline,alt_dbgfile,alt_dbgtype);
+
+ TAsmLabel = class(TAsmSymbol)
+ labelnr : longint;
+ labeltype : TAsmLabelType;
+ is_set : boolean;
+ constructor createlocal(nr:longint;ltyp:TAsmLabelType);
+ constructor createglobal(const modulename:string;nr:longint;ltyp:TAsmLabelType);
+ function getname:string;override;
+ end;
+
+ TAsmRelocation = class(TLinkedListItem)
+ address,
+ orgsize : aint; { original size of the symbol to relocate, required for COFF }
+ symbol : TAsmSymbol;
+ section : TAsmSection; { only used if symbol=nil }
+ typ : TAsmRelocationType;
+ constructor CreateSymbol(Aaddress:aint;s:Tasmsymbol;Atyp:TAsmRelocationType);
+ constructor CreateSymbolSize(Aaddress:aint;s:Tasmsymbol;Aorgsize:aint;Atyp:TAsmRelocationType);
+ constructor CreateSection(Aaddress:aint;sec:TAsmSection;Atyp:TAsmRelocationType);
+ end;
+
+ TAsmSection = class(TNamedIndexItem)
+ owner : TAsmObjectData;
+ secoptions : TAsmSectionOptions;
+ sectype : TAsmSectionType;
+ secsymidx : longint; { index for the section in symtab }
+ addralign : longint; { alignment of the section }
+ { size of the data and in the file }
+ dataalignbytes : longint;
+ data : TDynamicArray;
+ datasize,
+ datapos : aint;
+ { size and position in memory }
+ memsize,
+ mempos : aint;
+ { relocation }
+ relocations : TLinkedList;
+ constructor create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);virtual;
+ destructor destroy;override;
+ function write(const d;l:aint):aint;
+ function writestr(const s:string):aint;
+ procedure writealign(l:longint);
+ function aligneddatasize:aint;
+ procedure setdatapos(var dpos:aint);
+ procedure alignsection;
+ procedure alloc(l:aint);
+ procedure addsymreloc(ofs:aint;p:tasmsymbol;relative:TAsmRelocationType);
+ procedure addsectionreloc(ofs:aint;sec:TAsmSection;relative:TAsmRelocationType);
+ procedure fixuprelocs;virtual;
+ end;
+ TAsmSectionClass = class of TAsmSection;
+
+ TAsmObjectData = class(TLinkedListItem)
+ private
+ FName : string[80];
+ FCurrSec : TAsmSection;
+ { Sections will be stored in order in SectsIndex, this is at least
+ required for stabs debuginfo. The SectsDict is only used for lookups (PFV) }
+ FSectsDict : TDictionary;
+ FSectsIndex : TIndexArray;
+ FCAsmSection : TAsmSectionClass;
+ { Symbols that will be defined in this object file }
+ FSymbols : TIndexArray;
+ { Special info sections that are written to during object generation }
+ FStabsRecSize : longint;
+ FStabsSec,
+ FStabStrSec : TAsmSection;
+ procedure section_reset(p:tnamedindexitem;arg:pointer);
+ procedure section_fixuprelocs(p:tnamedindexitem;arg:pointer);
+ protected
+ property StabsRecSize:longint read FStabsRecSize write FStabsRecSize;
+ property StabsSec:TAsmSection read FStabsSec write FStabsSec;
+ property StabStrSec:TAsmSection read FStabStrSec write FStabStrSec;
+ property CAsmSection:TAsmSectionClass read FCAsmSection write FCAsmSection;
+ public
+ constructor create(const n:string);virtual;
+ destructor destroy;override;
+ function sectionname(atype:tasmsectiontype;const aname:string):string;virtual;
+ function createsection(atype:tasmsectiontype;const aname:string;aalign:longint;aoptions:TAsmSectionOptions):tasmsection;virtual;
+ procedure setsection(asec:tasmsection);
+ procedure alloc(len:aint);
+ procedure allocalign(len:longint);
+ procedure allocstab(p:pchar);
+ procedure allocsymbol(currpass:byte;p:tasmsymbol;len:aint);
+ procedure writebytes(var data;len:aint);
+ procedure writereloc(data,len:aint;p:tasmsymbol;relative:TAsmRelocationType);virtual;abstract;
+ procedure writesymbol(p:tasmsymbol);virtual;abstract;
+ procedure writestab(offset:aint;ps:tasmsymbol;nidx,nother,line:longint;p:pchar);virtual;abstract;
+ procedure beforealloc;virtual;
+ procedure beforewrite;virtual;
+ procedure afteralloc;virtual;
+ procedure afterwrite;virtual;
+ procedure resetsections;
+ procedure fixuprelocs;
+ property Name:string[80] read FName;
+ property CurrSec:TAsmSection read FCurrSec;
+ property Symbols:TindexArray read FSymbols;
+ property Sects:TIndexArray read FSectsIndex;
+ end;
+ TAsmObjectDataClass = class of TAsmObjectData;
+
+ tasmsymbolidxarr = array[0..($7fffffff div sizeof(pointer))-1] of tasmsymbol;
+ pasmsymbolidxarr = ^tasmsymbolidxarr;
+
+ TAsmLibraryData = class(TLinkedListItem)
+ private
+ nextaltnr : longint;
+ nextlabelnr : array[Tasmlabeltype] of longint;
+ public
+ name,
+ realname : string[80];
+ symbolsearch : tdictionary; { contains ALL assembler symbols }
+ usedasmsymbollist : tsinglelist;
+ { ppu }
+ asmsymbolppuidx : longint;
+ asmsymbolidx : pasmsymbolidxarr; { used for translating ppu index->asmsymbol }
+ constructor create(const n:string);
+ destructor destroy;override;
+ procedure Freeasmsymbolidx;
+ procedure DerefAsmsymbol(var s:tasmsymbol);
+ { asmsymbol }
+ function newasmsymbol(const s : string;_bind:TAsmSymBind;_typ:TAsmsymtype) : tasmsymbol;
+ function getasmsymbol(const s : string) : tasmsymbol;
+ function renameasmsymbol(const sold, snew : string):tasmsymbol;
+ function newasmlabel(nr:longint;alt:tasmlabeltype;is_global:boolean) : tasmlabel;
+ {# create a new assembler label }
+ procedure getlabel(var l : tasmlabel;alt:tasmlabeltype);
+ {# create a new assembler label for jumps }
+ procedure getjumplabel(var l : tasmlabel);
+ { make l as a new label and flag is_addr }
+ procedure getaddrlabel(var l : tasmlabel);
+ { make l as a new label and flag is_data }
+ procedure getdatalabel(var l : tasmlabel);
+ {# return a label number }
+ procedure CreateUsedAsmSymbolList;
+ procedure DestroyUsedAsmSymbolList;
+ procedure UsedAsmSymbolListInsert(p:tasmsymbol);
+ { generate an alternative (duplicate) symbol }
+ procedure GenerateAltSymbol(p:tasmsymbol);
+ { reset alternative symbol information }
+ procedure UsedAsmSymbolListResetAltSym;
+ procedure UsedAsmSymbolListReset;
+ procedure UsedAsmSymbolListCheckUndefined;
+ end;
+
+ const
+ { alt_jump,alt_addr,alt_data,alt_dbgline,alt_dbgfile }
+ asmlabeltypeprefix : array[tasmlabeltype] of char = ('j','a','d','l','f','t');
+
+ var
+ objectlibrary : tasmlibrarydata;
+
+
+implementation
+
+ uses
+ strings,
+ verbose;
+
+ const
+ sectsgrow = 100;
+ symbolsgrow = 100;
+
+
+{*****************************************************************************
+ TAsmSymbol
+*****************************************************************************}
+
+ constructor tasmsymbol.create(const s:string;_bind:TAsmsymbind;_typ:Tasmsymtype);
+ begin;
+ inherited createname(s);
+ reset;
+ defbind:=_bind;
+ typ:=_typ;
+ inusedlist:=false;
+ pass:=255;
+ ppuidx:=-1;
+ { mainly used to remove unused labels from the al_procedures }
+ refs:=0;
+ end;
+
+
+ procedure tasmsymbol.reset;
+ begin
+ { reset section info }
+ section:=nil;
+ address:=0;
+ size:=0;
+ indexnr:=-1;
+ pass:=255;
+ currbind:=AB_EXTERNAL;
+ altsymbol:=nil;
+{ taiowner:=nil;}
+ end;
+
+
+ function tasmsymbol.is_used:boolean;
+ begin
+ is_used:=(refs>0);
+ end;
+
+
+ procedure tasmsymbol.increfs;
+ begin
+ inc(refs);
+ end;
+
+
+ procedure tasmsymbol.decrefs;
+ begin
+ dec(refs);
+ if refs<0 then
+ internalerror(200211121);
+ end;
+
+
+ function tasmsymbol.getrefs: longint;
+ begin
+ getrefs := refs;
+ end;
+
+
+ procedure tasmsymbol.setaddress(_pass:byte;sec:TAsmSection;offset,len:aint);
+ begin
+ if (_pass=pass) then
+ begin
+ Message1(asmw_e_duplicate_label,name);
+ exit;
+ end;
+ pass:=_pass;
+ section:=sec;
+ address:=offset;
+ size:=len;
+ { when the bind was reset to External, set it back to the default
+ bind it got when defined }
+ if (currbind=AB_EXTERNAL) and (defbind<>AB_NONE) then
+ currbind:=defbind;
+ end;
+
+
+{*****************************************************************************
+ TAsmLabel
+*****************************************************************************}
+
+ constructor tasmlabel.createlocal(nr:longint;ltyp:TAsmLabelType);
+ begin;
+ inherited create(target_asm.labelprefix+asmlabeltypeprefix[ltyp]+tostr(nr),AB_LOCAL,AT_LABEL);
+ labelnr:=nr;
+ labeltype:=ltyp;
+ is_set:=false;
+ end;
+
+
+ constructor tasmlabel.createglobal(const modulename:string;nr:longint;ltyp:TAsmLabelType);
+ begin;
+ inherited create('_$'+modulename+'$_L'+asmlabeltypeprefix[ltyp]+tostr(nr),AB_GLOBAL,AT_DATA);
+ labelnr:=nr;
+ labeltype:=ltyp;
+ is_set:=false;
+ { write it always }
+ increfs;
+ end;
+
+
+ function tasmlabel.getname:string;
+ begin
+ getname:=inherited getname;
+ increfs;
+ end;
+
+
+{****************************************************************************
+ TAsmRelocation
+****************************************************************************}
+
+ constructor TAsmRelocation.CreateSymbol(Aaddress:aint;s:Tasmsymbol;Atyp:TAsmRelocationType);
+ begin
+ Address:=Aaddress;
+ Symbol:=s;
+ OrgSize:=0;
+ Section:=nil;
+ Typ:=Atyp;
+ end;
+
+
+ constructor TAsmRelocation.CreateSymbolSize(Aaddress:aint;s:Tasmsymbol;Aorgsize:aint;Atyp:TAsmRelocationType);
+ begin
+ Address:=Aaddress;
+ Symbol:=s;
+ OrgSize:=Aorgsize;
+ Section:=nil;
+ Typ:=Atyp;
+ end;
+
+
+ constructor TAsmRelocation.CreateSection(Aaddress:aint;sec:TAsmSection;Atyp:TAsmRelocationType);
+ begin
+ Address:=Aaddress;
+ Symbol:=nil;
+ OrgSize:=0;
+ Section:=sec;
+ Typ:=Atyp;
+ end;
+
+
+{****************************************************************************
+ TAsmSection
+****************************************************************************}
+
+ constructor TAsmSection.create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);
+ begin
+ inherited createname(Aname);
+ sectype:=Atype;
+ name:=Aname;
+ secoptions:=Aoptions;
+ secsymidx:=0;
+ addralign:=Aalign;
+ { data }
+ datasize:=0;
+ datapos:=0;
+ if (aso_alloconly in aoptions) then
+ data:=nil
+ else
+ Data:=TDynamicArray.Create(8192);
+ { memory }
+ mempos:=0;
+ memsize:=0;
+ { relocation }
+ relocations:=TLinkedList.Create;
+ end;
+
+
+ destructor TAsmSection.destroy;
+ begin
+ if assigned(Data) then
+ Data.Free;
+ relocations.free;
+ end;
+
+
+ function TAsmSection.write(const d;l:aint):aint;
+ begin
+ write:=datasize;
+ if assigned(Data) then
+ Data.write(d,l);
+ inc(datasize,l);
+ end;
+
+
+ function TAsmSection.writestr(const s:string):aint;
+ begin
+ writestr:=datasize;
+ if assigned(Data) then
+ Data.write(s[1],length(s));
+ inc(datasize,length(s));
+ end;
+
+
+ procedure TAsmSection.writealign(l:longint);
+ var
+ i : longint;
+ empty : array[0..63] of char;
+ begin
+ { no alignment needed for 0 or 1 }
+ if l<=1 then
+ exit;
+ i:=datasize mod l;
+ if i>0 then
+ begin
+ if assigned(data) then
+ begin
+ fillchar(empty,sizeof(empty),0);
+ Data.write(empty,l-i);
+ end;
+ inc(datasize,l-i);
+ end;
+ end;
+
+
+ function TAsmSection.aligneddatasize:aint;
+ begin
+ aligneddatasize:=align(datasize,addralign);
+ end;
+
+
+ procedure TAsmSection.setdatapos(var dpos:aint);
+ var
+ alignedpos : aint;
+ begin
+ { get aligned datapos }
+ alignedpos:=align(dpos,addralign);
+ dataalignbytes:=alignedpos-dpos;
+ datapos:=alignedpos;
+ { update datapos }
+ dpos:=datapos+aligneddatasize;
+ end;
+
+
+ procedure TAsmSection.alignsection;
+ begin
+ writealign(addralign);
+ end;
+
+
+ procedure TAsmSection.alloc(l:aint);
+ begin
+ inc(datasize,l);
+ end;
+
+
+ procedure TAsmSection.addsymreloc(ofs:aint;p:tasmsymbol;relative:TAsmRelocationType);
+ var
+ r : TAsmRelocation;
+ begin
+ r:=TAsmRelocation.Create;
+ r.address:=ofs;
+ r.orgsize:=0;
+ r.symbol:=p;
+ r.section:=nil;
+ r.typ:=relative;
+ relocations.concat(r);
+ end;
+
+
+ procedure TAsmSection.addsectionreloc(ofs:aint;sec:TAsmSection;relative:TAsmRelocationType);
+ var
+ r : TAsmRelocation;
+ begin
+ r:=TAsmRelocation.Create;
+ r.address:=ofs;
+ r.symbol:=nil;
+ r.orgsize:=0;
+ r.section:=sec;
+ r.typ:=relative;
+ relocations.concat(r);
+ end;
+
+
+ procedure TAsmSection.fixuprelocs;
+ begin
+ end;
+
+
+{****************************************************************************
+ TAsmObjectData
+****************************************************************************}
+
+ constructor TAsmObjectData.create(const n:string);
+ begin
+ inherited create;
+ FName:=n;
+ { sections, the SectsIndex owns the items, the FSectsDict
+ is only used for lookups }
+ FSectsDict:=tdictionary.create;
+ FSectsDict.noclear:=true;
+ FSectsIndex:=tindexarray.create(sectsgrow);
+ FStabsRecSize:=1;
+ FStabsSec:=nil;
+ FStabStrSec:=nil;
+ { symbols }
+ FSymbols:=tindexarray.create(symbolsgrow);
+ FSymbols.noclear:=true;
+ { section class type for creating of new sections }
+ FCAsmSection:=TAsmSection;
+ end;
+
+
+ destructor TAsmObjectData.destroy;
+ begin
+ FSectsDict.free;
+ FSectsIndex.free;
+ FSymbols.free;
+ end;
+
+
+ function TAsmObjectData.sectionname(atype:tasmsectiontype;const aname:string):string;
+ const
+ secnames : array[tasmsectiontype] of string[12] = ('',
+ 'code','data','rodata','bss','threadvar',
+ 'common',
+ 'note',
+ 'text',
+ 'stab','stabstr',
+ 'idata2','idata4','idata5','idata6','idata7','edata',
+ 'eh_frame',
+ 'debug_frame',
+ 'fpc'
+ );
+ begin
+ if aname<>'' then
+ result:=secnames[atype]+'.'+aname
+ else
+ result:=secnames[atype];
+ end;
+
+
+ function TAsmObjectData.createsection(atype:tasmsectiontype;const aname:string;aalign:longint;aoptions:TAsmSectionOptions):TAsmSection;
+ var
+ secname : string;
+ begin
+ secname:=sectionname(atype,aname);
+ result:=TasmSection(FSectsDict.search(secname));
+ if not assigned(result) then
+ begin
+{$warning TODO make alloconly configurable}
+ if atype=sec_bss then
+ include(aoptions,aso_alloconly);
+ result:=CAsmSection.create(secname,atype,aalign,aoptions);
+ FSectsDict.Insert(result);
+ FSectsIndex.Insert(result);
+ result.owner:=self;
+ end;
+ FCurrSec:=result;
+ end;
+
+
+ procedure TAsmObjectData.setsection(asec:tasmsection);
+ begin
+ if asec.owner<>self then
+ internalerror(200403041);
+ FCurrSec:=asec;
+ end;
+
+
+ procedure TAsmObjectData.writebytes(var data;len:aint);
+ begin
+ if not assigned(currsec) then
+ internalerror(200402251);
+ currsec.write(data,len);
+ end;
+
+
+ procedure TAsmObjectData.alloc(len:aint);
+ begin
+ if not assigned(currsec) then
+ internalerror(200402252);
+ currsec.alloc(len);
+ end;
+
+
+ procedure TAsmObjectData.allocalign(len:longint);
+ var
+ modulo : aint;
+ begin
+ if not assigned(currsec) then
+ internalerror(200402253);
+ modulo:=currsec.datasize mod len;
+ if modulo > 0 then
+ currsec.alloc(len-modulo);
+ end;
+
+
+ procedure TAsmObjectData.allocsymbol(currpass:byte;p:tasmsymbol;len:aint);
+ begin
+ p.setaddress(currpass,currsec,currsec.datasize,len);
+ end;
+
+
+ procedure TAsmObjectData.allocstab(p:pchar);
+ begin
+ if not(assigned(FStabsSec) and assigned(FStabStrSec)) then
+ internalerror(200402254);
+ FStabsSec.alloc(FStabsRecSize);
+ if assigned(p) and (p[0]<>#0) then
+ FStabStrSec.alloc(strlen(p)+1);
+ end;
+
+
+ procedure TAsmObjectData.section_reset(p:tnamedindexitem;arg:pointer);
+ begin
+ with tasmsection(p) do
+ begin
+ datasize:=0;
+ datapos:=0;
+ end;
+ end;
+
+
+ procedure TAsmObjectData.section_fixuprelocs(p:tnamedindexitem;arg:pointer);
+ begin
+ tasmsection(p).fixuprelocs;
+ end;
+
+
+ procedure TAsmObjectData.beforealloc;
+ begin
+ end;
+
+
+ procedure TAsmObjectData.beforewrite;
+ begin
+ end;
+
+
+ procedure TAsmObjectData.afteralloc;
+ begin
+ end;
+
+
+ procedure TAsmObjectData.afterwrite;
+ begin
+ end;
+
+
+ procedure TAsmObjectData.resetsections;
+ begin
+ FSectsDict.foreach(@section_reset,nil);
+ end;
+
+
+ procedure TAsmObjectData.fixuprelocs;
+ begin
+ FSectsDict.foreach(@section_fixuprelocs,nil);
+ end;
+
+
+{****************************************************************************
+ TAsmLibraryData
+****************************************************************************}
+
+ constructor TAsmLibraryData.create(const n:string);
+ var
+ alt : TAsmLabelType;
+ begin
+ inherited create;
+ realname:=n;
+ name:=upper(n);
+ { symbols }
+ symbolsearch:=tdictionary.create;
+ symbolsearch.usehash;
+ { labels }
+ nextaltnr:=1;
+ for alt:=low(TAsmLabelType) to high(TAsmLabelType) do
+ nextlabelnr[alt]:=1;
+ { ppu }
+ asmsymbolppuidx:=0;
+ asmsymbolidx:=nil;
+ end;
+
+
+ destructor TAsmLibraryData.destroy;
+ begin
+ symbolsearch.free;
+ Freeasmsymbolidx;
+ end;
+
+
+ procedure TAsmLibraryData.Freeasmsymbolidx;
+ begin
+ if assigned(asmsymbolidx) then
+ begin
+ Freemem(asmsymbolidx);
+ asmsymbolidx:=nil;
+ end;
+ end;
+
+
+ procedure TAsmLibraryData.DerefAsmsymbol(var s:tasmsymbol);
+ begin
+ if assigned(s) then
+ begin
+ if not assigned(asmsymbolidx) then
+ internalerror(200208072);
+ if (ptrint(pointer(s))<1) or (ptrint(pointer(s))>asmsymbolppuidx) then
+ internalerror(200208073);
+ s:=asmsymbolidx^[ptrint(pointer(s))-1];
+ end;
+ end;
+
+
+ function TAsmLibraryData.newasmsymbol(const s : string;_bind:TAsmSymBind;_typ:Tasmsymtype) : tasmsymbol;
+ var
+ hp : tasmsymbol;
+ begin
+ hp:=tasmsymbol(symbolsearch.search(s));
+ if assigned(hp) then
+ begin
+ {$IFDEF EXTDEBUG}
+ if (_typ <> AT_NONE) and
+ (hp.typ <> _typ) and
+ not(cs_compilesystem in aktmoduleswitches) then
+ begin
+ //Writeln('Error symbol '+hp.name+' type is ',Ord(_typ),', should be ',Ord(hp.typ));
+ InternalError(2004031501);
+ end;
+ {$ENDIF}
+ if (_bind<>AB_EXTERNAL) then
+ hp.defbind:=_bind
+ end
+ else
+ begin
+ { Not found, insert it. }
+ hp:=tasmsymbol.create(s,_bind,_typ);
+ symbolsearch.insert(hp);
+ end;
+ newasmsymbol:=hp;
+ end;
+
+
+ function TAsmLibraryData.getasmsymbol(const s : string) : tasmsymbol;
+ begin
+ getasmsymbol:=tasmsymbol(symbolsearch.search(s));
+ end;
+
+
+ function TAsmLibraryData.renameasmsymbol(const sold, snew : string):tasmsymbol;
+ begin
+ renameasmsymbol:=tasmsymbol(symbolsearch.rename(sold,snew));
+ end;
+
+
+ procedure TAsmLibraryData.CreateUsedAsmSymbolList;
+ begin
+ if assigned(usedasmsymbollist) then
+ internalerror(78455782);
+ usedasmsymbollist:=TSingleList.create;
+ end;
+
+
+ procedure TAsmLibraryData.DestroyUsedAsmSymbolList;
+ begin
+ usedasmsymbollist.destroy;
+ usedasmsymbollist:=nil;
+ end;
+
+
+ procedure TAsmLibraryData.UsedAsmSymbolListInsert(p:tasmsymbol);
+ begin
+ if not p.inusedlist then
+ usedasmsymbollist.insert(p);
+ p.inusedlist:=true;
+ end;
+
+
+ procedure TAsmLibraryData.GenerateAltSymbol(p:tasmsymbol);
+ begin
+ if not assigned(p.altsymbol) then
+ begin
+ p.altsymbol:=tasmsymbol.create(p.name+'_'+tostr(nextaltnr),p.defbind,p.typ);
+ symbolsearch.insert(p.altsymbol);
+ { add also the original sym to the usedasmsymbollist,
+ that list is used to reset the altsymbol }
+ if not p.inusedlist then
+ usedasmsymbollist.insert(p);
+ p.inusedlist:=true;
+ end;
+ end;
+
+
+ procedure TAsmLibraryData.UsedAsmSymbolListReset;
+ var
+ hp : tasmsymbol;
+ begin
+ hp:=tasmsymbol(usedasmsymbollist.first);
+ while assigned(hp) do
+ begin
+ with hp do
+ begin
+ reset;
+ inusedlist:=false;
+ end;
+ hp:=tasmsymbol(hp.listnext);
+ end;
+ end;
+
+
+ procedure TAsmLibraryData.UsedAsmSymbolListResetAltSym;
+ var
+ hp : tasmsymbol;
+ begin
+ hp:=tasmsymbol(usedasmsymbollist.first);
+ inc(nextaltnr);
+ while assigned(hp) do
+ begin
+ with hp do
+ begin
+ altsymbol:=nil;
+ inusedlist:=false;
+ end;
+ hp:=tasmsymbol(hp.listnext);
+ end;
+ end;
+
+
+ procedure TAsmLibraryData.UsedAsmSymbolListCheckUndefined;
+ var
+ hp : tasmsymbol;
+ begin
+ hp:=tasmsymbol(usedasmsymbollist.first);
+ while assigned(hp) do
+ begin
+ with hp do
+ begin
+ if is_used and
+ (section=nil) and
+ not(currbind in [AB_EXTERNAL,AB_COMMON]) then
+ Message1(asmw_e_undefined_label,name);
+ end;
+ hp:=tasmsymbol(hp.listnext);
+ end;
+ end;
+
+
+ function TAsmLibraryData.newasmlabel(nr:longint;alt:tasmlabeltype;is_global:boolean) : tasmlabel;
+ var
+ hp : tasmlabel;
+ begin
+ if is_global then
+ hp:=tasmlabel.createglobal(name,nr,alt)
+ else
+ hp:=tasmlabel.createlocal(nr,alt);
+ symbolsearch.insert(hp);
+ newasmlabel:=hp;
+ end;
+
+
+ procedure TAsmLibraryData.getlabel(var l : tasmlabel;alt:tasmlabeltype);
+ begin
+ l:=tasmlabel.createlocal(nextlabelnr[alt],alt);
+ inc(nextlabelnr[alt]);
+ symbolsearch.insert(l);
+ end;
+
+ procedure TAsmLibraryData.getjumplabel(var l : tasmlabel);
+ begin
+ l:=tasmlabel.createlocal(nextlabelnr[alt_jump],alt_jump);
+ inc(nextlabelnr[alt_jump]);
+ symbolsearch.insert(l);
+ end;
+
+
+ procedure TAsmLibraryData.getdatalabel(var l : tasmlabel);
+ begin
+ l:=tasmlabel.createglobal(name,nextlabelnr[alt_data],alt_data);
+ inc(nextlabelnr[alt_data]);
+ symbolsearch.insert(l);
+ end;
+
+
+ procedure TAsmLibraryData.getaddrlabel(var l : tasmlabel);
+ begin
+ l:=tasmlabel.createlocal(nextlabelnr[alt_addr],alt_addr);
+ inc(nextlabelnr[alt_addr]);
+ symbolsearch.insert(l);
+ end;
+
+
+end.
diff --git a/compiler/aasmtai.pas b/compiler/aasmtai.pas
new file mode 100644
index 0000000000..c733364dd0
--- /dev/null
+++ b/compiler/aasmtai.pas
@@ -0,0 +1,2349 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an abstract asmoutput class for all processor types
+
+ 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.
+
+ ****************************************************************************
+}
+{ @abstract(This unit implements an abstract asm output class for all processor types)
+ This unit implements an abstract assembler output class for all processors, these
+ are then overriden for each assembler writer to actually write the data in these
+ classes to an assembler file.
+}
+
+unit aasmtai;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,systems,
+ cpuinfo,cpubase,
+ cgbase,cgutils,
+ symtype,
+ aasmbase;
+
+ type
+ taitype = (
+ ait_none,
+ ait_align,
+ ait_section,
+ ait_comment,
+ ait_string,
+ ait_instruction,
+ ait_datablock,
+ ait_symbol,
+ ait_symbol_end, { needed to calc the size of a symbol }
+ ait_directive,
+ ait_label,
+ { the const_xx must be below each other so it can be used as
+ array index }
+ ait_const_128bit,
+ ait_const_64bit,
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit,
+ ait_const_sleb128bit,
+ ait_const_uleb128bit,
+ ait_const_rva_symbol, { win32 only }
+ ait_const_indirect_symbol, { darwin only }
+ ait_real_32bit,
+ ait_real_64bit,
+ ait_real_80bit,
+ ait_comp_64bit,
+ ait_real_128bit,
+ ait_stab,
+ ait_force_line,
+ ait_function_name,
+{$ifdef alpha}
+ { the follow is for the DEC Alpha }
+ ait_frame,
+ ait_ent,
+{$endif alpha}
+{$ifdef ia64}
+ ait_bundle,
+ ait_stop,
+{$endif ia64}
+{$ifdef m68k}
+ ait_labeled_instruction,
+{$endif m68k}
+ { used to split into tiny assembler files }
+ ait_cutobject,
+ ait_regalloc,
+ ait_tempalloc,
+ { used to mark assembler blocks and inlined functions }
+ ait_marker
+ );
+
+ const
+{$ifdef cpu64bit}
+ ait_const_aint = ait_const_64bit;
+ ait_const_ptr = ait_const_64bit;
+{$else cpu64bit}
+ ait_const_aint = ait_const_32bit;
+ ait_const_ptr = ait_const_32bit;
+{$endif cpu64bit}
+
+ taitypestr : array[taitype] of string[24] = (
+ '<none>',
+ 'align',
+ 'section',
+ 'comment',
+ 'string',
+ 'instruction',
+ 'datablock',
+ 'symbol',
+ 'symbol_end',
+ 'symbol_directive',
+ 'label',
+ 'const_128bit',
+ 'const_64bit',
+ 'const_32bit',
+ 'const_16bit',
+ 'const_8bit',
+ 'const_sleb128bit',
+ 'const_uleb128bit',
+ 'const_rva_symbol',
+ 'const_indirect_symbol',
+ 'real_32bit',
+ 'real_64bit',
+ 'real_80bit',
+ 'comp_64bit',
+ 'real_128bit',
+ 'stab',
+ 'force_line',
+ 'function_name',
+{$ifdef alpha}
+ { the follow is for the DEC Alpha }
+ 'frame',
+ 'ent',
+{$endif alpha}
+{$ifdef ia64}
+ 'bundle',
+ 'stop',
+{$endif ia64}
+{$ifdef m68k}
+ 'labeled_instr',
+{$endif m68k}
+ 'cut',
+ 'regalloc',
+ 'tempalloc',
+ 'marker'
+ );
+
+ type
+ { Types of operand }
+ toptype=(top_none,top_reg,top_ref,top_const,top_bool,top_local
+{$ifdef arm}
+ { ARM only }
+ ,top_regset
+ ,top_shifterop
+{$endif arm}
+{$ifdef m68k}
+ { m68k only }
+ ,top_regset
+{$endif m68k}
+ { i386 only});
+
+ { kinds of operations that an instruction can perform on an operand }
+ topertype = (operand_read,operand_write,operand_readwrite);
+
+ tlocaloper = record
+ localsym : pointer;
+ localsymderef : tderef;
+ localsymofs : longint;
+ localindexreg : tregister;
+ localscale : byte;
+ localgetoffset,
+ localforceref : boolean
+ end;
+ plocaloper = ^tlocaloper;
+
+ { please keep the size of this record <=12 bytes and keep it properly aligned }
+ toper = record
+ ot : longint;
+ case typ : toptype of
+ top_none : ();
+ top_reg : (reg:tregister);
+ top_ref : (ref:preference);
+ top_const : (val:aint);
+ top_bool : (b:boolean);
+ { local varsym that will be inserted in pass_2 }
+ top_local : (localoper:plocaloper);
+ {$ifdef arm}
+ top_regset : (regset:^tcpuregisterset);
+ top_shifterop : (shifterop : pshifterop);
+ {$endif arm}
+ {$ifdef m68k}
+ top_regset : (regset:^tcpuregisterset);
+ {$endif m68k}
+ end;
+ poper=^toper;
+
+{ ait_* types which don't result in executable code or which don't influence }
+{ the way the program runs/behaves, but which may be encountered by the }
+{ optimizer (= if it's sometimes added to the exprasm list). Update if you add }
+{ a new ait type! }
+ const
+ SkipInstr = [ait_comment, ait_symbol,ait_section
+ ,ait_stab, ait_function_name, ait_force_line
+ ,ait_regalloc, ait_tempalloc, ait_symbol_end, ait_directive];
+
+{ ait_* types which do not have line information (and hence which are of type
+ tai, otherwise, they are of type tailineinfo }
+ SkipLineInfo =[ait_label,
+ ait_regalloc,ait_tempalloc,
+ ait_stab,ait_function_name,
+ ait_cutobject,ait_marker,ait_align,ait_section,ait_comment,
+ ait_const_8bit,ait_const_16bit,ait_const_32bit,ait_const_64bit,ait_const_128bit,
+ ait_const_sleb128bit,ait_const_uleb128bit,
+ ait_const_rva_symbol,ait_const_indirect_symbol,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_real_128bit
+ ];
+
+
+ type
+ { cut type, required for alphanumeric ordering of the assembler filenames }
+ TCutPlace=(cut_normal,cut_begin,cut_end);
+
+ TRegAllocType = (ra_alloc,ra_dealloc,ra_sync,ra_resize);
+
+ TMarker = (NoPropInfoStart,NoPropInfoEnd,
+ AsmBlockStart,AsmBlockEnd,
+ InlineStart,InlineEnd,marker_blockstart,
+ marker_position);
+
+ { Buffer type used for alignment }
+ tfillbuffer = array[0..63] of char;
+
+ Tspill_temp_list=array[tsuperregister] of Treference;
+
+ { abstract assembler item }
+ tai = class(TLinkedListItem)
+{$ifndef NOOPT}
+ { pointer to record with optimizer info about this tai object }
+ optinfo : pointer;
+{$endif NOOPT}
+ typ : taitype;
+ constructor Create;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);virtual;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ procedure buildderefimpl;virtual;
+ procedure derefimpl;virtual;
+ end;
+
+ { abstract assembler item with line information }
+ tailineinfo = class(tai)
+ fileinfo : tfileposinfo;
+ constructor Create;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tai_simple = class(tai)
+ constructor create(_typ : taitype);
+ end;
+
+ taiclass = class of tai;
+
+ taiclassarray = array[taitype] of taiclass;
+
+ { Generates an assembler string }
+ tai_string = class(tailineinfo)
+ str : pchar;
+ { extra len so the string can contain an \0 }
+ len : longint;
+ constructor Create(const _str : string);
+ constructor Create_pchar(_str : pchar;length : longint);
+ destructor Destroy;override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function getcopy:tlinkedlistitem;override;
+ end;
+
+ { Generates a common label }
+ tai_symbol = class(tailineinfo)
+ is_global : boolean;
+ sym : tasmsymbol;
+ size : longint;
+ constructor Create(_sym:tasmsymbol;siz:longint);
+ constructor Create_Global(_sym:tasmsymbol;siz:longint);
+ constructor Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint);
+ constructor Createname_global(const _name : string;_symtyp:Tasmsymtype;siz:longint);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ end;
+
+ tai_symbol_end = class(tailineinfo)
+ sym : tasmsymbol;
+ constructor Create(_sym:tasmsymbol);
+ constructor Createname(const _name : string);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ end;
+
+ tasmdirective=(asd_non_lazy_symbol_pointer,asd_indirect_symbol,asd_lazy_symbol_pointer,
+ asd_extern,asd_nasm_import);
+
+ tai_directive = class(tailineinfo)
+ name : pstring;
+ directive : tasmdirective;
+ constructor Create(_directive:tasmdirective;const _name:string);
+ destructor Destroy;override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ { Generates an assembler label }
+ tai_label = class(tai)
+ is_global : boolean;
+ l : tasmlabel;
+ constructor Create(_l : tasmlabel);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ end;
+
+ { Generates an assembler comment }
+ tai_comment = class(tai)
+ str : pchar;
+ constructor Create(_str : pchar);
+ destructor Destroy; override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function getcopy:tlinkedlistitem;override;
+ end;
+
+
+ { Generates a section / segment directive }
+ tai_section = class(tai)
+ sectype : TAsmSectionType;
+ secalign : byte;
+ name : pstring;
+ sec : TAsmSection; { used in binary writer }
+ constructor Create(Asectype:TAsmSectionType;Aname:string;Aalign:byte);
+ destructor Destroy;override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+
+ { Generates an uninitializised data block }
+ tai_datablock = class(tailineinfo)
+ is_global : boolean;
+ sym : tasmsymbol;
+ size : longint;
+ constructor Create(const _name : string;_size : longint);
+ constructor Create_global(const _name : string;_size : longint);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ end;
+
+
+ { Generates an integer const }
+ tai_const = class(tai)
+ sym,
+ endsym : tasmsymbol;
+ value : int64;
+ { we use for the 128bit int64/qword for now because I can't imagine a
+ case where we need 128 bit now (FK) }
+ constructor Create(_typ:taitype;_value : int64);
+ constructor Create_128bit(_value : int64);
+ constructor Create_64bit(_value : int64);
+ constructor Create_32bit(_value : longint);
+ constructor Create_16bit(_value : word);
+ constructor Create_8bit(_value : byte);
+ constructor Create_sleb128bit(_value : int64);
+ constructor Create_uleb128bit(_value : qword);
+ constructor Create_aint(_value : aint);
+ constructor Create_sym(_sym:tasmsymbol);
+ constructor Create_sym_offset(_sym:tasmsymbol;ofs:aint);
+ constructor Create_rel_sym(_typ:taitype;_sym,_endsym:tasmsymbol);
+ constructor Create_rva_sym(_sym:tasmsymbol);
+ constructor Create_indirect_sym(_sym:tasmsymbol);
+ constructor Createname(const name:string;_symtyp:Tasmsymtype;ofs:aint);
+ constructor Createname_rva(const name:string);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ function getcopy:tlinkedlistitem;override;
+ function size:longint;
+ end;
+
+ { Generates a single float (32 bit real) }
+ tai_real_32bit = class(tai)
+ value : ts32real;
+ constructor Create(_value : ts32real);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tformatoptions = (fo_none,fo_hiloswapped);
+
+ { Generates a double float (64 bit real) }
+ tai_real_64bit = class(tai)
+ value : ts64real;
+{$ifdef ARM}
+ formatoptions : tformatoptions;
+ constructor Create_hiloswapped(_value : ts64real);
+{$endif ARM}
+ constructor Create(_value : ts64real);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+
+ { Generates an extended float (80 bit real) }
+ tai_real_80bit = class(tai)
+ value : ts80real;
+ constructor Create(_value : ts80real);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+
+ { Generates an float128 (128 bit real) }
+ tai_real_128bit = class(tai)
+ value : ts128real;
+ constructor Create(_value : ts128real);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ { Generates a comp int (integer over 64 bits)
+
+ This is Intel 80x86 specific, and is not
+ really supported on other processors.
+ }
+ tai_comp_64bit = class(tai)
+ value : ts64comp;
+ constructor Create(_value : ts64comp);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tstabtype = (stab_stabs,stab_stabn,stab_stabd);
+
+ tai_stab = class(tai)
+ str : pchar;
+ stabtype : tstabtype;
+ constructor Create(_stabtype:tstabtype;_str : pchar);
+ constructor Create_str(_stabtype:tstabtype;const s:string);
+ destructor Destroy;override;
+ end;
+
+ tai_force_line = class(tailineinfo)
+ constructor Create;
+ end;
+
+ tai_function_name = class(tai)
+ funcname : pstring;
+ constructor create(const s:string);
+ destructor destroy;override;
+ end;
+
+ { Insert a cut to split assembler into several smaller files }
+ tai_cutobject = class(tai)
+ place : tcutplace;
+ constructor Create;
+ constructor Create_begin;
+ constructor Create_end;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ { Insert a marker for assembler and inline blocks }
+ tai_marker = class(tai)
+ Kind: TMarker;
+ Constructor Create(_Kind: TMarker);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tai_tempalloc = class(tai)
+ allocation : boolean;
+{$ifdef EXTDEBUG}
+ problem : pstring;
+{$endif EXTDEBUG}
+ temppos,
+ tempsize : longint;
+ constructor alloc(pos,size:longint);
+ constructor dealloc(pos,size:longint);
+{$ifdef EXTDEBUG}
+ constructor allocinfo(pos,size:longint;const st:string);
+{$endif EXTDEBUG}
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tai_regalloc = class(tai)
+ reg : tregister;
+ ratype : TRegAllocType;
+ { reg(de)alloc belongs to this instruction, this
+ is only used for automatic inserted (de)alloc for
+ imaginary register and required for spilling code }
+ instr : tai;
+ constructor alloc(r : tregister;ainstr:tai);
+ constructor dealloc(r : tregister;ainstr:tai);
+ constructor sync(r : tregister);
+ constructor resize(r : tregister);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ Taasmoutput=class;
+
+ tadd_reg_instruction_proc=procedure(instr:Tai;r:tregister) of object;
+ Trggetproc=procedure(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister) of object;
+ Trgungetproc=procedure(list:Taasmoutput;position:Tai;r:Tregister) of object;
+
+ { Class template for assembler instructions
+ }
+ tai_cpu_abstract = class(tailineinfo)
+ protected
+ procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);virtual;abstract;
+ procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);virtual;abstract;
+ procedure ppubuildderefimploper(var o:toper);virtual;abstract;
+ procedure ppuderefoper(var o:toper);virtual;abstract;
+ public
+ { Condition flags for instruction }
+ condition : TAsmCond;
+ { Number of operands to instruction }
+ ops : byte;
+ { Number of allocate oper structures }
+ opercnt : byte;
+ { Operands of instruction }
+ oper : array[0..max_operands-1] of poper;
+ { Actual opcode of instruction }
+ opcode : tasmop;
+{$ifdef x86}
+ segprefix : tregister;
+{$endif x86}
+ { true if instruction is a jmp }
+ is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
+ Constructor Create(op : tasmop);virtual;
+ Destructor Destroy;override;
+ function getcopy:TLinkedListItem;override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure SetCondition(const c:TAsmCond);
+ procedure allocate_oper(opers:longint);
+ procedure loadconst(opidx:longint;l:aint);
+ procedure loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
+ procedure loadlocal(opidx:longint;s:pointer;sofs:longint;indexreg:tregister;scale:byte;getoffset,forceref:boolean);
+ procedure loadref(opidx:longint;const r:treference);
+ procedure loadreg(opidx:longint;r:tregister);
+ procedure loadoper(opidx:longint;o:toper);
+ procedure clearop(opidx:longint);
+ { register allocator }
+ function is_same_reg_move(regtype: Tregistertype):boolean;virtual;
+ function spilling_get_operation_type(opnr: longint): topertype;virtual;
+ function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;virtual;
+
+ function Pass1(offset:longint):longint;virtual;abstract;
+ procedure Pass2(objdata:TAsmObjectdata);virtual;abstract;
+ end;
+ tai_cpu_class = class of tai_cpu_abstract;
+
+ { alignment for operator }
+ tai_align_abstract = class(tai)
+ aligntype : byte; { 1 = no align, 2 = word align, 4 = dword align }
+ fillsize : byte; { real size to fill }
+ fillop : byte; { value to fill with - optional }
+ use_op : boolean;
+ constructor Create(b:byte);virtual;
+ constructor Create_op(b: byte; _op: byte);virtual;
+ constructor Create_zeros(b:byte);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function calculatefillbuf(var buf : tfillbuffer):pchar;virtual;
+ end;
+ tai_align_class = class of tai_align_abstract;
+
+ taasmoutput = class(tlinkedlist)
+ constructor create;
+ function empty : boolean;
+ function getlasttaifilepos : pfileposinfo;
+ procedure InsertAfter(Item,Loc : TLinkedListItem);override;
+ end;
+
+ { Type of asmlists. The order is important for the layout of the
+ information in the .o file. The stabs for the types must be defined
+ before they can be referenced and therefor they need to be written
+ first (PFV) }
+ Tasmlist=(al_stabsstart,
+ al_stabs,
+ al_procedures,
+ al_globals,
+ al_const,
+ al_typedconsts,
+ al_rotypedconsts,
+ al_threadvars,
+ al_imports,
+ al_exports,
+ al_resources,
+ al_rtti,
+ al_dwarf,
+ al_picdata,
+ al_resourcestrings,
+ al_stabsend);
+ const
+ TasmlistStr : array[tasmlist] of string[24] =(
+ 'al_stabsstart',
+ 'al_stabs',
+ 'al_procedures',
+ 'al_globals',
+ 'al_const',
+ 'al_typedconsts',
+ 'al_rotypedconsts',
+ 'al_threadvars',
+ 'al_imports',
+ 'al_exports',
+ 'al_resources',
+ 'al_rtti',
+ 'al_dwarf',
+ 'al_picdata',
+ 'al_resourcestrings',
+ 'al_stabsend');
+
+ regallocstr : array[tregalloctype] of string[10]=('allocated','released','sync','resized');
+ tempallocstr : array[boolean] of string[10]=('released','allocated');
+ stabtypestr : array[tstabtype] of string[5]=('stabs','stabn','stabd');
+ directivestr : array[tasmdirective] of string[24]=(
+ 'non_lazy_symbol_pointer','indirect_symbol','lazy_symbol_pointer',
+ 'extern','nasm_import'
+ );
+
+ var
+ { array with all class types for tais }
+ aiclass : taiclassarray;
+
+ { Current expression list }
+ exprasmlist : taasmoutput;
+
+ { labels for BREAK and CONTINUE }
+ aktbreaklabel,aktcontinuelabel : tasmlabel;
+
+ { label when the result is true or false }
+ truelabel,falselabel : tasmlabel;
+
+ { hook to notify uses of registers }
+ add_reg_instruction_hook : tadd_reg_instruction_proc;
+
+ asmlist:array[Tasmlist] of Taasmoutput;
+
+ cai_align : tai_align_class;
+ cai_cpu : tai_cpu_class;
+
+ function use_smartlink_section:boolean;
+ function maybe_smartlink_symbol:boolean;
+
+ procedure maybe_new_object_file(list:taasmoutput);
+ procedure new_section(list:taasmoutput;Asectype:TAsmSectionType;Aname:string;Aalign:byte);
+ procedure section_symbol_start(list:taasmoutput;const Aname:string;Asymtyp:Tasmsymtype;
+ Aglobal:boolean;Asectype:TAsmSectionType;Aalign:byte);
+ procedure section_symbol_end(list:taasmoutput;const Aname:string);
+
+ function ppuloadai(ppufile:tcompilerppufile):tai;
+ procedure ppuwriteai(ppufile:tcompilerppufile;n:tai);
+
+
+implementation
+
+ uses
+ strings,
+ verbose;
+
+ const
+ pputaimarker = 254;
+
+
+{****************************************************************************
+ Helpers
+ ****************************************************************************}
+
+ function ppuloadai(ppufile:tcompilerppufile):tai;
+ var
+ b : byte;
+ t : taitype;
+ begin
+ { marker }
+ b:=ppufile.getbyte;
+ if b<>pputaimarker then
+ internalerror(200208181);
+ { load nodetype }
+ t:=taitype(ppufile.getbyte);
+ if t<>ait_none then
+ begin
+ if t>high(taitype) then
+ internalerror(200208182);
+ if not assigned(aiclass[t]) then
+ internalerror(200208183);
+ {writeln('taiload: ',taitypestr[t]);}
+ { generate tai of the correct class }
+ ppuloadai:=aiclass[t].ppuload(t,ppufile);
+ end
+ else
+ ppuloadai:=nil;
+ end;
+
+
+ procedure ppuwriteai(ppufile:tcompilerppufile;n:tai);
+ begin
+ { marker, read by ppuloadnode }
+ ppufile.putbyte(pputaimarker);
+ if assigned(n) then
+ begin
+ { type, read by ppuloadnode }
+ ppufile.putbyte(byte(n.typ));
+ {writeln('taiwrite: ',taitypestr[n.typ]);}
+ n.ppuwrite(ppufile);
+ end
+ else
+ ppufile.putbyte(byte(ait_none));
+ end;
+
+
+ function use_smartlink_section:boolean;
+ begin
+ result:=(af_smartlink_sections in target_asm.flags) and
+ (tf_smartlink_sections in target_info.flags);
+ end;
+
+
+ function maybe_smartlink_symbol:boolean;
+ begin
+ result:=(cs_create_smart in aktmoduleswitches) or
+ use_smartlink_section;
+ end;
+
+
+ procedure maybe_new_object_file(list:taasmoutput);
+ begin
+ if (cs_create_smart in aktmoduleswitches) and
+ (not use_smartlink_section) then
+ list.concat(tai_cutobject.create);
+ end;
+
+
+ procedure new_section(list:taasmoutput;Asectype:TAsmSectionType;Aname:string;Aalign:byte);
+ begin
+ list.concat(tai_section.create(Asectype,Aname,Aalign));
+ list.concat(cai_align.create(Aalign));
+ end;
+
+
+ procedure section_symbol_start(list:taasmoutput;const Aname:string;Asymtyp:Tasmsymtype;
+ Aglobal:boolean;Asectype:TAsmSectionType;Aalign:byte);
+ begin
+ maybe_new_object_file(list);
+ list.concat(tai_section.create(Asectype,Aname,Aalign));
+ list.concat(cai_align.create(Aalign));
+ if Aglobal or
+ maybe_smartlink_symbol then
+ list.concat(tai_symbol.createname_global(Aname,Asymtyp,0))
+ else
+ list.concat(tai_symbol.createname(Aname,Asymtyp,0));
+ end;
+
+
+ procedure section_symbol_end(list:taasmoutput;const Aname:string);
+ begin
+ list.concat(tai_symbol_end.createname(Aname));
+ end;
+
+
+{****************************************************************************
+ TAI
+ ****************************************************************************}
+
+ constructor tai.Create;
+ begin
+{$ifndef NOOPT}
+ optinfo:=nil;
+{$endif NOOPT}
+ end;
+
+
+ constructor tai.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ typ:=t;
+{$ifndef NOOPT}
+ optinfo:=nil;
+{$endif}
+ end;
+
+
+ procedure tai.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ end;
+
+
+ procedure tai.buildderefimpl;
+ begin
+ end;
+
+
+ procedure tai.derefimpl;
+ begin
+ end;
+
+
+{****************************************************************************
+ TAILINEINFO
+ ****************************************************************************}
+
+ constructor tailineinfo.create;
+ begin
+ inherited create;
+ if not(inlining_procedure and
+ (cs_gdb_valgrind in aktglobalswitches)) then
+ fileinfo:=aktfilepos;
+ end;
+
+
+ constructor tailineinfo.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getposinfo(fileinfo);
+ end;
+
+
+ procedure tailineinfo.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putposinfo(fileinfo);
+ end;
+
+
+{****************************************************************************
+ TAI_SIMPLE
+ ****************************************************************************}
+
+ constructor tai_simple.create(_typ : taitype);
+ begin
+ inherited create;
+ typ:=_typ;
+ end;
+
+
+{****************************************************************************
+ TAI_SECTION
+ ****************************************************************************}
+
+ constructor tai_section.Create(Asectype:TAsmSectionType;Aname:string;Aalign:byte);
+ begin
+ inherited Create;
+ typ:=ait_section;
+ sectype:=asectype;
+ secalign:=Aalign;
+ name:=stringdup(Aname);
+ sec:=nil;
+ end;
+
+
+ constructor tai_section.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ sectype:=tasmsectiontype(ppufile.getbyte);
+ secalign:=ppufile.getbyte;
+ name:=stringdup(ppufile.getstring);
+ sec:=nil;
+ end;
+
+
+ destructor tai_section.Destroy;
+ begin
+ stringdispose(name);
+ end;
+
+
+ procedure tai_section.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(sectype));
+ ppufile.putbyte(secalign);
+ ppufile.putstring(name^);
+ end;
+
+
+{****************************************************************************
+ TAI_DATABLOCK
+ ****************************************************************************}
+
+ constructor tai_datablock.Create(const _name : string;_size : longint);
+
+ begin
+ inherited Create;
+ typ:=ait_datablock;
+ sym:=objectlibrary.newasmsymbol(_name,AB_LOCAL,AT_DATA);
+ { keep things aligned }
+ if _size<=0 then
+ _size:=4;
+ size:=_size;
+ is_global:=false;
+ end;
+
+
+ constructor tai_datablock.Create_global(const _name : string;_size : longint);
+ begin
+ inherited Create;
+ typ:=ait_datablock;
+ sym:=objectlibrary.newasmsymbol(_name,AB_GLOBAL,AT_DATA);
+ { keep things aligned }
+ if _size<=0 then
+ _size:=4;
+ size:=_size;
+ is_global:=true;
+ end;
+
+
+ constructor tai_datablock.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited Create;
+ sym:=ppufile.getasmsymbol;
+ size:=ppufile.getlongint;
+ is_global:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_datablock.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(sym);
+ ppufile.putlongint(size);
+ ppufile.putbyte(byte(is_global));
+ end;
+
+
+ procedure tai_datablock.derefimpl;
+ begin
+ objectlibrary.DerefAsmsymbol(sym);
+ end;
+
+
+{****************************************************************************
+ TAI_SYMBOL
+ ****************************************************************************}
+
+ constructor tai_symbol.Create(_sym:tasmsymbol;siz:longint);
+ begin
+ inherited Create;
+ typ:=ait_symbol;
+ sym:=_sym;
+ size:=siz;
+ sym.defbind:=AB_LOCAL;
+ is_global:=false;
+ end;
+
+ constructor tai_symbol.Create_global(_sym:tasmsymbol;siz:longint);
+ begin
+ inherited Create;
+ typ:=ait_symbol;
+ sym:=_sym;
+ size:=siz;
+ sym.defbind:=AB_GLOBAL;
+ is_global:=true;
+ end;
+
+ constructor tai_symbol.Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint);
+ begin
+ inherited Create;
+ typ:=ait_symbol;
+ sym:=objectlibrary.newasmsymbol(_name,AB_LOCAL,_symtyp);
+ size:=siz;
+ is_global:=false;
+ end;
+
+ constructor tai_symbol.Createname_global(const _name : string;_symtyp:Tasmsymtype;siz:longint);
+ begin
+ inherited Create;
+ typ:=ait_symbol;
+ sym:=objectlibrary.newasmsymbol(_name,AB_GLOBAL,_symtyp);
+ size:=siz;
+ is_global:=true;
+ end;
+
+ constructor tai_symbol.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ sym:=ppufile.getasmsymbol;
+ size:=ppufile.getlongint;
+ is_global:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_symbol.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(sym);
+ ppufile.putlongint(size);
+ ppufile.putbyte(byte(is_global));
+ end;
+
+
+ procedure tai_symbol.derefimpl;
+ begin
+ objectlibrary.DerefAsmsymbol(sym);
+ end;
+
+
+{****************************************************************************
+ TAI_SYMBOL_END
+ ****************************************************************************}
+
+ constructor tai_symbol_end.Create(_sym:tasmsymbol);
+ begin
+ inherited Create;
+ typ:=ait_symbol_end;
+ sym:=_sym;
+ end;
+
+ constructor tai_symbol_end.Createname(const _name : string);
+ begin
+ inherited Create;
+ typ:=ait_symbol_end;
+ sym:=objectlibrary.newasmsymbol(_name,AB_GLOBAL,AT_NONE);
+ end;
+
+ constructor tai_symbol_end.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ sym:=ppufile.getasmsymbol;
+ end;
+
+
+ procedure tai_symbol_end.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(sym);
+ end;
+
+
+ procedure tai_symbol_end.derefimpl;
+ begin
+ objectlibrary.DerefAsmsymbol(sym);
+ end;
+
+
+{****************************************************************************
+ TAI_SYMBOL_END
+ ****************************************************************************}
+
+ constructor tai_directive.Create(_directive:tasmdirective;const _name:string);
+ begin
+ inherited Create;
+ typ:=ait_directive;
+ name:=stringdup(_name);
+ directive:=_directive;
+ end;
+
+
+ destructor tai_directive.Destroy;
+ begin
+ stringdispose(name);
+ end;
+
+
+ constructor tai_directive.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ name:=stringdup(ppufile.getstring);
+ directive:=tasmdirective(ppufile.getbyte);
+ end;
+
+
+ procedure tai_directive.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putstring(name^);
+ ppufile.putbyte(byte(directive));
+ end;
+
+
+{****************************************************************************
+ TAI_CONST
+ ****************************************************************************}
+
+ constructor tai_const.Create(_typ:taitype;_value : int64);
+ begin
+ inherited Create;
+ typ:=_typ;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_128bit(_value : int64);
+ begin
+ inherited Create;
+ typ:=ait_const_128bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_64bit(_value : int64);
+ begin
+ inherited Create;
+ typ:=ait_const_64bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_32bit(_value : longint);
+ begin
+ inherited Create;
+ typ:=ait_const_32bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_16bit(_value : word);
+ begin
+ inherited Create;
+ typ:=ait_const_16bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_8bit(_value : byte);
+ begin
+ inherited Create;
+ typ:=ait_const_8bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_sleb128bit(_value : int64);
+ begin
+ inherited Create;
+ typ:=ait_const_sleb128bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_uleb128bit(_value : qword);
+ begin
+ inherited Create;
+ typ:=ait_const_uleb128bit;
+ value:=int64(_value);
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_aint(_value : aint);
+ begin
+ inherited Create;
+ typ:=ait_const_aint;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_sym(_sym:tasmsymbol);
+ begin
+ inherited Create;
+ typ:=ait_const_ptr;
+ { sym is allowed to be nil, this is used to write nil pointers }
+ sym:=_sym;
+ endsym:=nil;
+ value:=0;
+ { update sym info }
+ if assigned(sym) then
+ sym.increfs;
+ end;
+
+
+ constructor tai_const.Create_sym_offset(_sym:tasmsymbol;ofs:aint);
+ begin
+ inherited Create;
+ typ:=ait_const_ptr;
+ if not assigned(_sym) then
+ internalerror(200404121);
+ sym:=_sym;
+ endsym:=nil;
+ value:=ofs;
+ { update sym info }
+ sym.increfs;
+ end;
+
+
+ constructor tai_const.Create_rel_sym(_typ:taitype;_sym,_endsym:tasmsymbol);
+ begin
+ inherited Create;
+ typ:=_typ;
+ sym:=_sym;
+ endsym:=_endsym;
+ value:=0;
+ { update sym info }
+ sym.increfs;
+ endsym.increfs;
+ end;
+
+
+ constructor tai_const.Create_rva_sym(_sym:tasmsymbol);
+ begin
+ inherited Create;
+ typ:=ait_const_rva_symbol;
+ sym:=_sym;
+ endsym:=nil;
+ value:=0;
+ { update sym info }
+ sym.increfs;
+ end;
+
+
+ constructor tai_const.Create_indirect_sym(_sym:tasmsymbol);
+ begin
+ inherited Create;
+ typ:=ait_const_indirect_symbol;
+ sym:=_sym;
+ endsym:=nil;
+ value:=0;
+ { update sym info }
+ sym.increfs;
+ end;
+
+
+ constructor tai_const.Createname(const name:string;_symtyp:Tasmsymtype;ofs:aint);
+ begin
+ inherited Create;
+ typ:=ait_const_ptr;
+ sym:=objectlibrary.newasmsymbol(name,AB_EXTERNAL,_symtyp);
+ endsym:=nil;
+ value:=ofs;
+ { update sym info }
+ sym.increfs;
+ end;
+
+
+ constructor tai_const.Createname_rva(const name:string);
+ begin
+ inherited Create;
+ typ:=ait_const_rva_symbol;
+ sym:=objectlibrary.newasmsymbol(name,AB_EXTERNAL,AT_FUNCTION);
+ endsym:=nil;
+ value:=0;
+ { update sym info }
+ sym.increfs;
+ end;
+
+
+ constructor tai_const.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ sym:=ppufile.getasmsymbol;
+ endsym:=ppufile.getasmsymbol;
+ value:=ppufile.getint64;
+ end;
+
+
+ procedure tai_const.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(sym);
+ ppufile.putasmsymbol(endsym);
+ ppufile.putint64(value);
+ end;
+
+
+ procedure tai_const.derefimpl;
+ begin
+ objectlibrary.DerefAsmsymbol(sym);
+ objectlibrary.DerefAsmsymbol(endsym);
+ end;
+
+
+ function tai_const.getcopy:tlinkedlistitem;
+ begin
+ getcopy:=inherited getcopy;
+ { we need to increase the reference number }
+ sym.increfs;
+ if assigned(endsym) then
+ endsym.increfs;
+ end;
+
+
+ function tai_const.size:longint;
+ begin
+ case typ of
+ ait_const_8bit :
+ result:=1;
+ ait_const_16bit :
+ result:=2;
+ ait_const_32bit :
+ result:=4;
+ ait_const_64bit :
+ result:=8;
+ ait_const_indirect_symbol,
+ ait_const_rva_symbol :
+ result:=sizeof(aint);
+ end;
+ end;
+
+
+{****************************************************************************
+ TAI_real_32bit
+ ****************************************************************************}
+
+ constructor tai_real_32bit.Create(_value : ts32real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_32bit;
+ value:=_value;
+ end;
+
+ constructor tai_real_32bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ value:=ppufile.getreal;
+ end;
+
+
+ procedure tai_real_32bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putreal(value);
+ end;
+
+
+{****************************************************************************
+ TAI_real_64bit
+ ****************************************************************************}
+
+ constructor tai_real_64bit.Create(_value : ts64real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_64bit;
+ value:=_value;
+ end;
+
+
+{$ifdef ARM}
+ constructor tai_real_64bit.Create_hiloswapped(_value : ts64real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_64bit;
+ value:=_value;
+ formatoptions:=fo_hiloswapped;
+ end;
+{$endif ARM}
+
+ constructor tai_real_64bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ value:=ppufile.getreal;
+{$ifdef ARM}
+ formatoptions:=tformatoptions(ppufile.getbyte);
+{$endif ARM}
+ end;
+
+
+ procedure tai_real_64bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putreal(value);
+{$ifdef ARM}
+ ppufile.putbyte(byte(formatoptions));
+{$endif ARM}
+ end;
+
+
+{****************************************************************************
+ TAI_real_80bit
+ ****************************************************************************}
+
+ constructor tai_real_80bit.Create(_value : ts80real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_80bit;
+ value:=_value;
+ end;
+
+
+ constructor tai_real_80bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ value:=ppufile.getreal;
+ end;
+
+
+ procedure tai_real_80bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putreal(value);
+ end;
+
+
+{****************************************************************************
+ TAI_real_80bit
+ ****************************************************************************}
+
+ constructor tai_real_128bit.Create(_value : ts128real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_128bit;
+ value:=_value;
+ end;
+
+
+ constructor tai_real_128bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ value:=ppufile.getreal;
+ end;
+
+
+ procedure tai_real_128bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putreal(value);
+ end;
+
+
+{****************************************************************************
+ Tai_comp_64bit
+ ****************************************************************************}
+
+ constructor tai_comp_64bit.Create(_value : ts64comp);
+
+ begin
+ inherited Create;
+ typ:=ait_comp_64bit;
+ value:=_value;
+ end;
+
+
+ constructor tai_comp_64bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.putdata(value,sizeof(value));
+ end;
+
+
+ procedure tai_comp_64bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.getdata(value,sizeof(value));
+ end;
+
+
+{****************************************************************************
+ TAI_STRING
+ ****************************************************************************}
+
+ constructor tai_string.Create(const _str : string);
+ begin
+ inherited Create;
+ typ:=ait_string;
+ len:=length(_str);
+ getmem(str,len+1);
+ strpcopy(str,_str);
+ end;
+
+
+ constructor tai_string.Create_pchar(_str : pchar;length : longint);
+ begin
+ inherited Create;
+ typ:=ait_string;
+ str:=_str;
+ len:=length;
+ end;
+
+
+ destructor tai_string.destroy;
+ begin
+ if str<>nil then
+ freemem(str);
+ inherited Destroy;
+ end;
+
+
+ constructor tai_string.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ len:=ppufile.getlongint;
+ getmem(str,len);
+ ppufile.getdata(str^,len);
+ end;
+
+
+ procedure tai_string.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(len);
+ ppufile.putdata(str^,len);
+ end;
+
+
+ function tai_string.getcopy : tlinkedlistitem;
+ var
+ p : tlinkedlistitem;
+ begin
+ p:=inherited getcopy;
+ getmem(tai_string(p).str,len);
+ move(str^,tai_string(p).str^,len);
+ getcopy:=p;
+ end;
+
+
+{****************************************************************************
+ TAI_LABEL
+ ****************************************************************************}
+
+ constructor tai_label.create(_l : tasmlabel);
+ begin
+ inherited Create;
+ typ:=ait_label;
+ l:=_l;
+ l.is_set:=true;
+ is_global:=(l.defbind=AB_GLOBAL);
+ end;
+
+
+ constructor tai_label.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ l:=tasmlabel(ppufile.getasmsymbol);
+ is_global:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_label.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(l);
+ ppufile.putbyte(byte(is_global));
+ end;
+
+
+ procedure tai_label.derefimpl;
+ begin
+ objectlibrary.DerefAsmsymbol(tasmsymbol(l));
+ l.is_set:=true;
+ end;
+
+
+{****************************************************************************
+ tai_comment comment to be inserted in the assembler file
+ ****************************************************************************}
+
+ constructor tai_comment.Create(_str : pchar);
+
+ begin
+ inherited Create;
+ typ:=ait_comment;
+ str:=_str;
+ end;
+
+ destructor tai_comment.destroy;
+
+ begin
+ strdispose(str);
+ inherited Destroy;
+ end;
+
+ constructor tai_comment.ppuload(t:taitype;ppufile:tcompilerppufile);
+ var
+ len : longint;
+ begin
+ inherited ppuload(t,ppufile);
+ len:=ppufile.getlongint;
+ getmem(str,len+1);
+ ppufile.getdata(str^,len);
+ str[len]:=#0;
+ end;
+
+
+ procedure tai_comment.ppuwrite(ppufile:tcompilerppufile);
+ var
+ len : longint;
+ begin
+ inherited ppuwrite(ppufile);
+ len:=strlen(str);
+ ppufile.putlongint(len);
+ ppufile.putdata(str^,len);
+ end;
+
+
+ function tai_comment.getcopy : tlinkedlistitem;
+ var
+ p : tlinkedlistitem;
+ begin
+ p:=inherited getcopy;
+ getmem(tai_comment(p).str,strlen(str)+1);
+ move(str^,tai_comment(p).str^,strlen(str)+1);
+ getcopy:=p;
+ end;
+
+
+{****************************************************************************
+ TAI_STABS
+ ****************************************************************************}
+
+ constructor tai_stab.create(_stabtype:tstabtype;_str : pchar);
+ begin
+ inherited create;
+ typ:=ait_stab;
+ str:=_str;
+ stabtype:=_stabtype;
+ end;
+
+ constructor tai_stab.create_str(_stabtype:tstabtype;const s:string);
+ begin
+ self.create(_stabtype,strpnew(s));
+ end;
+
+ destructor tai_stab.destroy;
+ begin
+ strdispose(str);
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TAI_FORCE_LINE
+ ****************************************************************************}
+
+ constructor tai_force_line.create;
+ begin
+ inherited create;
+ typ:=ait_force_line;
+ end;
+
+
+{****************************************************************************
+ TAI_FUNCTION_NAME
+ ****************************************************************************}
+
+ constructor tai_function_name.create(const s:string);
+ begin
+ inherited create;
+ typ:=ait_function_name;
+ funcname:=stringdup(s);
+ end;
+
+ destructor tai_function_name.destroy;
+ begin
+ stringdispose(funcname);
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TAI_CUTOBJECT
+ ****************************************************************************}
+
+ constructor tai_cutobject.Create;
+ begin
+ inherited Create;
+ typ:=ait_cutobject;
+ place:=cut_normal;
+ end;
+
+
+ constructor tai_cutobject.Create_begin;
+ begin
+ inherited Create;
+ typ:=ait_cutobject;
+ place:=cut_begin;
+ end;
+
+
+ constructor tai_cutobject.Create_end;
+ begin
+ inherited Create;
+ typ:=ait_cutobject;
+ place:=cut_end;
+ end;
+
+
+ constructor tai_cutobject.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ place:=TCutPlace(ppufile.getbyte);
+ end;
+
+
+ procedure tai_cutobject.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(place));
+ end;
+
+
+{****************************************************************************
+ Tai_Marker
+ ****************************************************************************}
+
+ constructor Tai_Marker.Create(_Kind: TMarker);
+ begin
+ Inherited Create;
+ typ := ait_marker;
+ Kind := _Kind;
+ end;
+
+
+ constructor Tai_Marker.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ kind:=TMarker(ppufile.getbyte);
+ end;
+
+
+ procedure Tai_Marker.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(kind));
+ end;
+
+
+{*****************************************************************************
+ tai_tempalloc
+*****************************************************************************}
+
+ constructor tai_tempalloc.alloc(pos,size:longint);
+ begin
+ inherited Create;
+ typ:=ait_tempalloc;
+ allocation:=true;
+ temppos:=pos;
+ tempsize:=size;
+{$ifdef EXTDEBUG}
+ problem:=nil;
+{$endif EXTDEBUG}
+ end;
+
+
+ destructor tai_tempalloc.destroy;
+ begin
+{$ifdef EXTDEBUG}
+ stringdispose(problem);
+{$endif EXTDEBUG}
+ inherited destroy;
+ end;
+
+
+ constructor tai_tempalloc.dealloc(pos,size:longint);
+ begin
+ inherited Create;
+ typ:=ait_tempalloc;
+ allocation:=false;
+ temppos:=pos;
+ tempsize:=size;
+{$ifdef EXTDEBUG}
+ problem:=nil;
+{$endif EXTDEBUG}
+ end;
+
+
+{$ifdef EXTDEBUG}
+ constructor tai_tempalloc.allocinfo(pos,size:longint;const st:string);
+ begin
+ inherited Create;
+ typ:=ait_tempalloc;
+ allocation:=false;
+ temppos:=pos;
+ tempsize:=size;
+ problem:=stringdup(st);
+ end;
+{$endif EXTDEBUG}
+
+
+ constructor tai_tempalloc.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ temppos:=ppufile.getlongint;
+ tempsize:=ppufile.getlongint;
+ allocation:=boolean(ppufile.getbyte);
+{$ifdef EXTDEBUG}
+ problem:=nil;
+{$endif EXTDEBUG}
+ end;
+
+
+ procedure tai_tempalloc.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(temppos);
+ ppufile.putlongint(tempsize);
+ ppufile.putbyte(byte(allocation));
+ end;
+
+
+{*****************************************************************************
+ tai_regalloc
+*****************************************************************************}
+
+ constructor tai_regalloc.alloc(r : tregister;ainstr:tai);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ ratype:=ra_alloc;
+ reg:=r;
+ { ainstr must be an instruction }
+ if assigned(ainstr) and
+ (ainstr.typ<>ait_instruction) then
+ internalerror(200411011);
+ instr:=ainstr;
+ end;
+
+
+ constructor tai_regalloc.dealloc(r : tregister;ainstr:tai);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ ratype:=ra_dealloc;
+ reg:=r;
+ { ainstr must be an instruction }
+ if assigned(ainstr) and
+ (ainstr.typ<>ait_instruction) then
+ internalerror(200411012);
+ instr:=ainstr;
+ end;
+
+
+ constructor tai_regalloc.sync(r : tregister);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ ratype:=ra_sync;
+ reg:=r;
+ end;
+
+
+ constructor tai_regalloc.resize(r : tregister);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ ratype:=ra_resize;
+ reg:=r;
+ end;
+
+
+ constructor tai_regalloc.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getdata(reg,sizeof(Tregister));
+ ratype:=tregalloctype(ppufile.getbyte);
+ end;
+
+
+ procedure tai_regalloc.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putdata(reg,sizeof(Tregister));
+ ppufile.putbyte(byte(ratype));
+ end;
+
+
+{*****************************************************************************
+ TaiInstruction
+*****************************************************************************}
+
+ constructor tai_cpu_abstract.Create(op : tasmop);
+
+ begin
+ inherited create;
+ typ:=ait_instruction;
+ is_jmp:=false;
+ opcode:=op;
+ ops:=0;
+ fillchar(condition,sizeof(condition),0);
+ fillchar(oper,sizeof(oper),0);
+ end;
+
+
+ destructor tai_cpu_abstract.Destroy;
+ var
+ i : integer;
+ begin
+ for i:=0 to opercnt-1 do
+ begin
+ clearop(i);
+ dispose(oper[i]);
+ end;
+ inherited destroy;
+ end;
+
+
+{ ---------------------------------------------------------------------
+ Loading of operands.
+ ---------------------------------------------------------------------}
+
+ procedure tai_cpu_abstract.allocate_oper(opers:longint);
+ begin
+ while (opers>opercnt) do
+ begin
+ new(oper[opercnt]);
+ fillchar(oper[opercnt]^,sizeof(toper),0);
+ inc(opercnt);
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.loadconst(opidx:longint;l:aint);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_const then
+ clearop(opidx);
+ val:=l;
+ typ:=top_const;
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
+ var
+ r : treference;
+ begin
+ reference_reset_symbol(r,s,sofs);
+ r.refaddr:=addr_full;
+ loadref(opidx,r);
+ end;
+
+
+ procedure tai_cpu_abstract.loadlocal(opidx:longint;s:pointer;sofs:longint;indexreg:tregister;scale:byte;getoffset,forceref:boolean);
+ begin
+ if not assigned(s) then
+ internalerror(200204251);
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_local then
+ begin
+ clearop(opidx);
+ new(localoper);
+ end;
+ with oper[opidx]^.localoper^ do
+ begin
+ localsym:=s;
+ localsymofs:=sofs;
+ localindexreg:=indexreg;
+ localscale:=scale;
+ localgetoffset:=getoffset;
+ localforceref:=forceref;
+ end;
+ typ:=top_local;
+ end;
+ end;
+
+
+
+ procedure tai_cpu_abstract.loadref(opidx:longint;const r:treference);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_ref then
+ begin
+ clearop(opidx);
+ new(ref);
+ end;
+
+ ref^:=r;
+{$ifdef x86}
+ { We allow this exception for x86, since overloading this would be
+ too much of a a speed penalty}
+ if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
+ segprefix:=ref^.segment;
+{$endif}
+{$ifdef extdebug}
+ if (cs_create_pic in aktmoduleswitches) and
+ assigned(r.symbol) and
+ (r.refaddr=addr_no) then
+ internalerror(200502052);
+{$endif}
+ typ:=top_ref;
+ if assigned(add_reg_instruction_hook) then
+ begin
+ add_reg_instruction_hook(self,ref^.base);
+ add_reg_instruction_hook(self,ref^.index);
+ end;
+ { mark symbol as used }
+ if assigned(ref^.symbol) then
+ ref^.symbol.increfs;
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.loadreg(opidx:longint;r:tregister);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_reg then
+ clearop(opidx);
+ reg:=r;
+ typ:=top_reg;
+ end;
+ if assigned(add_reg_instruction_hook) then
+ add_reg_instruction_hook(self,r);
+{$ifdef ARM}
+ { R15 is the PC on the ARM thus moves to R15 are jumps.
+ Due to speed considerations we don't use a virtual overridden method here.
+ Because the pc/r15 isn't handled by the reg. allocator this should never cause
+ problems with iregs getting r15.
+ }
+ is_jmp:=(opcode=A_MOV) and (opidx=0) and (r=NR_R15);
+{$endif ARM}
+ end;
+
+
+ procedure tai_cpu_abstract.loadoper(opidx:longint;o:toper);
+ begin
+ allocate_oper(opidx+1);
+ clearop(opidx);
+ oper[opidx]^:=o;
+ { copy also the reference }
+ with oper[opidx]^ do
+ begin
+ case typ of
+ top_reg:
+ begin
+ if assigned(add_reg_instruction_hook) then
+ add_reg_instruction_hook(self,reg);
+ end;
+ top_ref:
+ begin
+ new(ref);
+ ref^:=o.ref^;
+ if assigned(add_reg_instruction_hook) then
+ begin
+ add_reg_instruction_hook(self,ref^.base);
+ add_reg_instruction_hook(self,ref^.index);
+ end;
+ end;
+{$ifdef ARM}
+ top_shifterop:
+ begin
+ new(shifterop);
+ shifterop^:=o.shifterop^;
+ if assigned(add_reg_instruction_hook) then
+ add_reg_instruction_hook(self,shifterop^.rs);
+ end;
+{$endif ARM}
+ end;
+ end;
+ end;
+
+ procedure tai_cpu_abstract.clearop(opidx:longint);
+ begin
+ with oper[opidx]^ do
+ begin
+ case typ of
+ top_ref:
+ dispose(ref);
+ top_local:
+ dispose(localoper);
+{$ifdef ARM}
+ top_shifterop:
+ dispose(shifterop);
+ top_regset:
+ dispose(regset);
+{$endif ARM}
+ end;
+ typ:=top_none;
+ end;
+ end;
+
+
+{ ---------------------------------------------------------------------
+ Miscellaneous methods.
+ ---------------------------------------------------------------------}
+
+ procedure tai_cpu_abstract.SetCondition(const c:TAsmCond);
+ begin
+ condition:=c;
+ end;
+
+
+ Function tai_cpu_abstract.getcopy:TLinkedListItem;
+ var
+ i : longint;
+ p : tai_cpu_abstract;
+ begin
+ p:=tai_cpu_abstract(inherited getcopy);
+ { make a copy of the references }
+ p.opercnt:=0;
+ p.allocate_oper(ops);
+ for i:=0 to ops-1 do
+ begin
+ p.oper[i]^:=oper[i]^;
+ case oper[i]^.typ of
+ top_local :
+ begin
+ new(p.oper[i]^.localoper);
+ p.oper[i]^.localoper^:=oper[i]^.localoper^;
+ end;
+ top_ref :
+ begin
+ new(p.oper[i]^.ref);
+ p.oper[i]^.ref^:=oper[i]^.ref^;
+ end;
+{$ifdef ARM}
+ top_shifterop:
+ begin
+ new(p.oper[i]^.shifterop);
+ p.oper[i]^.shifterop^:=oper[i]^.shifterop^;
+ end;
+{$endif ARM}
+ end;
+ end;
+ getcopy:=p;
+ end;
+
+
+ function tai_cpu_abstract.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ { When the generic RA is used this needs to be overriden, we don't use
+ virtual;abstract; to prevent a lot of warnings of unimplemented abstract methods
+ when tai_cpu is created (PFV) }
+ internalerror(200404091);
+ result:=false;
+ end;
+
+
+ function tai_cpu_abstract.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ internalerror(200404091);
+ result:=operand_readwrite;
+ end;
+
+
+ function tai_cpu_abstract.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
+ begin
+ result := operand_read;
+ end;
+
+
+ constructor tai_cpu_abstract.ppuload(t:taitype;ppufile:tcompilerppufile);
+ var
+ i : integer;
+ begin
+ inherited ppuload(t,ppufile);
+ { hopefully, we don't get problems with big/litte endian here when cross compiling :/ }
+ ppufile.getdata(condition,sizeof(tasmcond));
+ allocate_oper(ppufile.getbyte);
+ for i:=0 to ops-1 do
+ ppuloadoper(ppufile,oper[i]^);
+ opcode:=tasmop(ppufile.getword);
+{$ifdef x86}
+ ppufile.getdata(segprefix,sizeof(Tregister));
+{$endif x86}
+ is_jmp:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_cpu_abstract.ppuwrite(ppufile:tcompilerppufile);
+ var
+ i : integer;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putdata(condition,sizeof(tasmcond));
+ ppufile.putbyte(ops);
+ for i:=0 to ops-1 do
+ ppuwriteoper(ppufile,oper[i]^);
+ ppufile.putword(word(opcode));
+{$ifdef x86}
+ ppufile.putdata(segprefix,sizeof(Tregister));
+{$endif x86}
+ ppufile.putbyte(byte(is_jmp));
+ end;
+
+
+ procedure tai_cpu_abstract.buildderefimpl;
+ var
+ i : integer;
+ begin
+ for i:=0 to ops-1 do
+ ppubuildderefimploper(oper[i]^);
+ end;
+
+
+ procedure tai_cpu_abstract.derefimpl;
+ var
+ i : integer;
+ begin
+ for i:=0 to ops-1 do
+ ppuderefoper(oper[i]^);
+ end;
+
+
+{****************************************************************************
+ tai_align_abstract
+ ****************************************************************************}
+
+ constructor tai_align_abstract.Create(b: byte);
+ begin
+ inherited Create;
+ typ:=ait_align;
+ if b in [1,2,4,8,16,32] then
+ aligntype := b
+ else
+ aligntype := 1;
+ fillsize:=0;
+ fillop:=0;
+ use_op:=false;
+ end;
+
+
+ constructor tai_align_abstract.Create_op(b: byte; _op: byte);
+ begin
+ inherited Create;
+ typ:=ait_align;
+ if b in [1,2,4,8,16,32] then
+ aligntype := b
+ else
+ aligntype := 1;
+ fillsize:=0;
+ fillop:=_op;
+ use_op:=true;
+ end;
+
+
+ constructor tai_align_abstract.Create_zeros(b: byte);
+ begin
+ inherited Create;
+ typ:=ait_align;
+ if b in [1,2,4,8,16,32] then
+ aligntype := b
+ else
+ aligntype := 1;
+ use_op:=true;
+ fillsize:=0;
+ fillop:=0;
+ end;
+
+
+ function tai_align_abstract.calculatefillbuf(var buf : tfillbuffer):pchar;
+ begin
+ if fillsize>sizeof(buf) then
+ internalerror(200404293);
+ fillchar(buf,high(buf),fillop);
+ calculatefillbuf:=pchar(@buf);
+ end;
+
+
+ constructor tai_align_abstract.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ aligntype:=ppufile.getbyte;
+ fillsize:=0;
+ fillop:=ppufile.getbyte;
+ use_op:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_align_abstract.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(aligntype);
+ ppufile.putbyte(fillop);
+ ppufile.putbyte(byte(use_op));
+ end;
+
+
+{*****************************************************************************
+ TAAsmOutput
+*****************************************************************************}
+
+ constructor taasmoutput.create;
+ begin
+ inherited create;
+ { make sure the optimizer won't remove the first tai of this list}
+ insert(tai_marker.create(marker_blockstart));
+ end;
+
+
+ function taasmoutput.empty : boolean;
+ begin
+ { there is always a marker_blockstart available,
+ see taasmoutput.create }
+ result:=(count<=1);
+ end;
+
+
+ function taasmoutput.getlasttaifilepos : pfileposinfo;
+ var
+ hp : tlinkedlistitem;
+ begin
+ getlasttaifilepos := nil;
+ if assigned(last) then
+ begin
+ { find the last file information record }
+ if not (tai(last).typ in SkipLineInfo) then
+ getlasttaifilepos:=@tailineinfo(last).fileinfo
+ else
+ { go through list backwards to find the first entry
+ with line information
+ }
+ begin
+ hp:=tai(last);
+ while assigned(hp) and (tai(hp).typ in SkipLineInfo) do
+ hp:=hp.Previous;
+ { found entry }
+ if assigned(hp) then
+ getlasttaifilepos:=@tailineinfo(hp).fileinfo
+ end;
+ end;
+ end;
+
+ procedure Taasmoutput.InsertAfter(Item,Loc : TLinkedListItem);
+
+ begin
+ { This is not possible because it is not sure that the
+ tai at Loc has taifileinfo as parent }
+ {if assigned(Loc) then
+ tailineinfo(Item).fileinfo:=tailineinfo(Loc).fileinfo;}
+ inherited InsertAfter(Item,Loc);
+ end;
+
+begin
+ cai_cpu:=tai_cpu_abstract;
+ cai_align:=tai_align_abstract;
+end.
diff --git a/compiler/aggas.pas b/compiler/aggas.pas
new file mode 100644
index 0000000000..2dbd719841
--- /dev/null
+++ b/compiler/aggas.pas
@@ -0,0 +1,870 @@
+{
+ Copyright (c) 1998-2004 by the Free Pascal team
+
+ This unit implements generic GNU assembler (v2.8 or later)
+
+ 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.
+
+ ****************************************************************************
+}
+{ Base unit for writing GNU assembler output.
+}
+unit aggas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+{$IFDEF USE_SYSUTILS}
+ SysUtils,
+{$ELSE USE_SYSUTILS}
+ dos,
+{$ENDIF USE_SYSUTILS}
+ cclasses,
+ globals,
+ aasmbase,aasmtai,aasmcpu,
+ assemble;
+
+
+ type
+ {# This is a derived class which is used to write
+ GAS styled assembler.
+
+ The WriteInstruction() method must be overriden
+ to write a single instruction to the assembler
+ file.
+ }
+ TGNUAssembler=class(texternalassembler)
+ protected
+ function sectionname(atype:tasmsectiontype;const aname:string):string;virtual;
+ procedure WriteSection(atype:tasmsectiontype;const aname:string);
+ procedure WriteExtraHeader;virtual;
+ procedure WriteInstruction(hp: tai); virtual; abstract;
+ public
+ procedure WriteTree(p:TAAsmoutput);override;
+ procedure WriteAsmList;override;
+ end;
+
+
+implementation
+
+ uses
+ cutils,globtype,systems,
+ fmodule,finput,verbose,
+ itcpugas
+ ;
+
+ const
+ line_length = 70;
+
+ var
+ CurrSecType : TAsmSectionType; { last section type written }
+ lastfileinfo : tfileposinfo;
+ infile,
+ lastinfile : tinputfile;
+ symendcount : longint;
+
+ type
+{$ifdef cpuextended}
+ t80bitarray = array[0..9] of byte;
+{$endif cpuextended}
+ t64bitarray = array[0..7] of byte;
+ t32bitarray = array[0..3] of byte;
+
+{****************************************************************************}
+{ Support routines }
+{****************************************************************************}
+
+ function fixline(s:string):string;
+ {
+ return s with all leading and ending spaces and tabs removed
+ }
+ var
+ i,j,k : integer;
+ begin
+ i:=length(s);
+ while (i>0) and (s[i] in [#9,' ']) do
+ dec(i);
+ j:=1;
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ for k:=j to i do
+ if s[k] in [#0..#31,#127..#255] then
+ s[k]:='.';
+ fixline:=Copy(s,j,i-j+1);
+ end;
+
+ function single2str(d : single) : string;
+ var
+ hs : string;
+ begin
+ str(d,hs);
+ { replace space with + }
+ if hs[1]=' ' then
+ hs[1]:='+';
+ single2str:='0d'+hs
+ end;
+
+ function double2str(d : double) : string;
+ var
+ hs : string;
+ begin
+ str(d,hs);
+ { replace space with + }
+ if hs[1]=' ' then
+ hs[1]:='+';
+ double2str:='0d'+hs
+ end;
+
+ function extended2str(e : extended) : string;
+ var
+ hs : string;
+ begin
+ str(e,hs);
+ { replace space with + }
+ if hs[1]=' ' then
+ hs[1]:='+';
+ extended2str:='0d'+hs
+ end;
+
+
+ { convert floating point values }
+ { to correct endian }
+ procedure swap64bitarray(var t: t64bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[7];
+ t[7] := t[0];
+ t[0] := b;
+
+ b := t[6];
+ t[6] := t[1];
+ t[1] := b;
+
+ b:= t[5];
+ t[5] := t[2];
+ t[2] := b;
+
+ b:= t[4];
+ t[4] := t[3];
+ t[3] := b;
+ end;
+
+
+ procedure swap32bitarray(var t: t32bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[1];
+ t[1]:= t[2];
+ t[2]:= b;
+
+ b:= t[0];
+ t[0]:= t[3];
+ t[3]:= b;
+ end;
+
+
+ const
+ ait_const2str : array[ait_const_128bit..ait_const_indirect_symbol] of string[20]=(
+ #9'.fixme128'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9,#9'.byte'#9,
+ #9'.sleb128'#9,#9'.uleb128'#9,
+ #9'.rva'#9,#9'.indirect_symbol'#9
+ );
+
+{****************************************************************************}
+{ GNU Assembler writer }
+{****************************************************************************}
+
+ function TGNUAssembler.sectionname(atype:tasmsectiontype;const aname:string):string;
+ const
+ secnames : array[tasmsectiontype] of string[12] = ('',
+{$warning TODO .rodata not yet working}
+ '.text','.data','.data','.bss','.threadvar',
+ 'common',
+ '.note',
+ '__TEXT', { stubs }
+ '.stab','.stabstr',
+ '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
+ '.eh_frame',
+ '.debug_frame',
+ 'fpc.resptrs'
+ );
+ begin
+ if use_smartlink_section and
+ (aname<>'') then
+ result:=secnames[atype]+'.'+aname
+ else
+ result:=secnames[atype];
+ end;
+
+
+ procedure TGNUAssembler.WriteSection(atype:tasmsectiontype;const aname:string);
+ var
+ s : string;
+ begin
+ AsmLn;
+ case target_info.system of
+ system_i386_OS2,
+ system_i386_EMX : ;
+ system_powerpc_darwin :
+ begin
+ if atype=sec_stub then
+ AsmWrite('.section ');
+ end;
+ else
+ AsmWrite('.section ');
+ end;
+ s:=sectionname(atype,aname);
+ AsmWrite(s);
+ case atype of
+ sec_fpc :
+ AsmWrite(', "a", @progbits');
+ sec_stub :
+ begin
+ if target_info.system=system_powerpc_darwin then
+ AsmWrite(',__symbol_stub1,symbol_stubs,pure_instructions,16');
+ end;
+ end;
+ AsmLn;
+ CurrSecType:=atype;
+ end;
+
+
+ procedure TGNUAssembler.WriteTree(p:TAAsmoutput);
+
+ function needsObject(hp : tai_symbol) : boolean;
+ begin
+ needsObject :=
+ assigned(hp.next) and
+ (tai_symbol(hp.next).typ in [ait_const_rva_symbol,
+ ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit]);
+ end;
+
+ var
+ ch : char;
+ hp : tai;
+ hp1 : tailineinfo;
+ consttyp : taitype;
+ s : string;
+ i,pos,l : longint;
+ InlineLevel : longint;
+ last_align : longint;
+ co : comp;
+ sin : single;
+ d : double;
+{$ifdef cpuextended}
+ e : extended;
+{$endif cpuextended}
+ do_line : boolean;
+
+ sepChar : char;
+ begin
+ if not assigned(p) then
+ exit;
+
+ last_align := 2;
+ InlineLevel:=0;
+ { lineinfo is only needed for al_procedures (PFV) }
+ do_line:=(cs_asm_source in aktglobalswitches) or
+ ((cs_lineinfo in aktmoduleswitches)
+ and (p=asmlist[al_procedures]));
+ hp:=tai(p.first);
+ while assigned(hp) do
+ begin
+ if not(hp.typ in SkipLineInfo) then
+ begin
+ hp1 := hp as tailineinfo;
+ aktfilepos:=hp1.fileinfo;
+ { no line info for inlined code }
+ if do_line and (inlinelevel=0) then
+ begin
+ { load infile }
+ if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
+ begin
+ infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
+ if assigned(infile) then
+ begin
+ { open only if needed !! }
+ if (cs_asm_source in aktglobalswitches) then
+ infile.open;
+ end;
+ { avoid unnecessary reopens of the same file !! }
+ lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
+ { be sure to change line !! }
+ lastfileinfo.line:=-1;
+ end;
+ { write source }
+ if (cs_asm_source in aktglobalswitches) and
+ assigned(infile) then
+ begin
+ if (infile<>lastinfile) then
+ begin
+ AsmWriteLn(target_asm.comment+'['+infile.name^+']');
+ if assigned(lastinfile) then
+ lastinfile.close;
+ end;
+ if (hp1.fileinfo.line<>lastfileinfo.line) and
+ ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
+ begin
+ if (hp1.fileinfo.line<>0) and
+ ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
+ AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
+ fixline(infile.GetLineStr(hp1.fileinfo.line)));
+ { set it to a negative value !
+ to make that is has been read already !! PM }
+ if (infile.linebuf^[hp1.fileinfo.line]>=0) then
+ infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
+ end;
+ end;
+ lastfileinfo:=hp1.fileinfo;
+ lastinfile:=infile;
+ end;
+ end;
+
+ case hp.typ of
+
+ ait_comment :
+ Begin
+ AsmWrite(target_asm.comment);
+ AsmWritePChar(tai_comment(hp).str);
+ AsmLn;
+ End;
+
+ ait_regalloc :
+ begin
+ if (cs_asm_regalloc in aktglobalswitches) then
+ begin
+ AsmWrite(#9+target_asm.comment+'Register ');
+ repeat
+ AsmWrite(gas_regname(Tai_regalloc(hp).reg));
+ if (hp.next=nil) or
+ (tai(hp.next).typ<>ait_regalloc) or
+ (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmWrite(' ');
+ AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
+ end;
+ end;
+
+ ait_tempalloc :
+ begin
+ if (cs_asm_tempalloc in aktglobalswitches) then
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(tai_tempalloc(hp).problem) then
+ AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
+ tostr(tai_tempalloc(hp).tempsize)+' '+tai_tempalloc(hp).problem^)
+ else
+{$endif EXTDEBUG}
+ AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
+ tostr(tai_tempalloc(hp).tempsize)+' '+tempallocstr[tai_tempalloc(hp).allocation]);
+ end;
+ end;
+
+ ait_align :
+ begin
+ if tai_align(hp).aligntype>1 then
+ begin
+ if target_info.system <> system_powerpc_darwin then
+ begin
+ AsmWrite(#9'.balign '+tostr(tai_align(hp).aligntype));
+ if tai_align(hp).use_op then
+ AsmWrite(','+tostr(tai_align(hp).fillop))
+ end
+ else
+ begin
+ { darwin as only supports .align }
+ if not ispowerof2(tai_align(hp).aligntype,i) then
+ internalerror(2003010305);
+ AsmWrite(#9'.align '+tostr(i));
+ last_align := i;
+ end;
+ AsmLn;
+ end;
+ end;
+
+ ait_section :
+ begin
+ if tai_section(hp).sectype<>sec_none then
+ WriteSection(tai_section(hp).sectype,tai_section(hp).name^)
+ else
+ begin
+{$ifdef EXTDEBUG}
+ AsmWrite(target_asm.comment);
+ AsmWriteln(' sec_none');
+{$endif EXTDEBUG}
+ end;
+ end;
+
+ ait_datablock :
+ begin
+ if target_info.system=system_powerpc_darwin then
+ begin
+ {On Mac OS X you can't have common symbols in a shared
+ library, since those are in the TEXT section and the text section is
+ read-only in shared libraries (so it can be shared among different
+ processes). The alternate code creates some kind of common symbols in
+ the data segment. The generic code no longer uses common symbols, but
+ this doesn't work on Mac OS X as well.}
+ if tai_datablock(hp).is_global then
+ begin
+ asmwrite('.globl ');
+ asmwriteln(tai_datablock(hp).sym.name);
+ asmwriteln('.data');
+ asmwrite('.zerofill __DATA, __common, ');
+ asmwrite(tai_datablock(hp).sym.name);
+ asmwriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
+ if not(CurrSecType in [sec_data,sec_none]) then
+ writesection(CurrSecType,'');
+ end
+ else
+ begin
+ asmwrite(#9'.lcomm'#9);
+ asmwrite(tai_datablock(hp).sym.name);
+ asmwrite(','+tostr(tai_datablock(hp).size));
+ asmwrite(','+tostr(last_align));
+ asmwriteln('');
+ end
+ end
+ else
+ begin
+ if Tai_datablock(hp).is_global then
+ begin
+ asmwrite(#9'.globl ');
+ asmwriteln(Tai_datablock(hp).sym.name);
+ end;
+ asmwrite(Tai_datablock(hp).sym.name);
+ asmwriteln(':');
+ asmwriteln(#9'.space '+tostr(Tai_datablock(hp).size));
+ end;
+ end;
+
+{$ifndef cpu64bit}
+ ait_const_128bit :
+ begin
+ internalerror(200404291);
+ end;
+
+ ait_const_64bit :
+ begin
+ if assigned(tai_const(hp).sym) then
+ internalerror(200404292);
+ AsmWrite(ait_const2str[ait_const_32bit]);
+ if target_info.endian = endian_little then
+ begin
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ end
+ else
+ begin
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ end;
+ AsmLn;
+ end;
+{$endif cpu64bit}
+
+ ait_const_uleb128bit,
+ ait_const_sleb128bit,
+{$ifdef cpu64bit}
+ ait_const_128bit,
+ ait_const_64bit,
+{$endif cpu64bit}
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_const_indirect_symbol :
+ begin
+ AsmWrite(ait_const2str[hp.typ]);
+ consttyp:=hp.typ;
+ l:=0;
+ repeat
+ if assigned(tai_const(hp).sym) then
+ begin
+ if assigned(tai_const(hp).endsym) then
+ s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
+ else
+ s:=tai_const(hp).sym.name;
+ if tai_const(hp).value<>0 then
+ s:=s+tostr_with_plus(tai_const(hp).value);
+ end
+ else
+ s:=tostr(tai_const(hp).value);
+ AsmWrite(s);
+ inc(l,length(s));
+ { Values with symbols are written on a single line to improve
+ reading of the .s file (PFV) }
+ if assigned(tai_const(hp).sym) or
+ not(CurrSecType in [sec_data,sec_rodata]) or
+ (l>line_length) or
+ (hp.next=nil) or
+ (tai(hp.next).typ<>consttyp) or
+ assigned(tai_const(hp.next).sym) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmLn;
+ end;
+
+{$ifdef cpuextended}
+ ait_real_80bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
+ { Make sure e is a extended type, bestreal could be
+ a different type (bestreal) !! (PFV) }
+ e:=tai_real_80bit(hp).value;
+ AsmWrite(#9'.byte'#9);
+ for i:=0 to 9 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t80bitarray(e)[i]));
+ end;
+ AsmLn;
+ end;
+{$endif cpuextended}
+
+ ait_real_64bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
+ d:=tai_real_64bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap64bitarray(t64bitarray(d));
+ AsmWrite(#9'.byte'#9);
+{$ifdef arm}
+{ on a real arm cpu, it's already hi/lo swapped }
+{$ifndef cpuarm}
+ if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
+ begin
+ for i:=4 to 7 do
+ begin
+ if i<>4 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ for i:=0 to 3 do
+ begin
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ end
+ else
+{$endif cpuarm}
+{$endif arm}
+ begin
+ for i:=0 to 7 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ end;
+ AsmLn;
+ end;
+
+ ait_real_32bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
+ sin:=tai_real_32bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap32bitarray(t32bitarray(sin));
+ AsmWrite(#9'.byte'#9);
+ for i:=0 to 3 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t32bitarray(sin)[i]));
+ end;
+ AsmLn;
+ end;
+
+ ait_comp_64bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
+ AsmWrite(#9'.byte'#9);
+{$ifdef FPC}
+ co:=comp(tai_comp_64bit(hp).value);
+{$else}
+ co:=tai_comp_64bit(hp).value;
+{$endif}
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap64bitarray(t64bitarray(co));
+ for i:=0 to 7 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(co)[i]));
+ end;
+ AsmLn;
+ end;
+
+ ait_string :
+ begin
+ pos:=0;
+ for i:=1 to tai_string(hp).len do
+ begin
+ if pos=0 then
+ begin
+ AsmWrite(#9'.ascii'#9'"');
+ pos:=20;
+ end;
+ ch:=tai_string(hp).str[i-1];
+ case ch of
+ #0, {This can't be done by range, because a bug in FPC}
+ #1..#31,
+ #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
+ '"' : s:='\"';
+ '\' : s:='\\';
+ else
+ s:=ch;
+ end;
+ AsmWrite(s);
+ inc(pos,length(s));
+ if (pos>line_length) or (i=tai_string(hp).len) then
+ begin
+ AsmWriteLn('"');
+ pos:=0;
+ end;
+ end;
+ end;
+
+ ait_label :
+ begin
+ if (tai_label(hp).l.is_used) then
+ begin
+ if tai_label(hp).l.defbind=AB_GLOBAL then
+ begin
+ AsmWrite('.globl'#9);
+ AsmWriteLn(tai_label(hp).l.name);
+ end;
+ AsmWrite(tai_label(hp).l.name);
+ AsmWriteLn(':');
+ end;
+ end;
+ ait_symbol :
+ begin
+ if tai_symbol(hp).is_global then
+ begin
+ AsmWrite('.globl'#9);
+ AsmWriteLn(tai_symbol(hp).sym.name);
+ end;
+ if (target_info.system = system_powerpc64_linux) and
+ (tai_symbol(hp).sym.typ = AT_FUNCTION) then
+ begin
+ AsmWriteLn('.section "opd", "aw"');
+ AsmWriteLn('.align 3');
+ AsmWriteLn(tai_symbol(hp).sym.name + ':');
+ AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
+ AsmWriteLn('.previous');
+ AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
+ AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
+ AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
+ { the dotted name is the name of the actual function }
+ AsmWrite('.');
+ end
+ else
+ begin
+ if (target_info.system <> system_arm_linux) then
+ begin
+ sepChar := '@';
+ end
+ else
+ begin
+ sepChar := '#';
+ end;
+
+ if (tf_needs_symbol_type in target_info.flags) then
+ begin
+ AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
+ if (needsObject(tai_symbol(hp))) then
+ begin
+ AsmWriteLn(',' + sepChar + 'object');
+ end
+ else
+ begin
+ AsmWriteLn(',' + sepChar + 'function');
+ end;
+ end;
+ if (tf_needs_symbol_size in target_info.flags) and (tai_symbol(hp).sym.size > 0) then begin
+ AsmWriteLn(#9'.size'#9 + tai_symbol(hp).sym.name + ', ' + tostr(tai_symbol(hp).sym.size));
+ end;
+ end;
+ AsmWriteLn(tai_symbol(hp).sym.name + ':');
+ end;
+
+ ait_symbol_end :
+ begin
+ if tf_needs_symbol_size in target_info.flags then
+ begin
+ s:=target_asm.labelprefix+'e'+tostr(symendcount);
+ inc(symendcount);
+ AsmWriteLn(s+':');
+ AsmWrite(#9'.size'#9);
+ if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
+ begin
+ AsmWrite('.');
+ end;
+ AsmWrite(tai_symbol_end(hp).sym.name);
+ AsmWrite(', '+s+' - ');
+ if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
+ begin
+ AsmWrite('.');
+ end;
+ AsmWriteLn(tai_symbol_end(hp).sym.name);
+ end;
+ end;
+
+ ait_instruction :
+ begin
+ WriteInstruction(hp);
+ end;
+
+ ait_stab :
+ begin
+ if assigned(tai_stab(hp).str) then
+ begin
+ AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
+ AsmWritePChar(tai_stab(hp).str);
+ AsmLn;
+ end;
+ end;
+
+ ait_force_line,
+ ait_function_name : ;
+
+ ait_cutobject :
+ begin
+ if SmartAsm then
+ begin
+ { only reset buffer if nothing has changed }
+ if AsmSize=AsmStartSize then
+ AsmClear
+ else
+ begin
+ AsmClose;
+ DoAssemble;
+ AsmCreate(tai_cutobject(hp).place);
+ end;
+ { avoid empty files }
+ while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
+ begin
+ if tai(hp.next).typ=ait_section then
+ CurrSecType:=tai_section(hp.next).sectype;
+ hp:=tai(hp.next);
+ end;
+ if CurrSecType<>sec_none then
+ WriteSection(CurrSecType,'');
+ AsmStartSize:=AsmSize;
+ end;
+ end;
+
+ ait_marker :
+ if tai_marker(hp).kind=InlineStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=InlineEnd then
+ dec(InlineLevel);
+
+ ait_directive :
+ begin
+ AsmWrite('.'+directivestr[tai_directive(hp).directive]+' ');
+ if assigned(tai_directive(hp).name) then
+ AsmWrite(tai_directive(hp).name^);
+ AsmLn;
+ end;
+
+ else
+ internalerror(10000);
+ end;
+ hp:=tai(hp.next);
+ end;
+ end;
+
+
+ procedure TGNUAssembler.WriteExtraHeader;
+
+ begin
+ end;
+
+ procedure TGNUAssembler.WriteAsmList;
+ var
+ p:dirstr;
+ n:namestr;
+ e:extstr;
+ hal : tasmlist;
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource^);
+{$endif}
+
+ CurrSecType:=sec_none;
+ FillChar(lastfileinfo,sizeof(lastfileinfo),0);
+ LastInfile:=nil;
+
+ if assigned(current_module.mainsource) then
+{$IFDEF USE_SYSUTILS}
+ begin
+ p := SplitPath(current_module.mainsource^);
+ n := SplitName(current_module.mainsource^);
+ e := SplitExtension(current_module.mainsource^);
+ end
+{$ELSE USE_SYSUTILS}
+ fsplit(current_module.mainsource^,p,n,e)
+{$ENDIF USE_SYSUTILS}
+ else
+ begin
+ p:=inputdir;
+ n:=inputfile;
+ e:=inputextension;
+ end;
+ { to get symify to work }
+ AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
+ WriteExtraHeader;
+ AsmStartSize:=AsmSize;
+ symendcount:=0;
+
+ for hal:=low(Tasmlist) to high(Tasmlist) do
+ begin
+ AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
+ writetree(asmlist[hal]);
+ AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
+ end;
+
+ AsmLn;
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
+{$endif EXTDEBUG}
+ end;
+
+end.
diff --git a/compiler/alpha/aasmcpu.pas b/compiler/alpha/aasmcpu.pas
new file mode 100644
index 0000000000..10f02190f9
--- /dev/null
+++ b/compiler/alpha/aasmcpu.pas
@@ -0,0 +1,281 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ Implements the assembler classes specific for the Alpha
+
+ 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.
+
+ ****************************************************************************
+}
+{
+ Implements the assembler classes specific for the Alpha.
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,globals,verbose,
+ cpubase,aasmtai;
+
+ type
+ tai_frame = class(tai)
+ G,R : TRegister;
+ LS,LU : longint;
+ Constructor Create (GP : Tregister; Localsize : Longint; RA : TRegister; L : longint);
+ end;
+
+ tai_ent = class(tai)
+ Name : string;
+ Constructor Create (const ProcName : String);
+ end;
+
+
+ taicpu = class(taicpu_abstract)
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : longint);
+ constructor op_ref(op : tasmop;_op1 : preference);
+
+ constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_op1 : tregister;_op2 : preference);
+ constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
+
+ constructor op_const_reg(op : tasmop;_op1 : longint;_op2 : tregister);
+ constructor op_const_const(op : tasmop;_op1,_op2 : longint);
+ constructor op_const_ref(op : tasmop;_op1 : longint;_op2 : preference);
+
+ constructor op_ref_reg(op : tasmop;_op1 : preference;_op2 : tregister);
+ { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
+ constructor op_ref_ref(op : tasmop;_op1,_op2 : preference);
+
+ constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ constructor op_reg_const_reg(op : tasmop;_op1 : tregister;_op2 : longint;_op3 : tregister);
+ constructor op_const_ref_reg(op : tasmop;_op1 : longint;_op2 : preference;_op3 : tregister);
+ constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; _op3 : preference);
+ constructor op_const_reg_ref(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : preference);
+ constructor op_reg_ref_const(op : tasmop;_op1 : tregister;_op2 : preference;_op3 : longint);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ constructor op_sym_ofs_reg(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+ constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+implementation
+
+
+{*****************************************************************************
+ 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;
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_op1 : longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;_op1 : preference);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;_op2 : preference);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_const_reg(op : tasmop;_op1 : longint;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_const_const(op : tasmop;_op1,_op2 : longint);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_const_ref(op : tasmop;_op1 : longint;_op2 : preference);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+ constructor taicpu.op_ref_reg(op : tasmop;_op1 : preference;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_ref_ref(op : tasmop;_op1,_op2 : preference);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_reg_const_reg(op : tasmop;_op1 : tregister;_op2 : longint;_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister;_op3 : preference);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_const_ref_reg(op : tasmop;_op1 : longint;_op2 : preference;_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_const_reg_ref(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : preference);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_reg_ref_const(op : tasmop;_op1 : tregister;_op2 : preference;_op3 : longint);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ condition:=cond;
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_sym_ofs_reg(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+ Constructor tai_frame.create (GP : Tregister; Localsize : Longint; RA : TRegister; L : longint);
+
+ begin
+ Inherited Create;
+ typ:=ait_frame;
+ G:=GP;
+ R:=RA;
+ LS:=LocalSize;
+ LU:=L;
+ end;
+
+ Constructor tai_ent.Create (const ProcName : String);
+
+ begin
+ Inherited Create;
+ typ:=ait_ent;
+ Name:=ProcName;
+ end;
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+
+ end.
diff --git a/compiler/alpha/agaxpgas.pas b/compiler/alpha/agaxpgas.pas
new file mode 100644
index 0000000000..9757226278
--- /dev/null
+++ b/compiler/alpha/agaxpgas.pas
@@ -0,0 +1,126 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ This unit implements an asm for the DEC Alpha
+
+ 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 agaxpgas;
+
+ {$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globals,systems,aasmbase,aasmtai,
+ aggas,cpubase;
+
+ type
+ TAXPGNUAssembler=class(TGNUAssembler)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+ const
+ gas_reg2str : array[tregister] of string[4] = (
+ '',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '',''
+ );
+
+ implementation
+
+ const
+ op2str : array[tasmop] of string[14] = (
+ 'addf','addg','addl','addq',
+ 'adds','addt','amask','and','beq','bge',
+ 'bgt','bic','bis','blbc','blbs','ble',
+ 'blt','bne','br','bsr','call_pal','cmoveq',
+ 'cmovge','cmovgt','cmovlbc','cmovlbs','cmovle','cmovlt',
+ 'cmovne','cmpbge','cmpeq','cmpgeq','cmpgle','cmpglt',
+ 'cmple','cmplt','cmpteq','cmptle','cmptlt','cmptun',
+ 'cmpule','cmpult','cpys','cpyse','cpysn','ctlz',
+ 'ctpop','cttz','cvtdg','cvtgd','cvtgf','cvtgq',
+ 'cvtlq','cvtqf','cvtqg','cvtql','cvtqs','cvtqt',
+ 'cvtst','cvttq','cvtts','divf','divg','divs',
+ 'divt','ecb','eqv','excb','extbl','extlh',
+ 'extll','extqh','extql','extwh','extwl','fbeq',
+ 'fbge','fbgt','fble','fblt','fbne','fcmoveq',
+ 'fcmovge','fcmovgt','fcmovle','fcmovlt','fcmovne','fetch',
+ 'fetch_m','ftois','ftoit','implver','insbl','inslh',
+ 'insll','insqh','insql','inswh','inswl','itoff',
+ 'itofs','itoft','jmp','jsr','jsr_coroutine','lda',
+ 'ldah','ldbu','ldwu','ldf','ldg','ldl',
+ 'ldl_l','ldq','ldq_l','ldq_u','lds','ldt',
+ 'maxsb8','maxsw4','maxub8','maxuw4','mb','mf_fpcr',
+ 'minsb8','minsw4','minub8','minuw4','mskbl','msklh',
+ 'mskll','mskqh','mskql','mskwh','mskwl','mt_fpcr',
+ 'mulf','mulg','mull','mulq',
+ 'muls','mult','ornot','perr','pklb','pkwb',
+ 'rc','ret','rpcc','rs','s4addl','s4addq',
+ 's4subl','s4subq','s8addl','s8addq','s8subl','s8subq',
+ 'sextb','sextw','sll','sqrtf','sqrtg','sqrts',
+ 'sqrtt','sra','srl','stb','stf','stg',
+ 'sts','stl','stl_c','stq','stq_c','stq_u',
+ 'stt','stw','subf','subg','subl',
+ 'subq','subs','subt','trapb','umulh','unpkbl',
+ 'unpkbw','wh64','wmb','xor','zap','zapnot',
+ 'ldgp');
+
+ procedure TAXPGNUAssembler.WriteInstruction (hp : tai);
+ begin
+(*
+ op:=paicpu(hp)^.opcode;
+ calljmp:=is_calljmp(op);
+ { call maybe not translated to calll }
+ s:=#9+att_op2str[op]+cond2str[paicpu(hp)^.condition];
+ if (not calljmp) and
+ (not att_nosuffix[op]) and
+ not(
+ (paicpu(hp)^.oper[0].typ=top_reg) and
+ (paicpu(hp)^.oper[0].reg in [R_ST..R_ST7])
+ ) then
+ s:=s+att_opsize2str[paicpu(hp)^.opsize];
+ { process operands }
+ if paicpu(hp)^.ops<>0 then
+ begin
+ { call and jmp need an extra handling }
+ { this code is only called if jmp isn't a labeled instruction }
+ if calljmp then
+ s:=s+#9+getopstr_jmp(paicpu(hp)^.oper[0])
+ else
+ begin
+ for i:=0to paicpu(hp)^.ops-1 do
+ begin
+ if i=0 then
+ sep:=#9
+ else
+ sep:=',';
+ s:=s+sep+getopstr(paicpu(hp)^.oper[i])
+ end;
+ end;
+ end;
+ AsmWriteLn(s);
+*)
+ end;
+
+end.
diff --git a/compiler/alpha/aoptcpu.pas b/compiler/alpha/aoptcpu.pas
new file mode 100644
index 0000000000..494edf948c
--- /dev/null
+++ b/compiler/alpha/aoptcpu.pas
@@ -0,0 +1,38 @@
+{
+ Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the Alpha optimizer object
+
+ 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;
+
+Interface
+
+uses cpubase, aoptobj, aoptcpub;
+
+Type
+ TAOptCpu = Object(TAoptObj)
+ { uses the same constructor as TAopObj }
+ End;
+
+Implementation
+
+End.
diff --git a/compiler/alpha/aoptcpub.pas b/compiler/alpha/aoptcpub.pas
new file mode 100644
index 0000000000..aaad2910c3
--- /dev/null
+++ b/compiler/alpha/aoptcpub.pas
@@ -0,0 +1,115 @@
+ {
+ Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the 80x86 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 }
+
+{ 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
+ CPUAsm,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 = Object(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;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/compiler/alpha/aoptcpuc.pas b/compiler/alpha/aoptcpuc.pas
new file mode 100644
index 0000000000..121a45370f
--- /dev/null
+++ b/compiler/alpha/aoptcpuc.pas
@@ -0,0 +1,38 @@
+ {
+ Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ 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 aoptcpuc;
+
+Interface
+
+Uses
+ AOptCs;
+
+Type
+ TRegInfoCpu = Object(TRegInfo)
+ End;
+
+
+Implementation
+
+End.
diff --git a/compiler/alpha/aoptcpud.pas b/compiler/alpha/aoptcpud.pas
new file mode 100644
index 0000000000..c3ea9fe5f9
--- /dev/null
+++ b/compiler/alpha/aoptcpud.pas
@@ -0,0 +1,39 @@
+{
+ Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ 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;
+
+Interface
+
+uses
+ AOptDA;
+
+Type
+ PAOptDFACpu = ^TAOptDFACpu;
+ TAOptDFACpu = Object(TAOptDFA)
+ End;
+
+Implementation
+
+
+End.
diff --git a/compiler/alpha/cgcpu.pas b/compiler/alpha/cgcpu.pas
new file mode 100644
index 0000000000..07f3a9d92f
--- /dev/null
+++ b/compiler/alpha/cgcpu.pas
@@ -0,0 +1,160 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ This unit implements the code generator for the Alpha
+
+ 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 Alpha.
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cgbase,cgobj,aasmbase,aasmtai,aasmcpu,cginfo,cpubase,cpuinfo;
+
+type
+pcgalpha = ^tcgalpha;
+tcgalpha = class(tcg)
+ procedure a_call_name(list : taasmoutput;const s : string);override;
+ procedure a_load_const_reg(list : taasmoutput;size : tcgsize;a : aword;register : tregister);override;
+ procedure a_load_reg_ref(list : taasmoutput;size : tcgsize;register : tregister;const ref : treference);override;
+ procedure a_load_ref_reg(list : taasmoutput;size : tcgsize;const ref : treference;register : tregister);override;
+ procedure a_load_reg_reg(list : taasmoutput;fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+ procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;
+ reg : tregister; l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+ procedure a_cmp_reg_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg : tregister;l : tasmlabel);
+ procedure a_cmp_ref_const_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;
+ reg : tregister; l : tasmlabel);
+ procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
+ procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
+ procedure g_maybe_loadself(list : taasmoutput);override;
+ procedure g_restore_frame_pointer(list : taasmoutput);override;
+end;
+
+implementation
+
+uses
+ globtype,globals;
+
+procedure tcgalpha.g_stackframe_entry(list : taasmoutput;localsize : longint);
+
+begin
+ list.concat(taicpu.op_reg_ref(A_LDGP,Global_pointer,new_reference(R_27,0)));
+ list.concat(taicpu.op_reg_ref(A_LDA,stack_pointer_reg,new_reference(stack_pointer_reg,-LocalSize)));
+ If LocalSize<>0 then
+ list.concat(tai_frame.create(Global_pointer,LocalSize,R_27,0));
+ { Always generate a frame pointer. }
+ list.concat(taicpu.op_reg_reg_reg(A_BIS,stack_pointer_reg,stack_pointer_reg,frame_pointer_reg));
+end;
+
+procedure g_exitcode(list : taasmoutput;parasize : longint; nostackframe,inlined : boolean);
+
+begin
+ { Restore stack pointer from frame pointer }
+ list.Concat (taicpu.op_reg_reg_reg(A_BIS,frame_pointer_reg,frame_pointer_reg,stack_pointer_reg));
+ { Restore previous stack position}
+ list.Concat (taicpu.op_reg_const_reg(A_ADDQ,stack_pointer_reg,Parasize,stack_pointer_reg));
+ { return... }
+ list.Concat(taicpu.op_reg_ref_const(A_RET,stack_pointer_reg,new_reference(Return_pointer,0),1));
+ { end directive
+ Concat (paiend,init(''));
+ }
+end;
+
+procedure tcgalpha.a_call_name(list : taasmoutput;const s : string);
+
+ begin
+ { list^.concat(taicpu,op_sym(A_CALL,S_NO,newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)))); }
+ {!!!!!!!!!1 offset is ignored }
+ abstract;
+ end;
+
+procedure tcgalpha.a_load_const_reg(list : taasmoutput;size : tcgsize;a : aword;register : tregister);
+
+begin
+end;
+
+
+procedure tcgalpha.a_load_reg_ref(list : taasmoutput;size : tcgsize;register : tregister;const ref : treference);
+
+begin
+end;
+
+
+procedure tcgalpha.a_load_ref_reg(list : taasmoutput;size : tcgsize;const ref : treference;register : tregister);
+
+begin
+end;
+
+
+procedure tcgalpha.a_load_reg_reg(list : taasmoutput;fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+
+begin
+end;
+
+
+procedure tcgalpha.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
+ l : tasmlabel);
+
+begin
+end;
+
+
+procedure tcgalpha.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+
+begin
+end;
+
+
+procedure tcgalpha.a_cmp_reg_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg : tregister;l : tasmlabel);
+
+begin
+end;
+
+
+procedure tcgalpha.a_cmp_ref_const_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;
+ reg : tregister; l : tasmlabel);
+
+begin
+end;
+
+
+procedure tcgalpha.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
+
+begin
+end;
+
+
+procedure tcgalpha.g_maybe_loadself(list : taasmoutput);
+
+begin
+end;
+
+
+procedure tcgalpha.g_restore_frame_pointer(list : taasmoutput);
+
+begin
+end;
+
+
+end.
diff --git a/compiler/alpha/cpubase.pas b/compiler/alpha/cpubase.pas
new file mode 100644
index 0000000000..e4ccede6f6
--- /dev/null
+++ b/compiler/alpha/cpubase.pas
@@ -0,0 +1,457 @@
+{
+ Copyright (C) 1998-2000 by Florian Klaempfl
+
+ This unit implements an asmlistitem class for the Alpha 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.
+
+ ****************************************************************************
+}
+{
+ This unit implements an asmlistitem class for the Alpha architecture.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,cclasses,globals,aasmbase,cpuinfo,cginfo;
+
+ type
+ { all registers }
+ TRegister = (R_NO, { R_NO is Mandatory, signifies no register }
+ R_0,R_1,R_2,R_3,R_4,R_5,R_6,R_7,R_8,R_9,
+ R_10,R_11,R_12,R_13,R_14,R_15,R_16,R_17,R_18,R_19,
+ R_20,R_21,R_22,R_23,R_24,R_25,R_26,R_27,R_28,R_29,
+ R_30,R_31,
+ R_F0,R_F1,R_F2,R_F3,R_F4,R_F5,R_F6,R_F7,R_F8,R_F9,
+ R_F10,R_F11,R_F12,R_F13,R_F14,R_F15,R_F16,R_F17,R_F18,R_F19,
+ R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,
+ R_F30,R_F31);
+
+ tasmop = (A_ADDF,A_ADDG,A_ADDL,A_ADDQ,
+ A_ADDS,A_ADDT,A_AMASK,A_AND,A_BEQ,A_BGE,
+ A_BGT,A_BIC,A_BIS,A_BLBC,A_BLBS,A_BLE,
+ A_BLT,A_BNE,A_BR,A_BSR,A_CALL_PAL,A_CMOVEQ,
+ A_CMOVGE,A_CMOVGT,A_CMOVLBC,A_CMOVLBS,A_CMOVLE,A_CMOVLT,
+ A_CMOVNE,A_CMPBGE,A_CMPEQ,A_CMPGEQ,A_CMPGLE,A_CMPGLT,
+ A_CMPLE,A_CMPLT,A_CMPTEQ,A_CMPTLE,A_CMPTLT,A_CMPTUN,
+ A_CMPULE,A_CMPULT,A_CPYS,A_CPYSE,A_CPYSN,A_CTLZ,
+ A_CTPOP,A_CTTZ,A_CVTDG,A_CVTGD,A_CVTGF,A_CVTGQ,
+ A_CVTLQ,A_CVTQF,A_CVTQG,A_CVTQL,A_CVTQS,A_CVTQT,
+ A_CVTST,A_CVTTQ,A_CVTTS,A_DIVF,A_DIVG,A_DIVS,
+ A_DIVT,A_ECB,A_EQV,A_EXCB,A_EXTBL,A_EXTLH,
+ A_EXTLL,A_EXTQH,A_EXTQL,A_EXTWH,A_EXTWL,A_FBEQ,
+ A_FBGE,A_FBGT,A_FBLE,A_FBLT,A_FBNE,A_FCMOVEQ,
+ A_FCMOVGE,A_FCMOVGT,A_FCMOVLE,A_FCMOVLT,A_FCMOVNE,A_FETCH,
+ A_FETCH_M,A_FTOIS,A_FTOIT,A_IMPLVER,A_INSBL,A_INSLH,
+ A_INSLL,A_INSQH,A_INSQL,A_INSWH,A_INSWL,A_ITOFF,
+ A_ITOFS,A_ITOFT,A_JMP,A_JSR,A_JSR_COROUTINE,A_LDA,
+ A_LDAH,A_LDBU,A_LDWU,A_LDF,A_LDG,A_LDL,
+ A_LDL_L,A_LDQ,A_LDQ_L,A_LDQ_U,A_LDS,A_LDT,
+ A_MAXSB8,A_MAXSW4,A_MAXUB8,A_MAXUW4,A_MB,A_MF_FPCR,
+ A_MINSB8,A_MINSW4,A_MINUB8,A_MINUW4,A_MSKBL,A_MSKLH,
+ A_MSKLL,A_MSKQH,A_MSKQL,A_MSKWH,A_MSKWL,A_MT_FPCR,
+ A_MULF,A_MULG,A_MULL,A_MULQ,
+ A_MULS,A_MULT,A_ORNOT,A_PERR,A_PKLB,A_PKWB,
+ A_RC,A_RET,A_RPCC,A_RS,A_S4ADDL,A_S4ADDQ,
+ A_S4SUBL,A_S4SUBQ,A_S8ADDL,A_S8ADDQ,A_S8SUBL,A_S8SUBQ,
+ A_SEXTB,A_SEXTW,A_SLL,A_SQRTF,A_SQRTG,A_SQRTS,
+ A_SQRTT,A_SRA,A_SRL,A_STB,A_STF,A_STG,
+ A_STS,A_STL,A_STL_C,A_STQ,A_STQ_C,A_STQ_U,
+ A_STT,A_STW,A_SUBF,A_SUBG,A_SUBL,
+ A_SUBQ,A_SUBS,A_SUBT,A_TRAPB,A_UMULH,
+ A_UNPKBL,A_UNPKBW,A_WH64,A_WMB,A_XOR,A_ZAP,
+ A_ZAPNOT
+ { Psuedo code understood by the gnu assembler }
+ ,A_LDGP);
+
+ const
+ firstop = low(tasmop);
+ lastop = high(tasmop);
+
+ std_reg2str : array[tregister] of string[4] = (
+ '',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '',''
+ );
+
+
+ type
+ TAsmCond =
+ (
+ C_None,C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
+ C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,C_NS,C_NZ,C_O,C_P,
+ C_PE,C_PO,C_S,C_Z
+ );
+
+ TRegisterset = Set of TRegister;
+
+ tregister64 = tregister;
+
+ Const
+ Firstreg = R_0;
+ LastReg = R_F31;
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_64;
+ { the natural int size for a processor, }
+ OS_INT = OS_64;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F80;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M64;
+
+ stack_pointer_reg = R_30;
+ frame_pointer_reg = R_15;
+ self_pointer_reg = R_16;
+ accumulator = R_0;
+ {the return_result_reg, is used inside the called function to store its return
+ value when that is a scalar value otherwise a pointer to the address of the
+ result is placed inside it}
+ return_result_reg = accumulator;
+
+ {the function_result_reg contains the function result after a call to a scalar
+ function othewise it contains a pointer to the returned result}
+ function_result_reg = accumulator;
+ fpu_result_reg = R_F0;
+ global_pointer = R_29;
+ return_pointer = R_26;
+ { it is used to pass the offset to the destructor helper routine }
+ vmt_offset_reg = R_1;
+
+ { low and high of the available maximum width integer general purpose }
+ { registers }
+ LoGPReg = R_0;
+ HiGPReg = R_31;
+
+ { low and high of every possible width general purpose register (same as
+ above on most architctures apart from the 80x86) }
+ LoReg = R_0;
+ HiReg = R_31;
+
+ { Constant defining possibly all registers which might require saving }
+ ALL_REGISTERS = [firstreg..lastreg];
+
+ general_registers = [R_0..R_31];
+
+ availabletempregsint = [R_0..R_14,R_16..R_25,R_28];
+ availabletempregsfpu = [R_F0..R_F30];
+ availabletempregsmm = [];
+
+ intregs = [R_0..R_31];
+ usableregsint = [];
+ c_countusableregsint = 26;
+
+ maxfpuregs = 32;
+ fpuregs = [R_F0..R_F31];
+ usableregsfpu = [];
+ c_countusableregsfpu = 31;
+
+ mmregs = [];
+ usableregsmm = [];
+ c_countusableregsmm = 0;
+
+ max_operands = 4;
+
+ registers_saved_on_cdecl = [R_9..R_14,R_F2..R_F9];
+
+ firstsaveintreg = R_NO;
+ lastsaveintreg = R_NO;
+ firstsavefpureg = R_NO;
+ lastsavefpureg = R_NO;
+ firstsavemmreg = R_NO;
+ lastsavemmreg = R_NO;
+ maxvarregs = 6;
+
+ varregs : Array [1..maxvarregs] of Tregister =
+ (R_9,R_10,R_11,R_12,R_13,R_14);
+
+ maxfpuvarregs = 8;
+
+ { Registers which are defined as scratch and no need to save across
+ routine calls or in assembler blocks.
+ }
+ max_scratch_regs = 2;
+ scratch_regs : array[1..max_scratch_regs] of tregister = (R_1,R_2);
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ { Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+ }
+ stab_regindex : array[tregister] of shortint =
+ (0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+ type
+ { The Alpha doesn't have flags but some generic code depends on this type. }
+ TResFlags = (F_NO);
+
+
+ { reference record }
+ pparareference = ^tparareference;
+ tparareference = packed record
+ index : tregister;
+ offset : longint;
+ end;
+
+ trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
+
+ TReference = record
+ offset : aword;
+ symbol : tasmsymbol;
+ base : tregister;
+ { The index isn't used by the alpha port, but some generic code depends on it }
+ index : tregister;
+ is_immediate : boolean;
+ offsetfixup : word; {needed for inline}
+ options : trefoptions;
+ { the boundary to which the reference is surely aligned }
+ alignment : byte;
+ end;
+ PReference = ^TReference;
+
+ TLoc=(
+ LOC_INVALID, { added for tracking problems}
+ LOC_CONSTANT, { constant value }
+ LOC_JUMP, { boolean results only, jump to false or true label }
+ LOC_FLAGS, { boolean results only, flags are set }
+ LOC_CREFERENCE, { in memory constant value reference (cannot change) }
+ LOC_REFERENCE, { in memory value }
+ LOC_REGISTER, { in a processor register }
+ LOC_CREGISTER, { Constant register which shouldn't be modified }
+ LOC_FPUREGISTER, { FPU stack }
+ LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
+ LOC_SSEREGISTER,
+ LOC_CSSEREGISTER,
+ LOC_CMMREGISTER,
+ LOC_MMREGISTER
+ );
+
+ { tparamlocation describes where a parameter for a procedure is stored.
+ References are given from the caller's point of view. The usual
+ TLocation isn't used, because contains a lot of unnessary fields.
+ }
+ tparalocation = packed record
+ size : TCGSize;
+ loc : TLoc;
+ sp_fixup : longint;
+ case TLoc of
+ LOC_REFERENCE : (reference : tparareference);
+ { segment in reference at the same place as in loc_register }
+ LOC_REGISTER,LOC_CREGISTER : (
+ case longint of
+ 1 : (register,register64.reghi : tregister);
+ { overlay a register64.reglo }
+ 2 : (register64.reglo : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ );
+ end;
+
+ tlocation = packed record
+ loc : TLoc;
+ size : TCGSize;
+ case TLoc of
+ LOC_CONSTANT : (
+ case longint of
+ 1 : (value : AWord);
+ { can't do this, this layout depends on the host cpu. Use }
+ { lo(valueqword)/hi(valueqword) instead (JM) }
+ { 2 : (valuelow, valuehigh:AWord); }
+ { overlay a complete 64 Bit value }
+ 3 : (valueqword : qword);
+ );
+ LOC_CREFERENCE,
+ LOC_REFERENCE : (reference : treference);
+ { segment in reference at the same place as in loc_register }
+ LOC_REGISTER,LOC_CREGISTER : (
+ case longint of
+ 1 : (register,register64.reghi,segment : tregister);
+ { overlay a register64.reglo }
+ 2 : (register64.reglo : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ );
+ end;
+
+{*****************************************************************************
+ Operands
+*****************************************************************************}
+
+
+ { Types of operand }
+ toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
+
+ toper=record
+ ot : longint;
+ case typ : toptype of
+ top_none : ();
+ top_reg : (reg:tregister);
+ top_ref : (ref:preference);
+ top_const : (val:longint);
+ top_symbol : (sym:tasmsymbol;symofs:longint);
+ end;
+
+ const
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ std_saved_registers = [];
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 8;
+
+ { offsets for the integer and floating point registers }
+ INT_REG = 0;
+ FLOAT_REG = 32;
+
+ { operator qualifiers }
+ OQ_CHOPPED_ROUNDING = $01; { /C }
+ OQ_ROUNDING_MODE_DYNAMIC = $02; { /D }
+ OQ_ROUND_TOWARD_MINUS_INFINITY = $04; { /M }
+ OQ_INEXACT_RESULT_ENABLE = $08; { /I }
+ OQ_SOFTWARE_COMPLETION_ENABLE = $10; { /S }
+ OQ_FLOATING_UNDERFLOW_ENABLE = $20; { /U }
+ OQ_INTEGER_OVERFLOW_ENABLE = $40; { /V }
+
+
+{*****************************************************************************
+ Opcode propeties (needed for optimizer)
+*****************************************************************************}
+
+{$ifndef NOOPT}
+Type
+{What an instruction can change}
+ TInsChange = (Ch_None);
+{$endif}
+
+
+{ resets all values of ref to defaults }
+procedure reset_reference(var ref : treference);
+{ set mostly used values of a new reference }
+function new_reference(base : tregister;offset : longint) : preference;
+function newreference(const r : treference) : preference;
+procedure disposereference(var r : preference);
+
+function reg2str(r : tregister) : string;
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure InitCpu;
+ procedure DoneCpu;
+
+implementation
+
+uses
+ verbose;
+
+function reg2str(r : tregister) : string;
+
+ begin
+ if r in [R_0..R_31] then
+ reg2str:='R'+tostr(longint(r)-longint(R_0))
+ else if r in [R_F0..R_F31] then
+ reg2str:='F'+tostr(longint(r)-longint(R_F0))
+ else internalerror(38991);
+ end;
+
+procedure reset_reference(var ref : treference);
+begin
+ FillChar(ref,sizeof(treference),0);
+end;
+
+
+function new_reference(base : tregister;offset : longint) : preference;
+var
+ r : preference;
+begin
+ new(r);
+ FillChar(r^,sizeof(treference),0);
+ r^.offset:=offset;
+ r^.alignment:=8;
+ new_reference:=r;
+end;
+
+function newreference(const r : treference) : preference;
+
+var
+ p : preference;
+begin
+ new(p);
+ p^:=r;
+ newreference:=p;
+end;
+
+procedure disposereference(var r : preference);
+
+begin
+ dispose(r);
+ r:=Nil;
+end;
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure InitCpu;
+ begin
+ end;
+
+ procedure DoneCpu;
+ begin
+ end;
+
+end.
diff --git a/compiler/alpha/cpuinfo.pas b/compiler/alpha/cpuinfo.pas
new file mode 100644
index 0000000000..cd02692320
--- /dev/null
+++ b/compiler/alpha/cpuinfo.pas
@@ -0,0 +1,68 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1998-2000 by the Free Pascal development team
+
+ Basic Processor information about the Alpha
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+{
+ Basic Processor information about the Alpha
+}
+Unit CPUInfo;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Type
+ { Natural integer register type and size for the target machine }
+{$ifdef FPC}
+ AWord = Qword;
+{$else FPC}
+ AWord = Longint;
+{$endif FPC}
+ PAWord = ^AWord;
+
+ { This must be an ordinal type with the same size as a pointer
+ Note: Must be unsigned! Otherwise, ugly code like
+ pointer(-1) will result in a pointer with the value
+ $fffffffffffffff on a 32bit machine if the compiler uses
+ int64 constants internally (JM) }
+ TConstPtrUInt = qword;
+
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts64comp = extended;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors =
+ (no_processor,
+ ClassEV7,
+ ClassEV8
+ );
+
+Const
+ { Size of native extended type }
+ extended_size = 16;
+ {# Size of a pointer }
+ sizeof(aint) = 8;
+ {# Size of a multimedia register }
+ mmreg_size = 8;
+
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'alpha';
+
+Implementation
+
+end.
diff --git a/compiler/alpha/cpunode.pas b/compiler/alpha/cpunode.pas
new file mode 100644
index 0000000000..c62bc9c303
--- /dev/null
+++ b/compiler/alpha/cpunode.pas
@@ -0,0 +1,54 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Imports the Alpha 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.
+
+ ****************************************************************************
+}
+{
+ This unit imports the Alpha code generator.
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+// naxpadd,
+// naxpcal,
+// naxpcon,
+// naxpflw,
+// naxpmem,
+// naxpset,
+// naxpinl,
+// nppcopt,
+ { this not really a node }
+// naxpobj,
+// naxpmat,
+// naxpcnv
+ ;
+
+end.
diff --git a/compiler/alpha/cpupara.pas b/compiler/alpha/cpupara.pas
new file mode 100644
index 0000000000..ff19c1648c
--- /dev/null
+++ b/compiler/alpha/cpupara.pas
@@ -0,0 +1,290 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Alpha specific calling conventions
+
+ 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.
+ ****************************************************************************
+}
+{ Alpha specific calling conventions are handled by this unit
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ symconst,symbase,symtype,symdef,paramgr;
+
+ type
+ talphaparamanager = class(tparamanager)
+ function getintparaloc(nr : longint) : tparalocation;override;
+ procedure create_param_loc_info(p : tabstractprocdef);override;
+ function getfuncretparaloc(p : tabstractprocdef) : tparalocation;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,
+ globtype,
+ cpuinfo,cginfo,cgbase,
+ defbase;
+
+ function talphaparamanager.getintparaloc(nr : longint) : tparalocation;
+
+ begin
+ fillchar(result,sizeof(tparalocation),0);
+ if nr<1 then
+ internalerror(2002070801)
+ else if nr<=8 then
+ begin
+ result.loc:=LOC_REGISTER;
+ result.register:=tregister(longint(R_2)+nr);
+ end
+ else
+ begin
+ result.loc:=LOC_REFERENCE;
+ result.reference.index:=stack_pointer_reg;
+ result.reference.offset:=(nr-8)*4;
+ end;
+ end;
+
+ function getparaloc(p : tdef) : tloc;
+
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.deftype of
+ orddef:
+ getparaloc:=LOC_REGISTER;
+ floatdef:
+ getparaloc:=LOC_FPUREGISTER;
+ enumdef:
+ getparaloc:=LOC_REGISTER;
+ pointerdef:
+ getparaloc:=LOC_REGISTER;
+ formaldef:
+ getparaloc:=LOC_REGISTER;
+ classrefdef:
+ getparaloc:=LOC_REGISTER;
+ recorddef:
+ getparaloc:=LOC_REFERENCE;
+ objectdef:
+ if is_object(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ procvardef:
+ if (po_methodpointer in tprocvardef(p).procoptions) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ filedef:
+ getparaloc:=LOC_REGISTER;
+ arraydef:
+ getparaloc:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ getparaloc:=LOC_REGISTER
+ else
+ getparaloc:=LOC_REFERENCE;
+ variantdef:
+ getparaloc:=LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ getparaloc:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+ procedure talphaparamanager.create_param_loc_info(p : tabstractprocdef);
+
+ var
+ nextintreg,nextfloatreg,nextmmreg : tregister;
+ stack_offset : aword;
+ hp : tparaitem;
+ loc : tloc;
+ is_64bit: boolean;
+
+ begin
+ nextintreg:=R_3;
+ nextfloatreg:=R_F1;
+ // nextmmreg:=R_M1;
+ stack_offset:=0;
+ { pointer for structured results ? }
+ if not is_void(p.rettype.def) then
+ begin
+ if not(ret_in_reg(p.rettype.def)) then
+ inc(nextintreg);
+ end;
+
+ { frame pointer for nested procedures? }
+ { inc(nextintreg); }
+ { constructor? }
+ { destructor? }
+ hp:=tparaitem(p.para.last);
+ while assigned(hp) do
+ begin
+ loc:=getparaloc(hp.paratype.def);
+ hp.paraloc.sp_fixup:=0;
+ case loc of
+ LOC_REGISTER:
+ begin
+ hp.paraloc.size := def_cgsize(hp.paratype.def);
+ { for things like formaldef }
+ if hp.paraloc.size = OS_NO then
+ hp.paraloc.size := OS_ADDR;
+ is_64bit := hp.paraloc.size in [OS_64,OS_S64];
+ if nextintreg<=tregister(ord(R_10)-ord(is_64bit)) then
+ begin
+ hp.paraloc.loc:=LOC_REGISTER;
+ hp.paraloc.register64.reglo:=nextintreg;
+ inc(nextintreg);
+ if is_64bit then
+ begin
+ hp.paraloc.register64.reghi:=nextintreg;
+ inc(nextintreg);
+ end;
+ end
+ else
+ begin
+ nextintreg := R_11;
+ hp.paraloc.loc:=LOC_REFERENCE;
+ hp.paraloc.reference.index:=stack_pointer_reg;
+ hp.paraloc.reference.offset:=stack_offset;
+ if not is_64bit then
+ inc(stack_offset,4)
+ else
+ inc(stack_offset,8);
+ end;
+ end;
+ LOC_FPUREGISTER:
+ begin
+ if hp.paratyp in [vs_var,vs_out] then
+ begin
+ if nextintreg<=R_10 then
+ begin
+ hp.paraloc.size:=OS_ADDR;
+ hp.paraloc.loc:=LOC_REGISTER;
+ hp.paraloc.register:=nextintreg;
+ inc(nextintreg);
+ end
+ else
+ begin
+ {!!!!!!!}
+ hp.paraloc.size:=def_cgsize(hp.paratype.def);
+ internalerror(2002071006);
+ end;
+ end
+ else if nextfloatreg<=R_F10 then
+ begin
+ hp.paraloc.size:=def_cgsize(hp.paratype.def);
+ hp.paraloc.loc:=LOC_FPUREGISTER;
+ hp.paraloc.register:=nextfloatreg;
+ inc(nextfloatreg);
+ end
+ else
+ begin
+ {!!!!!!!}
+ hp.paraloc.size:=def_cgsize(hp.paratype.def);
+ internalerror(2002071004);
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ hp.paraloc.size:=OS_ADDR;
+ if push_addr_param(hp.paratype.def,p.proccalloption in [pocall_cdecl,pocall_cppdecl]) or (hp.paratyp in [vs_var,vs_out]) then
+ begin
+ if nextintreg<=R_10 then
+ begin
+ hp.paraloc.loc:=LOC_REGISTER;
+ hp.paraloc.register:=nextintreg;
+ inc(nextintreg);
+ end
+ else
+ begin
+ hp.paraloc.loc:=LOC_REFERENCE;
+ hp.paraloc.reference.index:=stack_pointer_reg;
+ hp.paraloc.reference.offset:=stack_offset;
+ inc(stack_offset,4);
+ end;
+ end
+ else
+ begin
+ hp.paraloc.loc:=LOC_REFERENCE;
+ hp.paraloc.reference.index:=stack_pointer_reg;
+ hp.paraloc.reference.offset:=stack_offset;
+ inc(stack_offset,hp.paratype.def.size);
+ end;
+ end;
+ else
+ internalerror(2002071002);
+ end;
+ hp:=tparaitem(hp.previous);
+ end;
+ end;
+
+ function talphaparamanager.getfuncretparaloc(p : tabstractprocdef) : tparalocation;
+ begin
+ case p.rettype.def.deftype of
+ orddef,
+ enumdef:
+ begin
+ getfuncretparaloc.loc:=LOC_REGISTER;
+ getfuncretparaloc.register:=R_3;
+ getfuncretparaloc.size:=def_cgsize(p.rettype.def);
+ if getfuncretparaloc.size in [OS_S64,OS_64] then
+ getfuncretparaloc.register64.reghi:=R_4;
+ end;
+ floatdef:
+ begin
+ getfuncretparaloc.loc:=LOC_FPUREGISTER;
+ getfuncretparaloc.register:=R_F1;
+ getfuncretparaloc.size:=def_cgsize(p.rettype.def);
+ end;
+ pointerdef,
+ formaldef,
+ classrefdef,
+ recorddef,
+ objectdef,
+ stringdef,
+ procvardef,
+ filedef,
+ arraydef,
+ errordef:
+ begin
+ getfuncretparaloc.loc:=LOC_REGISTER;
+ getfuncretparaloc.register:=R_3;
+ getfuncretparaloc.size:=OS_ADDR;
+ end;
+ else
+ internalerror(2002090903);
+ end;
+ end;
+
+
+begin
+ paramanager:=talphaparamanager.create;
+end.
diff --git a/compiler/alpha/cpupi.pas b/compiler/alpha/cpupi.pas
new file mode 100644
index 0000000000..6b1470cde0
--- /dev/null
+++ b/compiler/alpha/cpupi.pas
@@ -0,0 +1,43 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ 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 contains the CPU specific part of tprocinfo.
+}
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase;
+
+ type
+ talphaprocinfo = class(tprocinfo)
+ end;
+
+
+ implementation
+
+begin
+ cprocinfo:=talphaprocinfo;
+end.
diff --git a/compiler/alpha/cpuswtch.pas b/compiler/alpha/cpuswtch.pas
new file mode 100644
index 0000000000..b84dca877d
--- /dev/null
+++ b/compiler/alpha/cpuswtch.pas
@@ -0,0 +1,121 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ This units interprets the commandline options which are Alpha specific.
+
+ 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 units interprets the commandline options which are Alpha specific.
+}
+unit cpuswtch;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ options;
+
+type
+ toptionalpha = class(toption)
+ procedure interpret_proc_specific_options(const opt:string);override;
+ end;
+
+implementation
+
+uses
+ cutils,globtype,systems,globals;
+
+procedure toptionalpha.interpret_proc_specific_options(const opt:string);
+var
+ more: string;
+ j: longint;
+begin
+ More:=Upper(copy(opt,3,length(opt)-2));
+ case opt[2] of
+ 'O' : Begin
+ j := 3;
+ While (j <= Length(Opt)) Do
+ Begin
+ case opt[j] of
+ '-' :
+ begin
+ initglobalswitches:=initglobalswitches-[cs_optimize,cs_fastoptimize,cs_slowoptimize,cs_littlesize,
+ cs_regalloc,cs_uncertainopts];
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+ end;
+ 'a' :
+ begin
+ UpdateAlignmentStr(Copy(Opt,j+1,255),ParaAlignment);
+ j:=length(Opt);
+ end;
+ 'g' : initglobalswitches:=initglobalswitches+[cs_littlesize];
+ 'G' : initglobalswitches:=initglobalswitches-[cs_littlesize];
+ 'r' :
+ begin
+ initglobalswitches:=initglobalswitches+[cs_regalloc];
+ Simplify_ppu:=false;
+ end;
+ 'u' : initglobalswitches:=initglobalswitches+[cs_uncertainopts];
+ '1' : initglobalswitches:=initglobalswitches-[cs_fastoptimize,cs_slowoptimize]+[cs_optimize];
+ '2' : initglobalswitches:=initglobalswitches-[cs_slowoptimize]+[cs_optimize,cs_fastoptimize];
+ '3' : initglobalswitches:=initglobalswitches+[cs_optimize,cs_fastoptimize,cs_slowoptimize];
+{$ifdef dummy}
+ 'p' :
+ Begin
+ If j < Length(Opt) Then
+ Begin
+ Case opt[j+1] Of
+ '1': initoptprocessor := Class386;
+ '2': initoptprocessor := ClassP5;
+ '3': initoptprocessor := ClassP6
+ Else IllegalPara(Opt)
+ End;
+ Inc(j);
+ End
+ Else IllegalPara(opt)
+ End;
+{$endif dummy}
+ else IllegalPara(opt);
+ End;
+ Inc(j)
+ end;
+ end;
+{$ifdef dummy}
+ 'R' : begin
+ if More='GAS' then
+ initasmmode:=asmmode_ppc_gas
+ else
+ if More='MOTOROLA' then
+ initasmmode:=asmmode_ppc_motorola
+ else
+ if More='DIRECT' then
+ initasmmode:=asmmode_direct
+ else
+ IllegalPara(opt);
+ end;
+{$endif dummy}
+ else
+ IllegalPara(opt);
+ end;
+end;
+
+
+initialization
+ coption:=toptionalpha;
+end.
diff --git a/compiler/alpha/cputarg.pas b/compiler/alpha/cputarg.pas
new file mode 100644
index 0000000000..f7e38332c7
--- /dev/null
+++ b/compiler/alpha/cputarg.pas
@@ -0,0 +1,51 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the powerpc dependent target units
+
+ 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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGAXPGAS}
+ ,agaxpgas
+ {$endif}
+ ;
+
+end.
diff --git a/compiler/alpha/radirect.pas b/compiler/alpha/radirect.pas
new file mode 100644
index 0000000000..68f56bc747
--- /dev/null
+++ b/compiler/alpha/radirect.pas
@@ -0,0 +1,313 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Reads inline Alpha assembler and writes the lines direct to the output
+
+ 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 reads Alpha inline assembler and writes the lines direct to the output file.
+}
+unit radirect;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node;
+
+ function assemble : tnode;
+
+ implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globals,verbose,
+ systems,
+ { aasm }
+ aasmbase,aasmtai,aasmcpu,
+ { symtable }
+ symconst,symbase,symtype,symsym,symtable,defbase,
+ { pass 1 }
+ nbas,
+ { parser }
+ scanner,
+ { codegen }
+ cgbase,
+ { constants }
+ agaxpgas,
+ cpubase
+ ;
+
+ function assemble : tnode;
+
+ var
+ retstr,s,hs : string;
+ c : char;
+ ende : boolean;
+ srsym,sym : tsym;
+ srsymtable : tsymtable;
+ code : TAAsmoutput;
+ i,l : longint;
+
+ procedure writeasmline;
+ var
+ i : longint;
+ begin
+ i:=length(s);
+ while (i>0) and (s[i] in [' ',#9]) do
+ dec(i);
+ s[0]:=chr(i);
+ if s<>'' then
+ code.concat(Tai_direct.Create(strpnew(s)));
+ { consider it set function set if the offset was loaded }
+ if assigned(aktprocdef.funcretsym) and
+ (pos(retstr,upper(s))>0) then
+ tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
+ s:='';
+ end;
+
+ begin
+ ende:=false;
+ s:='';
+ if assigned(aktprocdef.funcretsym) and
+ is_fpu(aktprocdef.rettype.def) then
+ tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
+ { !!!!!
+ if (not is_void(aktprocdef.rettype.def)) then
+ retstr:=upper(tostr(procinfo^.return_offset)+'('+gas_reg2str[procinfo^.framepointer]+')')
+ else
+ }
+ retstr:='';
+
+ c:=current_scanner.asmgetchar;
+ code:=TAAsmoutput.Create;
+ while not(ende) do
+ begin
+ { wrong placement
+ current_scanner.gettokenpos; }
+ case c of
+ 'A'..'Z','a'..'z','_':
+ begin
+ current_scanner.gettokenpos;
+ i:=0;
+ hs:='';
+ while ((ord(c)>=ord('A')) and (ord(c)<=ord('Z')))
+ or ((ord(c)>=ord('a')) and (ord(c)<=ord('z')))
+ or ((ord(c)>=ord('0')) and (ord(c)<=ord('9')))
+ or (c='_') do
+ begin
+ inc(i);
+ hs[i]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ hs[0]:=chr(i);
+ if upper(hs)='END' then
+ ende:=true
+ else
+ begin
+ if c=':' then
+ begin
+ searchsym(upper(hs),srsym,srsymtable);
+ if srsym<>nil then
+ if (srsym.typ = labelsym) then
+ Begin
+ hs:=tlabelsym(srsym).lab.name;
+ tlabelsym(srsym).lab.is_set:=true;
+ end
+ else
+ Message(asmr_w_using_defined_as_local);
+ end
+ else
+ { access to local variables }
+ if assigned(aktprocdef) then
+ begin
+ { I don't know yet, what the ppc port requires }
+ { we'll see how things settle down }
+
+ { is the last written character an special }
+ { char ? }
+ { !!!
+ if (s[length(s)]='%') and
+ ret_in_acc(aktprocdef.rettype.def) and
+ ((pos('AX',upper(hs))>0) or
+ (pos('AL',upper(hs))>0)) then
+ tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
+ }
+ if ((s[length(s)]<>'0') or (hs[1]<>'x')) then
+ begin
+ if assigned(aktprocdef.localst) and
+ (lexlevel >= normal_function_level) then
+ sym:=tsym(aktprocdef.localst.search(upper(hs)))
+ else
+ sym:=nil;
+ if assigned(sym) then
+ begin
+ if (sym.typ=labelsym) then
+ Begin
+ hs:=tlabelsym(sym).lab.name;
+ end
+ else if sym.typ=varsym then
+ begin
+ if (vo_is_external in tvarsym(sym).varoptions) then
+ hs:=tvarsym(sym).mangledname
+ else
+ begin
+ if (tvarsym(sym).reg<>R_NO) then
+ hs:=gas_reg2str[procinfo.framepointer]
+ else
+ hs:=tostr(tvarsym(sym).address)+
+ '('+gas_reg2str[procinfo.framepointer]+')';
+ end;
+ end
+ else
+ { call to local function }
+ if (sym.typ=procsym) and (pos('BL',upper(s))>0) then
+ hs:=tprocsym(sym).first_procdef.mangledname;
+ end
+ else
+ begin
+ if assigned(aktprocdef.parast) then
+ sym:=tsym(aktprocdef.parast.search(upper(hs)))
+ else
+ sym:=nil;
+ if assigned(sym) then
+ begin
+ if sym.typ=varsym then
+ begin
+ l:=tvarsym(sym).address;
+ { set offset }
+ inc(l,aktprocdef.parast.address_fixup);
+ hs:=tostr(l)+'('+gas_reg2str[procinfo.framepointer]+')';
+ if pos(',',s) > 0 then
+ tvarsym(sym).varstate:=vs_used;
+ end;
+ end
+ { I added that but it creates a problem in line.ppi
+ because there is a local label wbuffer and
+ a static variable WBUFFER ...
+ what would you decide, florian ?}
+ else
+ begin
+ searchsym(upper(hs),sym,srsymtable);
+ if assigned(sym) and (sym.owner.symtabletype in [globalsymtable,staticsymtable]) then
+ begin
+ case sym.typ of
+ varsym :
+ begin
+ Message2(asmr_h_direct_global_to_mangled,hs,tvarsym(sym).mangledname);
+ hs:=tvarsym(sym).mangledname;
+ inc(tvarsym(sym).refs);
+ end;
+ typedconstsym :
+ begin
+ Message2(asmr_h_direct_global_to_mangled,hs,ttypedconstsym(sym).mangledname);
+ hs:=ttypedconstsym(sym).mangledname;
+ end;
+ procsym :
+ begin
+ { procs can be called or the address can be loaded }
+ if (pos('BL',upper(s))>0) {or (pos('LEA',upper(s))>0))} then
+ begin
+ if Tprocsym(sym).procdef_count>1 then
+ Message1(asmr_w_direct_global_is_overloaded_func,hs);
+ Message2(asmr_h_direct_global_to_mangled,hs,tprocsym(sym).first_procdef.mangledname);
+ hs:=tprocsym(sym).first_procdef.mangledname;
+ end;
+ end;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+{$ifdef dummy}
+ else if upper(hs)='__SELF' then
+ begin
+ if assigned(procinfo^._class) then
+ hs:=tostr(procinfo^.selfpointer_offset)+
+ '('+gas_reg2str[procinfo^.framepointer]+')'
+ else
+ Message(asmr_e_cannot_use_SELF_outside_a_method);
+ end
+ else if upper(hs)='__RESULT' then
+ begin
+ if (not is_void(aktprocdef.rettype.def)) then
+ hs:=retstr
+ else
+ Message(asmr_e_void_function);
+ end
+ { implement old stack/frame pointer access for nested procedures }
+ {!!!!
+ else if upper(hs)='__OLDSP' then
+ begin
+ { complicate to check there }
+ { we do it: }
+ if lexlevel>normal_function_level then
+ hs:=tostr(procinfo^.framepointer_offset)+
+ '('+gas_reg2str[procinfo^.framepointer]+')'
+ else
+ Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
+ end;
+ }
+ end;
+{$endif dummy}
+ end;
+ end;
+ end;
+ end;
+ s:=s+hs;
+ end;
+ end;
+ '{',';',#10,#13:
+ begin
+ if pos(retstr,s) > 0 then
+ tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
+ writeasmline;
+ c:=current_scanner.asmgetchar;
+ end;
+ #26:
+ Message(scan_f_end_of_file);
+ else
+ begin
+ current_scanner.gettokenpos;
+ inc(byte(s[0]));
+ s[length(s)]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ end;
+ writeasmline;
+ assemble:=casmnode.create(code);
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_ppc_direct_info : tasmmodeinfo =
+ (
+ id : asmmode_direct;
+ idtxt : 'DIRECT'
+ );
+
+initialization
+ RegisterAsmMode(asmmode_ppc_direct_info);
+
+end.
diff --git a/compiler/alpha/rasm.pas b/compiler/alpha/rasm.pas
new file mode 100644
index 0000000000..0d715b5d87
--- /dev/null
+++ b/compiler/alpha/rasm.pas
@@ -0,0 +1,65 @@
+{
+ Copyright (c) 1998-2002 by The Free Pascal Team
+
+ This unit does the parsing process for the inline assembler
+
+ 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 does the parsing process for the inline assembler.
+}
+Unit Rasm;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses
+ node;
+
+ {
+ This routine is called to parse the instructions in assembler
+ blocks. It returns a complete list of directive and instructions
+ }
+ function assemble: tnode;
+
+
+Implementation
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmcpu,
+ { symtable }
+ symconst,symbase,symtype,symsym,symtable,
+ { pass 1 }
+ nbas,
+ { parser }
+ scanner
+ // ,rautils
+ ;
+
+ function assemble : tnode;
+ begin
+ end;
+
+Begin
+end.
diff --git a/compiler/alpha/rgcpu.pas b/compiler/alpha/rgcpu.pas
new file mode 100644
index 0000000000..23a1ca06e5
--- /dev/null
+++ b/compiler/alpha/rgcpu.pas
@@ -0,0 +1,69 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the powerpc specific class for the register
+ allocator
+
+ 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 rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ function getcpuregisterint(list: taasmoutput; reg: tregister): tregister; override;
+ procedure ungetregisterint(list: taasmoutput; reg: tregister); override;
+ end;
+
+ implementation
+
+ uses
+ cgobj;
+
+ function trgcpu.getcpuregisterint(list: taasmoutput; reg: tregister): tregister;
+
+ begin
+ if reg = R_0 then
+ begin
+ cg.a_reg_alloc(list,reg);
+ result := reg;
+ end
+ else result := inherited getcpuregisterint(list,reg);
+ end;
+
+
+ procedure trgcpu.ungetregisterint(list: taasmoutput; reg: tregister);
+
+ begin
+ if reg = R_0 then
+ cg.a_reg_dealloc(list,reg)
+ else
+ inherited ungetregisterint(list,reg);
+ end;
+
+initialization
+ rg := trgcpu.create;
+end.
diff --git a/compiler/alpha/tgcpu.pas b/compiler/alpha/tgcpu.pas
new file mode 100644
index 0000000000..90c4ac5175
--- /dev/null
+++ b/compiler/alpha/tgcpu.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (C) 1998-2000 by Florian Klaempfl
+
+ This unit handles the temporary variables stuff for Alpha
+
+ 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 handles the temporary variables stuff for Alpha.
+}
+unit tgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ tgobj;
+
+ type
+ ttgalpha = class(ttgobj)
+ end;
+
+implementation
+
+begin
+ tg:=ttgalpha.create;
+end.
diff --git a/compiler/aopt.pas b/compiler/aopt.pas
new file mode 100644
index 0000000000..c3d9e6ec0a
--- /dev/null
+++ b/compiler/aopt.pas
@@ -0,0 +1,267 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the interface routines between the code generator
+ and the optimizer.
+
+ 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 aopt;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ Uses
+ aasmbase,aasmtai,aasmcpu,
+ aoptobj;
+
+ Type
+ TAsmOptimizer = class(TAoptObj)
+
+ { _AsmL is the PAasmOutpout list that has to be optimized }
+ Constructor create(_AsmL: taasmoutput); virtual;
+
+ { call the necessary optimizer procedures }
+ Procedure Optimize;
+ Destructor destroy;override;
+
+ private
+ procedure FindLoHiLabels;
+ Procedure BuildLabelTableAndFixRegAlloc;
+ procedure clear;
+ procedure pass_1;
+ End;
+
+ var
+ casmoptimizer : class of tasmoptimizer;
+
+ procedure Optimize(AsmL:taasmoutput);
+
+ Implementation
+
+ uses
+ globtype, globals,
+ aoptda,aoptcpu,aoptcpud;
+
+ Constructor TAsmOptimizer.create(_AsmL: taasmoutput);
+ Begin
+ inherited create(_asml,nil,nil,nil);
+ {setup labeltable, always necessary}
+ New(LabelInfo);
+ End;
+
+ procedure TAsmOptimizer.FindLoHiLabels;
+ { Walks through the paasmlist to find the lowest and highest label number. }
+ { Returns the last Pai object of the current block }
+ Var LabelFound: Boolean;
+ p, prev: tai;
+ Begin
+ LabelInfo^.LowLabel := High(AWord);
+ LabelInfo^.HighLabel := 0;
+ LabelInfo^.LabelDif := 0;
+ LabelInfo^.LabelTable:=nil;
+ LabelFound := False;
+ P := BlockStart;
+ prev := p;
+ With LabelInfo^ Do
+ Begin
+ While Assigned(P) And
+ ((P.typ <> Ait_Marker) Or
+ (tai_Marker(P).Kind <> AsmBlockStart)) Do
+ Begin
+ If (p.typ = ait_label) Then
+ If (tai_Label(p).l.is_used) Then
+ Begin
+ LabelFound := True;
+ If (tai_Label(p).l.labelnr < LowLabel) Then
+ LowLabel := tai_Label(p).l.labelnr;
+ If (tai_Label(p).l.labelnr > HighLabel) Then
+ HighLabel := tai_Label(p).l.labelnr
+ End;
+ prev := p;
+ GetNextInstruction(p, p)
+ End;
+ if (prev.typ = ait_marker) and
+ (tai_marker(prev).kind = asmblockstart) then
+ blockend := prev
+ else blockend := nil;
+ If LabelFound
+ Then LabelDif := HighLabel-LowLabel+1
+ Else LabelDif := 0
+ End
+ End;
+
+ Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
+ { Builds a table with the locations of the labels in the taasmoutput. }
+ { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
+ Var p, hp1, hp2: tai;
+ UsedRegs: TRegSet;
+ Begin
+ UsedRegs := [];
+ With LabelInfo^ Do
+ If (LabelDif <> 0) Then
+ Begin
+ GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
+ FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
+ p := BlockStart;
+ While (P <> BlockEnd) Do
+ Begin
+ Case p.typ Of
+ ait_Label:
+ If tai_label(p).l.is_used Then
+ LabelTable^[tai_label(p).l.labelnr-LowLabel].PaiObj := p;
+ ait_regAlloc:
+ begin
+ {!!!!!!!!!
+ if tai_regalloc(p).ratype=ra_alloc then
+ Begin
+ If Not(tai_regalloc(p).Reg in UsedRegs) Then
+ UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
+ Else
+ Begin
+ hp1 := p;
+ hp2 := nil;
+ While GetLastInstruction(hp1, hp1) And
+ Not(RegInInstruction(tai_regalloc(p).Reg, hp1)) Do
+ hp2:=hp1;
+ If hp2<>nil Then
+ Begin
+ hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
+ InsertLLItem(tai(hp2.previous), hp2, hp1);
+ End;
+ End;
+ End
+ else
+ Begin
+ UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
+ hp1 := p;
+ hp2 := nil;
+ While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
+ GetNextInstruction(hp1, hp1) And
+ RegInInstruction(tai_regalloc(p).Reg, hp1) Do
+ hp2 := hp1;
+ If hp2 <> nil Then
+ Begin
+ hp1 := tai(p.previous);
+ AsmL.Remove(p);
+ InsertLLItem(hp2, tai(hp2.Next), p);
+ p := hp1;
+ End
+ End
+ };
+ End
+ End;
+ P := tai(p.Next);
+ While Assigned(p) and
+ (p <> blockend) and
+ (p.typ in (SkipInstr - [ait_regalloc])) Do
+ P := tai(P.Next)
+ End;
+ End
+ End;
+
+ procedure tasmoptimizer.clear;
+ begin
+ if LabelInfo^.labeldif <> 0 then
+ begin
+ freemem(LabelInfo^.labeltable);
+ LabelInfo^.labeltable := nil;
+ end;
+ end;
+
+ procedure tasmoptimizer.pass_1;
+ begin
+ findlohilabels;
+ BuildLabelTableAndFixRegAlloc;
+ end;
+
+
+ Procedure TAsmOptimizer.Optimize;
+ Var
+ HP: tai;
+ pass: longint;
+ Begin
+ pass:=0;
+ BlockStart := tai(AsmL.First);
+ pass_1;
+ While Assigned(BlockStart) Do
+ Begin
+ if pass = 0 then
+ PrePeepHoleOpts;
+ { Peephole optimizations }
+ PeepHoleOptPass1;
+ { Only perform them twice in the first pass }
+ if pass = 0 then
+ PeepHoleOptPass1;
+ If (cs_slowoptimize in aktglobalswitches) Then
+ Begin
+// DFA:=TAOptDFACpu.Create(AsmL,BlockStart,BlockEnd,LabelInfo);
+ { data flow analyzer }
+// DFA.DoDFA;
+ { common subexpression elimination }
+ { CSE;}
+ End;
+ { more peephole optimizations }
+ { PeepHoleOptPass2;}
+ { if pass = last_pass then }
+ PostPeepHoleOpts;
+ { free memory }
+ clear;
+ { continue where we left off, BlockEnd is either the start of an }
+ { assembler block or nil}
+ BlockStart := BlockEnd;
+ While Assigned(BlockStart) And
+ (BlockStart.typ = ait_Marker) And
+ (tai_Marker(BlockStart).Kind = AsmBlockStart) Do
+ Begin
+ { we stopped at an assembler block, so skip it }
+ While GetNextInstruction(BlockStart, BlockStart) And
+ ((BlockStart.Typ <> Ait_Marker) Or
+ (tai_Marker(Blockstart).Kind <> AsmBlockEnd)) Do;
+ { blockstart now contains a tai_marker(asmblockend) }
+ If GetNextInstruction(BlockStart, HP) And
+ ((HP.typ <> ait_Marker) Or
+ (Tai_Marker(HP).Kind <> AsmBlockStart)) Then
+ { There is no assembler block anymore after the current one, so }
+ { optimize the next block of "normal" instructions }
+ pass_1
+ { Otherwise, skip the next assembler block }
+ else
+ blockStart := hp;
+ End
+ End;
+ End;
+
+ Destructor TAsmOptimizer.Destroy;
+ Begin
+ Dispose(LabelInfo)
+ End;
+
+
+ procedure Optimize(AsmL:taasmoutput);
+ var
+ p : TAsmOptimizer;
+ begin
+ p:=casmoptimizer.Create(AsmL);
+ p.Optimize;
+ p.free
+ end;
+
+
+end.
diff --git a/compiler/aoptbase.pas b/compiler/aoptbase.pas
new file mode 100644
index 0000000000..83ad7b34ed
--- /dev/null
+++ b/compiler/aoptbase.pas
@@ -0,0 +1,257 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the base of all optimizer related objects
+
+ 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 aoptbase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmcpu,aasmtai,
+ cpubase,
+ cgbase,
+ cgutils;
+
+ Type
+ { the number of tai objects processed by an optimizer object since the last
+ time a register was modified }
+ { size at each dimension depends on the registers of this type }
+ TInstrSinceLastMod = Array[tregistertype] of pbyte;
+
+ { the TAopBase object implements the basic methods that most other }
+ { assembler optimizer objects require }
+ Type
+ TAoptBase = class
+ { processor independent methods }
+
+ constructor create; virtual;
+ destructor destroy;override;
+ { returns true if register Reg is used by instruction p1 }
+ Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;
+ { returns true if register Reg occurs in operand op }
+ Function RegInOp(Reg: TRegister; const op: toper): Boolean;
+ { returns true if register Reg is used in the reference Ref }
+ Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
+
+ { returns true if the references are completely equal }
+ {Function RefsEqual(Const R1, R2: TReference): Boolean;}
+
+ { gets the next tai object after current that contains info relevant }
+ { to the optimizer in p1. If there is none, it returns false and }
+ { sets p1 to nil }
+ Function GetNextInstruction(Current: tai; Var Next: tai): Boolean;
+ { gets the previous tai object after current that contains info }
+ { relevant to the optimizer in last. If there is none, it retuns }
+ { false and sets last to nil }
+ Function GetLastInstruction(Current: tai; Var Last: tai): Boolean;
+
+
+ { processor dependent methods }
+
+ { returns the maximum width component of Reg. Only has to be }
+ { overridden for the 80x86 (afaik) }
+ Function RegMaxSize(Reg: TRegister): TRegister; Virtual;
+ { returns true if Reg1 and Reg2 are of the samae width. Only has to }
+ { overridden for the 80x86 (afaik) }
+ Function RegsSameSize(Reg1, Reg2: TRegister): Boolean; Virtual;
+ { returns whether P is a load instruction (load contents from a }
+ { memory location or (register) variable into a register) }
+ Function IsLoadMemReg(p: tai): Boolean; Virtual;
+ { returns whether P is a load constant instruction (load a constant }
+ { into a register) }
+ Function IsLoadConstReg(p: tai): Boolean; Virtual;
+ { returns whether P is a store instruction (store contents from a }
+ { register to a memory location or to a (register) variable) }
+ Function IsStoreRegMem(p: tai): Boolean; Virtual;
+
+ { create a paicpu Object that loads the contents of reg1 into reg2 }
+ Function a_load_reg_reg(reg1, reg2: TRegister): taicpu; Virtual;
+
+ end;
+
+
+ implementation
+
+ uses
+ globtype,globals, aoptcpub;
+
+ constructor taoptbase.create;
+ begin
+ inherited create;
+ end;
+
+
+ destructor taoptbase.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ Function TAOptBase.RegInInstruction(Reg: TRegister; p1: tai): Boolean;
+ Var Count: AWord;
+ TmpResult: Boolean;
+ Begin
+ TmpResult := False;
+ Count := 0;
+ If (p1.typ = ait_instruction) Then
+ Repeat
+ TmpResult := RegInOp(Reg, PInstr(p1)^.oper[Count]^);
+ Inc(Count)
+ Until (Count = MaxOps) or TmpResult;
+ RegInInstruction := TmpResult
+ End;
+
+
+ Function TAOptBase.RegInOp(Reg: TRegister; const op: toper): Boolean;
+ Begin
+ Case op.typ Of
+ Top_Reg: RegInOp := Reg = op.reg;
+ Top_Ref: RegInOp := RegInRef(Reg, op.ref^)
+ Else RegInOp := False
+ End
+ End;
+
+
+ Function TAOptBase.RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
+ Begin
+ Reg := RegMaxSize(Reg);
+ RegInRef := (Ref.Base = Reg)
+ {$ifdef RefsHaveIndexReg}
+ Or (Ref.Index = Reg)
+ {$endif RefsHaveIndexReg}
+ End;
+
+ Function TAOptBase.GetNextInstruction(Current: tai; Var Next: tai): Boolean;
+ Begin
+ Repeat
+ Current := tai(Current.Next);
+ While Assigned(Current) And
+ ((Current.typ In SkipInstr) or
+{$ifdef SPARC}
+ ((Current.typ=ait_instruction) and
+ (taicpu(Current).opcode=A_NOP)
+ ) or
+{$endif SPARC}
+ ((Current.typ = ait_label) And
+ Not(Tai_Label(Current).l.is_used))) Do
+ Current := tai(Current.Next);
+ If Assigned(Current) And
+ (Current.typ = ait_Marker) And
+ (Tai_Marker(Current).Kind = NoPropInfoStart) Then
+ Begin
+ While Assigned(Current) And
+ ((Current.typ <> ait_Marker) Or
+ (Tai_Marker(Current).Kind <> NoPropInfoEnd)) Do
+ Current := Tai(Current.Next);
+ End;
+ Until Not(Assigned(Current)) Or
+ (Current.typ <> ait_Marker) Or
+ (Tai_Marker(Current).Kind <> NoPropInfoEnd);
+ Next := Current;
+ If Assigned(Current) And
+ Not((Current.typ In SkipInstr) or
+ ((Current.typ = ait_label) And
+ Not(Tai_Label(Current).l.is_used)))
+ Then GetNextInstruction := True
+ Else
+ Begin
+ Next := Nil;
+ GetNextInstruction := False;
+ End;
+ End;
+
+ Function TAOptBase.GetLastInstruction(Current: tai; Var Last: tai): Boolean;
+ Begin
+ Repeat
+ Current := Tai(Current.previous);
+ While Assigned(Current) And
+ (((Current.typ = ait_Marker) And
+ Not(Tai_Marker(Current).Kind in [AsmBlockEnd,NoPropInfoEnd])) or
+ (Current.typ In SkipInstr) or
+ ((Current.typ = ait_label) And
+ Not(Tai_Label(Current).l.is_used))) Do
+ Current := Tai(Current.previous);
+ If Assigned(Current) And
+ (Current.typ = ait_Marker) And
+ (Tai_Marker(Current).Kind = NoPropInfoEnd) Then
+ Begin
+ While Assigned(Current) And
+ ((Current.typ <> ait_Marker) Or
+ (Tai_Marker(Current).Kind <> NoPropInfoStart)) Do
+ Current := Tai(Current.previous);
+ End;
+ Until Not(Assigned(Current)) Or
+ (Current.typ <> ait_Marker) Or
+ (Tai_Marker(Current).Kind <> NoPropInfoStart);
+ If Not(Assigned(Current)) or
+ (Current.typ In SkipInstr) or
+ ((Current.typ = ait_label) And
+ Not(Tai_Label(Current).l.is_used)) or
+ ((Current.typ = ait_Marker) And
+ (Tai_Marker(Current).Kind = AsmBlockEnd))
+ Then
+ Begin
+ Last := Nil;
+ GetLastInstruction := False
+ End
+ Else
+ Begin
+ Last := Current;
+ GetLastInstruction := True;
+ End;
+ End;
+
+
+ { ******************* Processor dependent stuff *************************** }
+
+ Function TAOptBase.RegMaxSize(Reg: TRegister): TRegister;
+ Begin
+ RegMaxSize := Reg
+ End;
+
+ Function TAOptBase.RegsSameSize(Reg1, Reg2: TRegister): Boolean;
+ Begin
+ RegsSameSize := True
+ End;
+
+ Function TAOptBase.IsLoadMemReg(p: tai): Boolean;
+ Begin
+ Abstract
+ End;
+
+ Function TAOptBase.IsLoadConstReg(p: tai): Boolean;
+ Begin
+ Abstract
+ End;
+
+ Function TAOptBase.IsStoreRegMem(p: tai): Boolean;
+ Begin
+ Abstract
+ End;
+
+ Function TAoptBase.a_load_reg_reg(reg1, reg2: TRegister): taicpu;
+ Begin
+ Abstract
+ End;
+
+end.
diff --git a/compiler/aoptcs.pas b/compiler/aoptcs.pas
new file mode 100644
index 0000000000..460abd3c27
--- /dev/null
+++ b/compiler/aoptcs.pas
@@ -0,0 +1,848 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the common subexpression elimination object of the
+ assembler optimizer.
+
+ 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 aoptcs;
+
+interface
+
+uses aasm, aoptcpu, aoptobj;
+
+{ ************************************************************************* }
+{ info about the equivalence of registers when comparing two code sequences }
+{ ************************************************************************* }
+
+ TRegInfo = Object(TAoptBaseCpu)
+ { registers encountered in the new and old sequence }
+ NewRegsEncountered, OldRegsEncountered,
+ { registers which only have been loaded for use as base or index in a }
+ { reference later on }
+ RegsLoadedForRef: TRegSet;
+ { to which register in the old sequence corresponds every register in }
+ { the new sequence }
+ New2OldReg: TRegArray;
+
+ Constructor init;
+ { clear all information store in the object }
+ Procedure Clear;
+ { the contents of OldReg in the old sequence are now being loaded into }
+ { NewReg in the new sequence }
+ Procedure AddReg(OldReg, NewReg: TRegister); Virtual;
+ { the contents of OldOp in the old sequence are now being loaded into }
+ { NewOp in the new sequence. It is assumed that OldOp and NewOp are }
+ { equivalent }
+ Procedure AddOp(const OldOp, NewOp:Toper);
+ { check if a register in the old sequence (OldReg) can be equivalent to }
+ { a register in the new sequence (NewReg) if the operation OpAct is }
+ { performed on it. The RegInfo is updated (not necessary to call AddReg }
+ { afterwards) }
+ Function RegsEquivalent(OldReg, NewReg: TRegister; OpAct: TopAction):
+ Boolean;
+ { check if a reference in the old sequence (OldRef) can be equivalent }
+ { to a reference in the new sequence (NewRef) if the operation OpAct is }
+ { performed on it. The RegInfo is updated (not necessary to call AddOp }
+ { afterwards) }
+ Function RefsEquivalent(Const OldRef, NewRef: TReference; OpAct:
+ TOpAction): Boolean;
+ { check if an operand in the old sequence (OldOp) can be equivalent to }
+ { an operand in the new sequence (NewOp) if the operation OpAct is }
+ { performed on it. The RegInfo is updated (not necessary to call AddOp }
+ { afterwards) }
+ Function OpsEquivalent(const OldOp, NewOp: toper; OpAct: TopAction):
+ Boolean;
+ { check if an instruction in the old sequence (OldP) can be equivalent }
+ { to an instruction in the new sequence (Newp). The RegInfo is updated }
+ Function InstructionsEquivalent(OldP, NewP: Pai): Boolean;
+ End;
+
+
+{ ************************************************************************* }
+{ *************** The common subexpression elimination object ************* }
+{ ************************************************************************* }
+
+Type TAoptCSE = Object(TAoptObj)
+ { returns true if the instruction p1 modifies the register Reg }
+ Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
+ End;
+
+Implementation
+
+{ ************************************************************************* }
+{ ******************************* TReginfo ******************************** }
+{ ************************************************************************* }
+
+Constructor TRegInfo.Init;
+Begin
+ Clear;
+End;
+
+Procedure TRegInfo.Clear;
+Begin
+ RegsLoadedForRef := [];
+ NewRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG];
+ OldRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG];
+ New2OldReg[FRAME_POINTER_REG] := FRAME_POINTER_REG;
+ New2OldReg[STACK_POINTER_REG] := STACK_POINTER_REG;
+End;
+
+Procedure TRegInfo.AddReg(OldReg, NewReg: TRegister);
+{ updates the ???RegsEncountered and ???2???Reg fields of RegInfo. Assumes }
+{ that OldReg and NewReg have the same size (has to be chcked in advance }
+{ with RegsSameSize) and that neither equals R_NO }
+{ has to be overridden for architectures like the 80x86 when not all GP }
+{ regs are of the same size }
+Begin
+ NewRegsEncountered := NewRegsEncountered + [NewReg];
+ OldRegsEncountered := OldRegsEncountered + [OldReg];
+ New2OldReg[NewReg] := OldReg;
+End;
+
+Procedure TRegInfo.AddOp(const OldOp, NewOp:Toper);
+Begin
+ Case OldOp.typ Of
+ Top_Reg:
+ If (OldOp.reg <> R_NO) Then
+ AddReg(OldOp.reg, NewOp.reg);
+ Top_Ref:
+ Begin
+ If OldOp.ref^.base <> R_NO Then
+ AddReg(OldOp.ref^.base, NewOp.ref^.base);
+{$ifdef RefsHaveIndexReg}
+ If OldOp.ref^.index <> R_NO Then
+ AddReg(OldOp.ref^.index, NewOp.ref^.index);
+{$endif RefsHaveIndexReg}
+ End;
+ End;
+End;
+
+Function TRegInfo.RegsEquivalent(OldReg, NewReg: TRegister;
+ OPAct: TOpAction): Boolean;
+Begin
+ If Not((OldReg = R_NO) Or (NewReg = R_NO)) Then
+ If RegsSameSize(OldReg, NewReg) Then
+{ here we always check for the 32 bit component, because it is possible }
+{ that the 8 bit component has not been set, event though NewReg already }
+{ has been processed. This happens if it has been compared with a register }
+{ that doesn't have an 8 bit component (such as EDI). In that case the 8 }
+{ bit component is still set to R_NO and the comparison in the Else-part }
+{ will fail }
+ If (RegMaxSize(OldReg) in OldRegsEncountered) Then
+ If (RegMaxSize(NewReg) in NewRegsEncountered) Then
+ RegsEquivalent := (OldReg = New2OldReg[NewReg])
+{ If we haven't encountered the new register yet, but we have encountered }
+{ the old one already, the new one can only be correct if it's being }
+{ written to (and consequently the old one is also being written to), }
+{ otherwise }
+{ }
+{ movl -8(%ebp), %eax and movl -8(%ebp), %eax }
+{ movl (%eax), %eax movl (%edx), %edx }
+{ }
+{ are considered equivalent }
+ Else
+ If (OpAct = OpAct_Write) Then
+ Begin
+ AddReg(OldReg, NewReg);
+ RegsEquivalent := True
+ End
+ Else Regsequivalent := False
+ Else
+ If Not(RegMaxSize(NewReg) in NewRegsEncountered) Then
+ Begin
+ AddReg(OldReg, NewReg);
+ RegsEquivalent := True
+ End
+ Else RegsEquivalent := False
+ Else RegsEquivalent := False
+ Else RegsEquivalent := OldReg = NewReg
+End;
+
+Function TRegInfo.RefsEquivalent(Const OldRef, NewRef: TReference;
+ OpAct: TOpAction): Boolean;
+Begin
+ If OldRef.is_immediate Then
+ RefsEquivalent := NewRef.is_immediate and (OldRef.Offset = NewRef.Offset)
+ Else
+ RefsEquivalent := (OldRef.Offset+OldRef.OffsetFixup =
+ NewRef.Offset+NewRef.OffsetFixup) And
+ RegsEquivalent(OldRef.Base, NewRef.Base, OpAct)
+{$ifdef RefsHaveindexReg}
+ And RegsEquivalent(OldRef.Index, NewRef.Index, OpAct)
+{$endif RefsHaveIndexReg}
+{$ifdef RefsHaveScale}
+ And (OldRef.ScaleFactor = NewRef.ScaleFactor)
+{$endif RefsHaveScale}
+ And (OldRef.Symbol = NewRef.Symbol)
+{$ifdef RefsHaveSegment}
+ And (OldRef.Segment = NewRef.Segment)
+{$endif RefsHaveSegment}
+ ;
+End;
+
+Function TRegInfo.OpsEquivalent(const OldOp, NewOp: toper; OpAct: TopAction):
+ Boolean;
+Begin
+ OpsEquivalent := False;
+ if OldOp.typ=NewOp.typ then
+ Case OldOp.typ Of
+ Top_Const: OpsEquivalent := OldOp.val = NewOp.val;
+ Top_Reg: OpsEquivalent := RegsEquivalent(OldOp.reg,NewOp.reg, OpAct);
+ Top_Ref: OpsEquivalent := RefsEquivalent(OldOp.ref^, NewOp.ref^, OpAct);
+ Top_None: OpsEquivalent := True
+ End;
+End;
+
+Function TRegInfo.InstructionsEquivalent(OldP, NewP: Pai): Boolean;
+
+ Function OperandTypesEqual: Boolean;
+ Var Count: AWord;
+ Begin
+ OperandTypesEqual := False;
+ For Count := 0 to max_operands-1 Do
+ If (PInstr(OldP)^.oper[Count].typ <> PInstr(NewP)^.oper[Count].typ) Then
+ Exit;
+ OperandTypesEqual := True
+ End;
+
+Var Count: AWord;
+ TmpResult: Boolean;
+Begin
+ If Assigned(OldP) And Assigned(NewP) And
+ (Pai(OldP)^.typ = ait_instruction) And
+ (Pai(NewP)^.typ = ait_instruction) And
+ (PInstr(OldP)^.opcode = PInstr(NewP)^.opcode) And
+ OperandTypesEqual
+ Then
+{ both instructions have the same structure: }
+{ "<operator> <operand of type1>, <operand of type 2>, ..." }
+ If IsLoadMemReg(OldP) Then
+{ then also NewP = loadmemreg because of the previous check }
+ If Not(RegInRef(PInstr(OldP)^.oper[LoadDst].reg,
+ PInstr(OldP)^.oper[LoadSrc].ref^)) Then
+{ the "old" instruction is a load of a register with a new value, not with }
+{ a value based on the contents of this register (so no "mov (reg), reg") }
+ If Not(RegInRef(PInstr(NewP)^.oper[LoadDst].reg,
+ PInstr(NewP)^.oper[LoadSrc].ref^)) And
+ RefsEqual(PInstr(OldP)^.oper[LoadSrc].ref^,
+ PInstr(NewP)^.oper[LoadSrc].ref^)
+ Then
+{ the "new" instruction is also a load of a register with a new value, and }
+{ this value is fetched from the same memory location }
+ Begin
+ With PInstr(NewP)^.oper[LoadSrc].ref^ Do
+ Begin
+ If Not(Base in [ProcInfo.FramePointer, R_NO, STACK_POINTER_REG])
+{ it won't do any harm if the register is already in RegsLoadedForRef }
+ Then RegsLoadedForRef := RegsLoadedForRef + [Base];
+{$ifdef RefsHaveIndexReg}
+ If Not(Index in [ProcInfo.FramePointer, R_NO, STACK_POINTER_REG])
+ Then RegsLoadedForRef := RegsLoadedForRef + [Index];
+{$endif RefsHaveIndexReg}
+ End;
+{ add the registers from the reference (.oper[Src]) to the RegInfo, all }
+{ registers from the reference are the same in the old and in the new }
+{ instruction sequence (refsequal returned true) }
+ AddOp(PInstr(OldP)^.oper[LoadSrc], PInstr(OldP)^.oper[LoadSrc]);
+{ the registers from .oper[Dest] have to be equivalent, but not necessarily }
+{ equal }
+ InstructionsEquivalent :=
+ RegsEquivalent(PInstr(OldP)^.oper[LoadDst].reg,
+ PInstr(NewP)^.oper[LoadDst].reg, OpAct_Write);
+ End
+{ the registers are loaded with values from different memory locations. If }
+{ this were allowed, the instructions "mov -4(%esi),%eax" and }
+{ "mov -4(%ebp),%eax" would be considered equivalent }
+ Else InstructionsEquivalent := False
+ Else
+{ load register with a value based on the current value of this register }
+ Begin
+ With PInstr(NewP)^.oper[0].ref^ Do
+{ Assume the registers occurring in the reference have only been loaded with }
+{ the value they contain now to calculate an address (so the value they have }
+{ now, won't be stored to memory later on) }
+ Begin
+ If Not(Base in [ProcInfo.FramePointer,
+ RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg),
+ R_NO,STACK_POINTER_REG])
+{ It won't do any harm if the register is already in RegsLoadedForRef }
+ Then
+ Begin
+ RegsLoadedForRef := RegsLoadedForRef + [Base];
+{$ifdef csdebug}
+ Writeln(std_reg2str[base], ' added');
+{$endif csdebug}
+ end;
+{$Ifdef RefsHaveIndexReg}
+ If Not(Index in [ProcInfo.FramePointer,
+ RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg),
+ R_NO,StackPtr])
+ Then
+ Begin
+ RegsLoadedForRef := RegsLoadedForRef + [Index];
+{$ifdef csdebug}
+ Writeln(std_reg2str[index], ' added');
+{$endif csdebug}
+ end;
+{$endif RefsHaveIndexReg}
+ End;
+
+{ now, remove the destination register of the load from the }
+{ RegsLoadedForReg, since if it's loaded with a new value, it certainly }
+{ will still be used later on }
+ If Not(RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg) In
+ [ProcInfo.FramePointer,R_NO,STACK_POINTER_REG])
+ Then
+ Begin
+ RegsLoadedForRef := RegsLoadedForRef -
+ [RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg)];
+{$ifdef csdebug}
+ Writeln(std_reg2str[RegMaxSize(PInstr(NewP)^.oper[1].reg)], ' removed');
+{$endif csdebug}
+ end;
+ InstructionsEquivalent :=
+ OpsEquivalent(PInstr(OldP)^.oper[LoadSrc],
+ PInstr(NewP)^.oper[LoadSrc], OpAct_Read) And
+ OpsEquivalent(PInstr(OldP)^.oper[LoadDst],
+ PInstr(NewP)^.oper[LoadDst], OpAct_Write)
+ End
+ Else
+{ OldP and NewP are not a load instruction, but have the same structure }
+{ (opcode, operand types), so they're equivalent if all operands are }
+{ equivalent }
+ Begin
+ Count := 0;
+ TmpResult := true;
+ Repeat
+ TmpResult :=
+ OpsEquivalent(PInstr(OldP)^.oper[Count], PInstr(NewP)^.oper[Count],
+ OpAct_Unknown);
+ Inc(Count)
+ Until (Count = MaxOps) or not(TmpResult);
+ InstructionsEquivalent := TmpResult
+ End
+{ the instructions haven't even got the same structure, so they're certainly }
+{ not equivalent }
+ Else InstructionsEquivalent := False;
+End;
+
+
+Function TRegInfo.CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint):
+ Boolean;
+{checks whether the current instruction sequence (starting with p) and the
+ one between StartMod and EndMod of Reg are the same. If so, the number of
+ instructions that match is stored in Found and true is returned, otherwise
+ Found holds the number of instructions between StartMod and EndMod and false
+ is returned}
+
+{ note: the NrOfMods field can hold two deifferent values depending on }
+{ which instruction it belongs to: }
+{ * if it is the first instruction of a sequence that describes the }
+{ contents of a register, NrOfMods contains how many instructions are }
+{ in the sequence }
+{ * otherwise, NrOfMods contains how many instructions are in the }
+{ describing the contents of the register after the current instruction }
+{ has been executed }
+
+Var oldp, newp: Pai;
+ PrevNonRemovablePai: Pai;
+ OrgRegInfo, HighRegInfo: PRegInfo;
+ HighFound, OrgRegFound: Byte;
+ RegCounter: TRegister;
+ OrgRegResult: Boolean;
+ TmpResult: Boolean;
+ OldNrOfMods: Byte;
+Begin {CheckSequence}
+ Reg := RegMaxSize(Reg);
+{ have we found a sequence of instructions equivalent to the new one? }
+ TmpResult := False;
+{ HighRegInfo will contain the RegInfo for the longest sequence of matching }
+{ instructions found }
+ New(HighRegInfo, Init);
+{ how many instructions are in the sequence describing the content of Reg }
+{ (the parameter) in the old sequence }
+ OrgRegFound := 0;
+{ how many instructions are in the longest sequence of matching }
+{ instructions found until now? }
+ HighFound := 0;
+{ does the content of Reg in the old equence match the content of Reg in }
+{ the new sequence }
+ OrgRegResult := False;
+ RegCounter := LoGPReg;
+{ PrevNonRemovablePai's OptInfo contains the contents of the registers }
+{ before the current instruction is executed. It will be used to compare }
+{ the new contents with and to see whether the new instructions can be }
+{ removed }
+ GetLastInstruction(p, PrevNonRemovablePai);
+{ don't check registers that only contain a constant or something unknown }
+ While (RegCounter <= HiGPReg And
+ (PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].Typ <> Con_Ref) Do
+ Inc(RegCounter);
+ While (RegCounter <= HiGPReg) Do
+ Begin
+ { reinitialize the reginfo fields }
+ Init;
+ { no matching instructions found yet }
+ Found := 0;
+ With PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter] Do
+ Begin
+ { get the first instruction that describes the content of the }
+ { the register we're going to check the way it was before the }
+ { current instruction got executed }
+ oldp := StartMod;
+ { how many instructions describe the content of the register }
+ { before the current instructions got executed? }
+ OldNrOfMods := NrOfMods
+ End;
+ { p is the first instruction that describes the content of Reg }
+ { after p (= the current instruction) got executed }
+ newp := p;
+ { it's possible that the old contents of the current register are }
+ { described by a sequence of instructions that also contains the }
+ { one in parameter p. In that case, we have to compare until we }
+ { encounter p. Otherwise, compare as much instructions as there are }
+ { in the old sequence or until there's a mismatch }
+ While (p <> oldp) And
+ (Found < OldNrOfMods) And
+ { old new }
+ InstructionsEquivalent(oldp, newp, RegInfo) Do
+ Begin
+ GetNextInstruction(oldp, oldp);
+ GetNextInstruction(newp, newp);
+ Inc(Found)
+ End;
+ If (Found < OldNrOfMods) Then
+ Begin
+ { the old sequence was longer than than the new one, so no match }
+ TmpResult := False;
+ { If there is no match, we have to set the CanBeRemoved flag of }
+ { all pai objects part of the new sequence to false, because it's }
+ { possible that some of them have already been scheduled for }
+ { removal after checking another sequence (an instruction can be }
+ { of more than one sequence). If we return false, the number }
+ { returned in found denotes how many instructions have to have }
+ { their CanBeRemoved flag set to false }
+ { We only have to set those flags to false if their was a partial }
+ { match of instructions (found > 0), because otherwise they can't }
+ { have been set to true in a previous comparison }
+ If (found > 0) Then
+ Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
+ End
+ Else TmpResult := True;
+ If (RegCounter = Reg) Then
+ Begin
+ OrgRegFound := Found;
+ OrgRegResult := TmpResult;
+ New(OrgRegInfo, InitWithValue(RegInfo));
+ End
+ Else
+ If TmpResult And
+ (Found > HighFound) Then
+ Begin
+ HighFound := Found;
+ HighRegInfo^.InitWithValue(RegInfo);
+ End;
+ RegInfo.Done;
+ Repeat
+ Inc(RegCounter);
+ Until (RegCounter > HiGPReg) or
+ (PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].Typ =
+ Con_Ref);
+ End;
+ If (HighFound > 0) And
+ (Not(OrgRegResult) Or
+ (HighFound > OrgRegFound)) Then
+ Begin
+ CheckSequence := True;
+ Found := HighFound
+ InitWithValue(HighRegInfo);
+ End
+ Else
+ Begin
+ CheckSequence := OrgRegResult;
+ Found := OrgRegFound;
+ InitWithValue(OrgRegInfo);
+ End;
+ Dispose(HighRegInfo, Done);
+ Dispose(OrgRegInfo, Done)
+End; {CheckSequence}
+
+
+{ ************************************************************************* }
+{ ******************************* TAOptCSE ******************************** }
+{ ************************************************************************* }
+
+
+Function TAOptCSE.RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
+Var hp: Pai;
+Begin
+ If GetLastInstruction(p1, hp)
+ Then
+ RegModifiedByInstruction :=
+ PPAiProp(p1^.OptInfo)^.GetWState <>
+ PPAiProp(hp^.OptInfo)^.GetWState
+ Else RegModifiedByInstruction := True;
+End;
+
+Procedure TAoptCSE.RestoreContents(Current: Pai; Reg: TRegister);
+Var Prev, hp3, hp5: Pai;
+ TmpState: TStateInt;
+ Cnt, Cnt2: Byte;
+Begin
+{ load Cnt2 with the total number of instructions of this sequence }
+ Cnt2 := PPaiProp(Prev^.OptInfo)^.Regs[RegInfo.New2OldReg[reg]].
+ NrOfMods;
+{ sometimes, a register can not be removed from a sequence, because it's }
+{ still used afterwards: }
+{ }
+{ movl -8(%ebp), %eax movl -8(%ebp), %eax }
+{ movl 70(%eax), %eax movl 70(%eax), %eax }
+{ cmpl 74(%eax), %eax cmpl 74(%eax), %eax }
+{ jne l1 can't be changed to jne l1 }
+{ movl -8(%ebp), %eax }
+{ movl 70(%eax), %edi movl %eax, %edi }
+{ boundl R_282, %edi boundl R_282, %edi }
+{ pushl 70(%eax) pushl 70(%eax) }
+{ }
+{ because eax now contains the wrong value when 70(%eax) is pushed }
+
+{ start at the first instruction of the sequence }
+ hp3 := Current;
+ For Cnt := 1 to Pred(Cnt2) Do
+ GetNextInstruction(hp3, hp3);
+{ hp3 now containts the last instruction of the sequence }
+{ get the writestate at this point of the register in TmpState }
+ TmpState := PPaiProp(hp3^.OptInfo)^.GetWState(reg);
+{ hp3 := first instruction after the sequence }
+ GetNextInstruction(hp3, hp3);
+
+{ now, even though reg is in RegsLoadedForRef, sometimes it's still used }
+{ afterwards. It is not if either it is not in usedregs anymore after the }
+{ sequence, or if it is loaded with a new value right after the sequence }
+ If (TmpState <> PPaiProp(hp3^.OptInfo)^.Regs[reg].WState) Or
+ Not(reg in PPaiProp(hp3^.OptInfo)^.UsedRegs) Then
+{ the register is not used anymore after the sequence! }
+ Begin
+{$ifdef csdebug}
+ Writeln('Cnt2: ',Cnt2);
+ hp5 := new(pai_asm_comment,init(strpnew('starting here...')));
+ InsertLLItem(Pai(Current^.previous), Current, hp5);
+{$endif csdebug}
+ hp3 := Current;
+{ first change the contents of the register inside the sequence }
+ For Cnt := 1 to Cnt2 Do
+ Begin
+ {save the WState of the last pai object of the sequence for later use}
+ TmpState := PPaiProp(hp3^.OptInfo)^.Regs[reg].WState;
+{$ifdef csdebug}
+ hp5 := new(pai_asm_comment,init(strpnew('WState for '+
+ std_reg2str[reg]+': '+tostr(tmpstate))));
+ InsertLLItem(hp3, pai(hp3^.next), hp5);
+{$endif csdebug}
+ PPaiProp(hp3^.OptInfo)^.Regs[reg] :=
+ PPaiProp(Prev^.OptInfo)^.Regs[reg];
+ GetNextInstruction(hp3, hp3);
+ End;
+{ here, hp3 = p = Pai object right after the sequence, TmpState = WState of }
+{ reg at the last Pai object of the sequence }
+ GetLastInstruction(hp3, hp3);
+{ now, as long as the register isn't modified after the sequence, set its }
+{ contents to what they were before the sequence }
+ While GetNextInstruction(hp3, hp3) And
+ (PPaiProp(hp3^.OptInfo)^.GetWState(Reg) = TmpState) Do
+{$ifdef csdebug}
+ begin
+ hp5 := new(pai_asm_comment,init(strpnew('WState for '+std_reg2str[reg]+': '+
+ tostr(PPaiProp(hp3^.OptInfo)^.GetWState(reg)))));
+ InsertLLItem(hp3, pai(hp3^.next), hp5);
+{$endif csdebug}
+ PPaiProp(hp3^.OptInfo)^.Regs[reg] :=
+ PPaiProp(Prev^.OptInfo)^.Regs[reg];
+{$ifdef csdebug}
+ end;
+{$endif csdebug}
+ End
+ Else
+{ the register is still used after the sequence, so undelete all }
+{ instructions in the sequence that modify reg }
+ Begin
+{$ifdef csdebug}
+ Writeln('Got there for ',std_reg2str[reg]);
+{$endif csdebug}
+ hp3 := Current;
+ For Cnt := 1 to Cnt2 Do
+ Begin
+ If RegModifiedByInstruction(reg, hp3) Then
+ PPaiProp(hp3^.OptInfo)^.CanBeRemoved := False;
+ GetNextInstruction(hp3, hp3);
+ End;
+ End;
+{$ifdef csdebug}
+ hp5 := new(pai_asm_comment,init(strpnew('stopping here...')));
+ InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
+{$endif csdebug}
+End;
+
+Procedure TAoptCSE.DoCSE;
+{marks the instructions that can be removed by RemoveInstructs. They're not
+ removed immediately because sometimes an instruction needs to be checked in
+ two different sequences}
+Var Cnt, Cnt2: Longint;
+ p, hp1, Current: Pai;
+ hp3, Prev: Pai;
+{$ifdef csdebug}
+ hp5: pai;
+{$endif csdebug}
+ RegInfo: TRegInfo;
+ RegCounter: TRegister;
+ TmpState: Byte;
+Begin
+ p := SkipHead(BlockStart);
+ While (p <> BlockEnd) Do
+ Begin
+ Case p^.typ Of
+ ait_instruction:
+ Begin
+{ Case PInstr(p)^.opcode Of
+ A_CLD: If GetLastInstruction(p, hp1) And
+ (PPaiProp(hp1^.OptInfo)^.DirFlag = F_NotSet) Then
+ PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;}
+ If IsLoadMemReg(p) Then
+ Begin
+ If (p = PPaiProp(p^.OptInfo)^.Regs[RegMaxSize(
+ PInstr(p)^.oper[LoadDst].reg)].StartMod) And
+ GetLastInstruction (p, hp1) And
+ (hp1^.typ <> ait_marker) Then
+{so we don't try to check a sequence when p is the first instruction of the block}
+ If CheckSequence(p, PInstr(p)^.oper[LoadDst].reg, Cnt) And
+ (Cnt > 0) Then
+ Begin
+ hp1 := nil;
+{ although it's perfectly ok to remove an instruction which doesn't contain }
+{ the register that we've just checked (CheckSequence takes care of that), }
+{ the sequence containing this other register should also be completely }
+{ checked (and either removed or marked as non-removable), otherwise we }
+{ may get situations like this: }
+{ }
+{ movl 12(%ebp), %edx movl 12(%ebp), %edx }
+{ movl 16(%ebp), %eax movl 16(%ebp), %eax }
+{ movl 8(%edx), %edx movl 8(%edx), %edx }
+{ movl (%eax), eax movl (%eax), eax }
+{ cmpl %eax, %edx cmpl %eax, %edx }
+{ jnz l123 getting converted to jnz l123 }
+{ movl 12(%ebp), %edx movl 4(%eax), eax }
+{ movl 16(%ebp), %eax }
+{ movl 8(%edx), %edx }
+{ movl 4(%eax), eax }
+ Current := p;
+ Cnt2 := 1;
+{ after this while loop, if hp1 <> nil it will contain the pai object }
+{ that's the start of a sequence that's not completely checked yet }
+ While Cnt2 <= Cnt Do
+ Begin
+ If (hp1 = nil) And
+ Not(RegInInstruction(
+ PInstr(Current)^.oper[LoadDst].reg,p) Or
+ RegInInstruction(RegMaxSize(PInstr(
+ Current)^.oper[LoadDst].reg), p)) And
+{ do not recheck a sequence if it's completely part of the one we just }
+{ checked }
+ Not(IsLoadMemReg(p) And
+ (PPaiProp(p^.OptInfo)^.Regs[RegMaxSize(
+ PInstr(p)^.Oper[LoadDst].reg)]
+ .NrOfMods <= (Cnt - Cnt2 + 1))) Then
+ hp1 := p;
+{$ifndef noremove}
+ PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
+{$endif noremove}
+ Inc(Cnt2);
+ GetNextInstruction(p, p);
+ End;
+{ insert a marker noting that for the following instructions no PPaiProp's }
+{ (containing optimizer info) have been generated, so GetNext/ }
+{ LastInstruction will ignore them (it will use the original instructions) }
+ hp3 := New(Pai_Marker,Init(NoPropInfoStart));
+ InsertLLItem(Pai(Current^.Previous), Current, hp3);
+{ Prev is used to get the contents of the registers before the sequence }
+ GetLastInstruction(Current, Prev);
+{ If some registers were different in the old and the new sequence, move }
+{ the contents of those old registers to the new ones, e.g. }
+{ }
+{ mov mem1, reg1 mov mem1, reg1 }
+{ ... can be changed to ... }
+{ mov mem1, reg2 mov reg1, reg2 }
+
+{$IfDef CSDebug}
+ For RegCounter := LoGPReg To HiGPReg Do
+ If (RegCounter in RegInfo.RegsLoadedForRef) Then
+ Begin
+ hp5 := new(pai_asm_comment,init(strpnew(
+ 'New: '+std_reg2str[RegCounter]+', Old: '+
+ std_reg2str[RegInfo.New2OldReg[RegCounter]])));
+ InsertLLItem(AsmL, Pai(Current^.previous), Current, hp5);
+ End;
+{$EndIf CSDebug}
+ For RegCounter := LoGPReg to HiGPReg Do
+ Begin
+{ if New2OldReg[RegCounter] = R_NO, it means this register doesn't appear }
+{ the new nor the old sequence }
+ If (RegInfo.New2OldReg[RegCounter] <> R_NO) Then
+{ if a register is in RegsLoadedForRef, it means this register was loaded }
+{ with a value only to function as a base or index in a reference. The }
+{ practical upshot of this is that this value won't be used anymore later }
+{ on, so even if another register was used in the new sequence for this, }
+{ we don't have to load it. E.g. }
+{ }
+{ movl 8(%ebp), %eax " }
+{ movl 4(%eax), %eax " }
+{ movl (%eax), %edi " }
+{ movl %edi, 12(%ebp) " }
+{ ... can be changed to " }
+{ movl 8(%ebp), %edx }
+{ movl 4(%edx), %edx }
+{ movl (%edx), %ebx movl %edi, %ebx }
+{ }
+{ There is no need to also add a "movl %eax, %edx" }
+ If Not(RegCounter In RegInfo.RegsLoadedForRef) And
+ {old reg new reg}
+{ no need to reload the register if it's the same in the old and new }
+{ sequence }
+ (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
+
+ Begin
+ hp3 := a_load_reg_reg(
+ {old reg new reg}
+ RegInfo.New2OldReg[RegCounter], RegCounter));
+ InsertLLItem(Pai(Current^.previous), Current, hp3);
+ End
+ Else
+{ As noted before, if a register is in RegsLoadedForRef, it doesn't have }
+{ to be loaded. However, when data flow analyzer processed this code, the }
+{ was loaded, so we need to change that. This is done by setting the }
+{ contents of the register to its contents before the new sequence, for }
+{ every instruction until the first load of the register with a new value }
+ If (RegCounter In RegInfo.RegsLoadedForRef) Then
+ RestoreOrigContents(Current, RegCounter);
+
+ End;
+{ the end of the area where instructions without optimizer info can occur }
+ hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
+ InsertLLItem(AsmL, Pai(Current^.Previous), Current, hp3);
+{ if we found an instruction sequence that needs complete re-evaluation, }
+{ process it }
+ If hp1 <> nil Then p := hp1;
+ Continue;
+ End
+ Else
+{ checksequence returned false. In that case, if the current instruction }
+{ was already deleted (as part of another sequence), we have to undelete }
+{ all instructions pertaining to the register whose sequence we just }
+{ checked }
+ If (Cnt > 0) And
+ (PPaiProp(p^.OptInfo)^. Regs[RegMaxSize(PInstr(p)^.
+ oper[LoadDst].reg)].Typ = Con_Ref) And
+ (PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
+ Begin
+ Current := p;
+ Cnt2 := 1;
+ While Cnt2 <= Cnt Do
+ Begin
+ If RegInInstruction(PInstr(Current)^.
+ oper[LoadDst].reg, p) Or
+ RegInInstruction(RegMaxSize(PInstr(Current)^.
+ oper[LoadDst].reg), p) Then
+ PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
+ Inc(Cnt2);
+ GetNextInstruction(p, p);
+ End;
+ Continue;
+ End;
+ End
+ Else if IsLoadConstReg(p) Then
+ Begin
+ If GetLastInstruction(p, hp1) Then
+ With PPaiProp(hp1^.OptInfo)^.Regs[
+ RegMaxSize(PInstr(p)^.oper[LoadDst].reg)] Do
+ If (Typ = Con_Const) And
+ (StartMod = p) Then
+ PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
+ End
+ Else
+ CpuCSE(p);
+{ A_STD: If GetLastInstruction(p, hp1) And
+ (PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then
+ PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
+ A_XOR:
+ Begin
+ If (Paicpu(p)^.oper[0].typ = top_reg) And
+ (Paicpu(p)^.oper[0].typ = top_reg) And
+ (Paicpu(p)^.oper[1].reg = Paicpu(p)^.oper[1].reg) And
+ GetLastInstruction(p, hp1) And
+ (PPaiProp(hp1^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)].typ = con_const) And
+ (PPaiProp(hp1^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)].StartMod = nil)
+ Then PPaiProp(p^.OptInfo)^.CanBeRemoved := True
+ End
+ End;
+ End;
+ GetNextInstruction(p, p);
+ End;
+End;
+
+Procedure RemoveInstructs;
+{Removes the marked instructions and disposes the PPaiProps of the other
+ instructions, restoring their line number}
+Var p, hp1: Pai;
+ InstrCnt: Longint;
+Begin
+ p := SkipHead(BlockStart);
+ InstrCnt := 1;
+ While (p <> BlockEnd) Do
+ Begin
+{$ifndef noinstremove}
+ If PPaiProp(p^.OptInfo)^.CanBeRemoved
+ Then
+ Begin
+ Dispose(PPaiProp(p^.OptInfo));
+ GetNextInstruction(p, hp1);
+ AsmL^.Remove(p);
+ Dispose(p, Done);
+ p := hp1;
+ Inc(InstrCnt);
+ End
+ Else
+{$endif noinstremove}
+ Begin
+ Dispose(PPaiProp(p^.OptInfo));
+ p^.OptInfo := nil;
+ GetNextInstruction(p, p);
+ Inc(InstrCnt);
+ End;
+ End;
+End;
+
+Procedure TAoptCSE.CSE;
+Begin
+ DoCSE;
+ RemoveInstructs;
+End;
+
+
+
+End.
diff --git a/compiler/aoptda.pas b/compiler/aoptda.pas
new file mode 100644
index 0000000000..25bc035898
--- /dev/null
+++ b/compiler/aoptda.pas
@@ -0,0 +1,183 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the data flow analyzer object of the assembler
+ optimizer.
+
+ 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 aoptda;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ cpubase,cgbase,
+ aasmbase,aasmtai,aasmcpu,
+ aoptcpub, aoptbase;
+
+ Type
+ TAOptDFA = class
+ { uses the same constructor as TAoptCpu = constructor from TAoptObj }
+
+ { gathers the information regarding the contents of every register }
+ { at the end of every instruction }
+ Procedure DoDFA;
+
+ { handles the processor dependent dataflow analizing }
+ Procedure CpuDFA(p: PInstr); Virtual;
+
+ { How many instructions are between the current instruction and the }
+ { last one that modified the register }
+ InstrSinceLastMod: TInstrSinceLastMod;
+
+ { convert a TInsChange value into the corresponding register }
+ //!!!!!!!!!! Function TCh2Reg(Ch: TInsChange): TRegister; Virtual;
+ { returns whether the instruction P reads from register Reg }
+ Function RegReadByInstr(Reg: TRegister; p: tai): Boolean; Virtual;
+ End;
+
+ Implementation
+
+ uses
+ globals, aoptobj;
+
+ Procedure TAOptDFA.DoDFA;
+ { Analyzes the Data Flow of an assembler list. Analyses the reg contents }
+ { for the instructions between blockstart and blockend. Returns the last pai }
+ { which has been processed }
+ Var
+ CurProp: TPaiProp;
+ UsedRegs: TUsedRegs;
+ p, hp, NewBlockStart : tai;
+ TmpReg: TRegister;
+ Begin
+ {!!!!!!!!!!
+ p := BlockStart;
+ UsedRegs.Create;
+ UsedRegs.Update(p);
+ NewBlockStart := SkipHead(p);
+ { done implicitely by the constructor
+ FillChar(InstrSinceLastMod, SizeOf(InstrSinceLastMod), 0); }
+ While (P <> BlockEnd) Do
+ Begin
+ CurProp:=TPaiProp.Create;
+ If (p <> NewBlockStart) Then
+ Begin
+ GetLastInstruction(p, hp);
+ CurProp.Regs := TPaiProp(hp.OptInfo).Regs;
+ { !!!!!!!!!!!! }
+ {$ifdef x86}
+ CurProp.CondRegs.Flags :=
+ TPaiProp(hp.OptInfo).CondRegs.Flags;
+ {$endif}
+ End;
+ CurProp.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
+ UsedRegs.Update(tai(p.Next));
+ TPaiProp(p.OptInfo) := CurProp;
+ For TmpReg := LoGPReg To HiGPReg Do
+ Inc(InstrSinceLastMod[TmpReg]);
+ Case p^.typ Of
+ ait_label:
+ If (Pai_label(p)^.l^.is_used) Then
+ CurProp^.DestroyAllRegs(InstrSinceLastMod);
+ ait_stab, ait_force_line, ait_function_name:;
+ ait_instruction:
+ if not(PInstr(p)^.is_jmp) then
+ begin
+ If IsLoadMemReg(p) Then
+ Begin
+ CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
+ TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
+ If RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^) And
+ (CurProp^.GetRegContentType(TmpReg) = Con_Ref) Then
+ Begin
+ { a load based on the value this register already }
+ { contained }
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ CurProp^.IncWState(TmpReg);
+ {also store how many instructions are part of the }
+ { sequence in the first instruction's PPaiProp, so }
+ { it can be easily accessed from within }
+ { CheckSequence }
+ Inc(NrOfMods, InstrSinceLastMod[TmpReg]);
+ PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
+ InstrSinceLastMod[TmpReg] := 0
+ End
+ End
+ Else
+ Begin
+ { load of a register with a completely new value }
+ CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
+ If Not(RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^)) Then
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ Typ := Con_Ref;
+ StartMod := p;
+ NrOfMods := 1;
+ End
+ End;
+ {$ifdef StateDebug}
+ hp := new(pai_asm_comment,init(strpnew(std_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
+ InsertLLItem(AsmL, p, p^.next, hp);
+ {$endif StateDebug}
+
+ End
+ Else if IsLoadConstReg(p) Then
+ Begin
+ TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
+ typ := Con_Const;
+ StartMod := Pointer(PInstr(p)^.oper[LoadSrc].val);
+ End
+ End
+ Else CpuDFA(Pinstr(p));
+ End;
+ Else CurProp^.DestroyAllRegs(InstrSinceLastMod);
+ End;
+ { Inc(InstrCnt);}
+ GetNextInstruction(p, p);
+ End;
+ }
+ End;
+
+ Procedure TAoptDFA.CpuDFA(p: PInstr);
+ Begin
+ Abstract;
+ End;
+
+ {!!!!!!!
+ Function TAOptDFA.TCh2Reg(Ch: TInsChange): TRegister;
+ Begin
+ TCh2Reg:=R_NO;
+ Abstract;
+ End;
+ }
+
+ Function TAOptDFA.RegReadByInstr(Reg: TRegister; p: tai): Boolean;
+ Begin
+ RegReadByInstr:=false;
+ Abstract;
+ End;
+
+
+End.
diff --git a/compiler/aoptobj.pas b/compiler/aoptobj.pas
new file mode 100644
index 0000000000..49a1698a0e
--- /dev/null
+++ b/compiler/aoptobj.pas
@@ -0,0 +1,1125 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor independent assembler optimizer
+ object, base for the dataflow analyzer, peepholeoptimizer and
+ common subexpression elimination objects.
+
+ 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 AoptObj;
+
+ {$i fpcdefs.inc}
+
+ { general, processor independent objects for use by the assembler optimizer }
+
+ Interface
+
+ uses
+ globtype,
+ aasmbase,aasmcpu,aasmtai,
+ cclasses,
+ cgbase,cgutils,
+ cpubase,
+ aoptbase,aoptcpub,aoptda;
+
+ { ************************************************************************* }
+ { ********************************* Constants ***************************** }
+ { ************************************************************************* }
+
+ Const
+
+ {Possible register content types}
+ con_Unknown = 0;
+ con_ref = 1;
+ con_const = 2;
+
+ {***************** Types ****************}
+
+ Type
+
+ { ************************************************************************* }
+ { ************************* Some general type definitions ***************** }
+ { ************************************************************************* }
+ TRefCompare = Function(r1, r2: TReference): Boolean;
+ //!!! FIXME
+ TRegArray = Array[byte] of tsuperregister;
+ TRegSet = Set of byte;
+ { possible actions on an operand: read, write or modify (= read & write) }
+ TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
+
+ { ************************************************************************* }
+ { * Object to hold information on which regiters are in use and which not * }
+ { ************************************************************************* }
+ TUsedRegs = class
+ Constructor create;
+ Constructor create_regset(Const _RegSet: TRegSet);
+
+ Destructor Destroy;override;
+ { update the info with the pairegalloc objects coming after }
+ { p }
+ Procedure Update(p: Tai);
+ { is Reg currently in use }
+ Function IsUsed(Reg: TRegister): Boolean;
+ { get all the currently used registers }
+ Function GetUsedRegs: TRegSet;
+
+ Private
+
+ UsedRegs: TRegSet;
+ End;
+
+ { ************************************************************************* }
+ { ******************* Contents of the integer registers ******************* }
+ { ************************************************************************* }
+
+ { size of the integer that holds the state number of a register. Can be any }
+ { integer type, so it can be changed to reduce the size of the TContent }
+ { structure or to improve alignment }
+ TStateInt = Byte;
+
+ TContent = Record
+ { start and end of block instructions that defines the }
+ { content of this register. If Typ = con_const, then }
+ { Longint(StartMod) = value of the constant) }
+ StartMod: Tai;
+ { starts at 0, gets increased everytime the register is }
+ { written to }
+ WState: TStateInt;
+ { starts at 0, gets increased everytime the register is read }
+ { from }
+ RState: TStateInt;
+ { how many instructions starting with StarMod does the block }
+ { consist of }
+ NrOfMods: Byte;
+ { the type of the content of the register: unknown, memory }
+ { (variable) or constant }
+ Typ: Byte;
+ End;
+
+ //!!! FIXME
+ TRegContent = Array[byte] Of TContent;
+
+ { ************************************************************************** }
+ { information object with the contents of every register. Every Tai object }
+ { gets one of these assigned: a pointer to it is stored in the OptInfo field }
+ { ************************************************************************** }
+
+ TPaiProp = class(TAoptBaseCpu)
+ Regs: TRegContent;
+ { info about allocation of general purpose integer registers }
+ UsedRegs: TUsedRegs;
+ { can this instruction be removed? }
+ CanBeRemoved: Boolean;
+
+ Constructor create;
+
+ { checks the whole sequence of which (so regs[which].StartMod and and }
+ { the next NrOfMods Tai objects) to see whether Reg is used somewhere, }
+ { without it being loaded with something else first }
+ Function RegInSequence(Reg, which: TRegister): Boolean;
+ { destroy the contents of a register, as well as those whose contents }
+ { are based on those of that register }
+ Procedure DestroyReg(Reg: TRegister; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ { if the contents of WhichReg (can be R_NO in case of a constant) are }
+ { written to memory at the location Ref, the contents of the registers }
+ { that depend on Ref have to be destroyed }
+ Procedure DestroyRefs(Const Ref: TReference; WhichReg: TRegister; var
+ InstrSinceLastMod: TInstrSinceLastMod);
+
+ { an instruction reads from operand o }
+ Procedure ReadOp(const o:toper);
+ { an instruction reads from reference Ref }
+ Procedure ReadRef(Ref: PReference);
+ { an instruction reads from register Reg }
+ Procedure ReadReg(Reg: TRegister);
+
+ { an instruction writes/modifies operand o and this has special }
+ { side-effects or modifies the contents in such a way that we can't }
+ { simply add this instruction to the sequence of instructions that }
+ { describe the contents of the operand, so destroy it }
+ Procedure DestroyOp(const o:Toper; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ { destroy the contents of all registers }
+ Procedure DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
+ { a register's contents are modified, but not destroyed (the new value }
+ { depends on the old one) }
+ Procedure ModifyReg(reg: TRegister; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ { an operand's contents are modified, but not destroyed (the new value }
+ { depends on the old one) }
+ Procedure ModifyOp(const oper: TOper; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+
+ { increase the write state of a register (call every time a register is }
+ { written to) }
+ Procedure IncWState(Reg: TRegister);
+ { increase the read state of a register (call every time a register is }
+ { read from) }
+ Procedure IncRState(Reg: TRegister);
+ { get the write state of a register }
+ Function GetWState(Reg: TRegister): TStateInt;
+ { get the read state of a register }
+ Function GetRState(Reg: TRegister): TStateInt;
+
+ { get the type of contents of a register }
+ Function GetRegContentType(Reg: TRegister): Byte;
+
+ Destructor Done;
+
+ Private
+
+ Procedure IncState(var s: TStateInt);
+
+ { returns whether the reference Ref is used somewhere in the loading }
+ { sequence Content }
+ Function RefInSequence(Const Ref: TReference; Content: TContent;
+ RefsEq: TRefCompare): Boolean;
+
+ { returns whether the instruction P reads from and/or writes }
+ { to Reg }
+ Function RefInInstruction(Const Ref: TReference; p: Tai;
+ RefsEq: TRefCompare): Boolean;
+
+ { returns whether two references with at least one pointing to an array }
+ { may point to the same memory location }
+
+ End;
+
+
+ { ************************************************************************* }
+ { ************************ Label information ****************************** }
+ { ************************************************************************* }
+ TLabelTableItem = Record
+ PaiObj: Tai;
+ End;
+
+ {$ifndef TP}
+ TLabelTable = Array[0..2500000] Of TLabelTableItem;
+ {$else TP}
+ TLabelTable = Array[0..(65520 div sizeof(TLabelTableItem))] Of TLabelTableItem;
+ {$endif TP}
+ PLabelTable = ^TLabelTable;
+ PLabelInfo = ^TLabelInfo;
+ TLabelInfo = Record
+ { the highest and lowest label number occurring in the current code }
+ { fragment }
+ LowLabel, HighLabel: AWord;
+ LabelDif: AWord;
+ { table that contains the addresses of the Pai_Label objects associated
+ with each label number }
+ LabelTable: PLabelTable;
+ End;
+
+ { ************************************************************************* }
+ { ********** General optimizer object, used to derive others from ********* }
+ { ************************************************************************* }
+
+ TAOptObj = class(TAoptBaseCpu)
+ { the PAasmOutput list this optimizer instance works on }
+ AsmL: TAasmOutput;
+
+ { The labelinfo record contains the addresses of the Tai objects }
+ { that are labels, how many labels there are and the min and max }
+ { label numbers }
+ LabelInfo: PLabelInfo;
+
+ { Start and end of the block that is currently being optimized }
+ BlockStart, BlockEnd: Tai;
+
+ DFA: TAOptDFA;
+ { _AsmL is the PAasmOutpout list that has to be optimized, }
+ { _BlockStart and _BlockEnd the start and the end of the block }
+ { that has to be optimized and _LabelInfo a pointer to a }
+ { TLabelInfo record }
+ Constructor create(_AsmL: TAasmOutput; _BlockStart, _BlockEnd: Tai;
+ _LabelInfo: PLabelInfo); virtual;
+
+ { processor independent methods }
+
+ { returns true if the label L is found between hp and the next }
+ { instruction }
+ Function FindLabel(L: TasmLabel; Var hp: Tai): Boolean;
+
+ { inserts new_one between prev and foll in AsmL }
+ Procedure InsertLLItem(prev, foll, new_one: TLinkedListItem);
+
+
+ { If P is a Tai object releveant to the optimizer, P is returned
+ If it is not relevant tot he optimizer, the first object after P
+ that is relevant is returned }
+ Function SkipHead(P: Tai): Tai;
+
+ { returns true if the operands o1 and o2 are completely equal }
+ Function OpsEqual(const o1,o2:toper): Boolean;
+
+ { Returns true if a ait_alloc object for Reg is found in the block
+ of Tai's starting with StartPai and ending with the next "real"
+ instruction }
+ Function FindRegAlloc(Reg: TRegister; StartPai: Tai): Boolean;
+
+ { traces sucessive jumps to their final destination and sets it, e.g.
+ je l1 je l3
+ <code> <code>
+ l1: becomes l1:
+ je l2 je l3
+ <code> <code>
+ l2: l2:
+ jmp l3 jmp l3
+
+ the level parameter denotes how deeep we have already followed the jump,
+ to avoid endless loops with constructs such as "l5: ; jmp l5" }
+ function GetFinalDestination(hp: taicpu; level: longint): boolean;
+
+ function getlabelwithsym(sym: tasmlabel): tai;
+
+ { peephole optimizer }
+ procedure PrePeepHoleOpts;
+ procedure PeepHoleOptPass1;
+ procedure PeepHoleOptPass2;
+ procedure PostPeepHoleOpts;
+
+ { processor dependent methods }
+ // if it returns true, perform a "continue"
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; virtual;
+ function PostPeepHoleOptsCpu(var p: tai): boolean; virtual;
+ End;
+
+ Function ArrayRefsEq(const r1, r2: TReference): Boolean;
+
+ { ***************************** Implementation **************************** }
+
+ Implementation
+
+ uses
+ globals,
+ verbose,
+ procinfo;
+
+ { ************************************************************************* }
+ { ******************************** TUsedRegs ****************************** }
+ { ************************************************************************* }
+
+ Constructor TUsedRegs.create;
+ Begin
+ UsedRegs := [];
+ End;
+
+ Constructor TUsedRegs.create_regset(Const _RegSet: TRegSet);
+ Begin
+ UsedRegs := _RegSet;
+ End;
+
+ Procedure TUsedRegs.Update(p: Tai);
+ {updates UsedRegs with the RegAlloc Information coming after P}
+ Begin
+ Repeat
+ While Assigned(p) And
+ ((p.typ in (SkipInstr - [ait_RegAlloc])) or
+ ((p.typ = ait_label) And
+ Not(Tai_Label(p).l.is_used))) Do
+ p := Tai(p.next);
+ While Assigned(p) And
+ (p.typ=ait_RegAlloc) Do
+ Begin
+ {!!!!!!!! FIXME
+ if tai_regalloc(p).ratype=ra_alloc then
+ UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
+ else
+ UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
+ p := Tai(p.next);
+ }
+ End;
+ Until Not(Assigned(p)) Or
+ (Not(p.typ in SkipInstr) And
+ Not((p.typ = ait_label) And
+ Not(Tai_Label(p).l.is_used)));
+ End;
+
+ Function TUsedRegs.IsUsed(Reg: TRegister): Boolean;
+ Begin
+ //!!!!!!!!!!! IsUsed := Reg in UsedRegs
+ End;
+
+ Function TUsedRegs.GetUsedRegs: TRegSet;
+ Begin
+ GetUsedRegs := UsedRegs;
+ End;
+
+ Destructor TUsedRegs.Destroy;
+ Begin
+ inherited destroy;
+ end;
+
+ { ************************************************************************* }
+ { **************************** TPaiProp *********************************** }
+ { ************************************************************************* }
+
+ Constructor TPaiProp.Create;
+ Begin
+ {!!!!!!
+ UsedRegs.Init;
+ CondRegs.init;
+ }
+ { DirFlag: TFlagContents; I386 specific}
+ End;
+
+ Function TPaiProp.RegInSequence(Reg, which: TRegister): Boolean;
+ Var p: Tai;
+ RegsChecked: TRegSet;
+ content: TContent;
+ Counter: Byte;
+ TmpResult: Boolean;
+ Begin
+ {!!!!!!!!!!1
+ RegsChecked := [];
+ content := regs[which];
+ p := content.StartMod;
+ TmpResult := False;
+ Counter := 1;
+ While Not(TmpResult) And
+ (Counter <= Content.NrOfMods) Do
+ Begin
+ If IsLoadMemReg(p) Then
+ With PInstr(p)^.oper[LoadSrc]^.ref^ Do
+ If (Base = ProcInfo.FramePointer)
+ {$ifdef RefsHaveIndexReg}
+ And (Index = R_NO)
+ {$endif RefsHaveIndexReg} Then
+ Begin
+ RegsChecked := RegsChecked +
+ [RegMaxSize(PInstr(p)^.oper[LoadDst]^.reg)];
+ If Reg = RegMaxSize(PInstr(p)^.oper[LoadDst]^.reg) Then
+ Break;
+ End
+ Else
+ Begin
+ If (Base = Reg) And
+ Not(Base In RegsChecked)
+ Then TmpResult := True;
+ {$ifdef RefsHaveIndexReg}
+ If Not(TmpResult) And
+ (Index = Reg) And
+ Not(Index In RegsChecked)
+ Then TmpResult := True;
+ {$Endif RefsHaveIndexReg}
+ End
+ Else TmpResult := RegInInstruction(Reg, p);
+ Inc(Counter);
+ GetNextInstruction(p,p)
+ End;
+ RegInSequence := TmpResult
+ }
+ End;
+
+
+ Procedure TPaiProp.DestroyReg(Reg: TRegister; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ { Destroys the contents of the register Reg in the PPaiProp p1, as well as }
+ { the contents of registers are loaded with a memory location based on Reg }
+ Var TmpWState, TmpRState: Byte;
+ Counter: TRegister;
+ Begin
+ {!!!!!!!
+ Reg := RegMaxSize(Reg);
+ If (Reg in [LoGPReg..HiGPReg]) Then
+ For Counter := LoGPReg to HiGPReg Do
+ With Regs[Counter] Do
+ If (Counter = reg) Or
+ ((Typ = Con_Ref) And
+ RegInSequence(Reg, Counter)) Then
+ Begin
+ InstrSinceLastMod[Counter] := 0;
+ IncWState(Counter);
+ TmpWState := GetWState(Counter);
+ TmpRState := GetRState(Counter);
+ FillChar(Regs[Counter], SizeOf(TContent), 0);
+ WState := TmpWState;
+ RState := TmpRState
+ End
+ }
+ End;
+
+ Function ArrayRefsEq(const r1, r2: TReference): Boolean;
+ Begin
+ {!!!!!!!!!!
+ ArrayRefsEq := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
+ {$ifdef refsHaveSegmentReg}
+ (R1.Segment = R2.Segment) And
+ {$endif}
+ (R1.Base = R2.Base) And
+ (R1.Symbol=R2.Symbol);
+ }
+ End;
+
+ Procedure TPaiProp.DestroyRefs(Const Ref: TReference; WhichReg: TRegister;
+ var InstrSinceLastMod: TInstrSinceLastMod);
+ { destroys all registers which possibly contain a reference to Ref, WhichReg }
+ { is the register whose contents are being written to memory (if this proc }
+ { is called because of a "mov?? %reg, (mem)" instruction) }
+ Var RefsEq: TRefCompare;
+ Counter: TRegister;
+ Begin
+ {!!!!!!!!!!!
+ WhichReg := RegMaxSize(WhichReg);
+ If (Ref.base = procinfo.FramePointer) or
+ Assigned(Ref.Symbol) Then
+ Begin
+ If
+ {$ifdef refsHaveIndexReg}
+ (Ref.Index = R_NO) And
+ {$endif refsHaveIndexReg}
+ (Not(Assigned(Ref.Symbol)) or
+ (Ref.base = R_NO)) Then
+ { local variable which is not an array }
+ RefsEq := {$ifdef fpc}@{$endif}RefsEqual
+ Else
+ { local variable which is an array }
+ RefsEq := {$ifdef fpc}@{$endif}ArrayRefsEq;
+ {write something to a parameter, a local or global variable, so
+ * with uncertain optimizations on:
+ - destroy the contents of registers whose contents have somewhere a
+ "mov?? (Ref), %reg". WhichReg (this is the register whose contents
+ are being written to memory) is not destroyed if it's StartMod is
+ of that form and NrOfMods = 1 (so if it holds ref, but is not a
+ pointer or value based on Ref)
+ * with uncertain optimizations off:
+ - also destroy registers that contain any pointer}
+ For Counter := LoGPReg to HiGPReg Do
+ With Regs[Counter] Do
+ Begin
+ If (typ = Con_Ref) And
+ ((Not(cs_UncertainOpts in aktglobalswitches) And
+ (NrOfMods <> 1)
+ ) Or
+ (RefInSequence(Ref,Regs[Counter], RefsEq) And
+ ((Counter <> WhichReg) Or
+ ((NrOfMods <> 1) And
+ {StarMod is always of the type ait_instruction}
+ (PInstr(StartMod)^.oper[0].typ = top_ref) And
+ RefsEq(PInstr(StartMod)^.oper[0].ref^, Ref)
+ )
+ )
+ )
+ )
+ Then
+ DestroyReg(Counter, InstrSinceLastMod)
+ End
+ End
+ Else
+ {write something to a pointer location, so
+ * with uncertain optimzations on:
+ - do not destroy registers which contain a local/global variable or a
+ parameter, except if DestroyRefs is called because of a "movsl"
+ * with uncertain optimzations off:
+ - destroy every register which contains a memory location
+ }
+ For Counter := LoGPReg to HiGPReg Do
+ With Regs[Counter] Do
+ If (typ = Con_Ref) And
+ (Not(cs_UncertainOpts in aktglobalswitches) Or
+ {$ifdef x86}
+ {for movsl}
+ (Ref.Base = R_EDI) Or
+ {$endif}
+ {don't destroy if reg contains a parameter, local or global variable}
+ Not((NrOfMods = 1) And
+ (PInstr(StartMod)^.oper[0].typ = top_ref) And
+ ((PInstr(StartMod)^.oper[0].ref^.base = ProcInfo.FramePointer) Or
+ Assigned(PInstr(StartMod)^.oper[0].ref^.Symbol)
+ )
+ )
+ )
+ Then DestroyReg(Counter, InstrSinceLastMod)
+ }
+ End;
+
+ Procedure TPaiProp.DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
+ Var Counter: TRegister;
+ Begin {initializes/desrtoys all registers}
+ {!!!!!!!!!
+ For Counter := LoGPReg To HiGPReg Do
+ Begin
+ ReadReg(Counter);
+ DestroyReg(Counter, InstrSinceLastMod);
+ End;
+ CondRegs.Init;
+ { FPURegs.Init; }
+ }
+ End;
+
+ Procedure TPaiProp.DestroyOp(const o:Toper; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ Begin
+ {!!!!!!!
+ Case o.typ Of
+ top_reg: DestroyReg(o.reg, InstrSinceLastMod);
+ top_ref:
+ Begin
+ ReadRef(o.ref);
+ DestroyRefs(o.ref^, R_NO, InstrSinceLastMod);
+ End;
+ top_symbol:;
+ End;
+ }
+ End;
+
+ Procedure TPaiProp.ReadReg(Reg: TRegister);
+ Begin
+ {!!!!!!!
+ Reg := RegMaxSize(Reg);
+ If Reg in General_Registers Then
+ IncRState(RegMaxSize(Reg))
+ }
+ End;
+
+ Procedure TPaiProp.ReadRef(Ref: PReference);
+ Begin
+ {!!!!!!!
+ If Ref^.Base <> R_NO Then
+ ReadReg(Ref^.Base);
+ {$ifdef refsHaveIndexReg}
+ If Ref^.Index <> R_NO Then
+ ReadReg(Ref^.Index);
+ {$endif}
+ }
+ End;
+
+ Procedure TPaiProp.ReadOp(const o:toper);
+ Begin
+ Case o.typ Of
+ top_reg: ReadReg(o.reg);
+ top_ref: ReadRef(o.ref);
+ else
+ internalerror(200410241);
+ End;
+ End;
+
+ Procedure TPaiProp.ModifyReg(reg: TRegister; Var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ Begin
+ {!!!!!!!
+ With Regs[reg] Do
+ If (Typ = Con_Ref)
+ Then
+ Begin
+ IncState(WState);
+ {also store how many instructions are part of the sequence in the first
+ instructions PPaiProp, so it can be easily accessed from within
+ CheckSequence}
+ Inc(NrOfMods, InstrSinceLastMod[Reg]);
+ PPaiProp(StartMod.OptInfo)^.Regs[Reg].NrOfMods := NrOfMods;
+ InstrSinceLastMod[Reg] := 0;
+ End
+ Else
+ DestroyReg(Reg, InstrSinceLastMod);
+ }
+ End;
+
+ Procedure TPaiProp.ModifyOp(const oper: TOper; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ Begin
+ If oper.typ = top_reg Then
+ ModifyReg(RegMaxSize(oper.reg),InstrSinceLastMod)
+ Else
+ Begin
+ ReadOp(oper);
+ DestroyOp(oper, InstrSinceLastMod);
+ End
+ End;
+
+ Procedure TPaiProp.IncWState(Reg: TRegister);{$ifdef inl} inline;{$endif inl}
+ Begin
+ //!!!! IncState(Regs[Reg].WState);
+ End;
+
+ Procedure TPaiProp.IncRState(Reg: TRegister);{$ifdef inl} inline;{$endif inl}
+ Begin
+ //!!!! IncState(Regs[Reg].RState);
+ End;
+
+ Function TPaiProp.GetWState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl}
+ Begin
+ //!!!! GetWState := Regs[Reg].WState
+ End;
+
+ Function TPaiProp.GetRState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl}
+ Begin
+ //!!!! GetRState := Regs[Reg].RState
+ End;
+
+ Function TPaiProp.GetRegContentType(Reg: TRegister): Byte; {$ifdef inl} inline;{$endif inl}
+ Begin
+ //!!!! GetRegContentType := Regs[Reg].typ
+ End;
+
+ Destructor TPaiProp.Done;
+ Begin
+ //!!!! UsedRegs.Done;
+ //!!!! CondRegs.Done;
+ { DirFlag: TFlagContents; I386 specific}
+ End;
+ { ************************ private TPaiProp stuff ************************* }
+
+ Procedure TPaiProp.IncState(Var s: TStateInt); {$ifdef inl} inline;{$endif inl}
+ Begin
+ If s <> High(TStateInt) Then Inc(s)
+ Else s := 0
+ End;
+
+ Function TPaiProp.RefInInstruction(Const Ref: TReference; p: Tai;
+ RefsEq: TRefCompare): Boolean;
+ Var Count: AWord;
+ TmpResult: Boolean;
+ Begin
+ TmpResult := False;
+ If (p.typ = ait_instruction) Then
+ Begin
+ Count := 0;
+ Repeat
+ If (TInstr(p).oper[Count]^.typ = Top_Ref) Then
+ TmpResult := RefsEq(Ref, PInstr(p)^.oper[Count]^.ref^);
+ Inc(Count);
+ Until (Count = MaxOps) or TmpResult;
+ End;
+ RefInInstruction := TmpResult;
+ End;
+
+ Function TPaiProp.RefInSequence(Const Ref: TReference; Content: TContent;
+ RefsEq: TRefCompare): Boolean;
+ Var p: Tai;
+ Counter: Byte;
+ TmpResult: Boolean;
+ Begin
+ p := Content.StartMod;
+ TmpResult := False;
+ Counter := 1;
+ While Not(TmpResult) And
+ (Counter <= Content.NrOfMods) Do
+ Begin
+ If (p.typ = ait_instruction) And
+ RefInInstruction(Ref, p, {$ifdef fpc}@{$endif}references_equal)
+ Then TmpResult := True;
+ Inc(Counter);
+ GetNextInstruction(p,p)
+ End;
+ RefInSequence := TmpResult
+ End;
+
+ { ************************************************************************* }
+ { ***************************** TAoptObj ********************************** }
+ { ************************************************************************* }
+
+ Constructor TAoptObj.create(_AsmL: TAasmOutput; _BlockStart, _BlockEnd: Tai;
+ _LabelInfo: PLabelInfo);
+ Begin
+ AsmL := _AsmL;
+ BlockStart := _BlockStart;
+ BlockEnd := _BlockEnd;
+ LabelInfo := _LabelInfo
+ End;
+
+ Function TAOptObj.FindLabel(L: TasmLabel; Var hp: Tai): Boolean;
+ Var TempP: Tai;
+ Begin
+ TempP := hp;
+ While Assigned(TempP) and
+ (TempP.typ In SkipInstr + [ait_label]) Do
+ If (TempP.typ <> ait_Label) Or
+ (Tai_label(TempP).l <> L)
+ Then GetNextInstruction(TempP, TempP)
+ Else
+ Begin
+ hp := TempP;
+ FindLabel := True;
+ exit
+ End;
+ FindLabel := False;
+ End;
+
+ Procedure TAOptObj.InsertLLItem(prev, foll, new_one : TLinkedListItem);
+ Begin
+ If Assigned(prev) Then
+ If Assigned(foll) Then
+ Begin
+ If Assigned(new_one) Then
+ Begin
+ new_one.previous := prev;
+ new_one.next := foll;
+ prev.next := new_one;
+ foll.previous := new_one;
+ { should we update line information? }
+ if (not (tai(new_one).typ in SkipLineInfo)) and
+ (not (tai(foll).typ in SkipLineInfo)) then
+ Tailineinfo(new_one).fileinfo := Tailineinfo(foll).fileinfo
+ End
+ End
+ Else AsmL.Concat(new_one)
+ Else If Assigned(Foll) Then AsmL.Insert(new_one)
+ End;
+
+
+ Function TAOptObj.SkipHead(P: Tai): Tai;
+ Var OldP: Tai;
+ Begin
+ Repeat
+ OldP := P;
+ If (P.typ in SkipInstr) Or
+ ((P.typ = ait_marker) And
+ (Tai_Marker(P).Kind = AsmBlockEnd)) Then
+ GetNextInstruction(P, P)
+ Else If ((P.Typ = Ait_Marker) And
+ (Tai_Marker(P).Kind = NoPropInfoStart)) Then
+ { a marker of the type NoPropInfoStart can't be the first instruction of a }
+ { paasmoutput list }
+ GetNextInstruction(Tai(P.Previous),P);
+ If (P.Typ = Ait_Marker) And
+ (Tai_Marker(P).Kind = AsmBlockStart) Then
+ Begin
+ P := Tai(P.Next);
+ While (P.typ <> Ait_Marker) Or
+ (Tai_Marker(P).Kind <> AsmBlockEnd) Do
+ P := Tai(P.Next)
+ End;
+ Until P = OldP;
+ SkipHead := P;
+ End;
+
+ Function TAOptObj.OpsEqual(const o1,o2:toper): Boolean;
+ Begin
+ if o1.typ=o2.typ then
+ Case o1.typ Of
+ Top_Reg :
+ OpsEqual:=o1.reg=o2.reg;
+ Top_Ref :
+ OpsEqual := references_equal(o1.ref^, o2.ref^);
+ Top_Const :
+ OpsEqual:=o1.val=o2.val;
+ Top_None :
+ OpsEqual := True
+ else OpsEqual := False
+ End;
+ End;
+
+ Function TAOptObj.FindRegAlloc(Reg: TRegister; StartPai: Tai): Boolean;
+ Begin
+ FindRegAlloc:=False;
+ Repeat
+ While Assigned(StartPai) And
+ ((StartPai.typ in (SkipInstr - [ait_regAlloc])) Or
+ ((StartPai.typ = ait_label) and
+ Not(Tai_Label(StartPai).l.Is_Used))) Do
+ StartPai := Tai(StartPai.Next);
+ If Assigned(StartPai) And
+ (StartPai.typ = ait_regAlloc) and (tai_regalloc(StartPai).ratype=ra_alloc) Then
+ Begin
+ if tai_regalloc(StartPai).Reg = Reg then
+ begin
+ FindRegAlloc:=true;
+ exit;
+ end;
+ StartPai := Tai(StartPai.Next);
+ End
+ else
+ exit;
+ Until false;
+ End;
+
+
+ function SkipLabels(hp: tai; var hp2: tai): boolean;
+ {skips all labels and returns the next "real" instruction}
+ begin
+ while assigned(hp.next) and
+ (tai(hp.next).typ in SkipInstr + [ait_label,ait_align]) Do
+ hp := tai(hp.next);
+ if assigned(hp.next) then
+ begin
+ SkipLabels := True;
+ hp2 := tai(hp.next)
+ end
+ else
+ begin
+ hp2 := hp;
+ SkipLabels := False
+ end;
+ end;
+
+
+ function FindAnyLabel(hp: tai; var l: tasmlabel): Boolean;
+ begin
+ FindAnyLabel := false;
+ while assigned(hp.next) and
+ (tai(hp.next).typ in (SkipInstr+[ait_align])) Do
+ hp := tai(hp.next);
+ if assigned(hp.next) and
+ (tai(hp.next).typ = ait_label) then
+ begin
+ FindAnyLabel := true;
+ l := tai_label(hp.next).l;
+ end
+ end;
+
+
+{$ifopt r+}
+{$define rangewason}
+{$r-}
+{$endif}
+ function tAOptObj.getlabelwithsym(sym: tasmlabel): tai;
+ begin
+ if (sym.labelnr >= labelinfo^.lowlabel) and
+ (sym.labelnr <= labelinfo^.highlabel) then { range check, a jump can go past an assembler block! }
+ getlabelwithsym := labelinfo^.labeltable^[sym.labelnr-labelinfo^.lowlabel].paiobj
+ else
+ getlabelwithsym := nil;
+ end;
+{$ifdef rangewason}
+{$r+}
+{$undef rangewason}
+{$endif}
+
+ function TAOptObj.GetFinalDestination(hp: taicpu; level: longint): boolean;
+ {traces sucessive jumps to their final destination and sets it, e.g.
+ je l1 je l3
+ <code> <code>
+ l1: becomes l1:
+ je l2 je l3
+ <code> <code>
+ l2: l2:
+ jmp l3 jmp l3
+
+ the level parameter denotes how deeep we have already followed the jump,
+ to avoid endless loops with constructs such as "l5: ; jmp l5" }
+
+ var p1, p2: tai;
+ l: tasmlabel;
+
+ begin
+ GetfinalDestination := false;
+ if level > 20 then
+ exit;
+ p1 := getlabelwithsym(tasmlabel(hp.oper[0]^.ref^.symbol));
+ if assigned(p1) then
+ begin
+ SkipLabels(p1,p1);
+ if (tai(p1).typ = ait_instruction) and
+ (taicpu(p1).is_jmp) then
+ if { the next instruction after the label where the jump hp arrives}
+ { is unconditional or of the same type as hp, so continue }
+ (((taicpu(p1).opcode = aopt_uncondjmp) and
+ (taicpu(p1).oper[0]^.typ = top_ref) and
+ (assigned(taicpu(p1).oper[0]^.ref^.symbol)) and
+ (taicpu(p1).oper[0]^.ref^.symbol is TAsmLabel)) or
+ conditions_equal(taicpu(p1).condition,hp.condition)) or
+ { the next instruction after the label where the jump hp arrives}
+ { is the opposite of hp (so this one is never taken), but after }
+ { that one there is a branch that will be taken, so perform a }
+ { little hack: set p1 equal to this instruction (that's what the}
+ { last SkipLabels is for, only works with short bool evaluation)}
+ (conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) and
+ SkipLabels(p1,p2) and
+ (p2.typ = ait_instruction) and
+ (taicpu(p2).is_jmp) and
+ (((taicpu(p2).opcode = aopt_uncondjmp) and
+ (taicpu(p2).oper[0]^.typ = top_ref) and
+ (assigned(taicpu(p2).oper[0]^.ref^.symbol)) and
+ (taicpu(p2).oper[0]^.ref^.symbol is TAsmLabel)) or
+ (conditions_equal(taicpu(p2).condition,hp.condition))) and
+ SkipLabels(p1,p1)) then
+ begin
+ { quick check for loops of the form "l5: ; jmp l5 }
+ if (tasmlabel(taicpu(p1).oper[0]^.ref^.symbol).labelnr =
+ tasmlabel(hp.oper[0]^.ref^.symbol).labelnr) then
+ exit;
+ if not GetFinalDestination(taicpu(p1),succ(level)) then
+ exit;
+ tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol:=taicpu(p1).oper[0]^.ref^.symbol;
+ tasmlabel(hp.oper[0]^.ref^.symbol).increfs;
+ end
+ else
+ if conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) then
+ if not FindAnyLabel(p1,l) then
+ begin
+ {$ifdef finaldestdebug}
+ insertllitem(asml,p1,p1.next,tai_comment.Create(
+ strpnew('previous label inserted'))));
+ {$endif finaldestdebug}
+ objectlibrary.getjumplabel(l);
+ insertllitem(p1,p1.next,tai_label.Create(l));
+ tasmlabel(taicpu(hp).oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol := l;
+ l.increfs;
+ { this won't work, since the new label isn't in the labeltable }
+ { so it will fail the rangecheck. Labeltable should become a }
+ { hashtable to support this: }
+ { GetFinalDestination(asml, hp); }
+ end
+ else
+ begin
+ {$ifdef finaldestdebug}
+ insertllitem(asml,p1,p1.next,tai_comment.Create(
+ strpnew('next label reused'))));
+ {$endif finaldestdebug}
+ l.increfs;
+ hp.oper[0]^.ref^.symbol := l;
+ if not GetFinalDestination(hp,succ(level)) then
+ exit;
+ end;
+ end;
+ GetFinalDestination := true;
+ end;
+
+
+ procedure TAOptObj.PrePeepHoleOpts;
+ begin
+ end;
+
+
+ procedure TAOptObj.PeepHoleOptPass1;
+ var
+ p,hp1,hp2 : tai;
+ begin
+ p := BlockStart;
+ //!!!! UsedRegs := [];
+ while (p <> BlockEnd) Do
+ begin
+ //!!!! UpDateUsedRegs(UsedRegs, tai(p.next));
+ if PeepHoleOptPass1Cpu(p) then
+ continue;
+ case p.Typ Of
+ ait_instruction:
+ begin
+ { Handle Jmp Optimizations }
+ if taicpu(p).is_jmp then
+ begin
+ { the following if-block removes all code between a jmp and the next label,
+ because it can never be executed
+ }
+ if (taicpu(p).opcode = aopt_uncondjmp) and
+ (taicpu(p).oper[0]^.typ = top_ref) and
+ (assigned(taicpu(p).oper[0]^.ref^.symbol)) and
+ (taicpu(p).oper[0]^.ref^.symbol is TAsmLabel) then
+ begin
+ while GetNextInstruction(p, hp1) and
+ (hp1.typ <> ait_label) do
+ if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
+ begin
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else break;
+ end;
+ { remove jumps to a label coming right after them }
+ if GetNextInstruction(p, hp1) then
+ begin
+ if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp1) and
+ {$warning FIXME removing the first instruction fails}
+ (p<>blockstart) then
+ begin
+ hp2:=tai(hp1.next);
+ asml.remove(p);
+ p.free;
+ p:=hp2;
+ continue;
+ end
+ else
+ begin
+ if hp1.typ = ait_label then
+ SkipLabels(hp1,hp1);
+ if (tai(hp1).typ=ait_instruction) and
+ (taicpu(hp1).opcode=aopt_uncondjmp) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (assigned(taicpu(hp1).oper[0]^.ref^.symbol)) and
+ (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) and
+ GetNextInstruction(hp1, hp2) and
+ FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp2) then
+ begin
+ if taicpu(p).opcode=aopt_condjmp then
+ begin
+ taicpu(p).condition:=inverse_cond(taicpu(p).condition);
+ tai_label(hp2).l.decrefs;
+ taicpu(p).oper[0]^.ref^.symbol:=taicpu(hp1).oper[0]^.ref^.symbol;
+ taicpu(p).oper[0]^.ref^.symbol.increfs;
+{$ifdef SPARC}
+ hp2:=tai(hp1.next);
+ asml.remove(hp2);
+ hp2.free;
+{$endif SPARC}
+ asml.remove(hp1);
+ hp1.free;
+ GetFinalDestination(taicpu(p),0);
+ end
+ else
+ begin
+ GetFinalDestination(taicpu(p),0);
+ p:=tai(p.next);
+ continue;
+ end;
+ end
+ else
+ GetFinalDestination(taicpu(p),0);
+ end;
+ end;
+ end
+ else
+ { All other optimizes }
+ begin
+ end; { if is_jmp }
+ end;
+ end;
+ //!!!!!!!! updateUsedRegs(UsedRegs,p);
+ p:=tai(p.next);
+ end;
+ end;
+
+
+ procedure TAOptObj.PeepHoleOptPass2;
+ begin
+ end;
+
+
+ procedure TAOptObj.PostPeepHoleOpts;
+ var
+ p: tai;
+ begin
+ p := BlockStart;
+ //!!!! UsedRegs := [];
+ while (p <> BlockEnd) Do
+ begin
+ //!!!! UpDateUsedRegs(UsedRegs, tai(p.next));
+ if PostPeepHoleOptsCpu(p) then
+ continue;
+ //!!!!!!!! updateUsedRegs(UsedRegs,p);
+ p:=tai(p.next);
+ end;
+ end;
+
+
+ function TAOptObj.PeepHoleOptPass1Cpu(var p: tai): boolean;
+ begin
+ result := false;
+ end;
+
+
+ function TAOptObj.PostPeepHoleOptsCpu(var p: tai): boolean;
+ begin
+ result := false;
+ end;
+
+End.
diff --git a/compiler/arm/aasmcpu.pas b/compiler/arm/aasmcpu.pas
new file mode 100644
index 0000000000..534ca0099f
--- /dev/null
+++ b/compiler/arm/aasmcpu.pas
@@ -0,0 +1,2399 @@
+{
+ Copyright (c) 2003 by Florian Klaempfl
+
+ Contains the assembler object for the ARM
+
+ 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;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,globtype,globals,verbose,
+ aasmbase,aasmtai,
+ symtype,
+ cpubase,cpuinfo,cgbase,cgutils;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 1;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 0;
+
+ { Operand types }
+ OT_NONE = $00000000;
+
+ OT_BITS8 = $00000001; { size, and other attributes, of the operand }
+ OT_BITS16 = $00000002;
+ OT_BITS32 = $00000004;
+ OT_BITS64 = $00000008; { FPU only }
+ OT_BITS80 = $00000010;
+ OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
+ OT_NEAR = $00000040;
+ OT_SHORT = $00000080;
+ OT_BITSTINY = $00000100; { fpu constant }
+ OT_BITSSHIFTER =
+ $00000200;
+
+ OT_SIZE_MASK = $000003FF; { all the size attributes }
+ OT_NON_SIZE = longint(not OT_SIZE_MASK);
+
+ OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
+
+ OT_TO = $00000200; { operand is followed by a colon }
+ { reverse effect in FADD, FSUB &c }
+ OT_COLON = $00000400;
+
+ OT_SHIFTEROP = $00000800;
+ OT_REGISTER = $00001000;
+ OT_IMMEDIATE = $00002000;
+ OT_REGLIST = $00008000;
+ OT_IMM8 = $00002001;
+ OT_IMM24 = $00002002;
+ OT_IMM32 = $00002004;
+ OT_IMM64 = $00002008;
+ OT_IMM80 = $00002010;
+ OT_IMMTINY = $00002100;
+ OT_IMMSHIFTER= $00002200;
+ OT_IMMEDIATE24 = OT_IMM24;
+ OT_SHIFTIMM = OT_SHIFTEROP or OT_IMMSHIFTER;
+ OT_SHIFTIMMEDIATE = OT_SHIFTIMM;
+ OT_IMMEDIATESHIFTER = OT_IMMSHIFTER;
+
+ OT_IMMEDIATEFPU = OT_IMMTINY;
+
+ OT_REGMEM = $00200000; { for r/m, ie EA, operands }
+ OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
+ OT_REG8 = $00201001;
+ OT_REG16 = $00201002;
+ OT_REG32 = $00201004;
+ OT_REG64 = $00201008;
+ OT_VREG = $00201010; { vector register }
+ OT_MEMORY = $00204000; { register number in 'basereg' }
+ OT_MEM8 = $00204001;
+ OT_MEM16 = $00204002;
+ OT_MEM32 = $00204004;
+ OT_MEM64 = $00204008;
+ OT_MEM80 = $00204010;
+ { word/byte load/store }
+ OT_AM2 = $00010000;
+ { misc ld/st operations }
+ OT_AM3 = $00020000;
+ { multiple ld/st operations }
+ OT_AM4 = $00040000;
+ { co proc. ld/st operations }
+ OT_AM5 = $00080000;
+ OT_AMMASK = $000f0000;
+
+ OT_MEMORYAM2 = OT_MEMORY or OT_AM2;
+ OT_MEMORYAM3 = OT_MEMORY or OT_AM3;
+ OT_MEMORYAM4 = OT_MEMORY or OT_AM4;
+ OT_MEMORYAM5 = OT_MEMORY or OT_AM5;
+
+ OT_FPUREG = $01000000; { floating point stack registers }
+ OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
+ { a mask for the following }
+
+ OT_MEM_OFFS = $00604000; { special type of EA }
+ { simple [address] offset }
+ OT_ONENESS = $00800000; { special type of immediate operand }
+ { so UNITY == IMMEDIATE | ONENESS }
+ OT_UNITY = $00802000; { for shift/rotate instructions }
+
+ instabentries = {$i armnop.inc}
+
+ maxinfolen = 5;
+
+ IF_NONE = $00000000;
+
+ IF_ARMMASK = $000F0000;
+ IF_ARM7 = $00070000;
+ IF_FPMASK = $00F00000;
+ IF_FPA = $00100000;
+
+ { if the instruction can change in a second pass }
+ IF_PASS2 = longint($80000000);
+
+ type
+ TInsTabCache=array[TasmOp] of longint;
+ PInsTabCache=^TInsTabCache;
+
+ tinsentry = record
+ opcode : tasmop;
+ ops : byte;
+ optypes : array[0..3] of longint;
+ code : array[0..maxinfolen] of char;
+ flags : longint;
+ end;
+
+ pinsentry=^tinsentry;
+
+ const
+ InsTab : array[0..instabentries-1] of TInsEntry={$i armtab.inc}
+
+ var
+ InsTabCache : PInsTabCache;
+
+ type
+ taicpu = class(tai_cpu_abstract)
+ oppostfix : TOpPostfix;
+ roundingmode : troundingmode;
+ procedure loadshifterop(opidx:longint;const so:tshifterop);
+ procedure loadregset(opidx:longint;const s:tcpuregisterset);
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : longint);
+
+ 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_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
+
+ 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);
+ constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
+ { SFM/LFM }
+ constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
+
+ { *M*LL }
+ constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+
+ 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);
+
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+
+ { assembler }
+ public
+ { the next will reset all instructions that can change in pass 2 }
+ procedure ResetPass1;
+ procedure ResetPass2;
+ function CheckIfValid:boolean;
+ function GetString:string;
+ function Pass1(offset:longint):longint;override;
+ procedure Pass2(objdata:TAsmObjectdata);override;
+ protected
+ procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
+ procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
+ procedure ppubuildderefimploper(var o:toper);override;
+ procedure ppuderefoper(var o:toper);override;
+ private
+ { next fields are filled in pass1, so pass2 is faster }
+ inssize : shortint;
+ insoffset : longint;
+ LastInsOffset : longint; { need to be public to be reset }
+ insentry : PInsEntry;
+ function InsEnd:longint;
+ procedure create_ot;
+ function Matches(p:PInsEntry):longint;
+ function calcsize(p:PInsEntry):shortint;
+ procedure gencode(objdata:TAsmObjectData);
+ function NeedAddrPrefix(opidx:byte):boolean;
+ procedure Swapoperands;
+ function FindInsentry:boolean;
+ 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;
+
+ function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
+ function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
+ function setcondition(i : taicpu;c : tasmcond) : taicpu;
+
+ { inserts pc relative symbols at places where they are reachable }
+ procedure insertpcrelativedata(list,listtoinsert : taasmoutput);
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+
+implementation
+
+ uses
+ cutils,rgobj,itcpugas;
+
+
+ procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_shifterop then
+ begin
+ clearop(opidx);
+ new(shifterop);
+ end;
+ shifterop^:=so;
+ typ:=top_shifterop;
+ if assigned(add_reg_instruction_hook) then
+ add_reg_instruction_hook(self,shifterop^.rs);
+ end;
+ end;
+
+
+ procedure taicpu.loadregset(opidx:longint;const s:tcpuregisterset);
+ var
+ i : byte;
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_regset then
+ clearop(opidx);
+ new(regset);
+ regset^:=s;
+ typ:=top_regset;
+ for i:=RS_R0 to RS_R15 do
+ begin
+ if assigned(add_reg_instruction_hook) and (i in regset^) then
+ add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,R_SUBWHOLE));
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ 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_const(op : tasmop;_op1 : longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(0,aint(_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_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_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadref(0,_op1);
+ loadregset(1,_op2);
+ 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_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_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadreg(3,_op4);
+ 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_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_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_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_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadshifterop(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;
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ { allow the register allocator to remove unnecessary moves }
+ result:=(((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
+ ((opcode=A_MVF) 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.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ case opcode of
+ A_ADC,A_ADD,A_AND,
+ A_EOR,A_CLZ,
+ A_LDR,A_LDRB,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_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;
+ else
+ internalerror(200403151);
+ end;
+ end;
+
+
+ procedure BuildInsTabCache;
+ var
+ i : longint;
+ begin
+ new(instabcache);
+ FillChar(instabcache^,sizeof(tinstabcache),$ff);
+ i:=0;
+ while (i<InsTabEntries) do
+ begin
+ if InsTabCache^[InsTab[i].Opcode]=-1 then
+ InsTabCache^[InsTab[i].Opcode]:=i;
+ inc(i);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ if not assigned(instabcache) then
+ BuildInsTabCache;
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ if assigned(instabcache) then
+ begin
+ dispose(instabcache);
+ instabcache:=nil;
+ end;
+ end;
+
+
+ function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
+ begin
+ i.oppostfix:=pf;
+ result:=i;
+ end;
+
+
+ function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
+ begin
+ i.roundingmode:=rm;
+ result:=i;
+ end;
+
+
+ function setcondition(i : taicpu;c : tasmcond) : taicpu;
+ begin
+ i.condition:=c;
+ result:=i;
+ end;
+
+
+ procedure insertpcrelativedata(list,listtoinsert : taasmoutput);
+ var
+ curpos : longint;
+ lastpos : longint;
+ curop : longint;
+ curtai : tai;
+ curdatatai,hp : tai;
+ curdata : taasmoutput;
+ l : tasmlabel;
+ begin
+ curdata:=taasmoutput.create;
+ lastpos:=-1;
+ curpos:=0;
+ curtai:=tai(list.first);
+ while assigned(curtai) do
+ begin
+ { instruction? }
+ if curtai.typ=ait_instruction then
+ begin
+ { walk through all operand of the instruction }
+ for curop:=0 to taicpu(curtai).ops-1 do
+ begin
+ { reference? }
+ if (taicpu(curtai).oper[curop]^.typ=top_ref) then
+ begin
+ { pc relative symbol? }
+ curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
+ if assigned(curdatatai) then
+ begin
+ { if yes, insert till next symbol }
+ repeat
+ hp:=tai(curdatatai.next);
+ listtoinsert.remove(curdatatai);
+ curdata.concat(curdatatai);
+ curdatatai:=hp;
+ until (curdatatai=nil) or (curdatatai.typ=ait_label);
+ if lastpos=-1 then
+ lastpos:=curpos;
+ end;
+ end;
+ end;
+ inc(curpos);
+ end;
+
+ { split only at real instructions else the test below fails }
+ if ((curpos-lastpos)>1016) and (curtai.typ=ait_instruction) and
+ (
+ { don't split loads of pc to lr and the following move }
+ not(
+ (taicpu(curtai).opcode=A_MOV) and
+ (taicpu(curtai).oper[0]^.typ=top_reg) and
+ (taicpu(curtai).oper[0]^.reg=NR_R14) and
+ (taicpu(curtai).oper[1]^.typ=top_reg) and
+ (taicpu(curtai).oper[1]^.reg=NR_PC)
+ )
+ ) then
+ begin
+ lastpos:=curpos;
+ hp:=tai(curtai.next);
+ objectlibrary.getjumplabel(l);
+ curdata.insert(taicpu.op_sym(A_B,l));
+ curdata.concat(tai_label.create(l));
+ list.insertlistafter(curtai,curdata);
+ curtai:=hp;
+ end
+ else
+ curtai:=tai(curtai.next);
+ end;
+ list.concatlist(curdata);
+ curdata.free;
+ end;
+
+
+(*
+ Floating point instruction format information, taken from the linux kernel
+ ARM Floating Point Instruction Classes
+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+ |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
+ |c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2)
+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+ |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
+ |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
+ |c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+
+ CPDT data transfer instructions
+ LDF, STF, LFM (copro 2), SFM (copro 2)
+
+ CPDO dyadic arithmetic instructions
+ ADF, MUF, SUF, RSF, DVF, RDF,
+ POW, RPW, RMF, FML, FDV, FRD, POL
+
+ CPDO monadic arithmetic instructions
+ MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
+ SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
+
+ CPRT joint arithmetic/data transfer instructions
+ FIX (arithmetic followed by load/store)
+ FLT (load/store followed by arithmetic)
+ CMF, CNF CMFE, CNFE (comparisons)
+ WFS, RFS (write/read floating point status register)
+ WFC, RFC (write/read floating point control register)
+
+ cond condition codes
+ P pre/post index bit: 0 = postindex, 1 = preindex
+ U up/down bit: 0 = stack grows down, 1 = stack grows up
+ W write back bit: 1 = update base register (Rn)
+ L load/store bit: 0 = store, 1 = load
+ Rn base register
+ Rd destination/source register
+ Fd floating point destination register
+ Fn floating point source register
+ Fm floating point source register or floating point constant
+
+ uv transfer length (TABLE 1)
+ wx register count (TABLE 2)
+ abcd arithmetic opcode (TABLES 3 & 4)
+ ef destination size (rounding precision) (TABLE 5)
+ gh rounding mode (TABLE 6)
+ j dyadic/monadic bit: 0 = dyadic, 1 = monadic
+ i constant bit: 1 = constant (TABLE 6)
+ */
+
+ /*
+ TABLE 1
+ +-------------------------+---+---+---------+---------+
+ | Precision | u | v | FPSR.EP | length |
+ +-------------------------+---+---+---------+---------+
+ | Single | 0 | 0 | x | 1 words |
+ | Double | 1 | 1 | x | 2 words |
+ | Extended | 1 | 1 | x | 3 words |
+ | Packed decimal | 1 | 1 | 0 | 3 words |
+ | Expanded packed decimal | 1 | 1 | 1 | 4 words |
+ +-------------------------+---+---+---------+---------+
+ Note: x = don't care
+ */
+
+ /*
+ TABLE 2
+ +---+---+---------------------------------+
+ | w | x | Number of registers to transfer |
+ +---+---+---------------------------------+
+ | 0 | 1 | 1 |
+ | 1 | 0 | 2 |
+ | 1 | 1 | 3 |
+ | 0 | 0 | 4 |
+ +---+---+---------------------------------+
+ */
+
+ /*
+ TABLE 3: Dyadic Floating Point Opcodes
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ | a | b | c | d | Mnemonic | Description | Operation |
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ | 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm |
+ | 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm |
+ | 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm |
+ | 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn |
+ | 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm |
+ | 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn |
+ | 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm |
+ | 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn |
+ | 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) |
+ | 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm |
+ | 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm |
+ | 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn |
+ | 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) |
+ | 1 | 1 | 0 | 1 | | undefined instruction | trap |
+ | 1 | 1 | 1 | 0 | | undefined instruction | trap |
+ | 1 | 1 | 1 | 1 | | undefined instruction | trap |
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ Note: POW, RPW, POL are deprecated, and are available for backwards
+ compatibility only.
+ */
+
+ /*
+ TABLE 4: Monadic Floating Point Opcodes
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ | a | b | c | d | Mnemonic | Description | Operation |
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ | 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm |
+ | 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm |
+ | 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) |
+ | 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) |
+ | 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) |
+ | 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) |
+ | 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) |
+ | 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm |
+ | 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) |
+ | 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) |
+ | 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) |
+ | 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) |
+ | 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) |
+ | 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) |
+ | 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) |
+ | 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) |
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
+ available for backwards compatibility only.
+ */
+
+ /*
+ TABLE 5
+ +-------------------------+---+---+
+ | Rounding Precision | e | f |
+ +-------------------------+---+---+
+ | IEEE Single precision | 0 | 0 |
+ | IEEE Double precision | 0 | 1 |
+ | IEEE Extended precision | 1 | 0 |
+ | undefined (trap) | 1 | 1 |
+ +-------------------------+---+---+
+ */
+
+ /*
+ TABLE 5
+ +---------------------------------+---+---+
+ | Rounding Mode | g | h |
+ +---------------------------------+---+---+
+ | Round to nearest (default) | 0 | 0 |
+ | Round toward plus infinity | 0 | 1 |
+ | Round toward negative infinity | 1 | 0 |
+ | Round toward zero | 1 | 1 |
+ +---------------------------------+---+---+
+*)
+ function taicpu.GetString:string;
+ var
+ i : longint;
+ s : string;
+ addsize : boolean;
+ begin
+ s:='['+gas_op2str[opcode];
+ for i:=0 to ops-1 do
+ begin
+ with oper[i]^ do
+ begin
+ if i=0 then
+ s:=s+' '
+ else
+ s:=s+',';
+ { type }
+ addsize:=false;
+ if (ot and OT_VREG)=OT_VREG then
+ s:=s+'vreg'
+ else
+ if (ot and OT_FPUREG)=OT_FPUREG then
+ s:=s+'fpureg'
+ else
+ if (ot and OT_REGISTER)=OT_REGISTER then
+ begin
+ s:=s+'reg';
+ addsize:=true;
+ end
+ else
+ if (ot and OT_REGLIST)=OT_REGLIST then
+ begin
+ s:=s+'reglist';
+ addsize:=false;
+ end
+ else
+ if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
+ begin
+ s:=s+'imm';
+ addsize:=true;
+ end
+ else
+ if (ot and OT_MEMORY)=OT_MEMORY then
+ begin
+ s:=s+'mem';
+ addsize:=true;
+ if (ot and OT_AM2)<>0 then
+ s:=s+' am2 ';
+ end
+ else
+ s:=s+'???';
+ { size }
+ if addsize then
+ begin
+ if (ot and OT_BITS8)<>0 then
+ s:=s+'8'
+ else
+ if (ot and OT_BITS16)<>0 then
+ s:=s+'24'
+ else
+ if (ot and OT_BITS32)<>0 then
+ s:=s+'32'
+ else
+ if (ot and OT_BITSSHIFTER)<>0 then
+ s:=s+'shifter'
+ else
+ s:=s+'??';
+ { signed }
+ if (ot and OT_SIGNED)<>0 then
+ s:=s+'s';
+ end;
+ end;
+ end;
+ GetString:=s+']';
+ end;
+
+
+ procedure taicpu.ResetPass1;
+ begin
+ { we need to reset everything here, because the choosen insentry
+ can be invalid for a new situation where the previously optimized
+ insentry is not correct }
+ InsEntry:=nil;
+ InsSize:=0;
+ LastInsOffset:=-1;
+ end;
+
+
+ procedure taicpu.ResetPass2;
+ begin
+ { we are here in a second pass, check if the instruction can be optimized }
+ if assigned(InsEntry) and
+ ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ InsEntry:=nil;
+ InsSize:=0;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+
+ function taicpu.CheckIfValid:boolean;
+ begin
+ end;
+
+
+ function taicpu.Pass1(offset:longint):longint;
+ var
+ ldr2op : array[PF_B..PF_T] of tasmop = (
+ A_LDRB,A_LDRSB,A_LDRBT,A_LDRH,A_LDRSH,A_LDRT);
+ str2op : array[PF_B..PF_T] of tasmop = (
+ A_STRB,A_None,A_STRBT,A_STRH,A_None,A_STRT);
+ begin
+ Pass1:=0;
+ { Save the old offset and set the new offset }
+ InsOffset:=Offset;
+ { Error? }
+ if (Insentry=nil) and (InsSize=-1) then
+ exit;
+ { set the file postion }
+ aktfilepos:=fileinfo;
+
+ { tranlate LDR+postfix to complete opcode }
+ if (opcode=A_LDR) and (oppostfix<>PF_None) then
+ begin
+ if (oppostfix in [low(ldr2op)..high(ldr2op)]) then
+ opcode:=ldr2op[oppostfix]
+ else
+ internalerror(2005091001);
+ if opcode=A_None then
+ internalerror(2005091004);
+ { postfix has been added to opcode }
+ oppostfix:=PF_None;
+ end
+ else if (opcode=A_STR) and (oppostfix<>PF_None) then
+ begin
+ if (oppostfix in [low(str2op)..high(str2op)]) then
+ opcode:=str2op[oppostfix]
+ else
+ internalerror(2005091002);
+ if opcode=A_None then
+ internalerror(2005091003);
+ { postfix has been added to opcode }
+ oppostfix:=PF_None;
+ end;
+
+ { Get InsEntry }
+ if FindInsEntry then
+ begin
+ InsSize:=4;
+ LastInsOffset:=InsOffset;
+ Pass1:=InsSize;
+ exit;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+
+ procedure taicpu.Pass2(objdata:TAsmObjectdata);
+ begin
+ { error in pass1 ? }
+ if insentry=nil then
+ exit;
+ aktfilepos:=fileinfo;
+ { Generate the instruction }
+ GenCode(objdata);
+ end;
+
+
+ procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
+ begin
+ end;
+
+
+ procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
+ begin
+ end;
+
+
+ procedure taicpu.ppubuildderefimploper(var o:toper);
+ begin
+ end;
+
+
+ procedure taicpu.ppuderefoper(var o:toper);
+ begin
+ end;
+
+
+ function taicpu.InsEnd:longint;
+ begin
+ end;
+
+
+ procedure taicpu.create_ot;
+ var
+ i,l,relsize : longint;
+ dummy : byte;
+ begin
+ if ops=0 then
+ exit;
+ { update oper[].ot field }
+ for i:=0 to ops-1 do
+ with oper[i]^ do
+ begin
+ case typ of
+ top_regset:
+ begin
+ ot:=OT_REGLIST;
+ end;
+ top_reg :
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER:
+ ot:=OT_REG32 or OT_SHIFTEROP;
+ R_FPUREGISTER:
+ ot:=OT_FPUREG;
+ else
+ internalerror(2005090901);
+ end;
+ end;
+ top_ref :
+ begin
+ if ref^.refaddr=addr_no then
+ begin
+ { create ot field }
+ { we should get the size here dependend on the
+ instruction }
+ if (ot and OT_SIZE_MASK)=0 then
+ ot:=OT_MEMORY or OT_BITS32
+ else
+ ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+ if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
+ ot:=ot or OT_MEM_OFFS;
+ { if we need to fix a reference, we do it here }
+
+ { pc relative addressing }
+ if (ref^.base=NR_NO) and
+ (ref^.index=NR_NO) and
+ (ref^.shiftmode=SM_None)
+ { at least we should check if the destination symbol
+ is in a text section }
+ { and
+ (ref^.symbol^.owner="text") } then
+ ref^.base:=NR_PC;
+
+ { determine possible address modes }
+ if (ref^.base<>NR_NO) and
+ (
+ (
+ (ref^.index=NR_NO) and
+ (ref^.shiftmode=SM_None) and
+ (ref^.offset>=-4097) and
+ (ref^.offset<=4097)
+ ) or
+ (
+ (ref^.shiftmode=SM_None) and
+ (ref^.offset=0)
+ ) or
+ (
+ (ref^.index<>NR_NO) and
+ (ref^.shiftmode<>SM_None) and
+ (ref^.shiftimm<=31) and
+ (ref^.offset=0)
+ )
+ ) then
+ ot:=ot or OT_AM2;
+
+ if (ref^.index<>NR_NO) and
+ (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and
+ (
+ (ref^.base=NR_NO) and
+ (ref^.shiftmode=SM_None) and
+ (ref^.offset=0)
+ ) then
+ ot:=ot or OT_AM4;
+
+ end
+ else
+ begin
+ l:=ref^.offset;
+ if assigned(ref^.symbol) then
+ inc(l,ref^.symbol.address);
+ relsize:=(InsOffset+2)-l;
+ if (relsize<-33554428) or (relsize>33554428) then
+ ot:=OT_IMM32
+ else
+ ot:=OT_IMM24;
+ end;
+ end;
+ top_local :
+ begin
+ { we should get the size here dependend on the
+ instruction }
+ if (ot and OT_SIZE_MASK)=0 then
+ ot:=OT_MEMORY or OT_BITS32
+ else
+ ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+ end;
+ top_const :
+ begin
+ ot:=OT_IMMEDIATE;
+ if is_shifter_const(val,dummy) then
+ ot:=OT_IMMSHIFTER
+ else
+ ot:=OT_IMM32
+ end;
+ top_none :
+ begin
+ { generated when there was an error in the
+ assembler reader. It never happends when generating
+ assembler }
+ end;
+ top_shifterop:
+ begin
+ ot:=OT_SHIFTEROP;
+ end;
+ else
+ internalerror(200402261);
+ end;
+ end;
+ end;
+
+
+ function taicpu.Matches(p:PInsEntry):longint;
+ { * IF_SM stands for Size Match: any operand whose size is not
+ * explicitly specified by the template is `really' intended to be
+ * the same size as the first size-specified operand.
+ * Non-specification is tolerated in the input instruction, but
+ * _wrong_ specification is not.
+ *
+ * IF_SM2 invokes Size Match on only the first _two_ operands, for
+ * three-operand instructions such as SHLD: it implies that the
+ * first two operands must match in size, but that the third is
+ * required to be _unspecified_.
+ *
+ * IF_SB invokes Size Byte: operands with unspecified size in the
+ * template are really bytes, and so no non-byte specification in
+ * the input instruction will be tolerated. IF_SW similarly invokes
+ * Size Word, and IF_SD invokes Size Doubleword.
+ *
+ * (The default state if neither IF_SM nor IF_SM2 is specified is
+ * that any operand with unspecified size in the template is
+ * required to have unspecified size in the instruction too...)
+ }
+ var
+ i,j,asize,oprs : longint;
+ siz : array[0..3] of longint;
+ begin
+ Matches:=100;
+ writeln(getstring,'---');
+
+ { Check the opcode and operands }
+ if (p^.opcode<>opcode) or (p^.ops<>ops) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { Check that no spurious colons or TOs are present }
+ for i:=0 to p^.ops-1 do
+ if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { Check that the operand flags all match up }
+ for i:=0 to p^.ops-1 do
+ begin
+ if ((p^.optypes[i] and (not oper[i]^.ot)) or
+ ((p^.optypes[i] and OT_SIZE_MASK) and
+ ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
+ begin
+ if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
+ (oper[i]^.ot and OT_SIZE_MASK))<>0 then
+ begin
+ Matches:=0;
+ exit;
+ end
+ else
+ Matches:=1;
+ end;
+ end;
+
+ { check postfixes:
+ the existance of a certain postfix requires a
+ particular code }
+
+ { update condition flags
+ or floating point single }
+ if (oppostfix=PF_S) and
+ not(p^.code[0] in [#$04]) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { floating point size }
+ if (oppostfix in [PF_D,PF_E,PF_P,PF_EP]) and
+ not(p^.code[0] in []) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { multiple load/store address modes }
+ if (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and
+ not(p^.code[0] in [
+ // ldr,str,ldrb,strb
+ #$17,
+ // stm,ldm
+ #$26
+ ]) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { we shouldn't see any opsize prefixes here }
+ if (oppostfix in [PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T]) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ if (roundingmode<>RM_None) and not(p^.code[0] in []) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { Check operand sizes }
+ { as default an untyped size can get all the sizes, this is different
+ from nasm, but else we need to do a lot checking which opcodes want
+ size or not with the automatic size generation }
+ asize:=longint($ffffffff);
+ (*
+ if (p^.flags and IF_SB)<>0 then
+ asize:=OT_BITS8
+ else if (p^.flags and IF_SW)<>0 then
+ asize:=OT_BITS16
+ else if (p^.flags and IF_SD)<>0 then
+ asize:=OT_BITS32;
+ if (p^.flags and IF_ARMASK)<>0 then
+ begin
+ siz[0]:=0;
+ siz[1]:=0;
+ siz[2]:=0;
+ if (p^.flags and IF_AR0)<>0 then
+ siz[0]:=asize
+ else if (p^.flags and IF_AR1)<>0 then
+ siz[1]:=asize
+ else if (p^.flags and IF_AR2)<>0 then
+ siz[2]:=asize;
+ end
+ else
+ begin
+ { we can leave because the size for all operands is forced to be
+ the same
+ but not if IF_SB IF_SW or IF_SD is set PM }
+ if asize=-1 then
+ exit;
+ siz[0]:=asize;
+ siz[1]:=asize;
+ siz[2]:=asize;
+ end;
+
+ if (p^.flags and (IF_SM or IF_SM2))<>0 then
+ begin
+ if (p^.flags and IF_SM2)<>0 then
+ oprs:=2
+ else
+ oprs:=p^.ops;
+ for i:=0 to oprs-1 do
+ if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
+ begin
+ for j:=0 to oprs-1 do
+ siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
+ break;
+ end;
+ end
+ else
+ oprs:=2;
+
+ { Check operand sizes }
+ for i:=0 to p^.ops-1 do
+ begin
+ if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
+ ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
+ { Immediates can always include smaller size }
+ ((oper[i]^.ot and OT_IMMEDIATE)=0) and
+ (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
+ Matches:=2;
+ end;
+ *)
+ end;
+
+
+ function taicpu.calcsize(p:PInsEntry):shortint;
+ begin
+ result:=4;
+ end;
+
+
+ function taicpu.NeedAddrPrefix(opidx:byte):boolean;
+ begin
+ end;
+
+
+ procedure taicpu.Swapoperands;
+ begin
+ end;
+
+
+ function taicpu.FindInsentry:boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ { Things which may only be done once, not when a second pass is done to
+ optimize }
+ if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ { create the .ot fields }
+ create_ot;
+ { set the file postion }
+ aktfilepos:=fileinfo;
+ end
+ else
+ begin
+ { we've already an insentry so it's valid }
+ result:=true;
+ exit;
+ end;
+ { Lookup opcode in the table }
+ InsSize:=-1;
+ i:=instabcache^[opcode];
+ if i=-1 then
+ begin
+ Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
+ exit;
+ end;
+ insentry:=@instab[i];
+ while (insentry^.opcode=opcode) do
+ begin
+ if matches(insentry)=100 then
+ begin
+ result:=true;
+ exit;
+ end;
+ inc(i);
+ insentry:=@instab[i];
+ end;
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+ { No instruction found, set insentry to nil and inssize to -1 }
+ insentry:=nil;
+ inssize:=-1;
+ end;
+
+
+ procedure taicpu.gencode(objdata:TAsmObjectData);
+ var
+ bytes : dword;
+ i_field : byte;
+
+ procedure setshifterop(op : byte);
+ begin
+ case oper[op]^.typ of
+ top_const:
+ begin
+ i_field:=1;
+ bytes:=bytes or (oper[op]^.val and $fff);
+ end;
+ top_reg:
+ begin
+ i_field:=0;
+ bytes:=bytes or (getsupreg(oper[op]^.reg) shl 16);
+
+ { does a real shifter op follow? }
+ if (op+1<=op) and (oper[op+1]^.typ=top_shifterop) then
+ begin
+ end;
+ end;
+ else
+ internalerror(2005091103);
+ end;
+ end;
+
+ begin
+ bytes:=$0;
+ { evaluate and set condition code }
+
+ { condition code allowed? }
+
+ { setup rest of the instruction }
+ case insentry^.code[0] of
+ #$08:
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 26);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 21);
+
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+
+ { create shifter op }
+ setshifterop(1);
+
+ { set i field }
+ bytes:=bytes or (i_field shl 25);
+
+ { set s if necessary }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$ff:
+ internalerror(2005091101);
+ else
+ internalerror(2005091102);
+ end;
+ { we're finished, write code }
+ objdata.writebytes(bytes,sizeof(bytes));
+ end;
+
+
+end.
+
+{$ifdef dummy}
+ (*
+static void gencode (long segment, long offset, int bits,
+ insn *ins, char *codes, long insn_end)
+{
+ int has_S_code; /* S - setflag */
+ int has_B_code; /* B - setflag */
+ int has_T_code; /* T - setflag */
+ int has_W_code; /* ! => W flag */
+ int has_F_code; /* ^ => S flag */
+ int keep;
+ unsigned char c;
+ unsigned char bytes[4];
+ long data, size;
+ static int cc_code[] = /* bit pattern of cc */
+ { /* order as enum in */
+ 0x0E, 0x03, 0x02, 0x00, /* nasm.h */
+ 0x0A, 0x0C, 0x08, 0x0D,
+ 0x09, 0x0B, 0x04, 0x01,
+ 0x05, 0x07, 0x06,
+ };
+
+(*
+#ifdef DEBUG
+static char *CC[] =
+ { /* condition code names */
+ "AL", "CC", "CS", "EQ",
+ "GE", "GT", "HI", "LE",
+ "LS", "LT", "MI", "NE",
+ "PL", "VC", "VS", "",
+ "S"
+};
+*)
+
+ has_S_code = (ins->condition & C_SSETFLAG);
+ has_B_code = (ins->condition & C_BSETFLAG);
+ has_T_code = (ins->condition & C_TSETFLAG);
+ has_W_code = (ins->condition & C_EXSETFLAG);
+ has_F_code = (ins->condition & C_FSETFLAG);
+ ins->condition = (ins->condition & 0x0F);
+
+(*
+ if (rt_debug)
+ {
+ printf ("gencode: instruction: %s%s", insn_names[ins->opcode],
+ CC[ins->condition & 0x0F]);
+ if (has_S_code)
+ printf ("S");
+ if (has_B_code)
+ printf ("B");
+ if (has_T_code)
+ printf ("T");
+ if (has_W_code)
+ printf ("!");
+ if (has_F_code)
+ printf ("^");
+
+ printf ("\n");
+
+ c = *codes;
+
+ printf (" (%d) decode - '0x%02X'\n", ins->operands, c);
+
+
+ bytes[0] = 0xB;
+ bytes[1] = 0xE;
+ bytes[2] = 0xE;
+ bytes[3] = 0xF;
+ }
+*)
+ // First condition code in upper nibble
+ if (ins->condition < C_NONE)
+ {
+ c = cc_code[ins->condition] << 4;
+ }
+ else
+ {
+ c = cc_code[C_AL] << 4; // is often ALWAYS but not always
+ }
+
+
+ switch (keep = *codes)
+ {
+ case 1:
+ // B, BL
+ ++codes;
+ c |= *codes++;
+ bytes[0] = c;
+
+ if (ins->oprs[0].segment != segment)
+ {
+ // fais une relocation
+ c = 1;
+ data = 0; // Let the linker locate ??
+ }
+ else
+ {
+ c = 0;
+ data = ins->oprs[0].offset - (offset + 8);
+
+ if (data % 4)
+ {
+ errfunc (ERR_NONFATAL, "offset not aligned on 4 bytes");
+ }
+ }
+
+ if (data >= 0x1000)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+
+ data = data >> 2;
+ bytes[1] = (data >> 16) & 0xFF;
+ bytes[2] = (data >> 8) & 0xFF;
+ bytes[3] = (data ) & 0xFF;
+
+ if (c == 1)
+ {
+// out (offset, segment, &bytes[0], OUT_RAWDATA+1, NO_SEG, NO_SEG);
+ out (offset, segment, &bytes[0], OUT_REL3ADR+4, ins->oprs[0].segment, NO_SEG);
+ }
+ else
+ {
+ out (offset, segment, &bytes[0], OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ }
+ return;
+
+ case 2:
+ // SWI
+ ++codes;
+ c |= *codes++;
+ bytes[0] = c;
+ data = ins->oprs[0].offset;
+ bytes[1] = (data >> 16) & 0xFF;
+ bytes[2] = (data >> 8) & 0xFF;
+ bytes[3] = (data) & 0xFF;
+ out (offset, segment, &bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+ case 3:
+ // BX
+ ++codes;
+ c |= *codes++;
+ bytes[0] = c;
+ bytes[1] = *codes++;
+ bytes[2] = *codes++;
+ bytes[3] = *codes++;
+ c = regval (&ins->oprs[0],1);
+ if (c == 15) // PC
+ {
+ errfunc (ERR_WARNING, "'BX' with R15 has undefined behaviour");
+ }
+ else if (c > 15)
+ {
+ errfunc (ERR_NONFATAL, "Illegal register specified for 'BX'");
+ }
+
+ bytes[3] |= (c & 0x0F);
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+
+ case 4: // AND Rd,Rn,Rm
+ case 5: // AND Rd,Rn,Rm,<shift>Rs
+ case 6: // AND Rd,Rn,Rm,<shift>imm
+ case 7: // AND Rd,Rn,<shift>imm
+ ++codes;
+#ifdef DEBUG
+ if (rt_debug)
+ {
+ printf (" decode - '0x%02X'\n", keep);
+ printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
+ }
+#endif
+ bytes[0] = c | *codes;
+ ++codes;
+
+ bytes[1] = *codes;
+ if (has_S_code)
+ bytes[1] |= 0x10;
+ c = regval (&ins->oprs[1],1);
+ // Rn in low nibble
+ bytes[1] |= c;
+
+ // Rd in high nibble
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ if (keep != 7)
+ {
+ // Rm in low nibble
+ bytes[3] = regval (&ins->oprs[2],1);
+ }
+
+ // Shifts if any
+ if (keep == 5 || keep == 6)
+ {
+ // Shift in bytes 2 and 3
+ if (keep == 5)
+ {
+ // Rs
+ c = regval (&ins->oprs[3],1);
+ bytes[2] |= c;
+
+ c = 0x10; // Set bit 4 in byte[3]
+ }
+ if (keep == 6)
+ {
+ c = (ins->oprs[3].offset) & 0x1F;
+
+ // #imm
+ bytes[2] |= c >> 1;
+ if (c & 0x01)
+ {
+ bytes[3] |= 0x80;
+ }
+ c = 0; // Clr bit 4 in byte[3]
+ }
+ // <shift>
+ c |= shiftval (&ins->oprs[3]) << 5;
+
+ bytes[3] |= c;
+ }
+
+ // reg,reg,imm
+ if (keep == 7)
+ {
+ int shimm;
+
+ shimm = imm_shift (ins->oprs[2].offset);
+
+ if (shimm == -1)
+ {
+ errfunc (ERR_NONFATAL, "cannot create that constant");
+ }
+ bytes[3] = shimm & 0xFF;
+ bytes[2] |= (shimm & 0xF00) >> 8;
+ }
+
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+
+ case 8: // MOV Rd,Rm
+ case 9: // MOV Rd,Rm,<shift>Rs
+ case 0xA: // MOV Rd,Rm,<shift>imm
+ case 0xB: // MOV Rd,<shift>imm
+ ++codes;
+#ifdef DEBUG
+ if (rt_debug)
+ {
+ printf (" decode - '0x%02X'\n", keep);
+ printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
+ }
+#endif
+ bytes[0] = c | *codes;
+ ++codes;
+
+ bytes[1] = *codes;
+ if (has_S_code)
+ bytes[1] |= 0x10;
+
+ // Rd in high nibble
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ if (keep != 0x0B)
+ {
+ // Rm in low nibble
+ bytes[3] = regval (&ins->oprs[1],1);
+ }
+
+ // Shifts if any
+ if (keep == 0x09 || keep == 0x0A)
+ {
+ // Shift in bytes 2 and 3
+ if (keep == 0x09)
+ {
+ // Rs
+ c = regval (&ins->oprs[2],1);
+ bytes[2] |= c;
+
+ c = 0x10; // Set bit 4 in byte[3]
+ }
+ if (keep == 0x0A)
+ {
+ c = (ins->oprs[2].offset) & 0x1F;
+
+ // #imm
+ bytes[2] |= c >> 1;
+ if (c & 0x01)
+ {
+ bytes[3] |= 0x80;
+ }
+ c = 0; // Clr bit 4 in byte[3]
+ }
+ // <shift>
+ c |= shiftval (&ins->oprs[2]) << 5;
+
+ bytes[3] |= c;
+ }
+
+ // reg,imm
+ if (keep == 0x0B)
+ {
+ int shimm;
+
+ shimm = imm_shift (ins->oprs[1].offset);
+
+ if (shimm == -1)
+ {
+ errfunc (ERR_NONFATAL, "cannot create that constant");
+ }
+ bytes[3] = shimm & 0xFF;
+ bytes[2] |= (shimm & 0xF00) >> 8;
+ }
+
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+
+
+ case 0xC: // CMP Rn,Rm
+ case 0xD: // CMP Rn,Rm,<shift>Rs
+ case 0xE: // CMP Rn,Rm,<shift>imm
+ case 0xF: // CMP Rn,<shift>imm
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes;
+
+ // Implicit S code
+ bytes[1] |= 0x10;
+
+ c = regval (&ins->oprs[0],1);
+ // Rn in low nibble
+ bytes[1] |= c;
+
+ // No destination
+ bytes[2] = 0;
+
+ if (keep != 0x0B)
+ {
+ // Rm in low nibble
+ bytes[3] = regval (&ins->oprs[1],1);
+ }
+
+ // Shifts if any
+ if (keep == 0x0D || keep == 0x0E)
+ {
+ // Shift in bytes 2 and 3
+ if (keep == 0x0D)
+ {
+ // Rs
+ c = regval (&ins->oprs[2],1);
+ bytes[2] |= c;
+
+ c = 0x10; // Set bit 4 in byte[3]
+ }
+ if (keep == 0x0E)
+ {
+ c = (ins->oprs[2].offset) & 0x1F;
+
+ // #imm
+ bytes[2] |= c >> 1;
+ if (c & 0x01)
+ {
+ bytes[3] |= 0x80;
+ }
+ c = 0; // Clr bit 4 in byte[3]
+ }
+ // <shift>
+ c |= shiftval (&ins->oprs[2]) << 5;
+
+ bytes[3] |= c;
+ }
+
+ // reg,imm
+ if (keep == 0x0F)
+ {
+ int shimm;
+
+ shimm = imm_shift (ins->oprs[1].offset);
+
+ if (shimm == -1)
+ {
+ errfunc (ERR_NONFATAL, "cannot create that constant");
+ }
+ bytes[3] = shimm & 0xFF;
+ bytes[2] |= (shimm & 0xF00) >> 8;
+ }
+
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+
+ case 0x10: // MRS Rd,<psr>
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ c = regval (&ins->oprs[0],1);
+
+ bytes[2] = c << 4;
+
+ bytes[3] = 0;
+
+ c = ins->oprs[1].basereg;
+
+ if (c == R_CPSR || c == R_SPSR)
+ {
+ if (c == R_SPSR)
+ {
+ bytes[1] |= 0x40;
+ }
+ }
+ else
+ {
+ errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
+ }
+
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+
+ return;
+
+ case 0x11: // MSR <psr>,Rm
+ case 0x12: // MSR <psrf>,Rm
+ case 0x13: // MSR <psrf>,#expression
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ bytes[2] = *codes;
+
+
+ if (keep == 0x11 || keep == 0x12)
+ {
+ // Rm
+ c = regval (&ins->oprs[1],1);
+
+ bytes[3] = c;
+ }
+ else
+ {
+ int shimm;
+
+ shimm = imm_shift (ins->oprs[1].offset);
+
+ if (shimm == -1)
+ {
+ errfunc (ERR_NONFATAL, "cannot create that constant");
+ }
+ bytes[3] = shimm & 0xFF;
+ bytes[2] |= (shimm & 0xF00) >> 8;
+ }
+
+ c = ins->oprs[0].basereg;
+
+ if ( keep == 0x11)
+ {
+ if ( c == R_CPSR || c == R_SPSR)
+ {
+ if ( c== R_SPSR)
+ {
+ bytes[1] |= 0x40;
+ }
+ }
+ else
+ {
+ errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
+ }
+ }
+ else
+ {
+ if ( c == R_CPSR_FLG || c == R_SPSR_FLG)
+ {
+ if ( c== R_SPSR_FLG)
+ {
+ bytes[1] |= 0x40;
+ }
+ }
+ else
+ {
+ errfunc (ERR_NONFATAL, "CPSR_flg or SPSR_flg expected");
+ }
+ }
+ break;
+
+ case 0x14: // MUL Rd,Rm,Rs
+ case 0x15: // MULA Rd,Rm,Rs,Rn
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ bytes[3] = *codes;
+
+ // Rd
+ bytes[1] |= regval (&ins->oprs[0],1);
+ if (has_S_code)
+ bytes[1] |= 0x10;
+
+ // Rm
+ bytes[3] |= regval (&ins->oprs[1],1);
+
+ // Rs
+ bytes[2] = regval (&ins->oprs[2],1);
+
+ if (keep == 0x15)
+ {
+ bytes[2] |= regval (&ins->oprs[3],1) << 4;
+ }
+ break;
+
+ case 0x16: // SMLAL RdHi,RdLo,Rm,Rs
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ bytes[3] = *codes;
+
+ // RdHi
+ bytes[1] |= regval (&ins->oprs[1],1);
+ if (has_S_code)
+ bytes[1] |= 0x10;
+
+ // RdLo
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ // Rm
+ bytes[3] |= regval (&ins->oprs[2],1);
+
+ // Rs
+ bytes[2] |= regval (&ins->oprs[3],1);
+
+ break;
+
+ case 0x17: // LDR Rd, expression
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ if (has_B_code)
+ bytes[1] |= 0x40;
+ if (has_T_code)
+ {
+ errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
+ }
+ if (has_W_code)
+ {
+ errfunc (ERR_NONFATAL, "'!' not allowed");
+ }
+
+ // Rn - implicit R15
+ bytes[1] |= 0xF;
+
+ if (ins->oprs[1].segment != segment)
+ {
+ errfunc (ERR_NONFATAL, "label not in same segment");
+ }
+
+ data = ins->oprs[1].offset - (offset + 8);
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x1000)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+
+ bytes[2] |= ((data & 0xF00) >> 8);
+ bytes[3] = data & 0xFF;
+ break;
+
+ case 0x18: // LDR Rd, [Rn]
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ if (has_B_code)
+ bytes[1] |= 0x40;
+ if (has_T_code)
+ {
+ bytes[1] |= 0x20; // write-back
+ }
+ else
+ {
+ bytes[0] |= 0x01; // implicit pre-index mode
+ }
+
+ if (has_W_code)
+ {
+ bytes[1] |= 0x20; // write-back
+ }
+
+ // Rn
+ c = regval (&ins->oprs[1],1);
+ bytes[1] |= c;
+
+ if (c == 0x15) // R15
+ data = -8;
+ else
+ data = 0;
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ bytes[2] |= ((data & 0xF00) >> 8);
+ bytes[3] = data & 0xFF;
+ break;
+
+ case 0x19: // LDR Rd, [Rn,#expression]
+ case 0x20: // LDR Rd, [Rn,Rm]
+ case 0x21: // LDR Rd, [Rn,Rm,shift]
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ if (has_B_code)
+ bytes[1] |= 0x40;
+
+ // Rn
+ c = regval (&ins->oprs[1],1);
+ bytes[1] |= c;
+
+ if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
+ {
+ bytes[0] |= 0x01; // pre-index mode
+ if (has_W_code)
+ {
+ bytes[1] |= 0x20;
+ }
+ if (has_T_code)
+ {
+ errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
+ }
+ }
+ else
+ {
+ if (has_T_code) // Forced write-back in post-index mode
+ {
+ bytes[1] |= 0x20;
+ }
+ if (has_W_code)
+ {
+ errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
+ }
+ }
+
+ if (keep == 0x19)
+ {
+ data = ins->oprs[2].offset;
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x1000)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+
+ bytes[2] |= ((data & 0xF00) >> 8);
+ bytes[3] = data & 0xFF;
+ }
+ else
+ {
+ if (ins->oprs[2].minus == 0)
+ {
+ bytes[1] |= 0x80;
+ }
+ c = regval (&ins->oprs[2],1);
+ bytes[3] = c;
+
+ if (keep == 0x21)
+ {
+ c = ins->oprs[3].offset;
+ if (c > 0x1F)
+ {
+ errfunc (ERR_NONFATAL, "too large shiftvalue");
+ c = c & 0x1F;
+ }
+
+ bytes[2] |= c >> 1;
+ if (c & 0x01)
+ {
+ bytes[3] |= 0x80;
+ }
+ bytes[3] |= shiftval (&ins->oprs[3]) << 5;
+ }
+ }
+
+ break;
+
+ case 0x22: // LDRH Rd, expression
+ ++codes;
+
+ bytes[0] = c | 0x01; // Implicit pre-index
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ // Rn - implicit R15
+ bytes[1] |= 0xF;
+
+ if (ins->oprs[1].segment != segment)
+ {
+ errfunc (ERR_NONFATAL, "label not in same segment");
+ }
+
+ data = ins->oprs[1].offset - (offset + 8);
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x100)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+ bytes[3] = *codes++;
+
+ bytes[2] |= ((data & 0xF0) >> 4);
+ bytes[3] |= data & 0xF;
+ break;
+
+ case 0x23: // LDRH Rd, Rn
+ ++codes;
+
+ bytes[0] = c | 0x01; // Implicit pre-index
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ // Rn
+ c = regval (&ins->oprs[1],1);
+ bytes[1] |= c;
+
+ if (c == 0x15) // R15
+ data = -8;
+ else
+ data = 0;
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x100)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+ bytes[3] = *codes++;
+
+ bytes[2] |= ((data & 0xF0) >> 4);
+ bytes[3] |= data & 0xF;
+ break;
+
+ case 0x24: // LDRH Rd, Rn, expression
+ case 0x25: // LDRH Rd, Rn, Rm
+ ++codes;
+
+ bytes[0] = c;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ // Rn
+ c = regval (&ins->oprs[1],1);
+ bytes[1] |= c;
+
+ if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
+ {
+ bytes[0] |= 0x01; // pre-index mode
+ if (has_W_code)
+ {
+ bytes[1] |= 0x20;
+ }
+ }
+ else
+ {
+ if (has_W_code)
+ {
+ errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
+ }
+ }
+
+ bytes[3] = *codes++;
+
+ if (keep == 0x24)
+ {
+ data = ins->oprs[2].offset;
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x100)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+
+ bytes[2] |= ((data & 0xF0) >> 4);
+ bytes[3] |= data & 0xF;
+ }
+ else
+ {
+ if (ins->oprs[2].minus == 0)
+ {
+ bytes[1] |= 0x80;
+ }
+ c = regval (&ins->oprs[2],1);
+ bytes[3] |= c;
+
+ }
+ break;
+
+ case 0x26: // LDM/STM Rn, {reg-list}
+ ++codes;
+
+ bytes[0] = c;
+
+ bytes[0] |= ( *codes >> 4) & 0xF;
+ bytes[1] = ( *codes << 4) & 0xF0;
+ ++codes;
+
+ if (has_W_code)
+ {
+ bytes[1] |= 0x20;
+ }
+ if (has_F_code)
+ {
+ bytes[1] |= 0x40;
+ }
+
+ // Rn
+ bytes[1] |= regval (&ins->oprs[0],1);
+
+ data = ins->oprs[1].basereg;
+
+ bytes[2] = ((data >> 8) & 0xFF);
+ bytes[3] = (data & 0xFF);
+
+ break;
+
+ case 0x27: // SWP Rd, Rm, [Rn]
+ ++codes;
+
+ bytes[0] = c;
+
+ bytes[0] |= *codes++;
+
+ bytes[1] = regval (&ins->oprs[2],1);
+ if (has_B_code)
+ {
+ bytes[1] |= 0x40;
+ }
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ bytes[3] = *codes++;
+ bytes[3] |= regval (&ins->oprs[1],1);
+ break;
+
+ default:
+ errfunc (ERR_FATAL, "unknown decoding of instruction");
+
+ bytes[0] = c;
+ // And a fix nibble
+ ++codes;
+ bytes[0] |= *codes++;
+
+ if ( *codes == 0x01) // An I bit
+ {
+
+ }
+ if ( *codes == 0x02) // An I bit
+ {
+
+ }
+ ++codes;
+ }
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+}
+
+
+*)
+{$endif dummy
+}
diff --git a/compiler/arm/agarmgas.pas b/compiler/arm/agarmgas.pas
new file mode 100644
index 0000000000..7622ceaa85
--- /dev/null
+++ b/compiler/arm/agarmgas.pas
@@ -0,0 +1,237 @@
+{
+ Copyright (c) 2003 by Florian Klaempfl
+
+ This unit implements an asm for the ARM
+
+ 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 GNU Assembler writer for the ARM
+}
+
+unit agarmgas;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmtai,
+ aggas,
+ cpubase;
+
+ type
+ PARMGNUAssembler=^TARMGNUAssembler;
+ TARMGNUAssembler=class(TGNUassembler)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+ const
+ gas_shiftmode2str : array[tshiftmode] of string[3] = (
+ '','lsl','lsr','asr','ror','rrx');
+
+ implementation
+
+ uses
+ cutils,globals,verbose,
+ systems,
+ assemble,
+ aasmcpu,
+ itcpugas,
+ cgbase,cgutils;
+
+ const
+ as_arm_gas_info : tasminfo =
+ (
+ id : as_gas;
+
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+{$ifdef extdebug}
+ // if base=NR_NO then
+ // internalerror(200308292);
+
+ // if ((index<>NR_NO) or (shiftmode<>SM_None)) and ((offset<>0) or (symbol<>nil)) then
+ // internalerror(200308293);
+{$endif extdebug}
+
+ if assigned(symbol) then
+ begin
+ if (base<>NR_NO) and not(is_pc(base)) then
+ internalerror(200309011);
+ s:=symbol.name;
+ if offset<0 then
+ s:=s+tostr(offset)
+ else if offset>0 then
+ s:=s+'+'+tostr(offset);
+ end
+ else
+ begin
+ s:='['+gas_regname(base);
+ if addressmode=AM_POSTINDEXED then
+ s:=s+']';
+ if index<>NR_NO then
+ begin
+ if signindex<0 then
+ s:=s+', -'
+ else
+ s:=s+', ';
+
+ s:=s+gas_regname(index);
+
+ if shiftmode<>SM_None then
+ s:=s+' ,'+gas_shiftmode2str[shiftmode]+' #'+tostr(shiftimm);
+ end
+ else if offset<>0 then
+ s:=s+', #'+tostr(offset);
+
+ case addressmode of
+ AM_OFFSET:
+ s:=s+']';
+ AM_PREINDEXED:
+ s:=s+']!';
+ end;
+ end;
+
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ const
+ shiftmode2str: array[tshiftmode] of string[3] = ('','lsl','lsr','asr','ror','rrx');
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ first : boolean;
+ r : tsuperregister;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_shifterop:
+ begin
+ if (o.shifterop^.rs<>NR_NO) and (o.shifterop^.shiftimm=0) then
+ getopstr:=shiftmode2str[o.shifterop^.shiftmode]+' '+gas_regname(o.shifterop^.rs)
+ else if (o.shifterop^.rs=NR_NO) then
+ getopstr:=shiftmode2str[o.shifterop^.shiftmode]+' #'+tostr(o.shifterop^.shiftimm)
+ else internalerror(200308282);
+ end;
+ top_const:
+ getopstr:='#'+tostr(longint(o.val));
+ top_regset:
+ begin
+ getopstr:='{';
+ first:=true;
+ for r:=RS_R0 to RS_R15 do
+ if r in o.regset^ then
+ begin
+ if not(first) then
+ getopstr:=getopstr+',';
+ getopstr:=getopstr+gas_regname(newreg(R_INTREGISTER,r,R_SUBWHOLE));
+ first:=false;
+ end;
+ getopstr:=getopstr+'}';
+ end;
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=o.ref^.symbol.name;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(o.ref^);
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+
+ Procedure TARMGNUAssembler.WriteInstruction(hp : tai);
+ var op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ op:=taicpu(hp).opcode;
+ s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix];
+ if taicpu(hp).ops<>0 then
+ begin
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ // debug code
+ // writeln(s);
+ // writeln(taicpu(hp).fileinfo.line);
+
+ { LDM and STM use references as first operand but they are written like a register }
+ if (i=0) and (op in [A_LDM,A_STM]) then
+ begin
+ case taicpu(hp).oper[0]^.typ of
+ top_ref:
+ begin
+ s:=s+sep+gas_regname(taicpu(hp).oper[0]^.ref^.index);
+ if taicpu(hp).oper[0]^.ref^.addressmode=AM_PREINDEXED then
+ s:=s+'!';
+ end;
+ top_reg:
+ s:=s+sep+gas_regname(taicpu(hp).oper[0]^.reg);
+ else
+ internalerror(200311292);
+ end;
+ end
+ { register count of SFM and LFM is written without # }
+ else if (i=1) and (op in [A_SFM,A_LFM]) then
+ begin
+ case taicpu(hp).oper[1]^.typ of
+ top_const:
+ s:=s+sep+tostr(taicpu(hp).oper[1]^.val);
+ else
+ internalerror(200311292);
+ end;
+ end
+ else
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+
+ sep:=',';
+ end;
+ end;
+ AsmWriteLn(s);
+ end;
+
+
+begin
+ RegisterAssembler(as_arm_gas_info,TARMGNUAssembler);
+end.
diff --git a/compiler/arm/aoptcpu.pas b/compiler/arm/aoptcpu.pas
new file mode 100644
index 0000000000..e15acceb04
--- /dev/null
+++ b/compiler/arm/aoptcpu.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the ARM optimizer object
+
+ 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, aopt, aoptcpub;
+
+Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ End;
+
+Implementation
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+End.
diff --git a/compiler/arm/aoptcpub.pas b/compiler/arm/aoptcpub.pas
new file mode 100644
index 0000000000..d9bc456bf0
--- /dev/null
+++ b/compiler/arm/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the ARM 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_B;
+ aopt_condjmp = A_B;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/compiler/arm/aoptcpuc.pas b/compiler/arm/aoptcpuc.pas
new file mode 100644
index 0000000000..7532a77fa3
--- /dev/null
+++ b/compiler/arm/aoptcpuc.pas
@@ -0,0 +1,38 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ 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 aoptcpuc;
+
+Interface
+
+Uses
+ AOptCs;
+
+Type
+ TRegInfoCpu = Object(TRegInfo)
+ End;
+
+
+Implementation
+
+End.
diff --git a/compiler/arm/aoptcpud.pas b/compiler/arm/aoptcpud.pas
new file mode 100644
index 0000000000..2df7e2e49e
--- /dev/null
+++ b/compiler/arm/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ 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.
diff --git a/compiler/arm/armatt.inc b/compiler/arm/armatt.inc
new file mode 100644
index 0000000000..e29160bef4
--- /dev/null
+++ b/compiler/arm/armatt.inc
@@ -0,0 +1,90 @@
+{ don't edit, this file is generated from armins.dat }
+(
+'none',
+'abs',
+'acs',
+'asn',
+'atn',
+'adc',
+'add',
+'adf',
+'and',
+'b',
+'bic',
+'bl',
+'blx',
+'bkpt',
+'bx',
+'cdp',
+'cmf',
+'cmfe',
+'cmn',
+'cmp',
+'clz',
+'cnf',
+'cos',
+'dvf',
+'eor',
+'exp',
+'fdv',
+'flt',
+'fix',
+'fml',
+'frd',
+'ldc',
+'ldm',
+'ldrbt',
+'ldrb',
+'ldr',
+'ldrh',
+'ldrsb',
+'ldrsh',
+'ldrt',
+'ldf',
+'lfm',
+'lgn',
+'log',
+'mcr',
+'mla',
+'mov',
+'mnf',
+'muf',
+'mul',
+'mvf',
+'mvn',
+'orr',
+'rdf',
+'rfs',
+'rfc',
+'rmf',
+'rpw',
+'rsb',
+'rsc',
+'rsf',
+'rnd',
+'pol',
+'sbc',
+'sfm',
+'sin',
+'smlal',
+'smull',
+'sqt',
+'suf',
+'stf',
+'stm',
+'str',
+'strb',
+'strbt',
+'strh',
+'strt',
+'sub',
+'swi',
+'swp',
+'swpb',
+'tan',
+'teq',
+'tst',
+'umlal',
+'umull',
+'wfs'
+);
diff --git a/compiler/arm/armatts.inc b/compiler/arm/armatts.inc
new file mode 100644
index 0000000000..eb08065e2f
--- /dev/null
+++ b/compiler/arm/armatts.inc
@@ -0,0 +1,90 @@
+{ don't edit, this file is generated from armins.dat }
+(
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE
+);
diff --git a/compiler/arm/armins.dat b/compiler/arm/armins.dat
new file mode 100644
index 0000000000..1f4958b86d
--- /dev/null
+++ b/compiler/arm/armins.dat
@@ -0,0 +1,394 @@
+;
+; Table of assembler instructions for Free Pascal
+; adapted from Netwide Assembler by Florian Klaempfl
+;
+;
+; The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+; Julian Hall. All rights reserved. The software is
+; redistributable under the licence given in the file "Licence"
+; distributed in the NASM archive.
+;
+; Format of file: all four fields must be present on every functional
+; line. Hence `void' for no-operand instructions, and `\0' for such
+; as EQU. If the last three fields are all `ignore', no action is
+; taken except to register the opcode as being present.
+;
+;
+; 'ignore' means no instruc
+; 'void' means instruc with zero operands
+;
+; Third field has a first byte indicating how to
+; put together the bits, and then some codes
+; that may be used at will (see assemble.c)
+;
+; \1 - 24 bit pc-rel offset [B, BL]
+; \2 - 24 bit imm value [SWI]
+; \3 - 3 byte code [BX]
+;
+; \4 - reg,reg,reg [AND,EOR,SUB,RSB,ADD,ADC,SBC,RSC,ORR,BIC]
+; \5 - reg,reg,reg,<shift>reg [-"-]
+; \6 - reg,reg,reg,<shift>#imm [-"-]
+; \7 - reg,reg,#imm [-"-]
+;
+; \x8 - reg,reg [MOV,MVN]
+; \x9 - reg,reg,<shift>reg [-"-]
+; \xA - reg,reg,<shift>#imm [-"-]
+; \xB - reg,#imm [-"-]
+;
+; \xC - reg,reg [CMP,CMN,TEQ,TST]
+; \xD - reg,reg,<shift>reg [-"-]
+; \xE - reg,reg,<shift>#imm [-"-]
+; \xF - reg,#imm [-"-]
+;
+; \xFx - floating point instructions
+; Floating point instruction format information, taken from the linux kernel,
+; for detailed tables, see aasmcpu.pas
+;
+; ARM Floating Point Instruction Classes
+; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+; |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
+; |c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2)
+; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+; |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
+; |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
+; |c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
+; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+;
+; CPDT data transfer instructions
+; LDF, STF, LFM (copro 2), SFM (copro 2)
+;
+; CPDO dyadic arithmetic instructions
+; ADF, MUF, SUF, RSF, DVF, RDF,
+; POW, RPW, RMF, FML, FDV, FRD, POL
+;
+; CPDO monadic arithmetic instructions
+; MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
+; SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
+;
+; CPRT joint arithmetic/data transfer instructions
+; FIX (arithmetic followed by load/store)
+; FLT (load/store followed by arithmetic)
+; CMF, CNF CMFE, CNFE (comparisons)
+; WFS, RFS (write/read floating point status register)
+; WFC, RFC (write/read floating point control register)
+; \xF0 - CPDT
+; code 1: copro (1/2)
+; code 2: load/store bit
+; \xF1 - CPDO
+; \xF2 - CPDO monadic
+; \xF3 - CPRT
+; \xF4 - CPRT comparison
+;
+; \xFF - fix me
+;
+
+[NONE]
+void void none
+
+[ABScc]
+
+[ACScc]
+
+[ASNcc]
+
+[ATNcc]
+
+[ADCcc]
+reg32,reg32,reg32 \4\x0\xA0 ARM7
+reg32,reg32,reg32,reg32 \5\x0\xA0 ARM7
+reg32,reg32,reg32,imm \6\x0\xA0 ARM7
+reg32,reg32,imm \7\x2\xA0 ARM7
+
+[ADDcc]
+reg32,reg32,reg32 \4\x0\x80 ARM7
+reg32,reg32,reg32,reg32 \5\x0\x80 ARM7
+reg32,reg32,reg32,imm \6\x0\x80 ARM7
+reg32,reg32,imm \7\x2\x80 ARM7
+
+[ADFcc]
+
+[ANDcc]
+reg32,reg32,reg32 \4\x0\x00 ARM7
+reg32,reg32,reg32,reg32 \5\x0\x00 ARM7
+reg32,reg32,reg32,imm \6\x0\x00 ARM7
+reg32,reg32,imm \7\x2\x00 ARM7
+
+[Bcc]
+mem32 \1\x0A ARM7
+imm24 \1\x0A ARM7
+
+[BICcc]
+reg32,reg32,reg32 \4\x1\xC0 ARM7
+reg32,reg32,reg32,reg32 \5\x1\xC0 ARM7
+reg32,reg32,reg32,imm \6\x1\xC0 ARM7
+reg32,reg32,imm \7\x3\xC0 ARM7
+
+[BLcc]
+mem32 \1\x0B ARM7
+imm24 \1\x0B ARM7
+
+[BLX]
+mem32 \xff ARM7
+imm24 \xff ARM7
+
+[BKPTcc]
+
+[BXcc]
+reg32 \3\x01\x2F\xFF\x10 ARM7
+
+[CDP]
+reg8,reg8 \300\1\x10\101 ARM7
+
+[CMFcc]
+
+[CMFEcc]
+
+[CMNcc]
+reg32,reg32 \xC\x1\x60 ARM7
+reg32,reg32,reg32 \xD\x1\x60 ARM7
+reg32,reg32,imm \xE\x1\x60 ARM7
+reg32,imm \xF\x3\x60 ARM7
+
+[CMPcc]
+reg32,reg32 \xC\x1\x40 ARM7
+reg32,reg32,reg32 \xD\x1\x40 ARM7
+reg32,reg32,imm \xE\x1\x40 ARM7
+reg32,imm \xF\x3\x40 ARM7
+
+[CLZcc]
+reg32,reg32 \x27\x01\x01 ARM7
+
+[CNFcc]
+
+[COScc]
+
+[DVFcc]
+
+[EORcc]
+reg32,reg32,reg32 \4\x0\x20 ARM7
+reg32,reg32,reg32,reg32 \5\x0\x20 ARM7
+reg32,reg32,reg32,imm \6\x0\x20 ARM7
+reg32,reg32,imm \7\x2\x20 ARM7
+
+[EXPcc]
+
+[FDVcc]
+
+[FLTcc]
+
+[FIXcc]
+
+[FMLcc]
+
+[FRDcc]
+
+[LDC]
+reg32,reg32 \321\300\1\x11\101 ARM7
+
+[LDMcc]
+memam4,reglist \x26\x81 ARM7
+
+[LDRBTcc]
+
+[LDRBcc]
+reg32,memam2 \x17\x07\x10 ARM7
+
+[LDRcc]
+reg32,memam2 \x17\x05\x10 ARM7
+; reg32,imm32 \x17\x05\x10 ARM7
+; reg32,reg32 \x18\x04\x10 ARM7
+; reg32,reg32,imm32 \x19\x04\x10 ARM7
+; reg32,reg32,reg32 \x20\x06\x10 ARM7
+; reg32,reg32,reg32,imm32 \x21\x06\x10 ARM7
+
+[LDRHcc]
+reg32,imm32 \x22\x50\xB0 ARM7
+reg32,reg32 \x23\x50\xB0 ARM7
+reg32,reg32,imm32 \x24\x50\xB0 ARM7
+reg32,reg32,reg32 \x25\x10\xB0 ARM7
+
+[LDRSBcc]
+reg32,imm32 \x22\x50\xD0 ARM7
+reg32,reg32 \x23\x50\xD0 ARM7
+reg32,reg32,imm32 \x24\x50\xD0 ARM7
+reg32,reg32,reg32 \x25\x10\xD0 ARM7
+
+[LDRSHcc]
+reg32,imm32 \x22\x50\xF0 ARM7
+reg32,reg32 \x23\x50\xF0 ARM7
+reg32,reg32,imm32 \x24\x50\xF0 ARM7
+reg32,reg32,reg32 \x25\x10\xF0 ARM7
+
+[LDRTcc]
+
+[LDFcc]
+
+[LFMcc]
+reg32,imm8,fpureg \xF0\x02\x01 FPA
+
+[LGNcc]
+
+[LOGcc]
+
+[MCR]
+reg32,mem32 \320\301\1\x13\110 ARM7
+
+[MLAcc]
+reg32,reg32,reg32,reg32 \x15\x00\x20\x90 ARM7
+
+[MOVcc]
+reg32,shifterop \x8\x0\0xd ARM7
+reg32,immshifter \x8\x0\0xd ARM7
+; reg32,reg32,reg32 \x9\x1\xA0 ARM7
+; reg32,reg32,imm \xA\x1\xA0 ARM7
+; reg32,imm \xB\x3\xA0 ARM7
+
+; [MRC]
+; reg32,reg32 \321\301\1\x13\110 ARM7
+
+; [MRScc]
+; reg32,reg32 \x10\x01\x0F ARM7
+
+; [MSRcc]
+; reg32,reg32 \x11\x01\x29\xF0 ARM7
+; regf,reg32 \x12\x01\x28\xF0 ARM7
+; regf,imm \x13\x03\x28\xF0 ARM7
+
+[MNFcc]
+
+[MUFcc]
+
+[MULcc]
+reg32,reg32,reg32 \x14\x00\x00\x90 ARM7
+
+[MVFcc]
+fpureg,fpureg \xF2 FPA
+fpureg,immfpu \xF2 FPA
+
+[MVNcc]
+reg32,reg32 \x8\x0\0xf ARM7
+reg32,reg32,reg32 \x9\x1\xE0 ARM7
+reg32,reg32,imm \xA\x1\xE0 ARM7
+reg32,imm \xB\x3\xE0 ARM7
+
+[ORRcc]
+reg32,reg32,reg32 \4\x1\x80 ARM7
+reg32,reg32,reg32,reg32 \5\x1\x80 ARM7
+reg32,reg32,reg32,imm \6\x1\x80 ARM7
+reg32,reg32,imm \7\x3\x80 ARM7
+
+[RDFcc]
+
+[RFScc]
+
+[RFCcc]
+
+[RMFcc]
+
+[RPWcc]
+
+[RSBcc]
+reg32,reg32,reg32 \4\x0\x60 ARM7
+reg32,reg32,reg32,reg32 \5\x0\x60 ARM7
+reg32,reg32,reg32,imm \6\x0\x60 ARM7
+reg32,reg32,imm \7\x2\x60 ARM7
+
+[RSCcc]
+reg32,reg32,reg32 \4\x0\xE0 ARM7
+reg32,reg32,reg32,reg32 \5\x0\xE0 ARM7
+reg32,reg32,reg32,imm \6\x0\xE0 ARM7
+reg32,reg32,imm \7\x2\xE0 ARM7
+
+[RSFcc]
+
+[RNDcc]
+
+[POLcc]
+
+[SBCcc]
+reg32,reg32,reg32 \4\x0\xC0 ARM7
+reg32,reg32,reg32,reg32 \5\x0\xC0 ARM7
+reg32,reg32,reg32,imm \6\x0\xC0 ARM7
+reg32,reg32,imm \7\x2\xC0 ARM7
+
+[SFMcc]
+reg32,imm8,fpureg \xF0\x02\x00 FPA
+
+[SINcc]
+
+[SMLALcc]
+reg32,reg32,reg32,reg32 \x16\x00\xE0\x90 ARM7
+
+[SMULLcc]
+reg32,reg32,reg32,reg32 \x16\x00\xC0\x90 ARM7
+
+[SQTcc]
+
+[SUFcc]
+
+[STFcc]
+
+[STMcc]
+memam4,reglist \x26\x80 ARM7
+
+[STRcc]
+reg32,memam2 \x17\x04\x00 ARM7
+; reg32,imm32 \x17\x05\x00 ARM7
+; reg32,reg32 \x18\x04\x00 ARM7
+; reg32,reg32,imm32 \x19\x04\x00 ARM7
+; reg32,reg32,reg32 \x20\x06\x00 ARM7
+; reg32,reg32,reg32,imm32 \x21\x06\x00 ARM7
+
+[STRBcc]
+reg32,memam2 \x17\x06\x00 ARM7
+
+[STRBTcc]
+
+; A dummy since it is parsed as STR{cond}H
+[STRHcc]
+reg32,imm32 \x22\x40\xB0 ARM7
+reg32,reg32 \x23\x40\xB0 ARM7
+reg32,reg32,imm32 \x24\x40\xB0 ARM7
+reg32,reg32,reg32 \x25\x00\xB0 ARM7
+
+[STRTcc]
+
+[SUBcc]
+reg32,reg32,shifterop \4\x0\x40 ARM7
+reg32,reg32,immshifter \4\x0\x40 ARM7
+reg32,reg32,reg32 \4\x0\x40 ARM7
+; reg32,reg32,reg32,reg32 \5\x0\x40 ARM7
+; reg32,reg32,reg32,imm \6\x0\x40 ARM7
+; reg32,reg32,imm \7\x2\x40 ARM7
+
+[SWIcc]
+imm \2\x0F ARM7
+
+[SWPcc]
+reg32,reg32,reg32 \x27\x01\x90 ARM7
+
+[SWPBcc]
+reg32,reg32,reg32 \x27\x01\x90 ARM7
+
+[TANcc]
+
+[TEQcc]
+reg32,reg32 \xC\x1\x20 ARM7
+reg32,reg32,reg32 \xD\x1\x20 ARM7
+reg32,reg32,imm \xE\x1\x20 ARM7
+reg32,imm \xF\x3\x20 ARM7
+
+[TSTcc]
+reg32,reg32 \xC\x1\x00 ARM7
+reg32,reg32,reg32 \xD\x1\x00 ARM7
+reg32,reg32,imm \xE\x1\x00 ARM7
+reg32,imm \xF\x3\x00 ARM7
+
+[UMLALcc]
+reg32,reg32,reg32,reg32 \x16\x00\xA0\x90 ARM7
+
+[UMULLcc]
+reg32,reg32,reg32,reg32 \x16\x00\x80\x90 ARM7
+
+[WFScc]
+
diff --git a/compiler/arm/armnop.inc b/compiler/arm/armnop.inc
new file mode 100644
index 0000000000..5566510957
--- /dev/null
+++ b/compiler/arm/armnop.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from armins.dat }
+108;
diff --git a/compiler/arm/armop.inc b/compiler/arm/armop.inc
new file mode 100644
index 0000000000..134a8c8069
--- /dev/null
+++ b/compiler/arm/armop.inc
@@ -0,0 +1,90 @@
+{ don't edit, this file is generated from armins.dat }
+(
+A_NONE,
+A_ABS,
+A_ACS,
+A_ASN,
+A_ATN,
+A_ADC,
+A_ADD,
+A_ADF,
+A_AND,
+A_B,
+A_BIC,
+A_BL,
+A_BLX,
+A_BKPT,
+A_BX,
+A_CDP,
+A_CMF,
+A_CMFE,
+A_CMN,
+A_CMP,
+A_CLZ,
+A_CNF,
+A_COS,
+A_DVF,
+A_EOR,
+A_EXP,
+A_FDV,
+A_FLT,
+A_FIX,
+A_FML,
+A_FRD,
+A_LDC,
+A_LDM,
+A_LDRBT,
+A_LDRB,
+A_LDR,
+A_LDRH,
+A_LDRSB,
+A_LDRSH,
+A_LDRT,
+A_LDF,
+A_LFM,
+A_LGN,
+A_LOG,
+A_MCR,
+A_MLA,
+A_MOV,
+A_MNF,
+A_MUF,
+A_MUL,
+A_MVF,
+A_MVN,
+A_ORR,
+A_RDF,
+A_RFS,
+A_RFC,
+A_RMF,
+A_RPW,
+A_RSB,
+A_RSC,
+A_RSF,
+A_RND,
+A_POL,
+A_SBC,
+A_SFM,
+A_SIN,
+A_SMLAL,
+A_SMULL,
+A_SQT,
+A_SUF,
+A_STF,
+A_STM,
+A_STR,
+A_STRB,
+A_STRBT,
+A_STRH,
+A_STRT,
+A_SUB,
+A_SWI,
+A_SWP,
+A_SWPB,
+A_TAN,
+A_TEQ,
+A_TST,
+A_UMLAL,
+A_UMULL,
+A_WFS
+);
diff --git a/compiler/arm/armreg.dat b/compiler/arm/armreg.dat
new file mode 100644
index 0000000000..80b7fa00ab
--- /dev/null
+++ b/compiler/arm/armreg.dat
@@ -0,0 +1,84 @@
+;
+; ARM registers
+;
+; layout
+; <name>,<type>,<value>,<stdname>,<stab idx>,<dwarf idx>
+;
+NO,$00,$00,INVALID,-1,-1
+; Integer registers
+R0,$01,$00,r0,0,0
+R1,$01,$01,r1,1,1
+R2,$01,$02,r2,2,2
+R3,$01,$03,r3,3,3
+R4,$01,$04,r4,4,4
+R5,$01,$05,r5,5,5
+R6,$01,$06,r6,6,6
+R7,$01,$07,r7,7,7
+R8,$01,$08,r8,8,8
+R9,$01,$09,r9,9,9
+R10,$01,$0a,r10,10,10
+R11,$01,$0b,r11,11,11
+R12,$01,$0c,r12,12,12
+R13,$01,$0d,r13,13,13
+R14,$01,$0e,r14,14,14
+R15,$01,$0f,r15,15,15
+
+; Float registers
+F0,$02,$00,f0,32,16
+F1,$02,$01,f1,32,17
+F2,$02,$02,f2,32,18
+F3,$02,$03,f3,32,19
+F4,$02,$04,f4,32,20
+F5,$02,$05,f5,32,21
+F6,$02,$06,f6,32,22
+F7,$02,$07,f7,32,23
+
+; MM registers
+S0,$03,$00,s0,0,0
+S1,$03,$00,s1,0,0
+D0,$03,$00,d0,0,0
+S2,$03,$00,s2,0,0
+S3,$03,$00,s3,0,0
+D1,$03,$00,d1,0,0
+S4,$03,$00,s4,0,0
+S5,$03,$00,s5,0,0
+D2,$03,$00,d2,0,0
+S6,$03,$00,s6,0,0
+S7,$03,$00,s7,0,0
+D3,$03,$00,d3,0,0
+S8,$03,$00,s8,0,0
+S9,$03,$00,s9,0,0
+D4,$03,$00,d4,0,0
+S10,$03,$00,s10,0,0
+S11,$03,$00,s11,0,0
+D5,$03,$00,d5,0,0
+S12,$03,$00,s12,0,0
+S13,$03,$00,s13,0,0
+D6,$03,$00,d6,0,0
+S14,$03,$00,s14,0,0
+S15,$03,$00,s15,0,0
+D7,$03,$00,d7,0,0
+S16,$03,$00,s16,0,0
+S17,$03,$00,s17,0,0
+D8,$03,$00,d8,0,0
+S18,$03,$00,s18,0,0
+S19,$03,$00,s19,0,0
+D9,$03,$00,d9,0,0
+S20,$03,$00,s20,0,0
+S21,$03,$00,s21,0,0
+D10,$03,$00,d10,0,0
+S22,$03,$00,s22,0,0
+S23,$03,$00,s23,0,0
+D11,$03,$00,d11,0,0
+S24,$03,$00,s24,0,0
+S25,$03,$00,s25,0,0
+D12,$03,$00,d12,0,0
+S26,$03,$00,s26,0,0
+S27,$03,$00,s27,0,0
+D13,$03,$00,d13,0,0
+S28,$03,$00,s28,0,0
+S29,$03,$00,s29,0,0
+D14,$03,$00,d14,0,0
+S30,$03,$00,s20,0,0
+S31,$03,$00,s21,0,0
+D15,$03,$00,d15,0,0
diff --git a/compiler/arm/armtab.inc b/compiler/arm/armtab.inc
new file mode 100644
index 0000000000..1a81a1eed2
--- /dev/null
+++ b/compiler/arm/armtab.inc
@@ -0,0 +1,759 @@
+{ don't edit, this file is generated from armins.dat }
+(
+ (
+ opcode : A_NONE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #0;
+ flags : if_none
+ ),
+ (
+ opcode : A_ADC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_AND;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_AND;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_AND;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_AND;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#10;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+ code : #1#10;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BIC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#1#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BIC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#1#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BIC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#1#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BIC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#3#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#11;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BL;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+ code : #1#11;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #15#15;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+ code : #15#15;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BX;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none);
+ code : #3#1#47#255#16;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CDP;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
+ code : #192#1#16#65;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #12#1#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #13#1#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #14#1#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #15#3#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #12#1#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #13#1#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #14#1#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #15#3#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CLZ;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #39#1#1;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_EOR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_EOR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #209#192#1#17#65;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
+ code : #38#129;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+ code : #23#7#16;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+ code : #23#5#16;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #34#80#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #35#80#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #36#80#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #37#16#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #34#80#208;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #35#80#208;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #36#80#208;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #37#16#208;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #34#80#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #35#80#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #36#80#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #37#16#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LFM;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
+ code : #240#2#1;
+ flags : if_fpa
+ ),
+ (
+ opcode : A_MCR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory or ot_bits32,ot_none,ot_none);
+ code : #208#193#1#19#72;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MLA;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #21#0#32#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #8#1#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none);
+ code : #8#1#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #20#0#0#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MVF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none);
+ code : #242;
+ flags : if_fpa
+ ),
+ (
+ opcode : A_MVF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediatefpu,ot_none,ot_none);
+ code : #242;
+ flags : if_fpa
+ ),
+ (
+ opcode : A_MVN;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #8#1#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MVN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #9#1#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MVN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #10#1#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MVN;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #11#3#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#1#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ORR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#1#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ORR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#1#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#3#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SBC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SBC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SFM;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
+ code : #240#2#0;
+ flags : if_fpa
+ ),
+ (
+ opcode : A_SMLAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #22#0#224#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SMULL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #22#0#192#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
+ code : #38#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+ code : #23#4#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+ code : #23#6#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #34#64#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #35#64#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #36#64#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #37#0#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+ code : #4#0#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
+ code : #4#0#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SWI;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #2#15;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SWP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #39#1#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SWPB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #39#1#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #12#1#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #13#1#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #14#1#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #15#3#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #12#1#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TST;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #13#1#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TST;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #14#1#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #15#3#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_UMLAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #22#0#160#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_UMULL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #22#0#128#144;
+ flags : if_arm7
+ )
+);
diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas
new file mode 100644
index 0000000000..d168b47bb8
--- /dev/null
+++ b/compiler/arm/cgcpu.pas
@@ -0,0 +1,1712 @@
+{
+
+ Copyright (c) 2003 by Florian Klaempfl
+ Member of the Free Pascal development team
+
+ This unit implements the code generator for the ARM
+
+ 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 cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,symtype,symdef,
+ cgbase,cgutils,cgobj,
+ aasmbase,aasmcpu,aasmtai,
+ parabase,
+ cpubase,cpuinfo,node,cg64f32,rgcpu;
+
+
+ type
+ tcgarm = class(tcg)
+ { true, if the next arithmetic operation should modify the flags }
+ cgsetflags : boolean;
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+
+ procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : TCGPara);override;
+ procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
+ procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : TCGPara);override;
+
+ procedure a_call_name(list : taasmoutput;const s : string);override;
+ procedure a_call_reg(list : taasmoutput;reg: tregister); override;
+
+ procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
+ procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+
+ procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister); override;
+ procedure a_op_const_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op_reg_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+
+ { move instructions }
+ procedure a_load_const_reg(list : taasmoutput; size: tcgsize; a : aint;reg : tregister);override;
+ procedure a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
+ procedure a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
+ procedure a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
+
+ procedure a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+
+ procedure a_jmp_name(list : taasmoutput;const s : string); override;
+ procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
+ procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
+
+ procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+
+ procedure g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean); override;
+
+ procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
+
+ procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);override;
+ procedure g_concatcopy_unaligned(list : taasmoutput;const source,dest : treference;len : aint);override;
+ procedure g_concatcopy_move(list : taasmoutput;const source,dest : treference;len : aint);
+ procedure g_concatcopy_internal(list : taasmoutput;const source,dest : treference;len : aint;aligned : boolean);
+
+ procedure g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef); override;
+ procedure g_overflowCheck_loc(List:TAasmOutput;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
+
+ procedure g_save_standard_registers(list : taasmoutput);override;
+ procedure g_restore_standard_registers(list : taasmoutput);override;
+
+ procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
+ procedure fixref(list : taasmoutput;var ref : treference);
+ procedure handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
+
+ procedure g_intf_wrapper(list: taasmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ end;
+
+ tcg64farm = class(tcg64f32)
+ procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+ procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
+ procedure a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
+ procedure a_op64_const_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op64_reg_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+ end;
+
+ const
+ OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
+ C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI);
+
+ function get_fpu_postfix(def : tdef) : toppostfix;
+
+ implementation
+
+
+ uses
+ globals,verbose,systems,cutils,
+ fmodule,
+ symconst,symsym,
+ tgobj,
+ procinfo,cpupi,
+ paramgr;
+
+
+ function get_fpu_postfix(def : tdef) : toppostfix;
+ begin
+ if def.deftype=floatdef then
+ begin
+ case tfloatdef(def).typ of
+ s32real:
+ result:=PF_S;
+ s64real:
+ result:=PF_D;
+ s80real:
+ result:=PF_E;
+ else
+ internalerror(200401272);
+ end;
+ end
+ else
+ internalerror(200401271);
+ end;
+
+
+ procedure tcgarm.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ { currently, we save R14 always, so we can use it }
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
+ [RS_S0,RS_S1,RS_R2,RS_R3,RS_R4,RS_S31],first_mm_imreg,[]);
+ end;
+
+
+ procedure tcgarm.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_MMREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ procedure tcgarm.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : TCGPara);
+ var
+ ref: treference;
+ begin
+ paraloc.check_simple_location;
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,size,a,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref);
+ ref.base:=paraloc.location^.reference.index;
+ ref.offset:=paraloc.location^.reference.offset;
+ a_load_const_ref(list,size,a,ref);
+ end;
+ else
+ internalerror(2002081101);
+ end;
+ end;
+
+
+ procedure tcgarm.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : TCGPara);
+ var
+ tmpref, ref: treference;
+ location: pcgparalocation;
+ sizeleft: aint;
+ begin
+ location := paraloc.location;
+ tmpref := r;
+ sizeleft := paraloc.intsize;
+ while assigned(location) do
+ begin
+ case location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(ref,location^.reference.index,location^.reference.offset);
+ g_concatcopy(list,tmpref,ref,sizeleft);
+ if assigned(location^.next) then
+ internalerror(2005010710);
+ end;
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ case location^.size of
+ OS_F32, OS_F64:
+ a_loadfpu_ref_reg(list,location^.size,tmpref,location^.register);
+ else
+ internalerror(2002072801);
+ end;
+ LOC_VOID:
+ begin
+ // nothing to do
+ end;
+ else
+ internalerror(2002081103);
+ end;
+ inc(tmpref.offset,tcgsize2size[location^.size]);
+ dec(sizeleft,tcgsize2size[location^.size]);
+ location := location^.next;
+ end;
+ end;
+
+
+ procedure tcgarm.a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : TCGPara);
+ var
+ ref: treference;
+ tmpreg: tregister;
+ begin
+ paraloc.check_simple_location;
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadaddr_ref_reg(list,r,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ tmpreg := getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+
+
+ procedure tcgarm.a_call_name(list : taasmoutput;const s : string);
+ begin
+ list.concat(taicpu.op_sym(A_BL,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
+{
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+}
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgarm.a_call_reg(list : taasmoutput;reg: tregister);
+ var
+ r : tregister;
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
+{
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+}
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgarm.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
+ begin
+ a_op_const_reg_reg(list,op,size,a,reg,reg);
+ end;
+
+
+ procedure tcgarm.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+ begin
+ case op of
+ OP_NEG:
+ list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
+ OP_NOT:
+ begin
+ list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
+ case size of
+ OS_8 :
+ a_op_const_reg_reg(list,OP_AND,OS_INT,$ff,dst,dst);
+ OS_16 :
+ a_op_const_reg_reg(list,OP_AND,OS_INT,$ffff,dst,dst);
+ end;
+ end
+ else
+ a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
+ end;
+ end;
+
+
+ const
+ op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
+ (A_NONE,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
+ A_NONE,A_NONE,A_NONE,A_SUB,A_EOR);
+
+
+ procedure tcgarm.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister);
+ var
+ ovloc : tlocation;
+ begin
+ a_op_const_reg_reg_checkoverflow(list,op,size,a,src,dst,false,ovloc);
+ end;
+
+
+ procedure tcgarm.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister);
+ var
+ ovloc : tlocation;
+ begin
+ a_op_reg_reg_reg_checkoverflow(list,op,size,src1,src2,dst,false,ovloc);
+ end;
+
+
+ procedure tcgarm.a_op_const_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ shift : byte;
+ tmpreg : tregister;
+ so : tshifterop;
+ l1 : longint;
+ begin
+ ovloc.loc:=LOC_VOID;
+ if is_shifter_const(-a,shift) then
+ case op of
+ OP_ADD:
+ begin
+ op:=OP_SUB;
+ a:=dword(-a);
+ end;
+ OP_SUB:
+ begin
+ op:=OP_ADD;
+ a:=dword(-a);
+ end
+ end;
+
+ if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
+ case op of
+ OP_NEG,OP_NOT,
+ OP_DIV,OP_IDIV:
+ internalerror(200308281);
+ OP_SHL:
+ begin
+ if a>32 then
+ internalerror(200308291);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_LSL;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_SHR:
+ begin
+ if a>32 then
+ internalerror(200308292);
+ shifterop_reset(so);
+ if a<>0 then
+ begin
+ so.shiftmode:=SM_LSR;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_SAR:
+ begin
+ if a>32 then
+ internalerror(200308291);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ else
+ list.concat(setoppostfix(
+ taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
+ ));
+ if (cgsetflags or setflags) and (size in [OS_8,OS_16,OS_32]) then
+ begin
+ ovloc.loc:=LOC_FLAGS;
+ case op of
+ OP_ADD:
+ ovloc.resflags:=F_CS;
+ OP_SUB:
+ ovloc.resflags:=F_CC;
+ end;
+ end;
+ end
+ else
+ begin
+ { there could be added some more sophisticated optimizations }
+ if (op in [OP_MUL,OP_IMUL]) and (a=1) then
+ a_load_reg_reg(list,size,size,src,dst)
+ else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
+ a_load_const_reg(list,size,0,dst)
+ else if (op in [OP_IMUL]) and (a=-1) then
+ a_op_reg_reg(list,OP_NEG,size,src,dst)
+ { we do this here instead in the peephole optimizer because
+ it saves us a register }
+ else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a,l1) and not(cgsetflags or setflags) then
+ a_op_const_reg_reg(list,OP_SHL,size,l1,src,dst)
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,setflags,ovloc);
+ end;
+ end;
+ end;
+
+
+ procedure tcgarm.a_op_reg_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ so : tshifterop;
+ tmpreg,overflowreg : tregister;
+ asmop : tasmop;
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_NEG,OP_NOT,
+ OP_DIV,OP_IDIV:
+ internalerror(200308281);
+ OP_SHL:
+ begin
+ shifterop_reset(so);
+ so.rs:=src1;
+ so.shiftmode:=SM_LSL;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
+ end;
+ OP_SHR:
+ begin
+ shifterop_reset(so);
+ so.rs:=src1;
+ so.shiftmode:=SM_LSR;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
+ end;
+ OP_SAR:
+ begin
+ shifterop_reset(so);
+ so.rs:=src1;
+ so.shiftmode:=SM_ASR;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
+ end;
+ OP_IMUL,
+ OP_MUL:
+ begin
+ if cgsetflags or setflags then
+ begin
+ overflowreg:=getintregister(list,size);
+ if op=OP_IMUL then
+ asmop:=A_SMULL
+ else
+ asmop:=A_UMULL;
+ { the arm doesn't allow that rd and rm are the same }
+ if dst=src2 then
+ begin
+ if dst<>src1 then
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src1,src2))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,src2,dst);
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,tmpreg,src1));
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src2,src1));
+ if op=OP_IMUL then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=31;
+ list.concat(taicpu.op_reg_reg_shifterop(A_CMP,overflowreg,dst,so));
+ end
+ else
+ list.concat(taicpu.op_reg_const(A_CMP,overflowreg,0));
+
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end
+ else
+ begin
+ { the arm doesn't allow that rd and rm are the same }
+ if dst=src2 then
+ begin
+ if dst<>src1 then
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,src2,dst);
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
+ end;
+ end;
+ else
+ list.concat(setoppostfix(
+ taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
+ ));
+ end;
+ end;
+
+
+ procedure tcgarm.a_load_const_reg(list : taasmoutput; size: tcgsize; a : aint;reg : tregister);
+ var
+ imm_shift : byte;
+ l : tasmlabel;
+ hr : treference;
+ begin
+ if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
+ internalerror(2002090902);
+ if is_shifter_const(a,imm_shift) then
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a))
+ else if is_shifter_const(not(a),imm_shift) then
+ list.concat(taicpu.op_reg_const(A_MVN,reg,not(a)))
+ else
+ begin
+ reference_reset(hr);
+
+ objectlibrary.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ hr.symboldata:=current_procinfo.aktlocaldata.last;
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
+
+ hr.symbol:=l;
+ list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
+ end;
+ end;
+
+
+ procedure tcgarm.handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+ l : tasmlabel;
+ begin
+ tmpreg:=NR_NO;
+
+ { Be sure to have a base register }
+ if (ref.base=NR_NO) then
+ begin
+ if ref.shiftmode<>SM_None then
+ internalerror(200308294);
+ ref.base:=ref.index;
+ ref.index:=NR_NO;
+ end;
+
+ { absolute symbols can't be handled directly, we've to store the symbol reference
+ in the text segment and access it pc relative
+
+ For now, we assume that references where base or index equals to PC are already
+ relative, all other references are assumed to be absolute and thus they need
+ to be handled extra.
+
+ A proper solution would be to change refoptions to a set and store the information
+ if the symbol is absolute or relative there.
+ }
+
+ if (assigned(ref.symbol) and
+ not(is_pc(ref.base)) and
+ not(is_pc(ref.index))
+ ) or
+ { [#xxx] isn't a valid address operand }
+ ((ref.base=NR_NO) and (ref.index=NR_NO)) or
+ (ref.offset<-4095) or
+ (ref.offset>4095) or
+ ((oppostfix in [PF_SB,PF_H,PF_SH]) and
+ ((ref.offset<-255) or
+ (ref.offset>255)
+ )
+ ) or
+ ((op in [A_LDF,A_STF]) and
+ ((ref.offset<-1020) or
+ (ref.offset>1020)
+ )
+ ) then
+ begin
+ reference_reset(tmpref);
+
+ { load symbol }
+ tmpreg:=getintregister(list,OS_INT);
+ if assigned(ref.symbol) then
+ begin
+ objectlibrary.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset));
+
+ { load consts entry }
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
+ end
+ else
+ a_load_const_reg(list,OS_ADDR,ref.offset,tmpreg);
+
+ if (ref.base<>NR_NO) then
+ begin
+ if ref.index<>NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base:=tmpreg;
+ end
+ else
+ begin
+ ref.index:=tmpreg;
+ ref.shiftimm:=0;
+ ref.signindex:=1;
+ ref.shiftmode:=SM_None;
+ end;
+ end
+ else
+ ref.base:=tmpreg;
+ ref.offset:=0;
+ ref.symbol:=nil;
+ end;
+
+ if (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
+ begin
+ if tmpreg<>NR_NO then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
+ else
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
+ ref.base:=tmpreg;
+ end;
+ ref.offset:=0;
+ end;
+
+ { floating point operations have only limited references
+ we expect here, that a base is already set }
+ if (op in [A_LDF,A_STF]) and (ref.index<>NR_NO) then
+ begin
+ if ref.shiftmode<>SM_none then
+ internalerror(200309121);
+ if tmpreg<>NR_NO then
+ begin
+ if ref.base=tmpreg then
+ begin
+ if ref.signindex<0 then
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index))
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index));
+ ref.index:=NR_NO;
+ end
+ else
+ begin
+ if ref.index<>tmpreg then
+ internalerror(200403161);
+ if ref.signindex<0 then
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,ref.base,tmpreg))
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end
+ else
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end;
+ list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
+ end;
+
+
+ procedure tcgarm.a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
+ var
+ oppostfix:toppostfix;
+ begin
+ case ToSize of
+ { signed integer registers }
+ OS_8,
+ OS_S8:
+ oppostfix:=PF_B;
+ OS_16,
+ OS_S16:
+ oppostfix:=PF_H;
+ OS_32,
+ OS_S32:
+ oppostfix:=PF_None;
+ else
+ InternalError(200308295);
+ end;
+ handle_load_store(list,A_STR,oppostfix,reg,ref);
+ end;
+
+
+ procedure tcgarm.a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
+ var
+ oppostfix:toppostfix;
+ begin
+ case FromSize of
+ { signed integer registers }
+ OS_8:
+ oppostfix:=PF_B;
+ OS_S8:
+ oppostfix:=PF_SB;
+ OS_16:
+ oppostfix:=PF_H;
+ OS_S16:
+ oppostfix:=PF_SH;
+ OS_32,
+ OS_S32:
+ oppostfix:=PF_None;
+ else
+ InternalError(200308291);
+ end;
+ handle_load_store(list,A_LDR,oppostfix,reg,ref);
+ end;
+
+
+ procedure tcgarm.a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+ var
+ instr: taicpu;
+ so : tshifterop;
+ begin
+ shifterop_reset(so);
+ if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
+ (
+ (tcgsize2size[tosize] = tcgsize2size[fromsize]) and
+ (tosize <> fromsize) and
+ not(fromsize in [OS_32,OS_S32])
+ ) then
+ begin
+ case tosize of
+ OS_8:
+ list.concat(taicpu.op_reg_reg_const(A_AND,
+ reg2,reg1,$ff));
+ OS_S8:
+ begin
+ so.shiftmode:=SM_LSL;
+ so.shiftimm:=24;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=24;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
+ end;
+ OS_16:
+ begin
+ so.shiftmode:=SM_LSL;
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
+ so.shiftmode:=SM_LSR;
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
+ end;
+ OS_S16:
+ begin
+ so.shiftmode:=SM_LSL;
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
+ end;
+ OS_32,OS_S32:
+ begin
+ instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
+ list.concat(instr);
+ add_move_instruction(instr);
+ end;
+ else internalerror(2002090901);
+ end;
+ end
+ else
+ begin
+ if reg1<>reg2 then
+ begin
+ { same size, only a register mov required }
+ instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+ end;
+ end;
+
+
+ procedure tcgarm.a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const paraloc : TCGPara);
+ var
+ href,href2 : treference;
+ hloc : pcgparalocation;
+ begin
+ href:=ref;
+ hloc:=paraloc.location;
+ while assigned(hloc) do
+ begin
+ case hloc^.loc of
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ a_loadfpu_ref_reg(list,size,ref,hloc^.register);
+ LOC_REGISTER :
+ 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);
+ a_load_ref_ref(list,hloc^.size,hloc^.size,href,href2);
+ end;
+ else
+ internalerror(200408241);
+ end;
+ inc(href.offset,tcgsize2size[hloc^.size]);
+ hloc:=hloc^.next;
+ end;
+ end;
+
+
+ procedure tcgarm.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[size]));
+ end;
+
+
+ procedure tcgarm.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
+ var
+ oppostfix:toppostfix;
+ begin
+ case size of
+ OS_F32:
+ oppostfix:=PF_S;
+ OS_F64:
+ oppostfix:=PF_D;
+ OS_F80:
+ oppostfix:=PF_E;
+ else
+ InternalError(200309021);
+ end;
+ handle_load_store(list,A_LDF,oppostfix,reg,ref);
+ end;
+
+
+ procedure tcgarm.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
+ var
+ oppostfix:toppostfix;
+ begin
+ case size of
+ OS_F32:
+ oppostfix:=PF_S;
+ OS_F64:
+ oppostfix:=PF_D;
+ OS_F80:
+ oppostfix:=PF_E;
+ else
+ InternalError(200309022);
+ end;
+ handle_load_store(list,A_STF,oppostfix,reg,ref);
+ end;
+
+
+ { comparison operations }
+ procedure tcgarm.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);
+ var
+ tmpreg : tregister;
+ b : byte;
+ begin
+ if is_shifter_const(a,b) then
+ list.concat(taicpu.op_reg_const(A_CMP,reg,a))
+ { CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
+ and CMP reg,$7fffffff regarding the flags according to the ARM manual }
+ else if (a<>$7fffffff) and (a<>-1) and is_shifter_const(-a,b) then
+ list.concat(taicpu.op_reg_const(A_CMN,reg,-a))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
+ end;
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgarm.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+ begin
+ list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgarm.a_jmp_name(list : taasmoutput;const s : string);
+ begin
+ list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
+ end;
+
+
+ procedure tcgarm.a_jmp_always(list : taasmoutput;l: tasmlabel);
+ begin
+ list.concat(taicpu.op_sym(A_B,l));
+ end;
+
+
+ procedure tcgarm.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgarm.g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister);
+ var
+ ai : taicpu;
+ begin
+ list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
+ list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond(flags_to_cond(f))));
+ end;
+
+
+ procedure tcgarm.g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);
+ var
+ ref : treference;
+ shift : byte;
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ begin
+ LocalSize:=align(LocalSize,4);
+ if not(nostackframe) then
+ begin
+ firstfloatreg:=RS_NO;
+ { save floating point registers? }
+ for r:=RS_F0 to RS_F7 do
+ if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
+ begin
+ if firstfloatreg=RS_NO then
+ firstfloatreg:=r;
+ lastfloatreg:=r;
+ end;
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+ a_reg_alloc(list,NR_FRAME_POINTER_REG);
+ a_reg_alloc(list,NR_R12);
+
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
+ { save int registers }
+ reference_reset(ref);
+ ref.index:=NR_STACK_POINTER_REG;
+ ref.addressmode:=AM_PREINDEXED;
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,
+ rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)+[RS_R11,RS_R12,RS_R14,RS_R15]),
+ PF_FD));
+
+ list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
+
+ { allocate necessary stack size }
+ { don't use a_op_const_reg_reg here because we don't allow register allocations
+ in the entry/exit code }
+ if not(is_shifter_const(localsize,shift)) then
+ begin
+ a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
+ a_reg_dealloc(list,NR_R12);
+ end
+ else
+ begin
+ a_reg_dealloc(list,NR_R12);
+ list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
+ end;
+ if firstfloatreg<>RS_NO then
+ begin
+ reference_reset(ref);
+ if not(is_shifter_const(-tarmprocinfo(current_procinfo).floatregstart,shift)) then
+ begin
+ a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,NR_FRAME_POINTER_REG,NR_R12));
+ ref.base:=NR_R12;
+ end
+ else
+ begin
+ ref.base:=NR_FRAME_POINTER_REG;
+ ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
+ end;
+ list.concat(taicpu.op_reg_const_ref(A_SFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
+ lastfloatreg-firstfloatreg+1,ref));
+ end;
+ end;
+ end;
+
+
+ procedure tcgarm.g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean);
+ var
+ ref : treference;
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ shift : byte;
+ begin
+ if not(nostackframe) then
+ begin
+ { restore floating point register }
+ firstfloatreg:=RS_NO;
+ { save floating point registers? }
+ for r:=RS_F0 to RS_F7 do
+ if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
+ begin
+ if firstfloatreg=RS_NO then
+ firstfloatreg:=r;
+ lastfloatreg:=r;
+ end;
+
+ if firstfloatreg<>RS_NO then
+ begin
+ reference_reset(ref);
+ if not(is_shifter_const(-tarmprocinfo(current_procinfo).floatregstart,shift)) then
+ begin
+ a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,NR_FRAME_POINTER_REG,NR_R12));
+ ref.base:=NR_R12;
+ end
+ else
+ begin
+ ref.base:=NR_FRAME_POINTER_REG;
+ ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
+ end;
+ list.concat(taicpu.op_reg_const_ref(A_LFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
+ lastfloatreg-firstfloatreg+1,ref));
+ end;
+
+ if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
+ else
+ begin
+ { restore int registers and return }
+ reference_reset(ref);
+ ref.index:=NR_FRAME_POINTER_REG;
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)+[RS_R11,RS_R13,RS_R15]),PF_EA));
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14));
+ end;
+
+
+ procedure tcgarm.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
+ var
+ b : byte;
+ tmpref : treference;
+ instr : taicpu;
+ begin
+ if ref.addressmode<>AM_OFFSET then
+ internalerror(200309071);
+ tmpref:=ref;
+ { Be sure to have a base register }
+ if (tmpref.base=NR_NO) then
+ begin
+ if tmpref.shiftmode<>SM_None then
+ internalerror(200308294);
+ if tmpref.signindex<0 then
+ internalerror(200312023);
+ tmpref.base:=tmpref.index;
+ tmpref.index:=NR_NO;
+ end;
+
+ if assigned(tmpref.symbol) or
+ not((is_shifter_const(tmpref.offset,b)) or
+ (is_shifter_const(-tmpref.offset,b))
+ ) then
+ fixref(list,tmpref);
+
+ { expect a base here if there is an index }
+ if (tmpref.base=NR_NO) and (tmpref.index<>NR_NO) then
+ internalerror(200312022);
+
+ if tmpref.index<>NR_NO then
+ begin
+ if tmpref.shiftmode<>SM_None then
+ internalerror(200312021);
+ if tmpref.signindex<0 then
+ a_op_reg_reg_reg(list,OP_SUB,OS_ADDR,tmpref.base,tmpref.index,r)
+ else
+ a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
+ if tmpref.offset<>0 then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
+ end
+ else
+ begin
+ if tmpref.offset<>0 then
+ begin
+ if tmpref.base<>NR_NO then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
+ else
+ a_load_const_reg(list,OS_ADDR,tmpref.offset,r);
+ end
+ else
+ begin
+ instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
+ list.concat(instr);
+ add_move_instruction(instr);
+ end;
+ end;
+ end;
+
+
+ procedure tcgarm.fixref(list : taasmoutput;var ref : treference);
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+ l : tasmlabel;
+ begin
+ { absolute symbols can't be handled directly, we've to store the symbol reference
+ in the text segment and access it pc relative
+
+ For now, we assume that references where base or index equals to PC are already
+ relative, all other references are assumed to be absolute and thus they need
+ to be handled extra.
+
+ A proper solution would be to change refoptions to a set and store the information
+ if the symbol is absolute or relative there.
+ }
+ { create consts entry }
+ reference_reset(tmpref);
+ objectlibrary.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ if assigned(ref.symbol) then
+ current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
+ else
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
+
+ { load consts entry }
+ tmpreg:=getintregister(list,OS_INT);
+ tmpref.symbol:=l;
+ tmpref.base:=NR_PC;
+ list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
+
+ if (ref.base<>NR_NO) then
+ begin
+ if ref.index<>NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base:=tmpreg;
+ end
+ else
+ begin
+ ref.index:=tmpreg;
+ ref.shiftimm:=0;
+ ref.signindex:=1;
+ ref.shiftmode:=SM_None;
+ end;
+ end
+ else
+ ref.base:=tmpreg;
+
+ ref.offset:=0;
+ ref.symbol:=nil;
+ end;
+
+
+ procedure tcgarm.g_concatcopy_move(list : taasmoutput;const source,dest : treference;len : aint);
+ var
+ paraloc1,paraloc2,paraloc3 : TCGPara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ paramanager.allocparaloc(list,paraloc3);
+ a_param_const(list,OS_INT,len,paraloc3);
+ paramanager.allocparaloc(list,paraloc2);
+ a_paramaddr_ref(list,dest,paraloc2);
+ paramanager.allocparaloc(list,paraloc2);
+ a_paramaddr_ref(list,source,paraloc1);
+ paramanager.freeparaloc(list,paraloc3);
+ paramanager.freeparaloc(list,paraloc2);
+ 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');
+ dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+ end;
+
+
+ procedure tcgarm.g_concatcopy_internal(list : taasmoutput;const source,dest : treference;len : aint;aligned : boolean);
+ var
+ srcref,dstref:treference;
+ srcreg,destreg,countreg,r:tregister;
+ helpsize:aword;
+ copysize:byte;
+ cgsize:Tcgsize;
+
+ procedure genloop(count : aword;size : byte);
+ const
+ size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
+ var
+ l : tasmlabel;
+ begin
+ objectlibrary.getjumplabel(l);
+ a_load_const_reg(list,OS_INT,count,countreg);
+ cg.a_label(list,l);
+ srcref.addressmode:=AM_POSTINDEXED;
+ dstref.addressmode:=AM_POSTINDEXED;
+ srcref.offset:=size;
+ dstref.offset:=size;
+ r:=getintregister(list,size2opsize[size]);
+ a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
+ a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
+ list.concat(setcondition(taicpu.op_sym(A_B,l),C_NE));
+ { keep the registers alive }
+ list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+ list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
+ list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
+ end;
+
+ begin
+ if len=0 then
+ exit;
+ helpsize:=12;
+ dstref:=dest;
+ srcref:=source;
+ if cs_littlesize in aktglobalswitches then
+ helpsize:=8;
+ if (len<=helpsize) and aligned then
+ begin
+ copysize:=4;
+ cgsize:=OS_32;
+ while len<>0 do
+ begin
+ if len<2 then
+ begin
+ copysize:=1;
+ cgsize:=OS_8;
+ end
+ else if len<4 then
+ begin
+ copysize:=2;
+ cgsize:=OS_16;
+ end;
+ dec(len,copysize);
+ r:=getintregister(list,cgsize);
+ a_load_ref_reg(list,cgsize,cgsize,srcref,r);
+ a_load_reg_ref(list,cgsize,cgsize,r,dstref);
+ inc(srcref.offset,copysize);
+ inc(dstref.offset,copysize);
+ end;
+ end
+ else
+ begin
+ destreg:=getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,dest,destreg);
+ reference_reset_base(dstref,destreg,0);
+
+ srcreg:=getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,source,srcreg);
+ reference_reset_base(srcref,srcreg,0);
+
+ countreg:=getintregister(list,OS_32);
+
+// if cs_littlesize in aktglobalswitches then
+ genloop(len,1);
+{
+ else
+ begin
+ helpsize:=len shr 2;
+ len:=len and 3;
+ if helpsize>1 then
+ begin
+ a_load_const_reg(list,OS_INT,helpsize,countreg);
+ list.concat(Taicpu.op_none(A_REP,S_NO));
+ end;
+ if helpsize>0 then
+ list.concat(Taicpu.op_none(A_MOVSD,S_NO));
+ if len>1 then
+ begin
+ dec(len,2);
+ list.concat(Taicpu.op_none(A_MOVSW,S_NO));
+ end;
+ if len=1 then
+ list.concat(Taicpu.op_none(A_MOVSB,S_NO));
+ end;
+}
+ end;
+ end;
+
+
+ procedure tcgarm.g_concatcopy_unaligned(list : taasmoutput;const source,dest : treference;len : aint);
+ begin
+ g_concatcopy_internal(list,source,dest,len,false);
+ end;
+
+
+ procedure tcgarm.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);
+ begin
+ g_concatcopy_internal(list,source,dest,len,true);
+ end;
+
+
+ procedure tcgarm.g_overflowCheck(list : taasmoutput;const l : tlocation;def : tdef);
+ var
+ ovloc : tlocation;
+ begin
+ ovloc.loc:=LOC_VOID;
+ g_overflowCheck_loc(list,l,def,ovloc);
+ end;
+
+
+ procedure tcgarm.g_overflowCheck_loc(List:TAasmOutput;const Loc:TLocation;def:TDef;ovloc : tlocation);
+ var
+ hl : tasmlabel;
+ ai:TAiCpu;
+ hflags : tresflags;
+ begin
+ if not(cs_check_overflow in aktlocalswitches) then
+ exit;
+ objectlibrary.getjumplabel(hl);
+ case ovloc.loc of
+ LOC_VOID:
+ begin
+ ai:=taicpu.op_sym(A_B,hl);
+ ai.is_jmp:=true;
+
+ if not((def.deftype=pointerdef) or
+ ((def.deftype=orddef) and
+ (torddef(def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,bool8bit,bool16bit,bool32bit]))) then
+ ai.SetCondition(C_VC)
+ else
+ ai.SetCondition(C_CC);
+
+ list.concat(ai);
+ end;
+ LOC_FLAGS:
+ begin
+ hflags:=ovloc.resflags;
+ inverse_flags(hflags);
+ cg.a_jmp_flags(list,hflags,hl);
+ end;
+ else
+ internalerror(200409281);
+ end;
+
+ a_call_name(list,'FPC_OVERFLOW');
+ a_label(list,hl);
+ end;
+
+
+ procedure tcgarm.g_save_standard_registers(list : taasmoutput);
+ begin
+ { this work is done in g_proc_entry }
+ end;
+
+
+ procedure tcgarm.g_restore_standard_registers(list : taasmoutput);
+ begin
+ { this work is done in g_proc_exit }
+ end;
+
+
+ procedure tcgarm.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai:=Taicpu.Op_sym(A_B,l);
+ ai.SetCondition(OpCmp2AsmCond[cond]);
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgarm.g_intf_wrapper(list: taasmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);
+
+ procedure loadvmttor12;
+ var
+ href : treference;
+ begin
+ reference_reset_base(href,NR_R0,0);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
+ end;
+
+
+ procedure op_onr12methodaddr;
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_R12,procdef._class.vmtmethodoffset(procdef.extnumber));
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
+ end;
+
+ var
+ lab : tasmsymbol;
+ make_global : boolean;
+ href : treference;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef._class) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>objectsymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ (cs_create_smart in aktmoduleswitches) or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ list.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ { case 4 }
+ if po_virtualmethod in procdef.procoptions then
+ begin
+ loadvmttor12;
+ op_onr12methodaddr;
+ end
+ { case 0 }
+ else
+ list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+
+ list.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+
+ procedure tcg64farm.a_op64_reg_reg(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+ var
+ tmpreg : tregister;
+ begin
+ case op of
+ OP_NEG:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
+ list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
+ end;
+ OP_NOT:
+ begin
+ cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reglo,regdst.reglo);
+ cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reghi,regdst.reghi);
+ end;
+ else
+ a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
+ end;
+ end;
+
+
+ procedure tcg64farm.a_op64_const_reg(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
+ begin
+ a_op64_const_reg_reg(list,op,size,value,reg,reg);
+ end;
+
+
+ procedure tcg64farm.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
+ var
+ ovloc : tlocation;
+ begin
+ a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,ovloc);
+ end;
+
+
+ procedure tcg64farm.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ var
+ ovloc : tlocation;
+ begin
+ a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,ovloc);
+ end;
+
+
+ procedure tcg64farm.a_op64_const_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ var
+ tmpreg : tregister;
+ b : byte;
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ if (setflags or tcgarm(cg).cgsetflags) and (op in [OP_ADD,OP_SUB]) then
+ begin
+ case op of
+ OP_ADD:
+ begin
+ if is_shifter_const(lo(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
+ end;
+
+ if is_shifter_const(hi(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg),PF_S));
+ end;
+ end;
+ OP_SUB:
+ begin
+ if is_shifter_const(lo(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
+ end;
+
+ if is_shifter_const(hi(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg),PF_S));
+ end;
+ end;
+ else
+ internalerror(200502131);
+ end;
+ if size=OS_64 then
+ begin
+ { the arm has an weired opinion how flags for SUB/ADD are handled }
+ ovloc.loc:=LOC_FLAGS;
+ case op of
+ OP_ADD:
+ ovloc.resflags:=F_CS;
+ OP_SUB:
+ ovloc.resflags:=F_CC;
+ end;
+ end;
+ end
+ else
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_const_reg_reg(list,op,OS_32,lo(value),regsrc.reglo,regdst.reglo);
+ cg.a_op_const_reg_reg(list,op,OS_32,hi(value),regsrc.reghi,regdst.reghi);
+ end;
+ OP_ADD:
+ begin
+ if is_shifter_const(lo(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
+ end;
+
+ if is_shifter_const(hi(value),b) then
+ list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
+ end;
+ end;
+ OP_SUB:
+ begin
+ if is_shifter_const(lo(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
+ end;
+
+ if is_shifter_const(hi(value),b) then
+ list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
+ end;
+ end;
+ else
+ internalerror(2003083101);
+ end;
+ end;
+ end;
+
+
+ procedure tcg64farm.a_op64_reg_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ var
+ op1,op2:TAsmOp;
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ if (setflags or tcgarm(cg).cgsetflags) and (op in [OP_ADD,OP_SUB]) then
+ begin
+ case op of
+ OP_ADD:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi),PF_S));
+ end;
+ OP_SUB:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi),PF_S));
+ end;
+ else
+ internalerror(2003083101);
+ end;
+ if size=OS_64 then
+ begin
+ { the arm has an weired opinion how flags for SUB/ADD are handled }
+ ovloc.loc:=LOC_FLAGS;
+ case op of
+ OP_ADD:
+ ovloc.resflags:=F_CC;
+ OP_SUB:
+ ovloc.resflags:=F_CS;
+ end;
+ end;
+ end
+ else
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
+ end;
+ OP_ADD:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
+ list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
+ end;
+ OP_SUB:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
+ list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
+ end;
+ else
+ internalerror(2003083101);
+ end;
+ end;
+ end;
+
+
+begin
+ cg:=tcgarm.create;
+ cg64:=tcg64farm.create;
+end.
diff --git a/compiler/arm/cpubase.pas b/compiler/arm/cpubase.pas
new file mode 100644
index 0000000000..097854076b
--- /dev/null
+++ b/compiler/arm/cpubase.pas
@@ -0,0 +1,520 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Contains the base types for the ARM
+
+ 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.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+ enumerations of registers, opcodes, sizes, and other
+ such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,
+ cpuinfo,
+ aasmbase,
+ cgbase
+ ;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp= {$i armop.inc}
+
+ { This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ const
+ { First value of opcode enumeration }
+ firstop = low(tasmop);
+ { Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rarmnor.inc}-1;
+
+ const
+ { Available Superregisters }
+ {$i rarmsup.inc}
+
+ RS_PC = RS_R15;
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+ {$i rarmcon.inc}
+
+ { aliases }
+ NR_PC = NR_R15;
+
+ { Integer Super registers first and last }
+ first_int_supreg = RS_R0;
+ first_int_imreg = $10;
+
+ { Float Super register first and last }
+ first_fpu_supreg = RS_F0;
+ first_fpu_imreg = $08;
+
+ { MM Super register first and last }
+ first_mm_supreg = RS_S0;
+ first_mm_imreg = $20;
+
+{$warning TODO Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rarmnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i rarmsta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i rarmdwa.inc}
+ );
+ { registers which may be destroyed by calls }
+ VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R15];
+ VOLATILE_FPUREGISTERS = [RS_F0..RS_F3];
+
+ type
+ totherregisterset = set of tregisterindex;
+
+{*****************************************************************************
+ Instruction post fixes
+*****************************************************************************}
+ type
+ { ARM instructions load/store and arithmetic instructions
+ can have several instruction post fixes which are collected
+ in this enumeration
+ }
+ TOpPostfix = (PF_None,
+ { update condition flags
+ or floating point single }
+ PF_S,
+ { floating point size }
+ PF_D,PF_E,PF_P,PF_EP,
+ { load/store }
+ PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
+ { multiple load/store address modes }
+ PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA
+ );
+
+ TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
+
+ const
+ cgsize2fpuoppostfix : array[OS_NO..OS_F128] of toppostfix = (
+ PF_E,
+ PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,
+ PF_S,PF_D,PF_E,PF_None,PF_None);
+
+ oppostfix2str : array[TOpPostfix] of string[2] = ('',
+ 's',
+ 'd','e','p','ep',
+ 'b','sb','bt','h','sh','t',
+ 'ia','ib','da','db','fd','fa','ed','ea');
+
+ roundingmode2str : array[TRoundingMode] of string[1] = ('',
+ 'p','m','z');
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+ C_GE,C_LT,C_GT,C_LE,C_AL,C_NV
+ );
+
+ const
+ cond2str : array[TAsmCond] of string[2]=('',
+ 'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls',
+ 'ge','lt','gt','le','al','nv'
+ );
+
+ uppercond2str : array[TAsmCond] of string[2]=('',
+ 'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS',
+ 'GE','LT','GT','LE','AL','NV'
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
+ F_GE,F_LT,F_GT,F_LE);
+
+{*****************************************************************************
+ Operands
+*****************************************************************************}
+
+ taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
+ tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX);
+
+ tupdatereg = (UR_None,UR_Update);
+
+ pshifterop = ^tshifterop;
+
+ tshifterop = record
+ shiftmode : tshiftmode;
+ rs : tregister;
+ shiftimm : byte;
+ end;
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 4;
+
+ {# Constant defining possibly all registers which might require saving }
+ ALL_OTHERREGISTERS = [];
+
+ general_superregisters = [RS_R0..RS_PC];
+
+ {# Table of registers which can be allocated by the code generator
+ internally, when generating the code.
+ }
+ { legend: }
+ { xxxregs = set of all possibly used registers of that type in the code }
+ { generator }
+ { usableregsxxx = set of all 32bit components of registers that can be }
+ { possible allocated to a regvar or using getregisterxxx (this }
+ { excludes registers which can be only used for parameter }
+ { passing on ABI's that define this) }
+ { c_countusableregsxxx = amount of registers in the usableregsxxx set }
+
+ maxintregs = 15;
+ { to determine how many registers to use for regvars }
+ maxintscratchregs = 3;
+ usableregsint = [RS_R4..RS_R10];
+ c_countusableregsint = 7;
+
+ maxfpuregs = 8;
+ fpuregs = [RS_F0..RS_F7];
+ usableregsfpu = [RS_F4..RS_F7];
+ c_countusableregsfpu = 4;
+
+ mmregs = [RS_D0..RS_D15];
+ usableregsmm = [RS_D8..RS_D15];
+ c_countusableregsmm = 8;
+
+ maxaddrregs = 0;
+ addrregs = [];
+ usableregsaddr = [];
+ c_countusableregsaddr = 0;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_BW,S_BL,S_WL,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
+ );
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ firstsaveintreg = RS_R4;
+ lastsaveintreg = RS_R10;
+ firstsavefpureg = RS_F4;
+ lastsavefpureg = RS_F7;
+ firstsavemmreg = RS_D8;
+ lastsavemmreg = RS_D15;
+
+ maxvarregs = 7;
+ varregs : Array [1..maxvarregs] of tsuperregister =
+ (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+
+ maxfpuvarregs = 4;
+ fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
+ (RS_F4,RS_F5,RS_F6,RS_F7);
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ { the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M32;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ { Stack pointer register }
+ NR_STACK_POINTER_REG = NR_R13;
+ RS_STACK_POINTER_REG = RS_R13;
+ { Frame pointer register }
+ RS_FRAME_POINTER_REG = RS_R11;
+ NR_FRAME_POINTER_REG = NR_R11;
+ { Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+ NR_PIC_OFFSET_REG = NR_R9;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R0;
+ RS_FUNCTION_RETURN_REG = RS_R0;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_R0;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_R0;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ NR_FPU_RESULT_REG = NR_F0;
+
+ NR_MM_RESULT_REG = NR_NO;
+
+ NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
+
+ { Offset where the parent framepointer is pushed }
+ PARENT_FRAMEPOINTER_OFFSET = 0;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..6] of tsuperregister =
+ (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ function is_calljmp(o:tasmop):boolean;
+ procedure inverse_flags(var f: TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ 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}
+
+ procedure shifterop_reset(var so : tshifterop);
+ function is_pc(const r : tregister) : boolean;
+
+ function is_shifter_const(d : aint;var imm_shift : byte) : boolean;
+
+ implementation
+
+ uses
+ rgBase,verbose;
+
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i rarmstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i rarmrni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rarmsri.inc}
+ );
+
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ begin
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ const subreg2cgsize:array[Tsubregister] of Tcgsize =
+ (OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO);
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ reg_cgsize:=OS_32;
+ R_FPUREGISTER :
+ reg_cgsize:=OS_F80;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
+ To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
+ is_calljmp:= o in [A_B,A_BL,A_BX,A_BLX];
+ end;
+
+
+ procedure inverse_flags(var f: TResFlags);
+ const
+ inv_flags: array[TResFlags] of TResFlags =
+ (F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI,
+ F_LT,F_GE,F_LE,F_GT);
+ begin
+ f:=inv_flags[f];
+ end;
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const
+ flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
+ (C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+ C_GE,C_LT,C_GT,C_LE);
+ begin
+ if f>high(flag_2_cond) then
+ internalerror(200112301);
+ result:=flag_2_cond[f];
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ procedure shifterop_reset(var so : tshifterop);
+ begin
+ FillChar(so,sizeof(so),0);
+ end;
+
+
+ function is_pc(const r : tregister) : boolean;
+ begin
+ is_pc:=(r=NR_R15);
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse: array[TAsmCond] of TAsmCond=(C_None,
+ C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
+ C_LT,C_GE,C_LE,C_GT,C_None,C_None
+ );
+ begin
+ result := inverse[c];
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+
+ function rotl(d : dword;b : byte) : dword;
+ begin
+ result:=(d shr (32-b)) or (d shl b);
+ end;
+
+
+ function is_shifter_const(d : aint;var imm_shift : byte) : boolean;
+ var
+ i : longint;
+ begin
+ for i:=0 to 15 do
+ begin
+ if (dword(d) and not(rotl($ff,i*2)))=0 then
+ begin
+ imm_shift:=i*2;
+ result:=true;
+ exit;
+ end;
+ end;
+ result:=false;
+ end;
+
+end.
diff --git a/compiler/arm/cpuinfo.pas b/compiler/arm/cpuinfo.pas
new file mode 100644
index 0000000000..c9aba464a9
--- /dev/null
+++ b/compiler/arm/cpuinfo.pas
@@ -0,0 +1,88 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the ARM
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = type extended;
+ ts128real = type extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors =
+ (no_processor,
+ armv3,
+ armv4,
+ armv5
+ );
+
+ tfputype =
+ (no_fpuprocessor,
+ fpu_soft,
+ fpu_libgcc,
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11,
+ fpu_vfp
+ );
+
+Const
+ {# Size of native extended floating point type }
+ extended_size = 12;
+ {# Size of a multimedia register }
+ mmreg_size = 16;
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'arm';
+
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { same as stdcall only different name mangling }
+ pocall_cdecl,
+ { same as stdcall only different name mangling }
+ pocall_cppdecl,
+ { same as stdcall but floating point numbers are handled like equal sized integers }
+ pocall_softfloat
+ ];
+
+ processorsstr : array[tprocessors] of string[5] = ('',
+ 'ARMV3',
+ 'ARMV4',
+ 'ARMV5'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'SOFT',
+ 'LIBGCC',
+ 'FPA',
+ 'FPA10',
+ 'FPA11',
+ 'VFP'
+ );
+
+
+Implementation
+
+end.
diff --git a/compiler/arm/cpunode.pas b/compiler/arm/cpunode.pas
new file mode 100644
index 0000000000..89993d5d1f
--- /dev/null
+++ b/compiler/arm/cpunode.pas
@@ -0,0 +1,46 @@
+{
+ Copyright (c) 2000-2003 by Florian Klaempfl
+
+ This unit includes the ARM code generator into the compiler
+
+ 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
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,ncgmat,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ narmadd,
+ narmcal,
+ narmmat,
+ narminl,
+ narmcnv,
+ narmcon
+ ;
+
+
+end.
diff --git a/compiler/arm/cpupara.pas b/compiler/arm/cpupara.pas
new file mode 100644
index 0000000000..f22ba181bd
--- /dev/null
+++ b/compiler/arm/cpupara.pas
@@ -0,0 +1,496 @@
+{
+ Copyright (c) 2003 by Florian Klaempfl
+
+ ARM specific calling conventions
+
+ 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.
+ ****************************************************************************
+}
+{ ARM specific calling conventions are handled by this unit
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,globals,
+ aasmtai,
+ cpuinfo,cpubase,cgbase,
+ symconst,symbase,symtype,symdef,parabase,paramgr;
+
+ type
+ tarmparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+ end;
+
+ implementation
+
+ uses
+ verbose,systems,
+ rgobj,
+ defutil,symsym,
+ cgutils;
+
+
+ function tarmparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=VOLATILE_INTREGISTERS;
+ end;
+
+
+ function tarmparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=VOLATILE_FPUREGISTERS;
+ end;
+
+
+ procedure tarmparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ internalerror(2002070801);
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.intsize:=tcgsize2size[OS_INT];
+ cgpara.alignment:=std_param_align;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ { the four first parameters are passed into registers }
+ if nr<=4 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,RS_R0+nr-1,R_SUBWHOLE);
+ end
+ else
+ begin
+ { the other parameters are passed on the stack }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=(nr-5)*4;
+ end;
+ end;
+ end;
+
+
+ function getparaloc(calloption : tproccalloption; p : tdef) : tcgloc;
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.deftype of
+ orddef:
+ getparaloc:=LOC_REGISTER;
+ floatdef:
+ if (calloption in [pocall_cdecl,pocall_cppdecl,pocall_softfloat]) or (cs_fp_emulation in aktmoduleswitches) then
+ getparaloc:=LOC_REGISTER
+ else
+ getparaloc:=LOC_FPUREGISTER;
+ enumdef:
+ getparaloc:=LOC_REGISTER;
+ pointerdef:
+ getparaloc:=LOC_REGISTER;
+ formaldef:
+ getparaloc:=LOC_REGISTER;
+ classrefdef:
+ getparaloc:=LOC_REGISTER;
+ recorddef:
+ getparaloc:=LOC_REFERENCE;
+ objectdef:
+ if is_object(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ procvardef:
+ if (po_methodpointer in tprocvardef(p).procoptions) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ filedef:
+ getparaloc:=LOC_REGISTER;
+ arraydef:
+ getparaloc:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ getparaloc:=LOC_REGISTER
+ else
+ getparaloc:=LOC_REFERENCE;
+ variantdef:
+ getparaloc:=LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ getparaloc:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+
+ function tarmparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ if varspez in [vs_var,vs_out] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.deftype of
+ variantdef,
+ formaldef,
+ recorddef:
+ result:=true;
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef :
+ result:=is_object(def);
+ setdef :
+ result:=(tsetdef(def).settype<>smallset);
+ stringdef :
+ result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
+ procvardef :
+ result:=po_methodpointer in tprocvardef(def).procoptions;
+ end;
+ end;
+
+
+ procedure tarmparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ curintreg:=RS_R0;
+ curfloatreg:=RS_F0;
+ curmmreg:=RS_D0;
+ cur_stack_offset:=0;
+ end;
+
+
+ function tarmparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+
+ var
+ nextintreg,nextfloatreg,nextmmreg : tsuperregister;
+ paradef : tdef;
+ paraloc : pcgparalocation;
+ stack_offset : aword;
+ hp : tparavarsym;
+ loc : tcgloc;
+ paracgsize : tcgsize;
+ paralen : longint;
+ i : integer;
+
+ procedure assignintreg;
+ begin
+ if nextintreg<=RS_R3 then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+ inc(nextintreg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,4);
+ end;
+ end;
+
+
+ begin
+ result:=0;
+ nextintreg:=curintreg;
+ nextfloatreg:=curfloatreg;
+ nextmmreg:=curmmreg;
+ stack_offset:=cur_stack_offset;
+
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ { currently only support C-style array of const,
+ there should be no location assigned to the vararg array itself }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(hp.vartype.def) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_R0;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption) then
+ paracgsize:=OS_ADDR
+ else
+ begin
+ paracgsize:=def_cgSize(hp.vartype.def);
+ if paracgsize=OS_NO then
+ paracgsize:=OS_ADDR;
+ end;
+
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].Alignment:=std_param_align;
+
+ if (hp.varspez in [vs_var,vs_out]) then
+ begin
+ paradef:=voidpointertype.def;
+ loc:=LOC_REGISTER;
+ end
+ else
+ begin
+ paradef:=hp.vartype.def;
+ loc:=getparaloc(p.proccalloption,paradef);
+ end;
+
+ paralen:=tcgsize2size[paracgsize];
+ hp.paraloc[side].intsize:=paralen;
+{$ifdef EXTDEBUG}
+ if paralen=0 then
+ internalerror(200410311);
+{$endif EXTDEBUG}
+ while paralen>0 do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { for things like formaldef }
+ if paracgsize=OS_NO then
+ paraloc^.size:=OS_ADDR
+ else if paracgsize in [OS_64,OS_S64] then
+ paraloc^.size:=OS_32
+ else if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
+ case paracgsize of
+ OS_F32:
+ paraloc^.size:=OS_32;
+ OS_F64:
+ paraloc^.size:=OS_64;
+ else
+ internalerror(2005082901);
+ end
+ else
+ paraloc^.size:=paracgsize;
+ case loc of
+ LOC_REGISTER:
+ begin
+ { this is not abi compliant }
+ if nextintreg<=RS_R3 then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+ inc(nextintreg);
+ end
+ else
+ begin
+ { LOC_REFERENCE covers always the overleft }
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=int_cgsize(paralen);
+ if (side=callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen:=0;
+ end;
+ end;
+ LOC_FPUREGISTER:
+ begin
+ if nextfloatreg<=RS_F3 then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
+ inc(nextfloatreg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ case paraloc^.size of
+ OS_F32:
+ inc(stack_offset,4);
+ OS_F64:
+ inc(stack_offset,8);
+ OS_F80:
+ inc(stack_offset,10);
+ OS_F128:
+ inc(stack_offset,16);
+ else
+ internalerror(200403201);
+ end;
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ paraloc^.size:=OS_ADDR;
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then
+ assignintreg
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,hp.vartype.def.size);
+ end;
+ end;
+ else
+ internalerror(2002071002);
+ end;
+ if side=calleeside then
+ begin
+ if paraloc^.loc=LOC_REFERENCE then
+ begin
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ inc(paraloc^.reference.offset,4);
+ end;
+ end;
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ { hack to swap doubles in int registers }
+ if is_double(hp.vartype.def) and (paracgsize=OS_64) and
+ (hp.paraloc[side].location^.loc=LOC_REGISTER) then
+ begin
+ paraloc:=hp.paraloc[side].location;
+ hp.paraloc[side].location:=hp.paraloc[side].location^.next;
+ hp.paraloc[side].location^.next:=paraloc;
+ paraloc^.next:=nil;
+ end;
+ end;
+ curintreg:=nextintreg;
+ curfloatreg:=nextfloatreg;
+ curmmreg:=nextmmreg;
+ cur_stack_offset:=stack_offset;
+ result:=cur_stack_offset;
+ end;
+
+
+ function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ retcgsize : tcgsize;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ retcgsize:=OS_ADDR
+ else
+ retcgsize:=def_cgsize(p.rettype.def);
+
+ location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
+ p.funcretloc[side].size:=retcgsize;
+
+ { void has no location }
+ if is_void(p.rettype.def) then
+ begin
+ location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
+ exit;
+ end;
+
+ { Return in FPU register? }
+ if p.rettype.def.deftype=floatdef then
+ begin
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_softfloat]) or (cs_fp_emulation in aktmoduleswitches) then
+ begin
+ case retcgsize of
+ OS_64,
+ OS_F64:
+ begin
+ { low }
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_HIGH_REG;
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_LOW_REG;
+ p.funcretloc[side].size:=OS_64;
+ end;
+ OS_32,
+ OS_F32:
+ begin
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
+ p.funcretloc[side].size:=OS_32;
+ end;
+ else
+ internalerror(2005082603);
+ end;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_FPUREGISTER;
+ p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+ end;
+ end
+ { Return in register? }
+ else if not ret_in_param(p.rettype.def,p.proccalloption) then
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { low }
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
+ end;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REFERENCE;
+ p.funcretloc[side].size:=retcgsize;
+ end;
+ end;
+
+
+ function tarmparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ { just continue loading the parameters in the registers }
+ result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset)
+ else
+ internalerror(200410231);
+ end;
+
+begin
+ paramanager:=tarmparamanager.create;
+end.
diff --git a/compiler/arm/cpupi.pas b/compiler/arm/cpupi.pas
new file mode 100644
index 0000000000..cfe10e315b
--- /dev/null
+++ b/compiler/arm/cpupi.pas
@@ -0,0 +1,105 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ 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 contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,cutils,
+ procinfo,cpuinfo,psub;
+
+ type
+ tarmprocinfo = class(tcgprocinfo)
+ floatregstart : aint;
+ // procedure handle_body_start;override;
+ // procedure after_pass1;override;
+ procedure set_first_temp_offset;override;
+ procedure allocate_push_parasize(size: longint);override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+
+ implementation
+
+ uses
+ globals,systems,
+ cpubase,
+ aasmtai,
+ tgobj,
+ symconst,symsym,paramgr,
+ cgbase,
+ cgobj;
+
+ procedure tarmprocinfo.set_first_temp_offset;
+ begin
+ { We allocate enough space to save all registers because we can't determine
+ the necessary space because the used registers aren't known before
+ secondpass is run. Even worse, patching
+ the local offsets after generating the code could cause trouble because
+ "shifter" constants could change to non-"shifter" constants. This
+ is especially a problem when taking the address of a local. For now,
+ this extra memory should hurt less than generating all local contants with offsets
+ >256 as non shifter constants }
+ tg.setfirsttemp(-12-28);
+ end;
+
+
+ procedure tarmprocinfo.allocate_push_parasize(size:longint);
+ begin
+ if size>maxpushedparasize then
+ maxpushedparasize:=size;
+ end;
+
+
+ function tarmprocinfo.calc_stackframe_size:longint;
+ var
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ floatsavesize : aword;
+ begin
+ maxpushedparasize:=align(maxpushedparasize,max(aktalignment.localalignmin,4));
+ firstfloatreg:=RS_NO;
+ { save floating point registers? }
+ for r:=RS_F0 to RS_F7 do
+ if r in cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
+ begin
+ if firstfloatreg=RS_NO then
+ firstfloatreg:=r;
+ lastfloatreg:=r;
+ end;
+ if firstfloatreg<>RS_NO then
+ floatsavesize:=(lastfloatreg-firstfloatreg+1)*12
+ else
+ floatsavesize:=0;
+ floatsavesize:=align(floatsavesize,max(aktalignment.localalignmin,4));
+ result:=Align(tg.direction*tg.lasttemp,max(aktalignment.localalignmin,4))+maxpushedparasize+floatsavesize;
+ floatregstart:=-result+maxpushedparasize;
+ end;
+
+
+begin
+ cprocinfo:=tarmprocinfo;
+end.
diff --git a/compiler/arm/cpuswtch.pas b/compiler/arm/cpuswtch.pas
new file mode 100644
index 0000000000..49ff032287
--- /dev/null
+++ b/compiler/arm/cpuswtch.pas
@@ -0,0 +1,118 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ interprets the commandline options which are arm specific
+
+ 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 cpuswtch;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ options;
+
+type
+ toptionarm=class(toption)
+ procedure interpret_proc_specific_options(const opt:string);override;
+ end;
+
+implementation
+
+uses
+ cutils,globtype,systems,globals;
+
+procedure toptionarm.interpret_proc_specific_options(const opt:string);
+var
+ more: string;
+ j: longint;
+begin
+ More:=Upper(copy(opt,3,length(opt)-2));
+ case opt[2] of
+ 'O' : Begin
+ j := 3;
+ While (j <= Length(Opt)) Do
+ Begin
+ case opt[j] of
+ '-' :
+ begin
+ initglobalswitches:=initglobalswitches-[cs_optimize,cs_fastoptimize,cs_slowoptimize,cs_littlesize,
+ cs_regvars,cs_uncertainopts];
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+ end;
+ 'a' :
+ begin
+ UpdateAlignmentStr(Copy(Opt,j+1,255),ParaAlignment);
+ j:=length(Opt);
+ end;
+ 'g' : initglobalswitches:=initglobalswitches+[cs_littlesize];
+ 'G' : initglobalswitches:=initglobalswitches-[cs_littlesize];
+ 'r' :
+ begin
+ initglobalswitches:=initglobalswitches+[cs_regvars];
+ Simplify_ppu:=false;
+ end;
+ 'u' : initglobalswitches:=initglobalswitches+[cs_uncertainopts];
+ '1' : initglobalswitches:=initglobalswitches-[cs_fastoptimize,cs_slowoptimize]+[cs_optimize];
+ '2' : initglobalswitches:=initglobalswitches-[cs_slowoptimize]+[cs_optimize,cs_fastoptimize];
+ '3' : initglobalswitches:=initglobalswitches+[cs_optimize,cs_fastoptimize,cs_slowoptimize];
+{$ifdef dummy}
+ 'p' :
+ Begin
+ If j < Length(Opt) Then
+ Begin
+ Case opt[j+1] Of
+ '1': initoptprocessor := Class386;
+ '2': initoptprocessor := ClassP5;
+ '3': initoptprocessor := ClassP6
+ Else IllegalPara(Opt)
+ End;
+ Inc(j);
+ End
+ Else IllegalPara(opt)
+ End;
+{$endif dummy}
+ else IllegalPara(opt);
+ End;
+ Inc(j)
+ end;
+ end;
+{$ifdef dummy}
+ 'R' : begin
+ if More='GAS' then
+ initasmmode:=asmmode_ppc_gas
+ else
+ if More='MOTOROLA' then
+ initasmmode:=asmmode_ppc_motorola
+ else
+ if More='DIRECT' then
+ initasmmode:=asmmode_direct
+ else
+ IllegalPara(opt);
+ end;
+{$endif dummy}
+ else
+ IllegalPara(opt);
+ end;
+end;
+
+
+initialization
+ coption:=toptionarm;
+end.
diff --git a/compiler/arm/cputarg.pas b/compiler/arm/cputarg.pas
new file mode 100644
index 0000000000..61429d9de6
--- /dev/null
+++ b/compiler/arm/cputarg.pas
@@ -0,0 +1,78 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the arm dependent target units
+
+ 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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETWINCE}
+ ,t_win
+ {$endif}
+ {$ifndef NOTARGETGBA}
+ ,t_gba
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGARMGAS}
+ ,agarmgas
+ {$endif}
+
+ ,ogcoff
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaarmgas}
+ ,raarmgas
+ {$endif NoRaarmgas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+ ;
+
+end.
diff --git a/compiler/arm/itcpugas.pas b/compiler/arm/itcpugas.pas
new file mode 100644
index 0000000000..74a186a20e
--- /dev/null
+++ b/compiler/arm/itcpugas.pas
@@ -0,0 +1,93 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the ARM GAS instruction tables
+
+ 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 itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+
+ const
+ { Standard opcode string table (for each tasmop enumeration). The
+ opcode strings should conform to the names as defined by the
+ processor manufacturer.
+ }
+ gas_op2str : op2strtable = {$i armatt.inc}
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose;
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {$i rarmstd.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rarmsri.inc}
+ );
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/compiler/arm/narmadd.pas b/compiler/arm/narmadd.pas
new file mode 100644
index 0000000000..5b53c9fd29
--- /dev/null
+++ b/compiler/arm/narmadd.pas
@@ -0,0 +1,336 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Code generation for add nodes on the ARM
+
+ 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 narmadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgadd,cpubase;
+
+ type
+ tarmaddnode = class(tcgaddnode)
+ private
+ function GetResFlags(unsigned:Boolean):TResFlags;
+ protected
+ procedure second_addfloat;override;
+ procedure second_cmpfloat;override;
+ procedure second_cmpordinal;override;
+ procedure second_cmpsmallset;override;
+ procedure second_cmp64bit;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmcpu,defutil,htypechk,
+ cgbase,cgutils,cgcpu,
+ cpuinfo,pass_1,pass_2,regvars,
+ cpupara,
+ ncon,nset,nadd,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+
+{*****************************************************************************
+ TSparcAddNode
+*****************************************************************************}
+
+ function tarmaddnode.GetResFlags(unsigned:Boolean):TResFlags;
+ begin
+ case NodeType of
+ equaln:
+ GetResFlags:=F_EQ;
+ unequaln:
+ GetResFlags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swaped in flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_GT;
+ lten:
+ GetResFlags:=F_GE;
+ gtn:
+ GetResFlags:=F_LT;
+ gten:
+ GetResFlags:=F_LE;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_LT;
+ lten:
+ GetResFlags:=F_LE;
+ gtn:
+ GetResFlags:=F_GT;
+ gten:
+ GetResFlags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swaped in Flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_HI;
+ lten:
+ GetResFlags:=F_CS;
+ gtn:
+ GetResFlags:=F_CC;
+ gten:
+ GetResFlags:=F_LS;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_CC;
+ lten:
+ GetResFlags:=F_LS;
+ gtn:
+ GetResFlags:=F_HI;
+ gten:
+ GetResFlags:=F_CS;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tarmaddnode.second_addfloat;
+ var
+ op : TAsmOp;
+ begin
+ case aktfputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ pass_left_right;
+ if (nf_swaped in flags) then
+ swapleftright;
+
+ case nodetype of
+ addn :
+ op:=A_ADF;
+ muln :
+ op:=A_MUF;
+ subn :
+ op:=A_SUF;
+ slashn :
+ op:=A_DVF;
+ else
+ internalerror(200308313);
+ end;
+
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(exprasmlist,left.location,true);
+ location_force_fpureg(exprasmlist,right.location,(left.location.loc<>LOC_CFPUREGISTER));
+
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ if left.location.loc<>LOC_CFPUREGISTER then
+ location.register:=left.location.register
+ else
+ location.register:=right.location.register;
+
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg_reg(op,
+ location.register,left.location.register,right.location.register),
+ cgsize2fpuoppostfix[def_cgsize(resulttype.def)]));
+
+ location.loc:=LOC_FPUREGISTER;
+ end;
+ fpu_soft:
+ { this case should be handled already by pass1 }
+ internalerror(200308252);
+ else
+ internalerror(200308251);
+ end;
+ end;
+
+
+ procedure tarmaddnode.second_cmpfloat;
+ begin
+ pass_left_right;
+ if (nf_swaped in flags) then
+ swapleftright;
+
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(exprasmlist,left.location,true);
+ location_force_fpureg(exprasmlist,right.location,true);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+
+ if nodetype in [equaln,unequaln] then
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg(A_CMF,
+ left.location.register,right.location.register),
+ cgsize2fpuoppostfix[def_cgsize(resulttype.def)]))
+ else
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg(A_CMFE,
+ left.location.register,right.location.register),
+ cgsize2fpuoppostfix[def_cgsize(resulttype.def)]));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(false);
+ end;
+
+
+ procedure tarmaddnode.second_cmpsmallset;
+ var
+ tmpreg : tregister;
+ begin
+ pass_left_right;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ force_reg_left_right(false,false);
+
+ case nodetype of
+ equaln:
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+ location.resflags:=F_EQ;
+ end;
+ unequaln:
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+ location.resflags:=F_NE;
+ end;
+ lten,
+ gten:
+ begin
+ if (not(nf_swaped in flags) and
+ (nodetype = lten)) or
+ ((nf_swaped in flags) and
+ (nodetype = gten)) then
+ swapleftright;
+ tmpreg:=cg.getintregister(exprasmlist,location.size);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_AND,tmpreg,left.location.register,right.location.register));
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,tmpreg,right.location.register));
+ location.resflags:=F_EQ;
+ end;
+ else
+ internalerror(2004012401);
+ end;
+ end;
+
+
+ procedure tarmaddnode.second_cmp64bit;
+ var
+ unsigned : boolean;
+ tmpreg : tregister;
+ oldnodetype : tnodetype;
+ begin
+ pass_left_right;
+ force_reg_left_right(false,false);
+
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+
+ { operation requiring proper N, Z and C flags ? }
+ if unsigned or (nodetype in [equaln,unequaln]) then
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
+ exprasmlist.concat(setcondition(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo),C_EQ));
+ end
+ else
+ { operation requiring proper N, Z and V flags ? }
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn:
+ begin
+ cg.a_jmp_flags(exprasmlist,getresflags(false),truelabel);
+ { cheat a little bit for the negative test }
+ toggleflag(nf_swaped);
+ cg.a_jmp_flags(exprasmlist,getresflags(false),falselabel);
+ toggleflag(nf_swaped);
+ end;
+ lten,gten:
+ begin
+ oldnodetype:=nodetype;
+ if nodetype=lten then
+ nodetype:=ltn
+ else
+ nodetype:=gtn;
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),truelabel);
+ { cheat for the negative test }
+ if nodetype=ltn then
+ nodetype:=gtn
+ else
+ nodetype:=ltn;
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),falselabel);
+ nodetype:=oldnodetype;
+ end;
+ end;
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo));
+ { the comparisaion of the low dword have to be
+ always unsigned! }
+ cg.a_jmp_flags(exprasmlist,getresflags(true),truelabel);
+ cg.a_jmp_always(exprasmlist,falselabel);
+ end;
+ end;
+
+
+ procedure tarmaddnode.second_cmpordinal;
+ var
+ unsigned : boolean;
+ tmpreg : tregister;
+ b : byte;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ if is_shifter_const(right.location.value,b) then
+ exprasmlist.concat(taicpu.op_reg_const(A_CMP,left.location.register,right.location.value))
+ else
+ begin
+ tmpreg:=cg.getintregister(exprasmlist,location.size);
+ cg.a_load_const_reg(exprasmlist,OS_INT,
+ right.location.value,tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register,tmpreg));
+ end;
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ end;
+
+begin
+ caddnode:=tarmaddnode;
+end.
diff --git a/compiler/arm/narmcal.pas b/compiler/arm/narmcal.pas
new file mode 100644
index 0000000000..432403f8a1
--- /dev/null
+++ b/compiler/arm/narmcal.pas
@@ -0,0 +1,50 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the ARM specific part of call 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 bymethodpointer
+ 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 narmcal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symdef,node,ncal,ncgcal;
+
+ type
+ tarmcallnode = class(tcgcallnode)
+ // procedure push_framepointer;override;
+ end;
+
+implementation
+
+ uses
+ paramgr;
+
+(*
+ procedure tarmcallnode.push_framepointer;
+ begin
+ framepointer_paraloc:=paramanager.getintparaloc(procdefinition.proccalloption,1);
+ end;
+*)
+
+begin
+ ccallnode:=tarmcallnode;
+end.
diff --git a/compiler/arm/narmcnv.pas b/compiler/arm/narmcnv.pas
new file mode 100644
index 0000000000..6fb0fdc62e
--- /dev/null
+++ b/compiler/arm/narmcnv.pas
@@ -0,0 +1,265 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate ARM assembler for type converting 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 narmcnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,defcmp;
+
+ type
+ tarmtypeconvnode = class(tcgtypeconvnode)
+ protected
+ function first_int_to_real: tnode;override;
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ // function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real;override;
+ // procedure second_real_to_real;override;
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+ uses
+ verbose,globtype,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,
+ defutil,
+ cgbase,cgutils,
+ pass_1,pass_2,
+ ncon,ncal,
+ ncgutil,
+ cpubase,aasmcpu,
+ rgobj,tgobj,cgobj,cgcpu;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function tarmtypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[19];
+ begin
+ if cs_fp_emulation in aktmoduleswitches then
+ begin
+ if target_info.system in system_wince then
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resulttype.def) or
+ is_currency(left.resulttype.def) then
+ begin
+ { hack to avoid double division by 10000, as it's
+ already done by resulttypepass.resulttype_int_to_real }
+ if is_currency(left.resulttype.def) then
+ left.resulttype := s64inttype;
+ if is_signed(left.resulttype.def) then
+ fname:='I64TOD'
+ else
+ fname:='UI64TOD';
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resulttype.def) then
+ fname:='ITOD'
+ else
+ fname:='UTOD';
+ firstpass(left);
+ end;
+ result:=ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ begin
+ internalerror(2005082803);
+ end;
+ end
+ else
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resulttype.def) or
+ is_currency(left.resulttype.def) then
+ begin
+ { hack to avoid double division by 10000, as it's
+ already done by resulttypepass.resulttype_int_to_real }
+ if is_currency(left.resulttype.def) then
+ left.resulttype := s64inttype;
+ if is_signed(left.resulttype.def) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resulttype.def) then
+ inserttypeconv(left,s32inttype)
+ else
+ inserttypeconv(left,u32inttype);
+ firstpass(left);
+ end;
+ result := nil;
+ if registersfpu<1 then
+ registersfpu:=1;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+ end;
+
+
+ procedure tarmtypeconvnode.second_int_to_real;
+ var
+ instr : taicpu;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ location_force_reg(exprasmlist,left.location,OS_32,true);
+ location.register:=cg.getfpuregister(exprasmlist,location.size);
+ instr:=taicpu.op_reg_reg(A_FLT,location.register,left.location.register);
+ instr.oppostfix:=cgsize2fpuoppostfix[def_cgsize(resulttype.def)];
+ exprasmlist.concat(instr);
+ end;
+
+
+ procedure tarmtypeconvnode.second_int_to_bool;
+ var
+ hregister : tregister;
+ href : treference;
+ resflags : tresflags;
+ hlabel,oldtruelabel,oldfalselabel : tasmlabel;
+ begin
+ oldtruelabel:=truelabel;
+ oldfalselabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+ { byte(boolean) or word(wordbool) or longint(longbool) must
+ be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resulttype.def.size=resulttype.def.size) and
+ (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ begin
+ location_copy(location,left.location);
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ exit;
+ end;
+
+ { Load left node into flag F_NE/F_E }
+ resflags:=F_NE;
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_ref_reg(exprasmlist,OS_32,OS_32,left.location.reference,hregister);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_ref_reg(exprasmlist,OP_OR,OS_32,href,hregister);
+ tcgarm(cg).cgsetflags:=false;
+ end
+ else
+ begin
+ location_force_reg(exprasmlist,left.location,left.location.size,true);
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_reg_reg(exprasmlist,OP_OR,left.location.size,left.location.register,left.location.register);
+ tcgarm(cg).cgsetflags:=false;
+ end;
+ end;
+ LOC_FLAGS :
+ begin
+ resflags:=left.location.resflags;
+ end;
+ LOC_REGISTER,LOC_CREGISTER :
+ begin
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,left.location.register64.reglo,hregister);
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_reg_reg(exprasmlist,OP_OR,OS_32,left.location.register64.reghi,hregister);
+ tcgarm(cg).cgsetflags:=false;
+ end
+ else
+ begin
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_reg_reg(exprasmlist,OP_OR,left.location.size,left.location.register,left.location.register);
+ tcgarm(cg).cgsetflags:=false;
+ end;
+ end;
+ LOC_JUMP :
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_INT);
+ objectlibrary.getjumplabel(hlabel);
+ cg.a_label(exprasmlist,truelabel);
+ cg.a_load_const_reg(exprasmlist,OS_INT,1,hregister);
+ cg.a_jmp_always(exprasmlist,hlabel);
+ cg.a_label(exprasmlist,falselabel);
+ cg.a_load_const_reg(exprasmlist,OS_INT,0,hregister);
+ cg.a_label(exprasmlist,hlabel);
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_reg_reg(exprasmlist,OP_OR,OS_INT,hregister,hregister);
+ tcgarm(cg).cgsetflags:=false;
+ end;
+ else
+ internalerror(200311301);
+ end;
+ { load flags to register }
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
+ location.register:=cg.getintregister(exprasmlist,location.size);
+ cg.g_flags2reg(exprasmlist,location.size,resflags,location.register);
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ end;
+
+
+begin
+ ctypeconvnode:=tarmtypeconvnode;
+end.
diff --git a/compiler/arm/narmcon.pas b/compiler/arm/narmcon.pas
new file mode 100644
index 0000000000..b37b240b4b
--- /dev/null
+++ b/compiler/arm/narmcon.pas
@@ -0,0 +1,141 @@
+{
+ Copyright (c) 2005 by Florian Klaempfl
+
+ Code generation for const nodes on the ARM
+
+ 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 narmcon;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgcon,cpubase;
+
+ type
+ tarmrealconstnode = class(tcgrealconstnode)
+ procedure pass_2;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,
+ globtype,globals,
+ cpuinfo,
+ aasmbase,aasmtai,
+ symconst,symdef,
+ defutil,
+ cgbase,cgutils,
+ procinfo,
+ ncon;
+
+{*****************************************************************************
+ TARMREALCONSTNODE
+*****************************************************************************}
+
+ procedure tarmrealconstnode.pass_2;
+ { I suppose the parser/pass_1 must make sure the generated real }
+ { constants are actually supported by the target processor? (JM) }
+ const
+ floattype2ait:array[tfloattype] of taitype=
+ (ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_comp_64bit,ait_real_128bit);
+ var
+ hp1 : tai;
+ lastlabel : tasmlabel;
+ realait : taitype;
+ hiloswapped : boolean;
+
+ begin
+ location_reset(location,LOC_CREFERENCE,def_cgsize(resulttype.def));
+ lastlabel:=nil;
+ realait:=floattype2ait[tfloatdef(resulttype.def).typ];
+ hiloswapped:=aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11];
+ { const already used ? }
+ if not assigned(lab_real) then
+ begin
+ objectlibrary.getjumplabel(lastlabel);
+ lab_real:=lastlabel;
+ current_procinfo.aktlocaldata.concat(Tai_label.Create(lastlabel));
+ location.reference.symboldata:=current_procinfo.aktlocaldata.last;
+ case realait of
+ ait_real_32bit :
+ begin
+ current_procinfo.aktlocaldata.concat(Tai_real_32bit.Create(ts32real(value_real)));
+ { range checking? }
+ if ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) and
+ (tai_real_32bit(asmlist[al_typedconsts].last).value=double(MathInf)) then
+ Message(parser_e_range_check_error);
+ end;
+
+ ait_real_64bit :
+ begin
+ if hiloswapped then
+ current_procinfo.aktlocaldata.concat(Tai_real_64bit.Create_hiloswapped(ts64real(value_real)))
+ else
+ current_procinfo.aktlocaldata.concat(Tai_real_64bit.Create(ts64real(value_real)));
+
+ { range checking? }
+ if ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) and
+ (tai_real_64bit(asmlist[al_typedconsts].last).value=double(MathInf)) then
+ Message(parser_e_range_check_error);
+ end;
+
+ ait_real_80bit :
+ begin
+ current_procinfo.aktlocaldata.concat(Tai_real_80bit.Create(value_real));
+
+ { range checking? }
+ if ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) and
+ (tai_real_80bit(asmlist[al_typedconsts].last).value=double(MathInf)) then
+ Message(parser_e_range_check_error);
+ end;
+{$ifdef cpufloat128}
+ ait_real_128bit :
+ begin
+ current_procinfo.aktlocaldata.concat(Tai_real_128bit.Create(value_real));
+
+ { range checking? }
+ if ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) and
+ (tai_real_128bit(asmlist[al_typedconsts].last).value=double(MathInf)) then
+ Message(parser_e_range_check_error);
+ end;
+{$endif cpufloat128}
+
+ { the round is necessary for native compilers where comp isn't a float }
+ ait_comp_64bit :
+ if (value_real>9223372036854775807.0) or (value_real<-9223372036854775808.0) then
+ message(parser_e_range_check_error)
+ else
+ current_procinfo.aktlocaldata.concat(Tai_comp_64bit.Create(round(value_real)));
+ else
+ internalerror(2005092401);
+ end;
+ end;
+ location.reference.symbol:=lab_real;
+ location.reference.base:=NR_R15;
+ end;
+
+begin
+ crealconstnode:=tarmrealconstnode;
+end.
diff --git a/compiler/arm/narminl.pas b/compiler/arm/narminl.pas
new file mode 100644
index 0000000000..ab9453c24c
--- /dev/null
+++ b/compiler/arm/narminl.pas
@@ -0,0 +1,216 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generates ARM inline 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 narminl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl,ncginl;
+
+ type
+ tarminlinenode = class(tcgInlineNode)
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ function first_sqrt_real: tnode; override;
+ { atn,sin,cos,lgn isn't supported by the linux fpe
+ function first_arctan_real: tnode; override;
+ function first_ln_real: tnode; override;
+ function first_cos_real: tnode; override;
+ function first_sin_real: tnode; override;
+ }
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_sqrt_real; override;
+ { atn,sin,cos,lgn isn't supported by the linux fpe
+ procedure second_arctan_real; override;
+ procedure second_ln_real; override;
+ procedure second_cos_real; override;
+ procedure second_sin_real; override;
+ }
+ private
+ procedure load_fpu_location;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,fmodule,
+ symconst,symdef,
+ aasmbase,aasmtai,aasmcpu,
+ cgbase,cgutils,
+ pass_1,pass_2,
+ cpubase,paramgr,
+ nbas,ncon,ncal,ncnv,nld,
+ tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu,cgcpu;
+
+{*****************************************************************************
+ tarminlinenode
+*****************************************************************************}
+
+ procedure tarminlinenode.load_fpu_location;
+ begin
+ secondpass(left);
+ location_force_fpureg(exprasmlist,left.location,true);
+ location_copy(location,left.location);
+ if left.location.loc=LOC_CFPUREGISTER then
+ begin
+ location.register:=cg.getfpuregister(exprasmlist,location.size);
+ location.loc := LOC_FPUREGISTER;
+ end;
+ end;
+
+
+ function tarminlinenode.first_abs_real : tnode;
+ begin
+ if cs_fp_emulation in aktmoduleswitches then
+ result:=inherited first_abs_real
+ else
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ first_abs_real:=nil;
+ end;
+ end;
+
+
+ function tarminlinenode.first_sqr_real : tnode;
+ begin
+ if cs_fp_emulation in aktmoduleswitches then
+ result:=inherited first_sqr_real
+ else
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ first_sqr_real:=nil;
+ end;
+ end;
+
+
+ function tarminlinenode.first_sqrt_real : tnode;
+ begin
+ if cs_fp_emulation in aktmoduleswitches then
+ result:=inherited first_sqrt_real
+ else
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ first_sqrt_real := nil;
+ end;
+ end;
+
+
+ { atn,sin,cos,lgn isn't supported by the linux fpe
+ function tarminlinenode.first_arctan_real: tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ result:=nil;
+ end;
+
+
+ function tarminlinenode.first_ln_real: tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ result:=nil;
+ end;
+
+ function tarminlinenode.first_cos_real: tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ result:=nil;
+ end;
+
+
+ function tarminlinenode.first_sin_real: tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ result:=nil;
+ end;
+ }
+
+
+ procedure tarminlinenode.second_abs_real;
+ begin
+ load_fpu_location;
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg(A_ABS,location.register,location.register),get_fpu_postfix(resulttype.def)));
+ end;
+
+
+ procedure tarminlinenode.second_sqr_real;
+ begin
+ load_fpu_location;
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg_reg(A_MUF,location.register,left.location.register,left.location.register),get_fpu_postfix(resulttype.def)));
+ end;
+
+
+ procedure tarminlinenode.second_sqrt_real;
+ begin
+ load_fpu_location;
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg(A_SQT,location.register,location.register),get_fpu_postfix(resulttype.def)));
+ end;
+
+
+ { atn, sin, cos, lgn isn't supported by the linux fpe
+ procedure tarminlinenode.second_arctan_real;
+ begin
+ load_fpu_location;
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg(A_ATN,location.register,location.register),get_fpu_postfix(resulttype.def)));
+ end;
+
+
+ procedure tarminlinenode.second_ln_real;
+ begin
+ load_fpu_location;
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg(A_LGN,location.register,location.register),get_fpu_postfix(resulttype.def)));
+ end;
+
+ procedure tarminlinenode.second_cos_real;
+ begin
+ load_fpu_location;
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg(A_COS,location.register,location.register),get_fpu_postfix(resulttype.def)));
+ end;
+
+
+ procedure tarminlinenode.second_sin_real;
+ begin
+ load_fpu_location;
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg(A_SIN,location.register,location.register),get_fpu_postfix(resulttype.def)));
+ end;
+ }
+
+begin
+ cinlinenode:=tarminlinenode;
+end.
diff --git a/compiler/arm/narmmat.pas b/compiler/arm/narmmat.pas
new file mode 100644
index 0000000000..884ff77a28
--- /dev/null
+++ b/compiler/arm/narmmat.pas
@@ -0,0 +1,121 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate ARM assembler for math 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 narmmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat;
+
+ type
+ tarmnotnode = class(tcgnotnode)
+ procedure second_boolean;override;
+ end;
+
+
+ tarmunaryminusnode = class(tcgunaryminusnode)
+ procedure second_float;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,
+ aasmbase,aasmcpu,aasmtai,
+ defutil,
+ cgbase,cgobj,cgutils,
+ pass_1,pass_2,
+ ncon,
+ cpubase,cpuinfo,
+ ncgutil,cgcpu,cg64f32,rgobj;
+
+{*****************************************************************************
+ TARMNOTNODE
+*****************************************************************************}
+
+ procedure tarmnotnode.second_boolean;
+ var
+ hl : tasmlabel;
+ ins : taicpu;
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc=LOC_JUMP then
+ begin
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ location.loc:=LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE :
+ begin
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),true);
+ exprasmlist.concat(taicpu.op_reg_const(A_CMP,left.location.register,0));
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_EQ;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end;
+
+{*****************************************************************************
+ TARMUNARYMINUSNODE
+*****************************************************************************}
+
+ procedure tarmunaryminusnode.second_float;
+ begin
+ secondpass(left);
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ location_force_fpureg(exprasmlist,left.location,false);
+ location:=left.location;
+ exprasmlist.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSF,
+ location.register,left.location.register,0),
+ cgsize2fpuoppostfix[def_cgsize(resulttype.def)]));
+ end;
+
+
+begin
+ cnotnode:=tarmnotnode;
+ cunaryminusnode:=tarmunaryminusnode;
+end.
diff --git a/compiler/arm/raarm.pas b/compiler/arm/raarm.pas
new file mode 100644
index 0000000000..0b22d8a41e
--- /dev/null
+++ b/compiler/arm/raarm.pas
@@ -0,0 +1,54 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common arm assembler reader routines
+
+ 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 raarm;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ aasmtai,
+ rautils;
+
+ type
+ TARMOperand=class(TOperand)
+ end;
+
+ TARMInstruction=class(TInstruction)
+ oppostfix : toppostfix;
+ function ConcatInstruction(p:TAAsmoutput) : tai;override;
+ end;
+
+ implementation
+
+ uses
+ aasmcpu;
+
+ function TARMInstruction.ConcatInstruction(p:TAAsmoutput) : tai;
+ begin
+ result:=inherited ConcatInstruction(p);
+ (result as taicpu).oppostfix:=oppostfix;
+ end;
+
+
+end.
diff --git a/compiler/arm/raarmgas.pas b/compiler/arm/raarmgas.pas
new file mode 100644
index 0000000000..f1ceb6d00c
--- /dev/null
+++ b/compiler/arm/raarmgas.pas
@@ -0,0 +1,797 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the ARM GNU AS styled inline assembler.
+
+ 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 raarmgas;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ raatt,raarm,
+ cpubase;
+
+ type
+ tarmattreader = class(tattreader)
+ actoppostfix : TOpPostfix;
+ function is_asmopcode(const s: string):boolean;override;
+ function is_register(const s:string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tarmoperand);
+ procedure BuildOperand(oper : tarmoperand);
+ function TryBuildShifterOp(oper : tarmoperand) : boolean;
+ procedure BuildOpCode(instr : tarminstruction);
+ procedure ReadSym(oper : tarmoperand);
+ procedure ConvertCalljmp(instr : tarminstruction);
+ end;
+
+
+ Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ { aasm }
+ cpuinfo,aasmbase,aasmtai,aasmcpu,
+ { symtable }
+ symconst,symbase,symtype,symsym,symtable,
+ { parser }
+ scanner,
+ procinfo,
+ itcpugas,
+ rabase,rautils,
+ cgbase,cgobj
+ ;
+
+
+ function tarmattreader.is_register(const s:string):boolean;
+ type
+ treg2str = record
+ name : string[2];
+ reg : tregister;
+ end;
+
+ const
+ extraregs : array[0..19] of treg2str = (
+ (name: 'A1'; reg : NR_R0),
+ (name: 'A2'; reg : NR_R1),
+ (name: 'A3'; reg : NR_R2),
+ (name: 'A4'; reg : NR_R3),
+ (name: 'V1'; reg : NR_R4),
+ (name: 'V2'; reg : NR_R5),
+ (name: 'V3'; reg : NR_R6),
+ (name: 'V4'; reg : NR_R7),
+ (name: 'V5'; reg : NR_R8),
+ (name: 'V6'; reg : NR_R9),
+ (name: 'V7'; reg : NR_R10),
+ (name: 'V8'; reg : NR_R11),
+ (name: 'WR'; reg : NR_R7),
+ (name: 'SB'; reg : NR_R9),
+ (name: 'SL'; reg : NR_R10),
+ (name: 'FP'; reg : NR_R11),
+ (name: 'IP'; reg : NR_R12),
+ (name: 'SP'; reg : NR_R13),
+ (name: 'LR'; reg : NR_R14),
+ (name: 'PC'; reg : NR_R15));
+
+ var
+ i : longint;
+
+ begin
+ result:=inherited is_register(s);
+ { reg found?
+ possible aliases are always 2 char
+ }
+ if result or (length(s)<>2) then
+ exit;
+ for i:=low(extraregs) to high(extraregs) do
+ begin
+ if s=extraregs[i].name then
+ begin
+ actasmregister:=extraregs[i].reg;
+ result:=true;
+ actasmtoken:=AS_REGISTER;
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure tarmattreader.ReadSym(oper : tarmoperand);
+ var
+ tempstr : string;
+ typesize,l,k : longint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ Procedure tarmattreader.BuildReference(oper : tarmoperand);
+
+ procedure Consume_RBracket;
+ begin
+ if actasmtoken<>AS_RBRACKET then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RBRACKET);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+
+ procedure read_index;
+ begin
+ Consume(AS_COMMA);
+ if actasmtoken=AS_REGISTER then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ end
+ else if actasmtoken=AS_HASH then
+ begin
+ Consume(AS_HASH);
+ inc(oper.opr.ref.offset,BuildConstExpression(false,true));
+ end;
+ end;
+
+
+ begin
+ Consume(AS_LBRACKET);
+ if actasmtoken=AS_REGISTER then
+ begin
+ oper.opr.ref.base:=actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { (reg) }
+ if actasmtoken=AS_RBRACKET then
+ Begin
+ Consume_RBracket;
+ oper.opr.ref.addressmode:=AM_POSTINDEXED;
+ if actasmtoken=AS_COMMA then
+ read_index;
+ exit;
+ end;
+ if actasmtoken=AS_COMMA then
+ begin
+ read_index;
+ Consume_RBracket;
+ end;
+ if actasmtoken=AS_NOT then
+ begin
+ consume(AS_NOT);
+ oper.opr.ref.addressmode:=AM_PREINDEXED;
+ end;
+ end {end case }
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+
+
+ function tarmattreader.TryBuildShifterOp(oper : tarmoperand) : boolean;
+
+ procedure handlepara(sm : tshiftmode);
+ begin
+ consume(AS_ID);
+ fillchar(oper.opr,sizeof(oper.opr),0);
+ oper.opr.typ:=OPR_SHIFTEROP;
+ oper.opr.shifterop.shiftmode:=sm;
+ if sm<>SM_RRX then
+ begin
+ case actasmtoken of
+ AS_REGISTER:
+ begin
+ oper.opr.shifterop.rs:=actasmregister;
+ consume(AS_REGISTER);
+ end;
+ AS_HASH:
+ begin
+ consume(AS_HASH);
+ oper.opr.shifterop.shiftimm:=BuildConstExpression(false,false);
+ end;
+ else
+ Message(asmr_e_illegal_shifterop_syntax);
+ end;
+ end;
+ end;
+
+ begin
+ result:=true;
+ if (actasmtoken=AS_ID) then
+ begin
+ if (actasmpattern='LSL') then
+ handlepara(SM_LSL)
+ else if (actasmpattern='LSR') then
+ handlepara(SM_LSR)
+ else if (actasmpattern='ASR') then
+ handlepara(SM_ASR)
+ else if (actasmpattern='ROR') then
+ handlepara(SM_ROR)
+ else if (actasmpattern='RRX') then
+ handlepara(SM_ROR)
+ else
+ result:=false;
+ end
+ else
+ result:=false;
+ end;
+
+
+ Procedure tarmattreader.BuildOperand(oper : tarmoperand);
+ var
+ expr : string;
+ typesize,l : longint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : longint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+
+ var
+ tempreg : tregister;
+ ireg : tsuperregister;
+ hl : tasmlabel;
+ ofs : longint;
+ registerset : tcpuregisterset;
+ Begin
+ expr:='';
+ case actasmtoken of
+ AS_LBRACKET: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_HASH: { Constant expression }
+ Begin
+ Consume(AS_HASH);
+ BuildConstantOperand(oper);
+ end;
+
+ (*
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ begin
+ ofs:=oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val,ofs);
+ end
+ else
+ BuildReference(oper);
+ end;
+ *)
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if not(oper.SetupVar(expr,false)) then
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ { Register, a variable reference or a constant reference }
+ AS_REGISTER:
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end
+ else if (actasmtoken=AS_NOT) and (actopcode in [A_LDM,A_STM]) then
+ begin
+ consume(AS_NOT);
+ oper.opr.typ:=OPR_REFERENCE;
+ oper.opr.ref.addressmode:=AM_PREINDEXED;
+ oper.opr.ref.index:=tempreg;
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+
+ { Registerset }
+ AS_LSBRACKET:
+ begin
+ consume(AS_LSBRACKET);
+ registerset:=[];
+ while true do
+ begin
+ if actasmtoken=AS_REGISTER then
+ begin
+ include(registerset,getsupreg(actasmregister));
+ tempreg:=actasmregister;
+ consume(AS_REGISTER);
+ if actasmtoken=AS_MINUS then
+ begin
+ consume(AS_MINUS);
+ for ireg:=getsupreg(tempreg) to getsupreg(actasmregister) do
+ include(registerset,ireg);
+ consume(AS_REGISTER);
+ end;
+ end
+ else
+ consume(AS_REGISTER);
+ if actasmtoken=AS_COMMA then
+ consume(AS_COMMA)
+ else
+ break;
+ end;
+ consume(AS_RSBRACKET);
+ oper.opr.typ:=OPR_REGSET;
+ oper.opr.regset:=registerset;
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+{*****************************************************************************
+ tarmattreader
+*****************************************************************************}
+
+ procedure tarmattreader.BuildOpCode(instr : tarminstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ oppostfix:=actoppostfix;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if ((instr.opcode=A_MOV) and (operandnum=2)) or
+ ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL])) then
+ begin
+ Consume(AS_COMMA);
+ if not(TryBuildShifterOp(instr.Operands[4] as tarmoperand)) then
+ Message(asmr_e_illegal_shifterop_syntax);
+ Inc(operandnum);
+ end
+ else
+ begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tarmoperand);
+ end; { end case }
+ until false;
+ instr.Ops:=operandnum;
+ end;
+
+
+ function tarmattreader.is_asmopcode(const s: string):boolean;
+
+ const
+ { sorted by length so longer postfixes will match first }
+ postfix2strsorted : array[1..19] of string[2] = (
+ 'EP','SB','BT','SH',
+ 'IA','IB','DA','DB','FD','FA','ED','EA',
+ 'B','D','E','P','T','H','S');
+
+ postfixsorted : array[1..19] of TOpPostfix = (
+ PF_EP,PF_SB,PF_BT,PF_SH,
+ PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
+ PF_B,PF_D,PF_E,PF_P,PF_T,PF_H,PF_S);
+
+ var
+ str2opentry: tstr2opentry;
+ len,
+ j,
+ sufidx : longint;
+ hs : string;
+ maxlen : longint;
+ icond : tasmcond;
+ Begin
+ { making s a value parameter would break other assembler readers }
+ hs:=s;
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+
+ actcondition:=C_None;
+
+ { first, handle B else BLS is read wrong }
+ if ((hs[1]='B') and (length(hs)=3)) then
+ begin
+ for icond:=low(tasmcond) to high(tasmcond) do
+ begin
+ if copy(hs,2,3)=uppercond2str[icond] then
+ begin
+ actopcode:=A_B;
+ actasmtoken:=AS_OPCODE;
+ actcondition:=icond;
+ is_asmopcode:=true;
+ exit;
+ end;
+ end;
+ end;
+ maxlen:=max(length(hs),5);
+ for j:=maxlen downto 1 do
+ begin
+ str2opentry:=tstr2opentry(iasmops.search(copy(hs,1,j)));
+ if assigned(str2opentry) then
+ begin
+ actopcode:=str2opentry.op;
+ actasmtoken:=AS_OPCODE;
+ { strip op code }
+ delete(hs,1,j);
+ break;
+ end;
+ end;
+ if not(assigned(str2opentry)) then
+ exit;
+ { search for condition, conditions are always 2 chars }
+ if length(hs)>1 then
+ begin
+ for icond:=low(tasmcond) to high(tasmcond) do
+ begin
+ if copy(hs,1,2)=uppercond2str[icond] then
+ begin
+ actcondition:=icond;
+ { strip condition }
+ delete(hs,1,2);
+ break;
+ end;
+ end;
+ end;
+ { check for postfix }
+ if length(hs)>0 then
+ begin
+ for j:=low(postfixsorted) to high(postfixsorted) do
+ begin
+ if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+ begin
+ actoppostfix:=postfixsorted[j];
+ { strip postfix }
+ delete(hs,1,length(postfix2strsorted[j]));
+ break;
+ end;
+ end;
+ end;
+ { if we stripped all postfixes, it's a valid opcode }
+ is_asmopcode:=length(hs)=0;
+ end;
+
+
+ procedure tarmattreader.ConvertCalljmp(instr : tarminstruction);
+ var
+ newopr : toprrec;
+ begin
+ if instr.Operands[1].opr.typ=OPR_REFERENCE then
+ begin
+ newopr.typ:=OPR_SYMBOL;
+ newopr.symbol:=instr.Operands[1].opr.ref.symbol;
+ newopr.symofs:=instr.Operands[1].opr.ref.offset;
+ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+ (instr.Operands[1].opr.ref.index<>NR_NO) then
+ Message(asmr_e_syn_operand);
+ instr.Operands[1].opr:=newopr;
+ end;
+ end;
+
+
+ procedure tarmattreader.handleopcode;
+ var
+ instr : tarminstruction;
+ begin
+ instr:=TarmInstruction.Create(TarmOperand);
+ BuildOpcode(instr);
+ if is_calljmp(instr.opcode) then
+ ConvertCalljmp(instr);
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ actoppostfix:=PF_None;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_arm_att_info : tasmmodeinfo =
+ (
+ id : asmmode_arm_gas;
+ idtxt : 'GAS';
+ casmreader : tarmattreader;
+ );
+
+ asmmode_arm_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : tarmattreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_arm_att_info);
+ RegisterAsmMode(asmmode_arm_standard_info);
+end.
diff --git a/compiler/arm/rarmcon.inc b/compiler/arm/rarmcon.inc
new file mode 100644
index 0000000000..910b6297dc
--- /dev/null
+++ b/compiler/arm/rarmcon.inc
@@ -0,0 +1,74 @@
+{ don't edit, this file is generated from armreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_S0 = tregister($03000000);
+NR_S1 = tregister($03000000);
+NR_D0 = tregister($03000000);
+NR_S2 = tregister($03000000);
+NR_S3 = tregister($03000000);
+NR_D1 = tregister($03000000);
+NR_S4 = tregister($03000000);
+NR_S5 = tregister($03000000);
+NR_D2 = tregister($03000000);
+NR_S6 = tregister($03000000);
+NR_S7 = tregister($03000000);
+NR_D3 = tregister($03000000);
+NR_S8 = tregister($03000000);
+NR_S9 = tregister($03000000);
+NR_D4 = tregister($03000000);
+NR_S10 = tregister($03000000);
+NR_S11 = tregister($03000000);
+NR_D5 = tregister($03000000);
+NR_S12 = tregister($03000000);
+NR_S13 = tregister($03000000);
+NR_D6 = tregister($03000000);
+NR_S14 = tregister($03000000);
+NR_S15 = tregister($03000000);
+NR_D7 = tregister($03000000);
+NR_S16 = tregister($03000000);
+NR_S17 = tregister($03000000);
+NR_D8 = tregister($03000000);
+NR_S18 = tregister($03000000);
+NR_S19 = tregister($03000000);
+NR_D9 = tregister($03000000);
+NR_S20 = tregister($03000000);
+NR_S21 = tregister($03000000);
+NR_D10 = tregister($03000000);
+NR_S22 = tregister($03000000);
+NR_S23 = tregister($03000000);
+NR_D11 = tregister($03000000);
+NR_S24 = tregister($03000000);
+NR_S25 = tregister($03000000);
+NR_D12 = tregister($03000000);
+NR_S26 = tregister($03000000);
+NR_S27 = tregister($03000000);
+NR_D13 = tregister($03000000);
+NR_S28 = tregister($03000000);
+NR_S29 = tregister($03000000);
+NR_D14 = tregister($03000000);
+NR_S30 = tregister($03000000);
+NR_S31 = tregister($03000000);
+NR_D15 = tregister($03000000);
diff --git a/compiler/arm/rarmdwa.inc b/compiler/arm/rarmdwa.inc
new file mode 100644
index 0000000000..b963effed4
--- /dev/null
+++ b/compiler/arm/rarmdwa.inc
@@ -0,0 +1,74 @@
+{ don't edit, this file is generated from armreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
diff --git a/compiler/arm/rarmnor.inc b/compiler/arm/rarmnor.inc
new file mode 100644
index 0000000000..44c9e774d1
--- /dev/null
+++ b/compiler/arm/rarmnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from armreg.dat }
+73
diff --git a/compiler/arm/rarmnum.inc b/compiler/arm/rarmnum.inc
new file mode 100644
index 0000000000..78c00db232
--- /dev/null
+++ b/compiler/arm/rarmnum.inc
@@ -0,0 +1,74 @@
+{ don't edit, this file is generated from armreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000),
+tregister($03000000)
diff --git a/compiler/arm/rarmrni.inc b/compiler/arm/rarmrni.inc
new file mode 100644
index 0000000000..f1de634d81
--- /dev/null
+++ b/compiler/arm/rarmrni.inc
@@ -0,0 +1,74 @@
+{ don't edit, this file is generated from armreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72
diff --git a/compiler/arm/rarmsri.inc b/compiler/arm/rarmsri.inc
new file mode 100644
index 0000000000..8cbe04bfc1
--- /dev/null
+++ b/compiler/arm/rarmsri.inc
@@ -0,0 +1,74 @@
+{ don't edit, this file is generated from armreg.dat }
+0,
+27,
+30,
+57,
+60,
+63,
+66,
+69,
+72,
+33,
+36,
+39,
+42,
+45,
+48,
+51,
+54,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+25,
+26,
+40,
+41,
+43,
+44,
+46,
+47,
+49,
+50,
+52,
+53,
+28,
+55,
+70,
+71,
+56,
+58,
+59,
+61,
+62,
+64,
+65,
+67,
+68,
+29,
+31,
+32,
+34,
+35,
+37,
+38
diff --git a/compiler/arm/rarmsta.inc b/compiler/arm/rarmsta.inc
new file mode 100644
index 0000000000..f72724eb6a
--- /dev/null
+++ b/compiler/arm/rarmsta.inc
@@ -0,0 +1,74 @@
+{ don't edit, this file is generated from armreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
diff --git a/compiler/arm/rarmstd.inc b/compiler/arm/rarmstd.inc
new file mode 100644
index 0000000000..cf1936e398
--- /dev/null
+++ b/compiler/arm/rarmstd.inc
@@ -0,0 +1,74 @@
+{ don't edit, this file is generated from armreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'s0',
+'s1',
+'d0',
+'s2',
+'s3',
+'d1',
+'s4',
+'s5',
+'d2',
+'s6',
+'s7',
+'d3',
+'s8',
+'s9',
+'d4',
+'s10',
+'s11',
+'d5',
+'s12',
+'s13',
+'d6',
+'s14',
+'s15',
+'d7',
+'s16',
+'s17',
+'d8',
+'s18',
+'s19',
+'d9',
+'s20',
+'s21',
+'d10',
+'s22',
+'s23',
+'d11',
+'s24',
+'s25',
+'d12',
+'s26',
+'s27',
+'d13',
+'s28',
+'s29',
+'d14',
+'s20',
+'s21',
+'d15'
diff --git a/compiler/arm/rarmsup.inc b/compiler/arm/rarmsup.inc
new file mode 100644
index 0000000000..9a92340b41
--- /dev/null
+++ b/compiler/arm/rarmsup.inc
@@ -0,0 +1,74 @@
+{ don't edit, this file is generated from armreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_S0 = $00;
+RS_S1 = $00;
+RS_D0 = $00;
+RS_S2 = $00;
+RS_S3 = $00;
+RS_D1 = $00;
+RS_S4 = $00;
+RS_S5 = $00;
+RS_D2 = $00;
+RS_S6 = $00;
+RS_S7 = $00;
+RS_D3 = $00;
+RS_S8 = $00;
+RS_S9 = $00;
+RS_D4 = $00;
+RS_S10 = $00;
+RS_S11 = $00;
+RS_D5 = $00;
+RS_S12 = $00;
+RS_S13 = $00;
+RS_D6 = $00;
+RS_S14 = $00;
+RS_S15 = $00;
+RS_D7 = $00;
+RS_S16 = $00;
+RS_S17 = $00;
+RS_D8 = $00;
+RS_S18 = $00;
+RS_S19 = $00;
+RS_D9 = $00;
+RS_S20 = $00;
+RS_S21 = $00;
+RS_D10 = $00;
+RS_S22 = $00;
+RS_S23 = $00;
+RS_D11 = $00;
+RS_S24 = $00;
+RS_S25 = $00;
+RS_D12 = $00;
+RS_S26 = $00;
+RS_S27 = $00;
+RS_D13 = $00;
+RS_S28 = $00;
+RS_S29 = $00;
+RS_D14 = $00;
+RS_S30 = $00;
+RS_S31 = $00;
+RS_D15 = $00;
diff --git a/compiler/arm/rgcpu.pas b/compiler/arm/rgcpu.pas
new file mode 100644
index 0000000000..a522a4f38c
--- /dev/null
+++ b/compiler/arm/rgcpu.pas
@@ -0,0 +1,168 @@
+{
+ Copyright (c) 1998-2003 by Florian Klaempfl
+
+ This unit implements the arm specific class for the register
+ allocator
+
+ 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 rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmcpu,
+ cgbase,cgutils,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ procedure do_spill_read(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure do_spill_written(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ end;
+
+ trgintcpu = class(trgcpu)
+ procedure add_cpu_interferences(p : tai);override;
+ end;
+
+ implementation
+
+ uses
+ verbose, cutils,
+ cgobj,
+ procinfo;
+
+
+ procedure trgcpu.do_spill_read(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ helpins: tai;
+ tmpref : treference;
+ helplist : taasmoutput;
+ l : tasmlabel;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=taasmoutput.create;
+ reference_reset(tmpref);
+ { create consts entry }
+ objectlibrary.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
+
+ { load consts entry }
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,R_SUBWHOLE)
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
+
+ reference_reset_base(tmpref,hreg,0);
+
+ if spilltemp.index<>NR_NO then
+ internalerror(200401263);
+
+ helpins:=spilling_create_load(tmpref,tempreg);
+ helplist.concat(helpins);
+ if pos=nil then
+ list.insertlistafter(list.first,helplist)
+ else
+ list.insertlistafter(pos.next,helplist);
+
+ helplist.free;
+ end
+ else
+ inherited do_spill_read(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcpu.do_spill_written(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ helpins: tai;
+ tmpref : treference;
+ helplist : taasmoutput;
+ l : tasmlabel;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=taasmoutput.create;
+ reference_reset(tmpref);
+ { create consts entry }
+ objectlibrary.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
+
+ { load consts entry }
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,R_SUBWHOLE)
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
+
+ if spilltemp.index<>NR_NO then
+ internalerror(200401263);
+
+ reference_reset_base(tmpref,hreg,0);
+
+ helplist.concat(spilling_create_store(tempreg,tmpref));
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist)
+ end
+ else
+ inherited do_spill_written(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgintcpu.add_cpu_interferences(p : tai);
+ begin
+ if p.typ=ait_instruction then
+ begin
+ case taicpu(p).opcode of
+ A_MUL:
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
+ A_UMULL,
+ A_UMLAL,
+ A_SMULL,
+ A_SMLAL:
+ begin
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
+ add_edge(getsupreg(taicpu(p).oper[1]^.reg),getsupreg(taicpu(p).oper[2]^.reg));
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[2]^.reg));
+ end;
+ end;
+ end;
+ end;
+
+
+end.
diff --git a/compiler/assemble.pas b/compiler/assemble.pas
new file mode 100644
index 0000000000..92f47eca39
--- /dev/null
+++ b/compiler/assemble.pas
@@ -0,0 +1,1482 @@
+{
+ Copyright (c) 1998-2004 by Peter Vreman
+
+ This unit handles the assemblerfile write and assembler calls of FPC
+
+ 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.
+
+ ****************************************************************************
+}
+{# @abstract(This unit handles the assembler file write and assembler calls of FPC)
+ Handles the calls to the actual external assemblers, as well as the generation
+ of object files for smart linking. Also contains the base class for writing
+ the assembler statements to file.
+}
+unit assemble;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+ uses
+{$IFDEF USE_SYSUTILS}
+ sysutils,
+{$ELSE USE_SYSUTILS}
+ strings,
+ dos,
+{$ENDIF USE_SYSUTILS}
+ systems,globtype,globals,aasmbase,aasmtai,ogbase;
+
+ const
+ { maximum of aasmoutput lists there will be }
+ maxoutputlists = 20;
+ { buffer size for writing the .s file }
+ AsmOutSize=32768;
+
+ type
+ TAssembler=class(TAbstractAssembler)
+ public
+ {filenames}
+ path : pathstr;
+ name : namestr;
+ asmfile, { current .s and .o file }
+ objfile : string;
+ ppufilename : string;
+ asmprefix : string;
+ SmartAsm : boolean;
+ SmartFilesCount,
+ SmartHeaderCount : longint;
+ Constructor Create(smart:boolean);virtual;
+ Destructor Destroy;override;
+ procedure NextSmartName(place:tcutplace);
+ procedure MakeObject;virtual;abstract;
+ end;
+
+ {# This is the base class which should be overriden for each each
+ assembler writer. It is used to actually assembler a file,
+ and write the output to the assembler file.
+ }
+ TExternalAssembler=class(TAssembler)
+ private
+ procedure CreateSmartLinkPath(const s:string);
+ protected
+ {outfile}
+ AsmSize,
+ AsmStartSize,
+ outcnt : longint;
+ outbuf : array[0..AsmOutSize-1] of char;
+ outfile : file;
+ ioerror : boolean;
+ public
+ {# Returns the complete path and executable name of the assembler
+ program.
+
+ It first tries looking in the UTIL directory if specified,
+ otherwise it searches in the free pascal binary directory, in
+ the current working directory and then in the directories
+ in the $PATH environment.}
+ Function FindAssembler:string;
+
+ {# Actually does the call to the assembler file. Returns false
+ if the assembling of the file failed.}
+ Function CallAssembler(const command:string; const para:TCmdStr):Boolean;
+
+ Function DoAssemble:boolean;virtual;
+ Procedure RemoveAsm;
+ Procedure AsmFlush;
+ Procedure AsmClear;
+
+ {# Write a string to the assembler file }
+ Procedure AsmWrite(const s:string);
+
+ {# Write a string to the assembler file }
+ Procedure AsmWritePChar(p:pchar);
+
+ {# Write a string to the assembler file followed by a new line }
+ Procedure AsmWriteLn(const s:string);
+
+ {# Write a new line to the assembler file }
+ Procedure AsmLn;
+
+ procedure AsmCreate(Aplace:tcutplace);
+ procedure AsmClose;
+
+ {# This routine should be overriden for each assembler, it is used
+ to actually write the abstract assembler stream to file.}
+ procedure WriteTree(p:TAAsmoutput);virtual;
+
+ {# This routine should be overriden for each assembler, it is used
+ to actually write all the different abstract assembler streams
+ by calling for each stream type, the @var(WriteTree) method.}
+ procedure WriteAsmList;virtual;
+ public
+ Constructor Create(smart:boolean);override;
+ procedure MakeObject;override;
+ end;
+
+ TInternalAssembler=class(TAssembler)
+ public
+ constructor create(smart:boolean);override;
+ destructor destroy;override;
+ procedure MakeObject;override;
+ protected
+ objectdata : TAsmObjectData;
+ objectoutput : tobjectoutput;
+ private
+ { the aasmoutput lists that need to be processed }
+ lists : byte;
+ list : array[1..maxoutputlists] of TAAsmoutput;
+ { current processing }
+ currlistidx : byte;
+ currlist : TAAsmoutput;
+ currpass : byte;
+ procedure convertstab(p:pchar);
+ function MaybeNextList(var hp:Tai):boolean;
+ function TreePass0(hp:Tai):Tai;
+ function TreePass1(hp:Tai):Tai;
+ function TreePass2(hp:Tai):Tai;
+ procedure writetree;
+ procedure writetreesmart;
+ end;
+
+ TAssemblerClass = class of TAssembler;
+
+ Procedure GenerateAsm(smart:boolean);
+ Procedure OnlyAsm;
+
+ procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
+ procedure InitAssembler;
+ procedure DoneAssembler;
+
+
+Implementation
+
+ uses
+{$ifdef hasunix}
+ {$ifdef havelinuxrtl10}
+ linux,
+ {$else}
+ unix,
+ {$endif}
+{$endif}
+ cutils,script,fmodule,verbose,
+{$ifdef memdebug}
+ cclasses,
+{$endif memdebug}
+{$ifdef m68k}
+ cpuinfo,
+{$endif m68k}
+ aasmcpu
+ ;
+
+ var
+ CAssembler : array[tasm] of TAssemblerClass;
+
+
+{*****************************************************************************
+ TAssembler
+*****************************************************************************}
+
+ Constructor TAssembler.Create(smart:boolean);
+ begin
+ { load start values }
+ asmfile:=current_module.get_asmfilename;
+ objfile:=current_module.objfilename^;
+ name:=Lower(current_module.modulename^);
+ path:=current_module.outputpath^;
+ asmprefix := current_module.asmprefix^;
+ if not assigned(current_module.outputpath) then
+ ppufilename := ''
+ else
+ ppufilename := current_module.ppufilename^;
+ SmartAsm:=smart;
+ SmartFilesCount:=0;
+ SmartHeaderCount:=0;
+ SmartLinkOFiles.Clear;
+ end;
+
+
+ Destructor TAssembler.Destroy;
+ begin
+ end;
+
+
+ procedure TAssembler.NextSmartName(place:tcutplace);
+ var
+ s : string;
+ begin
+ inc(SmartFilesCount);
+ if SmartFilesCount>999999 then
+ Message(asmw_f_too_many_asm_files);
+ case place of
+ cut_begin :
+ begin
+ inc(SmartHeaderCount);
+ s:=asmprefix+tostr(SmartHeaderCount)+'h';
+ end;
+ cut_normal :
+ s:=asmprefix+tostr(SmartHeaderCount)+'s';
+ cut_end :
+ s:=asmprefix+tostr(SmartHeaderCount)+'t';
+ end;
+ AsmFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
+ ObjFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
+ { insert in container so it can be cleared after the linking }
+ SmartLinkOFiles.Insert(Objfile);
+ end;
+
+
+{*****************************************************************************
+ TExternalAssembler
+*****************************************************************************}
+
+ Function DoPipe:boolean;
+ begin
+ DoPipe:=(cs_asm_pipe in aktglobalswitches) and
+ not(cs_asm_leave in aktglobalswitches)
+ and ((target_asm.id in [as_gas,as_darwin]));
+ end;
+
+
+ Constructor TExternalAssembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ if SmartAsm then
+ begin
+ path:=FixPath(path+FixFileName(name)+target_info.smartext,false);
+ CreateSmartLinkPath(path);
+ end;
+ Outcnt:=0;
+ end;
+
+
+ procedure TExternalAssembler.CreateSmartLinkPath(const s:string);
+ var
+{$IFDEF USE_SYSUTILS}
+ dir : TSearchRec;
+{$ELSE USE_SYSUTILS}
+ dir : searchrec;
+{$ENDIF USE_SYSUTILS}
+ hs : string;
+ begin
+ if PathExists(s) then
+ begin
+ { the path exists, now we clean only all the .o and .s files }
+ { .o files }
+{$IFDEF USE_SYSUTILS}
+ if findfirst(s+source_info.dirsep+'*'+target_info.objext,faAnyFile,dir) = 0
+ then repeat
+ RemoveFile(s+source_info.dirsep+dir.name);
+ until findnext(dir) <> 0;
+{$ELSE USE_SYSUTILS}
+ findfirst(s+source_info.dirsep+'*'+target_info.objext,anyfile,dir);
+ while (doserror=0) do
+ begin
+ RemoveFile(s+source_info.dirsep+dir.name);
+ findnext(dir);
+ end;
+{$ENDIF USE_SYSUTILS}
+ findclose(dir);
+ { .s files }
+{$IFDEF USE_SYSUTILS}
+ if findfirst(s+source_info.dirsep+'*'+target_info.asmext,faAnyFile,dir) = 0
+ then repeat
+ RemoveFile(s+source_info.dirsep+dir.name);
+ until findnext(dir) <> 0;
+{$ELSE USE_SYSUTILS}
+ findfirst(s+source_info.dirsep+'*'+target_info.asmext,anyfile,dir);
+ while (doserror=0) do
+ begin
+ RemoveFile(s+source_info.dirsep+dir.name);
+ findnext(dir);
+ end;
+{$ENDIF USE_SYSUTILS}
+ findclose(dir);
+ end
+ else
+ begin
+ hs:=s;
+ if hs[length(hs)] in ['/','\'] then
+ delete(hs,length(hs),1);
+ {$I-}
+ mkdir(hs);
+ {$I+}
+ if ioresult<>0 then;
+ end;
+ end;
+
+
+ const
+ lastas : byte=255;
+ var
+ LastASBin : pathstr;
+ Function TExternalAssembler.FindAssembler:string;
+ var
+ asfound : boolean;
+ UtilExe : string;
+ begin
+ asfound:=false;
+ if cs_link_on_target in aktglobalswitches then
+ begin
+ { If linking on target, don't add any path PM }
+ FindAssembler:=utilsprefix+AddExtension(target_asm.asmbin,target_info.exeext);
+ exit;
+ end
+ else
+ UtilExe:=utilsprefix+AddExtension(target_asm.asmbin,source_info.exeext);
+ if lastas<>ord(target_asm.id) then
+ begin
+ lastas:=ord(target_asm.id);
+ { is an assembler passed ? }
+ if utilsdirectory<>'' then
+ asfound:=FindFile(UtilExe,utilsdirectory,LastASBin);
+ if not AsFound then
+ asfound:=FindExe(UtilExe,LastASBin);
+ if (not asfound) and not(cs_asm_extern in aktglobalswitches) then
+ begin
+ Message1(exec_e_assembler_not_found,LastASBin);
+ aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
+ end;
+ if asfound then
+ Message1(exec_t_using_assembler,LastASBin);
+ end;
+ FindAssembler:=LastASBin;
+ end;
+
+
+ Function TExternalAssembler.CallAssembler(const command:string; const para:TCmdStr):Boolean;
+{$IFDEF USE_SYSUTILS}
+ var
+ DosExitCode:Integer;
+{$ENDIF USE_SYSUTILS}
+ begin
+ callassembler:=true;
+ if not(cs_asm_extern in aktglobalswitches) then
+{$IFDEF USE_SYSUTILS}
+ try
+ DosExitCode := ExecuteProcess(command,para);
+ if DosExitCode <>0
+ then begin
+ Message1(exec_e_error_while_assembling,tostr(dosexitcode));
+ callassembler:=false;
+ end;
+ except on E:EOSError do
+ begin
+ Message1(exec_e_cant_call_assembler,tostr(E.ErrorCode));
+ aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
+ callassembler:=false;
+ end
+ end
+{$ELSE USE_SYSUTILS}
+ begin
+ swapvectors;
+ exec(maybequoted(command),para);
+ swapvectors;
+ if (doserror<>0) then
+ begin
+ Message1(exec_e_cant_call_assembler,tostr(doserror));
+ aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
+ callassembler:=false;
+ end
+ else
+ if (dosexitcode<>0) then
+ begin
+ Message1(exec_e_error_while_assembling,tostr(dosexitcode));
+ callassembler:=false;
+ end;
+ end
+{$ENDIF USE_SYSUTILS}
+ else
+ AsmRes.AddAsmCommand(command,para,name);
+ end;
+
+
+ procedure TExternalAssembler.RemoveAsm;
+ var
+ g : file;
+ begin
+ if cs_asm_leave in aktglobalswitches then
+ exit;
+ if cs_asm_extern in aktglobalswitches then
+ AsmRes.AddDeleteCommand(AsmFile)
+ else
+ begin
+ assign(g,AsmFile);
+ {$I-}
+ erase(g);
+ {$I+}
+ if ioresult<>0 then;
+ end;
+ end;
+
+
+ Function TExternalAssembler.DoAssemble:boolean;
+ var
+ s : TCmdStr;
+ begin
+ DoAssemble:=true;
+ if DoPipe then
+ exit;
+ if not(cs_asm_extern in aktglobalswitches) then
+ begin
+ if SmartAsm then
+ begin
+ if (SmartFilesCount<=1) then
+ Message1(exec_i_assembling_smart,name);
+ end
+ else
+ Message1(exec_i_assembling,name);
+ end;
+ s:=target_asm.asmcmd;
+{$ifdef m68k}
+ if aktoptprocessor = MC68020 then
+ s:='-m68020 '+s
+ else
+ s:='-m68000 '+s;
+{$endif}
+ if (cs_link_on_target in aktglobalswitches) then
+ begin
+ Replace(s,'$ASM',maybequoted(ScriptFixFileName(AsmFile)));
+ Replace(s,'$OBJ',maybequoted(ScriptFixFileName(ObjFile)));
+ end
+ else
+ begin
+ Replace(s,'$ASM',maybequoted(AsmFile));
+ Replace(s,'$OBJ',maybequoted(ObjFile));
+ end;
+ if CallAssembler(FindAssembler,s) then
+ RemoveAsm
+ else
+ begin
+ DoAssemble:=false;
+ GenerateError;
+ end;
+ end;
+
+
+ Procedure TExternalAssembler.AsmFlush;
+ begin
+ if outcnt>0 then
+ begin
+ { suppress i/o error }
+ {$i-}
+ BlockWrite(outfile,outbuf,outcnt);
+ {$i+}
+ ioerror:=ioerror or (ioresult<>0);
+ outcnt:=0;
+ end;
+ end;
+
+
+ Procedure TExternalAssembler.AsmClear;
+ begin
+ outcnt:=0;
+ end;
+
+
+ Procedure TExternalAssembler.AsmWrite(const s:string);
+ begin
+ if OutCnt+length(s)>=AsmOutSize then
+ AsmFlush;
+ Move(s[1],OutBuf[OutCnt],length(s));
+ inc(OutCnt,length(s));
+ inc(AsmSize,length(s));
+ end;
+
+
+ Procedure TExternalAssembler.AsmWriteLn(const s:string);
+ begin
+ AsmWrite(s);
+ AsmLn;
+ end;
+
+
+ Procedure TExternalAssembler.AsmWritePChar(p:pchar);
+ var
+ i,j : longint;
+ begin
+ i:=StrLen(p);
+ j:=i;
+ while j>0 do
+ begin
+ i:=min(j,AsmOutSize);
+ if OutCnt+i>=AsmOutSize then
+ AsmFlush;
+ Move(p[0],OutBuf[OutCnt],i);
+ inc(OutCnt,i);
+ inc(AsmSize,i);
+ dec(j,i);
+ p:=pchar(@p[i]);
+ end;
+ end;
+
+
+ Procedure TExternalAssembler.AsmLn;
+ begin
+ if OutCnt>=AsmOutSize-2 then
+ AsmFlush;
+ if (cs_link_on_target in aktglobalswitches) then
+ begin
+ OutBuf[OutCnt]:=target_info.newline[1];
+ inc(OutCnt);
+ inc(AsmSize);
+ if length(target_info.newline)>1 then
+ begin
+ OutBuf[OutCnt]:=target_info.newline[2];
+ inc(OutCnt);
+ inc(AsmSize);
+ end;
+ end
+ else
+ begin
+ OutBuf[OutCnt]:=source_info.newline[1];
+ inc(OutCnt);
+ inc(AsmSize);
+ if length(source_info.newline)>1 then
+ begin
+ OutBuf[OutCnt]:=source_info.newline[2];
+ inc(OutCnt);
+ inc(AsmSize);
+ end;
+ end;
+ end;
+
+
+ procedure TExternalAssembler.AsmCreate(Aplace:tcutplace);
+ begin
+ if SmartAsm then
+ NextSmartName(Aplace);
+{$ifdef hasunix}
+ if DoPipe then
+ begin
+ Message1(exec_i_assembling_pipe,asmfile);
+ POpen(outfile,'as -o '+objfile,'W');
+ end
+ else
+{$endif}
+ begin
+ Assign(outfile,asmfile);
+ {$I-}
+ Rewrite(outfile,1);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ ioerror:=true;
+ Message1(exec_d_cant_create_asmfile,asmfile);
+ end;
+ end;
+ outcnt:=0;
+ AsmSize:=0;
+ AsmStartSize:=0;
+ end;
+
+
+ procedure TExternalAssembler.AsmClose;
+ var
+ f : file;
+ FileAge : longint;
+ begin
+ AsmFlush;
+{$ifdef hasunix}
+ if DoPipe then
+ begin
+ if PClose(outfile) <> 0 then
+ GenerateError;
+ end
+ else
+{$endif}
+ begin
+ {Touch Assembler time to ppu time is there is a ppufilename}
+ if ppufilename<>'' then
+ begin
+ Assign(f,ppufilename);
+ {$I-}
+ reset(f,1);
+ {$I+}
+ if ioresult=0 then
+ begin
+{$IFDEF USE_SYSUTILS}
+ FileAge := FileGetDate(GetFileHandle(f));
+{$ELSE USE_SYSUTILS}
+ GetFTime(f, FileAge);
+{$ENDIF USE_SYSUTILS}
+ close(f);
+ reset(outfile,1);
+{$IFDEF USE_SYSUTILS}
+ FileSetDate(GetFileHandle(outFile),FileAge);
+{$ELSE USE_SYSUTILS}
+ SetFTime(f, FileAge);
+{$ENDIF USE_SYSUTILS}
+ end;
+ end;
+ close(outfile);
+ end;
+ end;
+
+
+ procedure TExternalAssembler.WriteTree(p:TAAsmoutput);
+ begin
+ end;
+
+
+ procedure TExternalAssembler.WriteAsmList;
+ begin
+ end;
+
+
+ procedure TExternalAssembler.MakeObject;
+ begin
+ AsmCreate(cut_normal);
+ WriteAsmList;
+ AsmClose;
+ if not(ioerror) then
+ DoAssemble;
+ end;
+
+
+{*****************************************************************************
+ TInternalAssembler
+*****************************************************************************}
+
+ constructor TInternalAssembler.create(smart:boolean);
+ begin
+ inherited create(smart);
+ objectoutput:=nil;
+ objectdata:=nil;
+ SmartAsm:=smart;
+ currpass:=0;
+ end;
+
+
+ destructor TInternalAssembler.destroy;
+{$ifdef MEMDEBUG}
+ var
+ d : tmemdebug;
+{$endif}
+ begin
+{$ifdef MEMDEBUG}
+ d := tmemdebug.create(name+' - agbin');
+{$endif}
+ objectdata.free;
+ objectoutput.free;
+{$ifdef MEMDEBUG}
+ d.free;
+{$endif}
+ end;
+
+
+ procedure TInternalAssembler.convertstab(p:pchar);
+
+ function consumecomma(var p:pchar):boolean;
+ begin
+ while (p^=' ') do
+ inc(p);
+ result:=(p^=',');
+ inc(p);
+ end;
+
+ function consumenumber(var p:pchar;out value:longint):boolean;
+ var
+ hs : string;
+ len,
+ code : integer;
+ begin
+ value:=0;
+ while (p^=' ') do
+ inc(p);
+ len:=0;
+ while (p^ in ['0'..'9']) do
+ begin
+ inc(len);
+ hs[len]:=p^;
+ inc(p);
+ end;
+ if len>0 then
+ begin
+ hs[0]:=chr(len);
+ val(hs,value,code);
+ end
+ else
+ code:=-1;
+ result:=(code=0);
+ end;
+
+ function consumeoffset(var p:pchar;out relocsym:tasmsymbol;out value:longint):boolean;
+ var
+ hs : string;
+ len,
+ code : integer;
+ pstart : pchar;
+ sym : tasmsymbol;
+ exprvalue : longint;
+ gotmin,
+ dosub : boolean;
+ begin
+ result:=false;
+ value:=0;
+ relocsym:=nil;
+ gotmin:=false;
+ repeat
+ dosub:=false;
+ exprvalue:=0;
+ if gotmin then
+ begin
+ dosub:=true;
+ gotmin:=false;
+ end;
+ while (p^=' ') do
+ inc(p);
+ case p^ of
+ #0 :
+ break;
+ ' ' :
+ inc(p);
+ '0'..'9' :
+ begin
+ len:=0;
+ while (p^ in ['0'..'9']) do
+ begin
+ inc(len);
+ hs[len]:=p^;
+ inc(p);
+ end;
+ hs[0]:=chr(len);
+ val(hs,exprvalue,code);
+ end;
+ '.','_',
+ 'A'..'Z',
+ 'a'..'z' :
+ begin
+ pstart:=p;
+ while not(p^ in [#0,' ','-','+']) do
+ inc(p);
+ len:=p-pstart;
+ if len>255 then
+ internalerror(200509187);
+ move(pstart^,hs[1],len);
+ hs[0]:=chr(len);
+ sym:=objectlibrary.newasmsymbol(hs,AB_EXTERNAL,AT_NONE);
+ if not assigned(sym) then
+ internalerror(200509188);
+ objectlibrary.UsedAsmSymbolListInsert(sym);
+ { Second symbol? }
+ if assigned(relocsym) then
+ begin
+ if (relocsym.section<>sym.section) then
+ internalerror(2005091810);
+ relocsym:=nil;
+ end
+ else
+ begin
+ relocsym:=sym;
+ end;
+ exprvalue:=sym.address;
+ end;
+ '+' :
+ begin
+ { nothing, by default addition is done }
+ inc(p);
+ end;
+ '-' :
+ begin
+ gotmin:=true;
+ inc(p);
+ end;
+ else
+ internalerror(200509189);
+ end;
+ if dosub then
+ dec(value,exprvalue)
+ else
+ inc(value,exprvalue);
+ until false;
+ result:=true;
+ end;
+
+ const
+ N_Function = $24; { function or const }
+ var
+ ofs,
+ nline,
+ nidx,
+ nother,
+ i : longint;
+ relocsym : tasmsymbol;
+ pstr,
+ pcurr,
+ pendquote : pchar;
+ begin
+ pcurr:=nil;
+ pstr:=nil;
+ pendquote:=nil;
+
+ { Parse string part }
+ if p[0]='"' then
+ begin
+ pstr:=@p[1];
+ { Ignore \" inside the string }
+ i:=1;
+ while not((p[i]='"') and (p[i-1]<>'\')) and
+ (p[i]<>#0) do
+ inc(i);
+ pendquote:=@p[i];
+ pendquote^:=#0;
+ pcurr:=@p[i+1];
+ if not consumecomma(pcurr) then
+ internalerror(200509181);
+ end
+ else
+ pcurr:=p;
+
+ { When in pass 1 then only alloc and leave }
+ if currpass=1 then
+ objectdata.allocstab(pstr)
+ else
+ begin
+ { Stabs format: nidx,nother,nline[,offset] }
+ if not consumenumber(pcurr,nidx) then
+ internalerror(200509182);
+ if not consumecomma(pcurr) then
+ internalerror(200509183);
+ if not consumenumber(pcurr,nother) then
+ internalerror(200509184);
+ if not consumecomma(pcurr) then
+ internalerror(200509185);
+ if not consumenumber(pcurr,nline) then
+ internalerror(200509186);
+ if consumecomma(pcurr) then
+ consumeoffset(pcurr,relocsym,ofs)
+ else
+ begin
+ ofs:=0;
+ relocsym:=nil;
+ end;
+ if (nidx=N_Function) and
+ target_info.use_function_relative_addresses then
+ ofs:=0;
+ objectdata.writestab(ofs,relocsym,nidx,nother,nline,pstr);
+ end;
+ if assigned(pendquote) then
+ pendquote^:='"';
+ end;
+
+
+ function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
+ begin
+ { maybe end of list }
+ while not assigned(hp) do
+ begin
+ if currlistidx<lists then
+ begin
+ inc(currlistidx);
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ end
+ else
+ begin
+ MaybeNextList:=false;
+ exit;
+ end;
+ end;
+ MaybeNextList:=true;
+ end;
+
+
+ function TInternalAssembler.TreePass0(hp:Tai):Tai;
+ var
+ l : longint;
+ begin
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_align :
+ begin
+ { always use the maximum fillsize in this pass to avoid possible
+ short jumps to become out of range }
+ Tai_align(hp).fillsize:=Tai_align(hp).aligntype;
+ objectdata.alloc(Tai_align(hp).fillsize);
+ end;
+ ait_datablock :
+ begin
+ l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
+ if SmartAsm or (not Tai_datablock(hp).is_global) then
+ begin
+ objectdata.allocalign(l);
+ objectdata.alloc(Tai_datablock(hp).size);
+ end;
+ end;
+ ait_real_80bit :
+ objectdata.alloc(10);
+ ait_real_64bit :
+ objectdata.alloc(8);
+ ait_real_32bit :
+ objectdata.alloc(4);
+ ait_comp_64bit :
+ objectdata.alloc(8);
+ ait_const_64bit,
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_const_indirect_symbol :
+ objectdata.alloc(tai_const(hp).size);
+ ait_section:
+ begin
+ objectdata.CreateSection(Tai_section(hp).sectype,Tai_section(hp).name^,Tai_section(hp).secalign,[]);
+ Tai_section(hp).sec:=objectdata.CurrSec;
+ end;
+ ait_symbol :
+ objectdata.allocsymbol(currpass,Tai_symbol(hp).sym,0);
+ ait_label :
+ objectdata.allocsymbol(currpass,Tai_label(hp).l,0);
+ ait_string :
+ objectdata.alloc(Tai_string(hp).len);
+ ait_instruction :
+ begin
+{$ifdef i386}
+{$ifndef NOAG386BIN}
+ { reset instructions which could change in pass 2 }
+ Taicpu(hp).resetpass2;
+ objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
+{$endif NOAG386BIN}
+{$endif i386}
+{$ifdef arm}
+ { reset instructions which could change in pass 2 }
+ Taicpu(hp).resetpass2;
+ objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
+{$endif arm}
+ end;
+ ait_cutobject :
+ if SmartAsm then
+ break;
+ end;
+ hp:=Tai(hp.next);
+ end;
+ TreePass0:=hp;
+ end;
+
+
+ function TInternalAssembler.TreePass1(hp:Tai):Tai;
+ var
+ InlineLevel,
+ l,
+ i : longint;
+ begin
+ inlinelevel:=0;
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_align :
+ begin
+ { here we must determine the fillsize which is used in pass2 }
+ Tai_align(hp).fillsize:=align(objectdata.currsec.datasize,Tai_align(hp).aligntype)-
+ objectdata.currsec.datasize;
+ objectdata.alloc(Tai_align(hp).fillsize);
+ end;
+ ait_datablock :
+ begin
+ if not (objectdata.currsec.sectype in [sec_bss,sec_threadvar]) then
+ Message(asmw_e_alloc_data_only_in_bss);
+ l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
+{ if Tai_datablock(hp).is_global and
+ not SmartAsm then
+ begin}
+{ objectdata.allocsymbol(currpass,Tai_datablock(hp).sym,Tai_datablock(hp).size);}
+ { force to be common/external, must be after setaddress as that would
+ set it to AB_GLOBAL }
+{ Tai_datablock(hp).sym.currbind:=AB_COMMON;
+ end
+ else
+ begin}
+ objectdata.allocalign(l);
+ objectdata.allocsymbol(currpass,Tai_datablock(hp).sym,Tai_datablock(hp).size);
+ objectdata.alloc(Tai_datablock(hp).size);
+{ end;}
+ objectlibrary.UsedAsmSymbolListInsert(Tai_datablock(hp).sym);
+ end;
+ ait_real_80bit :
+ objectdata.alloc(10);
+ ait_real_64bit :
+ objectdata.alloc(8);
+ ait_real_32bit :
+ objectdata.alloc(4);
+ ait_comp_64bit :
+ objectdata.alloc(8);
+ ait_const_64bit,
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_const_indirect_symbol :
+ begin
+ objectdata.alloc(tai_const(hp).size);
+ if assigned(Tai_const(hp).sym) then
+ objectlibrary.UsedAsmSymbolListInsert(Tai_const(hp).sym);
+ if assigned(Tai_const(hp).endsym) then
+ objectlibrary.UsedAsmSymbolListInsert(Tai_const(hp).endsym);
+ end;
+ ait_section:
+ begin
+ { use cached value }
+ objectdata.setsection(Tai_section(hp).sec);
+ end;
+ ait_stab :
+ begin
+ if assigned(Tai_stab(hp).str) then
+ convertstab(Tai_stab(hp).str);
+ end;
+ ait_function_name,
+ ait_force_line : ;
+ ait_symbol :
+ begin
+ objectdata.allocsymbol(currpass,Tai_symbol(hp).sym,0);
+ objectlibrary.UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
+ end;
+ ait_symbol_end :
+ begin
+ if target_info.system in [system_i386_linux,system_i386_beos] then
+ begin
+ Tai_symbol_end(hp).sym.size:=objectdata.currsec.datasize-Tai_symbol_end(hp).sym.address;
+ objectlibrary.UsedAsmSymbolListInsert(Tai_symbol_end(hp).sym);
+ end;
+ end;
+ ait_label :
+ begin
+ objectdata.allocsymbol(currpass,Tai_label(hp).l,0);
+ objectlibrary.UsedAsmSymbolListInsert(Tai_label(hp).l);
+ end;
+ ait_string :
+ objectdata.alloc(Tai_string(hp).len);
+ ait_instruction :
+ begin
+ objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
+ { fixup the references }
+ for i:=1 to Taicpu(hp).ops do
+ begin
+ with Taicpu(hp).oper[i-1]^ do
+ begin
+ case typ of
+ top_ref :
+ begin
+ if assigned(ref^.symbol) then
+ objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
+ if assigned(ref^.relsymbol) then
+ objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
+ end;
+ end;
+ end;
+ end;
+ end;
+ ait_cutobject :
+ if SmartAsm then
+ break;
+ ait_marker :
+ if tai_marker(hp).kind=InlineStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=InlineEnd then
+ dec(InlineLevel);
+ end;
+ hp:=Tai(hp.next);
+ end;
+ TreePass1:=hp;
+ end;
+
+
+ function TInternalAssembler.TreePass2(hp:Tai):Tai;
+ var
+ fillbuffer : tfillbuffer;
+ InlineLevel,
+ l : longint;
+ v : int64;
+{$ifdef x86}
+ co : comp;
+{$endif x86}
+ begin
+ inlinelevel:=0;
+ { main loop }
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_align :
+ begin
+ if objectdata.currsec.sectype in [sec_bss,sec_threadvar] then
+ objectdata.alloc(Tai_align(hp).fillsize)
+ else
+ objectdata.writebytes(Tai_align(hp).calculatefillbuf(fillbuffer)^,Tai_align(hp).fillsize);
+ end;
+ ait_section :
+ begin
+ { use cached value }
+ objectdata.setsection(Tai_section(hp).sec);
+ end;
+ ait_symbol :
+ begin
+ objectdata.writesymbol(Tai_symbol(hp).sym);
+ objectoutput.exportsymbol(Tai_symbol(hp).sym);
+ end;
+ ait_datablock :
+ begin
+ l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
+ objectdata.writesymbol(Tai_datablock(hp).sym);
+ objectoutput.exportsymbol(Tai_datablock(hp).sym);
+{ if SmartAsm or (not Tai_datablock(hp).is_global) then
+ begin}
+ objectdata.allocalign(l);
+ objectdata.alloc(Tai_datablock(hp).size);
+{ end;}
+ end;
+ ait_real_80bit :
+ objectdata.writebytes(Tai_real_80bit(hp).value,10);
+ ait_real_64bit :
+ objectdata.writebytes(Tai_real_64bit(hp).value,8);
+ ait_real_32bit :
+ objectdata.writebytes(Tai_real_32bit(hp).value,4);
+ ait_comp_64bit :
+ begin
+{$ifdef x86}
+ co:=comp(Tai_comp_64bit(hp).value);
+ objectdata.writebytes(co,8);
+{$endif x86}
+ end;
+ ait_string :
+ objectdata.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
+ ait_const_64bit,
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit :
+ begin
+ if assigned(tai_const(hp).sym) then
+ begin
+ if assigned(tai_const(hp).endsym) then
+ begin
+ if tai_const(hp).endsym.section<>tai_const(hp).sym.section then
+ internalerror(200404124);
+ v:=tai_const(hp).endsym.address-tai_const(hp).sym.address+Tai_const(hp).value;
+ objectdata.writebytes(v,tai_const(hp).size);
+ end
+ else
+ objectdata.writereloc(Tai_const(hp).value,Tai_const(hp).size,
+ Tai_const(hp).sym,RELOC_ABSOLUTE);
+ end
+ else
+ objectdata.writebytes(Tai_const(hp).value,tai_const(hp).size);
+ end;
+ ait_const_rva_symbol :
+ objectdata.writereloc(Tai_const(hp).value,sizeof(aint),Tai_const(hp).sym,RELOC_RVA);
+ ait_label :
+ begin
+ objectdata.writesymbol(Tai_label(hp).l);
+ { exporting shouldn't be necessary as labels are local,
+ but it's better to be on the safe side (PFV) }
+ objectoutput.exportsymbol(Tai_label(hp).l);
+ end;
+ ait_instruction :
+ Taicpu(hp).Pass2(objectdata);
+ ait_stab :
+ convertstab(Tai_stab(hp).str);
+ ait_function_name,
+ ait_force_line : ;
+ ait_cutobject :
+ if SmartAsm then
+ break;
+ ait_marker :
+ if tai_marker(hp).kind=InlineStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=InlineEnd then
+ dec(InlineLevel);
+ end;
+ hp:=Tai(hp.next);
+ end;
+ TreePass2:=hp;
+ end;
+
+
+ procedure TInternalAssembler.writetree;
+ var
+ hp : Tai;
+ label
+ doexit;
+ begin
+ objectdata:=objectoutput.newobjectdata(Objfile);
+ { reset the asmsymbol list }
+ objectlibrary.CreateUsedAsmsymbolList;
+
+ { Pass 0 }
+ currpass:=0;
+ objectdata.createsection(sec_code,'',0,[]);
+ objectdata.beforealloc;
+ { start with list 1 }
+ currlistidx:=1;
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ while assigned(hp) do
+ begin
+ hp:=TreePass0(hp);
+ MaybeNextList(hp);
+ end;
+ objectdata.afteralloc;
+ { leave if errors have occured }
+ if errorcount>0 then
+ goto doexit;
+
+ { Pass 1 }
+ currpass:=1;
+ objectdata.resetsections;
+ objectdata.beforealloc;
+ objectdata.createsection(sec_code,'',0,[]);
+ { start with list 1 }
+ currlistidx:=1;
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ while assigned(hp) do
+ begin
+ hp:=TreePass1(hp);
+ MaybeNextList(hp);
+ end;
+ objectdata.createsection(sec_code,'',0,[]);
+ objectdata.afteralloc;
+ { check for undefined labels and reset }
+ objectlibrary.UsedAsmSymbolListCheckUndefined;
+
+ { leave if errors have occured }
+ if errorcount>0 then
+ goto doexit;
+
+ { Pass 2 }
+ currpass:=2;
+ objectdata.resetsections;
+ objectdata.beforewrite;
+ objectdata.createsection(sec_code,'',0,[]);
+ { start with list 1 }
+ currlistidx:=1;
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ while assigned(hp) do
+ begin
+ hp:=TreePass2(hp);
+ MaybeNextList(hp);
+ end;
+ objectdata.createsection(sec_code,'',0,[]);
+ objectdata.afterwrite;
+
+ { don't write the .o file if errors have occured }
+ if errorcount=0 then
+ begin
+ { write objectfile }
+ objectoutput.startobjectfile(ObjFile);
+ objectoutput.writeobjectfile(objectdata);
+ objectdata.free;
+ objectdata:=nil;
+ end;
+
+ doexit:
+ { reset the used symbols back, must be after the .o has been
+ written }
+ objectlibrary.UsedAsmsymbolListReset;
+ objectlibrary.DestroyUsedAsmsymbolList;
+ end;
+
+
+ procedure TInternalAssembler.writetreesmart;
+ var
+ hp : Tai;
+ startsectype : TAsmSectionType;
+ place: tcutplace;
+ begin
+ NextSmartName(cut_normal);
+ objectdata:=objectoutput.newobjectdata(Objfile);
+ startsectype:=sec_code;
+
+ { start with list 1 }
+ currlistidx:=1;
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ while assigned(hp) do
+ begin
+ { reset the asmsymbol list }
+ objectlibrary.CreateUsedAsmSymbolList;
+
+ { Pass 0 }
+ currpass:=0;
+ objectdata.resetsections;
+ objectdata.beforealloc;
+ objectdata.createsection(startsectype,'',0,[]);
+ TreePass0(hp);
+ objectdata.afteralloc;
+ { leave if errors have occured }
+ if errorcount>0 then
+ exit;
+
+ { Pass 1 }
+ currpass:=1;
+ objectdata.resetsections;
+ objectdata.beforealloc;
+ objectdata.createsection(startsectype,'',0,[]);
+ TreePass1(hp);
+ objectdata.afteralloc;
+ { check for undefined labels }
+ objectlibrary.UsedAsmSymbolListCheckUndefined;
+
+ { leave if errors have occured }
+ if errorcount>0 then
+ exit;
+
+ { Pass 2 }
+ currpass:=2;
+ objectoutput.startobjectfile(Objfile);
+ objectdata.resetsections;
+ objectdata.beforewrite;
+ objectdata.createsection(startsectype,'',0,[]);
+ hp:=TreePass2(hp);
+ { save section type for next loop, must be done before EndFileLineInfo
+ because that changes the section to sec_code }
+ startsectype:=objectdata.currsec.sectype;
+ objectdata.afterwrite;
+ { leave if errors have occured }
+ if errorcount>0 then
+ exit;
+
+ { write the current objectfile }
+ objectoutput.writeobjectfile(objectdata);
+ objectdata.free;
+ objectdata:=nil;
+
+ { reset the used symbols back, must be after the .o has been
+ written }
+ objectlibrary.UsedAsmsymbolListReset;
+ objectlibrary.DestroyUsedAsmsymbolList;
+
+ { end of lists? }
+ if not MaybeNextList(hp) then
+ break;
+
+ { we will start a new objectfile so reset everything }
+ { The place can still change in the next while loop, so don't init }
+ { the writer yet (JM) }
+ if (hp.typ=ait_cutobject) then
+ place := Tai_cutobject(hp).place
+ else
+ place := cut_normal;
+
+ { avoid empty files }
+ while assigned(hp) and
+ (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cutobject]) do
+ begin
+ if Tai(hp).typ=ait_section then
+ startsectype:=Tai_section(hp).sectype
+ else if (Tai(hp).typ=ait_cutobject) then
+ place:=Tai_cutobject(hp).place;
+ hp:=Tai(hp.next);
+ end;
+ { there is a problem if startsectype is sec_none !! PM }
+ if startsectype=sec_none then
+ startsectype:=sec_code;
+
+ if not MaybeNextList(hp) then
+ break;
+
+ { start next objectfile }
+ NextSmartName(place);
+ objectdata:=objectoutput.newobjectdata(Objfile);
+ end;
+ end;
+
+
+ procedure TInternalAssembler.MakeObject;
+
+ var to_do:set of Tasmlist;
+ i:Tasmlist;
+
+ procedure addlist(p:TAAsmoutput);
+ begin
+ inc(lists);
+ list[lists]:=p;
+ end;
+
+ begin
+ to_do:=[low(Tasmlist)..high(Tasmlist)];
+ if usedeffileforexports then
+ exclude(to_do,al_exports);
+ {$warning TODO internal writer support for dwarf}
+ exclude(to_do,al_dwarf);
+{$ifndef segment_threadvars}
+ exclude(to_do,al_threadvars);
+{$endif}
+ for i:=low(Tasmlist) to high(Tasmlist) do
+ if (i in to_do) and (asmlist[i]<>nil) then
+ addlist(asmlist[i]);
+
+ if SmartAsm then
+ writetreesmart
+ else
+ writetree;
+ end;
+
+
+{*****************************************************************************
+ Generate Assembler Files Main Procedure
+*****************************************************************************}
+
+ Procedure GenerateAsm(smart:boolean);
+ var
+ a : TAssembler;
+ begin
+ if not assigned(CAssembler[target_asm.id]) then
+ Message(asmw_f_assembler_output_not_supported);
+ a:=CAssembler[target_asm.id].Create(smart);
+ a.MakeObject;
+ a.Free;
+ end;
+
+
+ Procedure OnlyAsm;
+ var
+ a : TExternalAssembler;
+ begin
+ a:=TExternalAssembler.Create(false);
+ a.DoAssemble;
+ a.Free;
+ end;
+
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
+ var
+ t : tasm;
+ begin
+ t:=r.id;
+ if assigned(asminfos[t]) then
+ writeln('Warning: Assembler is already registered!')
+ else
+ Getmem(asminfos[t],sizeof(tasminfo));
+ asminfos[t]^:=r;
+ CAssembler[t]:=c;
+ end;
+
+
+ procedure InitAssembler;
+ begin
+ end;
+
+
+ procedure DoneAssembler;
+ begin
+ end;
+
+end.
diff --git a/compiler/browcol.pas b/compiler/browcol.pas
new file mode 100644
index 0000000000..298920d987
--- /dev/null
+++ b/compiler/browcol.pas
@@ -0,0 +1,2143 @@
+{
+ Copyright (c) 1998-2002 by Berczi Gabor
+ Modifications Copyright (c) 1999-2002 Florian Klaempfl and Pierre Muller
+
+ Support routines for getting browser info in collections
+
+ 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.
+
+ ****************************************************************************
+}
+{$ifdef TP}
+ {$N+,E+}
+{$endif}
+unit browcol;
+interface
+uses
+ objects,
+ cclasses,
+ symconst,symtable;
+
+{$ifndef FPC}
+ type
+ sw_integer = integer;
+{$endif FPC}
+
+const
+ SymbolTypLen : integer = 6;
+
+ RecordTypes : set of tsymtyp =
+ ([typesym,unitsym]);
+
+ sfRecord = $00000001;
+ sfObject = $00000002;
+ sfClass = $00000004;
+ sfPointer = $00000008;
+ sfHasMemInfo = $80000000;
+
+type
+ TStoreCollection = object(TStringCollection)
+ function Add(const S: string): PString;
+ end;
+
+ PModuleNameCollection = ^TModuleNameCollection;
+ TModuleNameCollection = object(TStoreCollection)
+ end;
+
+ PTypeNameCollection = ^TTypeNameCollection;
+ TTypeNameCollection = object(TStoreCollection)
+ end;
+
+ PSymbolCollection = ^TSymbolCollection;
+ PSortedSymbolCollection = ^TSortedSymbolCollection;
+ PReferenceCollection = ^TReferenceCollection;
+
+ PReference = ^TReference;
+ TReference = object(TObject)
+ FileName : PString;
+ Position : TPoint;
+ constructor Init(AFileName: PString; ALine, AColumn: Sw_integer);
+ function GetFileName: string;
+ destructor Done; virtual;
+ constructor Load(var S: TStream);
+ procedure Store(var S: TStream);
+ end;
+
+ PSymbolMemInfo = ^TSymbolMemInfo;
+ TSymbolMemInfo = record
+ Addr : longint;
+ Size : longint;
+ PushSize : longint;
+ end;
+
+ PSymbol = ^TSymbol;
+ TSymbol = object(TObject)
+ Name : PString;
+ Typ : tsymtyp;
+ Params : PString;
+ References : PReferenceCollection;
+ Items : PSymbolCollection;
+ DType : PString;
+ VType : PString;
+ TypeID : Ptrint;
+ RelatedTypeID : Ptrint;
+ DebuggerCount : longint;
+ Ancestor : PSymbol;
+ Flags : longint;
+ MemInfo : PSymbolMemInfo;
+ constructor Init(const AName: string; ATyp: tsymtyp; AParams: string; AMemInfo: PSymbolMemInfo);
+ procedure SetMemInfo(const AMemInfo: TSymbolMemInfo);
+ function GetReferenceCount: Sw_integer;
+ function GetReference(Index: Sw_integer): PReference;
+ function GetItemCount: Sw_integer;
+ function GetItem(Index: Sw_integer): PSymbol;
+ function GetName: string;
+ function GetText: string;
+ function GetTypeName: string;
+ destructor Done; virtual;
+ constructor Load(var S: TStream);
+ procedure Store(var S: TStream);
+ end;
+
+ PExport = ^TExport;
+ TExport = object(TObject)
+ constructor Init(const AName: string; AIndex: longint; ASymbol: PSymbol);
+ function GetDisplayText: string;
+ destructor Done; virtual;
+ private
+ Name: PString;
+ Index: longint;
+ Symbol: PSymbol;
+ end;
+
+ PExportCollection = ^TExportCollection;
+ TExportCollection = object(TSortedCollection)
+ function At(Index: sw_Integer): PExport;
+ function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
+ end;
+
+ PImport = ^TImport;
+ TImport = object(TObject)
+ constructor Init(const ALibName, AFuncName,ARealName: string; AIndex: longint);
+ function GetDisplayText: string;
+ destructor Done; virtual;
+ private
+ LibName: PString;
+ FuncName: PString;
+ RealName: PString;
+ Index: longint;
+ end;
+
+ PImportCollection = ^TImportCollection;
+ TImportCollection = object(TSortedCollection)
+ function At(Index: sw_Integer): PImport;
+ function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
+ end;
+
+ PObjectSymbolCollection = ^TObjectSymbolCollection;
+
+ PObjectSymbol = ^TObjectSymbol;
+ TObjectSymbol = object(TObject)
+ Parent : PObjectSymbol;
+ Symbol : PSymbol;
+ Expanded : boolean;
+ constructor Init(AParent: PObjectSymbol; ASymbol: PSymbol);
+ constructor InitName(const AName: string);
+ function GetName: string;
+ function GetDescendantCount: sw_integer;
+ function GetDescendant(Index: sw_integer): PObjectSymbol;
+ procedure AddDescendant(P: PObjectSymbol);
+ destructor Done; virtual;
+ constructor Load(var S: TStream);
+ procedure Store(S: TStream);
+ private
+ Name: PString;
+ Descendants: PObjectSymbolCollection;
+ end;
+
+ TSymbolCollection = object(TSortedCollection)
+ constructor Init(ALimit, ADelta: Integer);
+ function At(Index: Sw_Integer): PSymbol;
+ procedure Insert(Item: Pointer); virtual;
+ function LookUp(const S: string; var Idx: sw_integer): string; virtual;
+ end;
+
+ TSortedSymbolCollection = object(TSymbolCollection)
+ function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
+ procedure Insert(Item: Pointer); virtual;
+ function LookUp(const S: string; var Idx: sw_integer): string; virtual;
+ end;
+
+ PIDSortedSymbolCollection = ^TIDSortedSymbolCollection;
+ TIDSortedSymbolCollection = object(TSymbolCollection)
+ function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
+ procedure Insert(Item: Pointer); virtual;
+ function SearchSymbolByID(AID: longint): PSymbol;
+ end;
+
+ TObjectSymbolCollection = object(TSortedCollection)
+ constructor Init(ALimit, ADelta: Integer);
+ function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
+ function LookUp(const S: string; var Idx: sw_integer): string; virtual;
+ function At(Index: Sw_Integer): PObjectSymbol;
+ end;
+
+ TReferenceCollection = object(TCollection)
+ function At(Index: Sw_Integer): PReference;
+ end;
+
+ PSourceFile = ^TSourceFile;
+ TSourceFile = object(TObject)
+ SourceFileName: PString;
+ ObjFileName: PString;
+ PPUFileName: PString;
+ constructor Init(ASourceFileName, AObjFileName, APPUFileName: string);
+ destructor Done; virtual;
+ function GetSourceFilename: string;
+ function GetObjFileName: string;
+ function GetPPUFileName: string;
+ end;
+
+ PSourceFileCollection = ^TSourceFileCollection;
+ TSourceFileCollection = object(TCollection)
+ function At(Index: sw_Integer): PSourceFile;
+ end;
+
+ PModuleSymbol = ^TModuleSymbol;
+ TModuleSymbol = object(TSymbol)
+ Exports_ : PExportCollection;
+ Imports : PImportCollection;
+ LoadedFrom : PString;
+ UsedUnits : PSymbolCollection;
+ DependentUnits: PSymbolCollection;
+ MainSource: PString;
+ SourceFiles: PStringCollection;
+ constructor Init(const AName, AMainSource: string);
+ procedure SetLoadedFrom(const AModuleName: string);
+ procedure AddUsedUnit(P: PSymbol);
+ procedure AddDependentUnit(P: PSymbol);
+ procedure AddSourceFile(const Path: string);
+ destructor Done; virtual;
+ end;
+
+const
+ Modules : PSymbolCollection = nil;
+ ModuleNames : PModuleNameCollection = nil;
+ TypeNames : PTypeNameCollection = nil;
+ ObjectTree : PObjectSymbol = nil;
+ SourceFiles : PSourceFileCollection = nil;
+
+procedure DisposeBrowserCol;
+procedure NewBrowserCol;
+procedure CreateBrowserCol;
+procedure InitBrowserCol;
+procedure DoneBrowserCol;
+
+function LoadBrowserCol(S: PStream): boolean;
+function StoreBrowserCol(S: PStream) : boolean;
+
+procedure BuildObjectInfo;
+
+procedure BuildSourceList;
+
+function SearchObjectForSymbol(O: PSymbol): PObjectSymbol;
+
+procedure RegisterSymbols;
+
+implementation
+
+uses
+{$IFDEF USE_SYSUTILS}
+ SysUtils,
+{$ELSE USE_SYSUTILS}
+ Dos,{$ifndef FPC}strings,{$endif}
+{$ENDIF USE_SYSUTILS}
+{$ifdef DEBUG}
+ verbose,
+{$endif DEBUG}
+ CUtils,
+ globtype,globals,comphook,
+ finput,fmodule,
+ cpuinfo,cgbase,aasmbase,aasmtai,paramgr,
+ symsym,symdef,symtype,symbase,defutil;
+
+const
+ RModuleNameCollection: TStreamRec = (
+ ObjType: 3001;
+ VmtLink: Ofs(TypeOf(TModuleNameCollection)^);
+ Load: @TModuleNameCollection.Load;
+ Store: @TModuleNameCollection.Store
+ );
+ RTypeNameCollection: TStreamRec = (
+ ObjType: 3002;
+ VmtLink: Ofs(TypeOf(TTypeNameCollection)^);
+ Load: @TTypeNameCollection.Load;
+ Store: @TTypeNameCollection.Store
+ );
+ RReference: TStreamRec = (
+ ObjType: 3003;
+ VmtLink: Ofs(TypeOf(TReference)^);
+ Load: @TReference.Load;
+ Store: @TReference.Store
+ );
+ RSymbol: TStreamRec = (
+ ObjType: 3004;
+ VmtLink: Ofs(TypeOf(TSymbol)^);
+ Load: @TSymbol.Load;
+ Store: @TSymbol.Store
+ );
+ RObjectSymbol: TStreamRec = (
+ ObjType: 3005;
+ VmtLink: Ofs(TypeOf(TObjectSymbol)^);
+ Load: @TObjectSymbol.Load;
+ Store: @TObjectSymbol.Store
+ );
+ RSymbolCollection: TStreamRec = (
+ ObjType: 3006;
+ VmtLink: Ofs(TypeOf(TSymbolCollection)^);
+ Load: @TSymbolCollection.Load;
+ Store: @TSymbolCollection.Store
+ );
+ RSortedSymbolCollection: TStreamRec = (
+ ObjType: 3007;
+ VmtLink: Ofs(TypeOf(TSortedSymbolCollection)^);
+ Load: @TSortedSymbolCollection.Load;
+ Store: @TSortedSymbolCollection.Store
+ );
+ RIDSortedSymbolCollection: TStreamRec = (
+ ObjType: 3008;
+ VmtLink: Ofs(TypeOf(TIDSortedSymbolCollection)^);
+ Load: @TIDSortedSymbolCollection.Load;
+ Store: @TIDSortedSymbolCollection.Store
+ );
+ RObjectSymbolCollection: TStreamRec = (
+ ObjType: 3009;
+ VmtLink: Ofs(TypeOf(TObjectSymbolCollection)^);
+ Load: @TObjectSymbolCollection.Load;
+ Store: @TObjectSymbolCollection.Store
+ );
+ RReferenceCollection: TStreamRec = (
+ ObjType: 3010;
+ VmtLink: Ofs(TypeOf(TReferenceCollection)^);
+ Load: @TReferenceCollection.Load;
+ Store: @TReferenceCollection.Store
+ );
+ RModuleSymbol: TStreamRec = (
+ ObjType: 3011;
+ VmtLink: Ofs(TypeOf(TModuleSymbol)^);
+ Load: @TModuleSymbol.Load;
+ Store: @TModuleSymbol.Store
+ );
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+function GetStr(P: PString): string;
+begin
+ if P=nil then
+ GetStr:=''
+ else
+ GetStr:=P^;
+end;
+
+function IntToStr(L: longint): string;
+var S: string;
+begin
+ Str(L,S);
+ IntToStr:=S;
+end;
+
+function UpcaseStr(S: string): string;
+var I: integer;
+begin
+ for I:=1 to length(S) do
+ S[I]:=Upcase(S[I]);
+ UpcaseStr:=S;
+end;
+
+function FloatToStr(E: extended): string;
+var S: string;
+begin
+ Str(E:0:24,S);
+ if Pos('.',S)>0 then
+ begin
+ while (length(S)>0) and (S[length(S)]='0') do
+ Delete(S,length(S),1);
+ if (length(S)>0) and (S[length(S)]='.') then
+ Delete(S,length(S),1);
+ end;
+ if S='' then S:='0';
+ FloatToStr:=S;
+end;
+
+{****************************************************************************
+ TStoreCollection
+****************************************************************************}
+
+function TStoreCollection.Add(const S: string): PString;
+var P: PString;
+ Index: Sw_integer;
+begin
+ if S='' then P:=nil else
+ if Search(@S,Index) then P:=At(Index) else
+ begin
+ P:=NewStr(S);
+ Insert(P);
+ end;
+ Add:=P;
+end;
+
+
+{****************************************************************************
+ TSymbolCollection
+****************************************************************************}
+
+constructor TSymbolCollection.Init(ALimit, ADelta: Integer);
+begin
+ inherited Init(ALimit,ADelta);
+{ Duplicates:=true;}
+end;
+
+function TSymbolCollection.At(Index: Sw_Integer): PSymbol;
+begin
+ At:=inherited At(Index);
+end;
+
+procedure TSymbolCollection.Insert(Item: Pointer);
+begin
+
+ TCollection.Insert(Item);
+end;
+
+function TSymbolCollection.LookUp(const S: string; var Idx: sw_integer): string;
+begin
+ Idx:=-1;
+ LookUp:='';
+end;
+
+{****************************************************************************
+ TReferenceCollection
+****************************************************************************}
+
+function TReferenceCollection.At(Index: Sw_Integer): PReference;
+begin
+ At:=inherited At(Index);
+end;
+
+
+{****************************************************************************
+ TSortedSymbolCollection
+****************************************************************************}
+
+function TSortedSymbolCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
+var K1: PSymbol absolute Key1;
+ K2: PSymbol absolute Key2;
+ R: Sw_integer;
+ S1,S2: string;
+begin
+ S1:=Upper(K1^.GetName);
+ S2:=Upper(K2^.GetName);
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:=1 else
+ if K1^.TypeID=K2^.TypeID then R:=0 else
+ begin
+ S1:=K1^.GetName;
+ S2:=K2^.GetName;
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:=1 else
+ if K1^.TypeID<K2^.TypeID then R:=-1 else
+ if K1^.TypeID>K2^.TypeID then R:= 1 else
+ R:=0;
+ end;
+ Compare:=R;
+end;
+
+procedure TSortedSymbolCollection.Insert(Item: Pointer);
+begin
+ TSortedCollection.Insert(Item);
+end;
+
+function TSortedSymbolCollection.LookUp(const S: string; var Idx: sw_integer): string;
+var OLI,ORI,Left,Right,Mid: integer;
+ LeftP,RightP,MidP: PSymbol;
+ LeftS,MidS,RightS: string;
+ FoundS: string;
+ UpS : string;
+begin
+ Idx:=-1; FoundS:='';
+ Left:=0; Right:=Count-1;
+ UpS:=Upper(S);
+ if Left<Right then
+ begin
+ while (Left<Right) do
+ begin
+ OLI:=Left; ORI:=Right;
+ Mid:=Left+(Right-Left) div 2;
+ MidP:=At(Mid);
+{$ifdef DEBUG}
+ LeftP:=At(Left); RightP:=At(Right);
+ LeftS:=Upper(LeftP^.GetName);
+ RightS:=Upper(RightP^.GetName);
+{$endif DEBUG}
+ MidS:=Upper(MidP^.GetName);
+ if copy(MidS,1,length(UpS))=UpS then
+ begin
+ Idx:=Mid;
+ FoundS:=MidS;
+ end;
+{ else}
+ if UpS<MidS then
+ Right:=Mid
+ else
+ Left:=Mid;
+ if (OLI=Left) and (ORI=Right) then
+ begin
+ if idX<>-1 then
+ break;
+ if Mid=Left then
+ begin
+ RightP:=At(Right);
+ RightS:=Upper(RightP^.GetName);
+ if copy(RightS,1,length(UpS))=UpS then
+ begin
+ Idx:=Right;
+ FoundS:=RightS;
+ end;
+ end;
+ if Mid=Right then
+ begin
+ LeftP:=At(Left);
+ LeftS:=Upper(LeftP^.GetName);
+ if copy(LeftS,1,length(UpS))=UpS then
+ begin
+ Idx:=Left;
+ FoundS:=LeftS;
+ end;
+ end;
+ Break;
+ end;
+ end;
+ end;
+ LookUp:=FoundS;
+end;
+
+{****************************************************************************
+ TIDSortedSymbolCollection
+****************************************************************************}
+
+function TIDSortedSymbolCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
+var K1: PSymbol absolute Key1;
+ K2: PSymbol absolute Key2;
+ R: Sw_integer;
+begin
+ if K1^.TypeID<K2^.TypeID then R:=-1 else
+ if K1^.TypeID>K2^.TypeID then R:= 1 else
+ R:=0;
+ Compare:=R;
+end;
+
+procedure TIDSortedSymbolCollection.Insert(Item: Pointer);
+begin
+ TSortedCollection.Insert(Item);
+end;
+
+function TIDSortedSymbolCollection.SearchSymbolByID(AID: longint): PSymbol;
+var S: TSymbol;
+ Index: sw_integer;
+ P: PSymbol;
+begin
+ S.TypeID:=AID;
+ if Search(@S,Index)=false then P:=nil else
+ P:=At(Index);
+ SearchSymbolByID:=P;
+end;
+
+{****************************************************************************
+ TObjectSymbolCollection
+****************************************************************************}
+
+function TObjectSymbolCollection.At(Index: Sw_Integer): PObjectSymbol;
+begin
+ At:=inherited At(Index);
+end;
+
+constructor TObjectSymbolCollection.Init(ALimit, ADelta: Integer);
+begin
+ inherited Init(ALimit,ADelta);
+end;
+
+function TObjectSymbolCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
+var K1: PObjectSymbol absolute Key1;
+ K2: PObjectSymbol absolute Key2;
+ R: Sw_integer;
+ S1,S2: string;
+begin
+ S1:=Upper(K1^.GetName);
+ S2:=Upper(K2^.GetName);
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:=1 else
+ { make sure that we distinguish between different objects with the same name }
+ if Ptrint(K1^.Symbol)<Ptrint(K2^.Symbol) then R:=-1 else
+ if Ptrint(K1^.Symbol)>Ptrint(K2^.Symbol) then R:= 1 else
+ R:=0;
+ Compare:=R;
+end;
+
+function TObjectSymbolCollection.LookUp(const S: string; var Idx: sw_integer): string;
+var OLI,ORI,Left,Right,Mid: integer;
+ {LeftP,RightP,}MidP: PObjectSymbol;
+ {LeftS,RightS,}MidS: string;
+ FoundS: string;
+ UpS : string;
+begin
+ Idx:=-1; FoundS:='';
+ Left:=0; Right:=Count-1;
+ UpS:=Upper(S);
+ if Left<Right then
+ begin
+ while (Left<Right) do
+ begin
+ OLI:=Left; ORI:=Right;
+ Mid:=Left+(Right-Left) div 2;
+ {LeftP:=At(Left);
+ LeftS:=Upper(LeftP^.GetName);}
+ MidP:=At(Mid);
+ MidS:=Upper(MidP^.GetName);
+ {RightP:=At(Right);
+ RightS:=Upper(RightP^.GetName);}
+ if copy(MidS,1,length(UpS))=UpS then
+ begin
+ Idx:=Mid;
+ FoundS:=MidS;
+ end;
+{ else}
+ if UpS<MidS then
+ Right:=Mid
+ else
+ Left:=Mid;
+ if (OLI=Left) and (ORI=Right) then
+ Break;
+ end;
+ end;
+ LookUp:=FoundS;
+end;
+
+{****************************************************************************
+ TReference
+****************************************************************************}
+
+constructor TReference.Init(AFileName: PString; ALine, AColumn: Sw_integer);
+begin
+ inherited Init;
+ FileName:=AFileName;
+ Position.X:=AColumn;
+ Position.Y:=ALine;
+end;
+
+function TReference.GetFileName: string;
+begin
+ GetFileName:=GetStr(FileName);
+end;
+
+destructor TReference.Done;
+begin
+ inherited Done;
+end;
+
+constructor TReference.Load(var S: TStream);
+begin
+ S.Read(Position, SizeOf(Position));
+
+ { --- items needing fixup --- }
+ S.Read(FileName, SizeOf(FileName)); { ->ModulesNames^.Item }
+end;
+
+procedure TReference.Store(var S: TStream);
+begin
+ S.Write(Position, SizeOf(Position));
+
+ { --- items needing fixup --- }
+ S.Write(FileName, SizeOf(FileName));
+end;
+
+{****************************************************************************
+ TSymbol
+****************************************************************************}
+
+constructor TSymbol.Init(const AName: string; ATyp: tsymtyp; AParams: string; AMemInfo: PSymbolMemInfo);
+begin
+ inherited Init;
+ Name:=NewStr(AName); Typ:=ATyp;
+ if AMemInfo<>nil then
+ SetMemInfo(AMemInfo^);
+ New(References, Init(20,50));
+ if ATyp in RecordTypes then
+ begin
+ Items:=New(PSortedSymbolCollection, Init(50,100));
+ end;
+end;
+
+procedure TSymbol.SetMemInfo(const AMemInfo: TSymbolMemInfo);
+begin
+ if MemInfo=nil then New(MemInfo);
+ Move(AMemInfo,MemInfo^,SizeOf(MemInfo^));
+ Flags:=Flags or sfHasMemInfo;
+end;
+
+function TSymbol.GetReferenceCount: Sw_integer;
+var Count: Sw_integer;
+begin
+ if References=nil then Count:=0 else
+ Count:=References^.Count;
+ GetReferenceCount:=Count;
+end;
+
+function TSymbol.GetReference(Index: Sw_integer): PReference;
+begin
+ GetReference:=References^.At(Index);
+end;
+
+function TSymbol.GetItemCount: Sw_integer;
+var Count: Sw_integer;
+begin
+ if Items=nil then Count:=0 else
+ Count:=Items^.Count;
+ GetItemCount:=Count;
+end;
+
+function TSymbol.GetItem(Index: Sw_integer): PSymbol;
+begin
+ GetItem:=Items^.At(Index);
+end;
+
+function TSymbol.GetName: string;
+begin
+ GetName:=GetStr(Name);
+end;
+
+function TSymbol.GetText: string;
+var S: string;
+begin
+ S:=GetTypeName;
+ if length(S)>SymbolTypLen then
+ S:=Copy(S,1,SymbolTypLen)
+ else
+ begin
+ while length(S)<SymbolTypLen do
+ S:=S+' ';
+ end;
+ S:=S+' '+GetName;
+ if (Flags and sfRecord)<>0 then
+ S:=S+' = record'
+ else
+ if (Flags and sfObject)<>0 then
+ begin
+ S:=S+' = ';
+ if (Flags and sfClass)<>0 then
+ S:=S+'class'
+ else
+ S:=S+'object';
+ if Ancestor<>nil then
+ S:=S+'('+Ancestor^.GetName+')';
+ end
+ else
+ begin
+ if Assigned(DType) then
+ S:=S+' = '+DType^;
+ if Assigned(Params) then
+ S:=S+'('+Params^+')';
+ if Assigned(VType) then
+ S:=S+': '+VType^;
+ end;
+ GetText:=S;
+end;
+
+function TSymbol.GetTypeName: string;
+var S: string;
+begin
+ case Typ of
+ abstractsym : S:='abst';
+ fieldvarsym : S:='member';
+ globalvarsym,
+ localvarsym,
+ paravarsym : S:='var';
+ typesym : S:='type';
+ procsym : if VType=nil then
+ S:='proc'
+ else
+ S:='func';
+ unitsym : S:='unit';
+ constsym : S:='const';
+ enumsym : S:='enum';
+ typedconstsym: S:='const';
+ errorsym : S:='error';
+ syssym : S:='sys';
+ labelsym : S:='label';
+ absolutevarsym : S:='abs';
+ propertysym : S:='prop';
+ macrosym : S:='macro';
+ else S:='';
+ end;
+ GetTypeName:=S;
+end;
+
+destructor TSymbol.Done;
+begin
+ inherited Done;
+ if assigned(MemInfo) then
+ Dispose(MemInfo);
+ if assigned(References) then
+ Dispose(References, Done);
+ if assigned(Items) then
+ Dispose(Items, Done);
+ if assigned(Name) then
+ DisposeStr(Name);
+{ if assigned(Params) then
+ DisposeStr(Params); in TypeNames
+ if assigned(VType) then
+ DisposeStr(VType);
+ if assigned(DType) then
+ DisposeStr(DType);
+ if assigned(Ancestor) then
+ DisposeStr(Ancestor);}
+end;
+
+constructor TSymbol.Load(var S: TStream);
+var MI: TSymbolMemInfo;
+ W: word;
+begin
+ TObject.Init;
+
+ S.Read(Typ,SizeOf(Typ));
+ S.Read(TypeID, SizeOf(TypeID));
+ S.Read(RelatedTypeID, SizeOf(RelatedTypeID));
+ S.Read(Flags, SizeOf(Flags));
+ Name:=S.ReadStr;
+ if (Flags and sfHasMemInfo)<>0 then
+ begin
+ S.Read(MI,SizeOf(MI));
+ SetMemInfo(MI);
+ end;
+
+ W:=0;
+ S.Read(W,SizeOf(W));
+ if (W and 1)<>0 then
+ New(References, Load(S));
+ if (W and 2)<>0 then
+ New(Items, Load(S));
+
+ { --- items needing fixup --- }
+ S.Read(DType, SizeOf(DType));
+ S.Read(VType, SizeOf(VType));
+ S.Read(Params, SizeOf(Params));
+end;
+
+procedure TSymbol.Store(var S: TStream);
+var W: word;
+begin
+ S.Write(Typ,SizeOf(Typ));
+ S.Write(TypeID, SizeOf(TypeID));
+ S.Write(RelatedTypeID, SizeOf(RelatedTypeID));
+ S.Write(Flags, SizeOf(Flags));
+ S.WriteStr(Name);
+
+ if (Flags and sfHasMemInfo)<>0 then
+ S.Write(MemInfo^,SizeOf(MemInfo^));
+
+ W:=0;
+ if Assigned(References) then W:=W or 1;
+ if Assigned(Items) then W:=W or 2;
+ S.Write(W,SizeOf(W));
+ if Assigned(References) then References^.Store(S);
+ if Assigned(Items) then Items^.Store(S);
+
+ { --- items needing fixup --- }
+ S.Write(DType, SizeOf(DType));
+ S.Write(VType, SizeOf(VType));
+ S.Write(Params, SizeOf(Params));
+end;
+
+constructor TExport.Init(const AName: string; AIndex: longint; ASymbol: PSymbol);
+begin
+ inherited Init;
+ Name:=NewStr(AName); Index:=AIndex;
+ Symbol:=ASymbol;
+end;
+
+function TExport.GetDisplayText: string;
+var S: string;
+begin
+ S:=GetStr(Name)+' '+IntToStr(Index);
+ if Assigned(Symbol) and (UpcaseStr(Symbol^.GetName)<>UpcaseStr(GetStr(Name))) then
+ S:=S+' ('+Symbol^.GetName+')';
+ GetDisplayText:=S;
+end;
+
+destructor TExport.Done;
+begin
+ if Assigned(Name) then DisposeStr(Name);
+ inherited Done;
+end;
+
+constructor TImport.Init(const ALibName, AFuncName,ARealName: string; AIndex: longint);
+begin
+ inherited Init;
+ LibName:=NewStr(ALibName);
+ FuncName:=NewStr(AFuncName); RealName:=NewStr(ARealName);
+ Index:=AIndex;
+end;
+
+function TImport.GetDisplayText: string;
+var S: string;
+begin
+ S:=GetStr(RealName);
+ if Assigned(FuncName) then S:=GetStr(FuncName)+' ('+S+')';
+ if S='' then S:=IntToStr(Index);
+ S:=GetStr(LibName)+' '+S;
+ GetDisplayText:=S;
+end;
+
+destructor TImport.Done;
+begin
+ if Assigned(LibName) then DisposeStr(LibName);
+ if Assigned(FuncName) then DisposeStr(FuncName);
+ if Assigned(RealName) then DisposeStr(RealName);
+ inherited Done;
+end;
+
+function TImportCollection.At(Index: sw_Integer): PImport;
+begin
+ At:=inherited At(Index);
+end;
+
+function TImportCollection.Compare(Key1, Key2: Pointer): sw_Integer;
+var K1: PImport absolute Key1;
+ K2: PImport absolute Key2;
+ S1: string;
+ S2: string;
+ R: sw_integer;
+begin
+ if (K1^.RealName=nil) and (K2^.RealName<>nil) then R:= 1 else
+ if (K1^.RealName<>nil) and (K2^.RealName=nil) then R:=-1 else
+ if (K1^.RealName=nil) and (K2^.RealName=nil) then
+ begin
+ if K1^.Index<K2^.Index then R:=-1 else
+ if K1^.Index>K2^.Index then R:= 1 else
+ R:=0;
+ end
+ else
+ begin
+ if K1^.FuncName=nil then S1:=GetStr(K1^.RealName) else S1:=GetStr(K1^.FuncName);
+ if K2^.FuncName=nil then S2:=GetStr(K2^.RealName) else S2:=GetStr(K2^.FuncName);
+ S1:=UpcaseStr(S1); S2:=UpcaseStr(S2);
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:= 1 else
+ R:=0;
+ end;
+ Compare:=R;
+end;
+
+function TExportCollection.At(Index: sw_Integer): PExport;
+begin
+ At:=inherited At(Index);
+end;
+
+function TExportCollection.Compare(Key1, Key2: Pointer): sw_Integer;
+var K1: PExport absolute Key1;
+ K2: PExport absolute Key2;
+ S1: string;
+ S2: string;
+ R: sw_integer;
+begin
+ S1:=UpcaseStr(GetStr(K1^.Name)); S2:=UpcaseStr(GetStr(K2^.Name));
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:= 1 else
+ R:=0;
+ Compare:=R;
+end;
+
+constructor TModuleSymbol.Init(const AName, AMainSource: string);
+begin
+ inherited Init(AName,unitsym,'',nil);
+ MainSource:=NewStr(AMainSource);
+end;
+
+procedure TModuleSymbol.SetLoadedFrom(const AModuleName: string);
+begin
+ SetStr(LoadedFrom,AModuleName);
+end;
+
+procedure TModuleSymbol.AddUsedUnit(P: PSymbol);
+begin
+ if Assigned(UsedUnits)=false then
+ New(UsedUnits, Init(10,10));
+ UsedUnits^.Insert(P);
+end;
+
+procedure TModuleSymbol.AddDependentUnit(P: PSymbol);
+begin
+ if Assigned(DependentUnits)=false then
+ New(DependentUnits, Init(10,10));
+ DependentUnits^.Insert(P);
+end;
+
+procedure TModuleSymbol.AddSourceFile(const Path: string);
+begin
+ if Assigned(SourceFiles)=false then
+ New(SourceFiles, Init(10,10));
+ sourcefiles^.Insert(NewStr(Path));
+end;
+
+destructor TModuleSymbol.Done;
+begin
+ inherited Done;
+ if Assigned(MainSource) then DisposeStr(MainSource);
+ if assigned(Exports_) then
+ Dispose(Exports_, Done);
+ if Assigned(Imports) then
+ Dispose(Imports, Done);
+ if Assigned(LoadedFrom) then
+ DisposeStr(LoadedFrom);
+ if Assigned(UsedUnits) then
+ begin
+ UsedUnits^.DeleteAll;
+ Dispose(UsedUnits, Done);
+ end;
+ if Assigned(DependentUnits) then
+ begin
+ DependentUnits^.DeleteAll;
+ Dispose(DependentUnits, Done);
+ end;
+ if Assigned(SourceFiles) then Dispose(SourceFiles, Done);
+end;
+
+
+constructor TObjectSymbol.Init(AParent: PObjectSymbol; ASymbol: PSymbol);
+begin
+ inherited Init;
+ Parent:=AParent;
+ Symbol:=ASymbol;
+end;
+
+constructor TObjectSymbol.InitName(const AName: string);
+begin
+ inherited Init;
+ Name:=NewStr(AName);
+end;
+
+function TObjectSymbol.GetName: string;
+begin
+ if Name<>nil then
+ GetName:=Name^
+ else
+ GetName:=Symbol^.GetName;
+end;
+
+function TObjectSymbol.GetDescendantCount: sw_integer;
+var Count: sw_integer;
+begin
+ if Descendants=nil then Count:=0 else
+ Count:=Descendants^.Count;
+ GetDescendantCount:=Count;
+end;
+
+function TObjectSymbol.GetDescendant(Index: sw_integer): PObjectSymbol;
+begin
+ GetDescendant:=Descendants^.At(Index);
+end;
+
+procedure TObjectSymbol.AddDescendant(P: PObjectSymbol);
+begin
+ if Descendants=nil then
+ New(Descendants, Init(50,10));
+ Descendants^.Insert(P);
+end;
+
+destructor TObjectSymbol.Done;
+begin
+ if Assigned(Name) then DisposeStr(Name); Name:=nil;
+ if Assigned(Descendants) then Dispose(Descendants, Done); Descendants:=nil;
+ inherited Done;
+end;
+
+constructor TObjectSymbol.Load(var S: TStream);
+begin
+end;
+
+procedure TObjectSymbol.Store(S: TStream);
+begin
+end;
+
+{****************************************************************************
+ TSourceFile
+****************************************************************************}
+
+constructor TSourceFile.Init(ASourceFileName, AObjFileName, APPUFileName: string);
+begin
+ inherited Init;
+ SourceFileName:=NewStr(ASourceFileName);
+ ObjFileName:=NewStr(AObjFileName);
+ PPUFileName:=NewStr(APPUFileName);
+end;
+
+destructor TSourceFile.Done;
+begin
+ if assigned(SourceFileName) then DisposeStr(SourceFileName);
+ if assigned(ObjFileName) then DisposeStr(ObjFileName);
+ if assigned(PPUFileName) then DisposeStr(PPUFileName);
+ inherited Done;
+end;
+
+function TSourceFile.GetSourceFilename: string;
+begin
+ GetSourceFilename:=GetStr(SourceFileName);
+end;
+
+function TSourceFile.GetObjFileName: string;
+begin
+ GetObjFilename:=GetStr(ObjFileName);
+end;
+
+function TSourceFile.GetPPUFileName: string;
+begin
+ GetPPUFilename:=GetStr(PPUFileName);
+end;
+
+function TSourceFileCollection.At(Index: sw_Integer): PSourceFile;
+begin
+ At:=inherited At(Index);
+end;
+
+{*****************************************************************************
+ Main Routines
+*****************************************************************************}
+
+procedure DisposeBrowserCol;
+begin
+ if assigned(Modules) then
+ begin
+ dispose(Modules,Done);
+ Modules:=nil;
+ end;
+ if assigned(ModuleNames) then
+ begin
+ dispose(ModuleNames,Done);
+ ModuleNames:=nil;
+ end;
+ if assigned(TypeNames) then
+ begin
+ dispose(TypeNames,Done);
+ TypeNames:=nil;
+ end;
+ if assigned(ObjectTree) then
+ begin
+ Dispose(ObjectTree, Done);
+ ObjectTree:=nil;
+ end;
+end;
+
+
+procedure NewBrowserCol;
+begin
+ New(Modules, Init(50,50));
+ New(ModuleNames, Init(50,50));
+ New(TypeNames, Init(1000,5000));
+end;
+
+
+ procedure ProcessSymTable(OwnerSym: PSymbol; var Owner: PSymbolCollection; Table: TSymTable);
+ var J: longint;
+ Ref: TRef;
+ Sym: TSym;
+ Symbol: PSymbol;
+ Reference: PReference;
+ inputfile : Tinputfile;
+ procedure SetVType(Symbol: PSymbol; VType: string);
+ begin
+ Symbol^.VType:=TypeNames^.Add(VType);
+ end;
+ procedure SetDType(Symbol: PSymbol; DType: string);
+ begin
+ Symbol^.DType:=TypeNames^.Add(DType);
+ end;
+ function GetDefinitionStr(def: tdef): string; forward;
+ function GetEnumDefStr(def: tenumdef): string;
+ var Name: string;
+ esym: tenumsym;
+ Count: integer;
+ begin
+ Name:='(';
+ esym:=tenumsym(def.Firstenum); Count:=0;
+ while (esym<>nil) do
+ begin
+ if Count>0 then
+ Name:=Name+', ';
+ Name:=Name+esym.name;
+ esym:=esym.nextenum;
+ Inc(Count);
+ end;
+ Name:=Name+')';
+ GetEnumDefStr:=Name;
+ end;
+ function GetArrayDefStr(def: tarraydef): string;
+ var Name: string;
+ begin
+ Name:='array ['+IntToStr(def.lowrange)+'..'+IntToStr(def.highrange)+'] of ';
+ if assigned(def.elementtype.def) then
+ Name:=Name+GetDefinitionStr(def.elementtype.def);
+ GetArrayDefStr:=Name;
+ end;
+ function GetFileDefStr(def: tfiledef): string;
+ var Name: string;
+ begin
+ Name:='';
+ case def.filetyp of
+ ft_text : Name:='text';
+ ft_untyped : Name:='file';
+ ft_typed : Name:='file of '+GetDefinitionStr(def.typedfiletype.def);
+ end;
+ GetFileDefStr:=Name;
+ end;
+ function GetStringDefStr(def: tstringdef): string;
+ var Name: string;
+ begin
+ Name:='';
+ case def.string_typ of
+ st_shortstring :
+ if def.len=255 then
+ Name:='shortstring'
+ else
+ Name:='string['+IntToStr(def.len)+']';
+ st_longstring :
+ Name:='longstring';
+ st_ansistring :
+ Name:='ansistring';
+ st_widestring :
+ Name:='widestring';
+ else ;
+ end;
+ GetStringDefStr:=Name;
+ end;
+ function retdefassigned(def: tabstractprocdef): boolean;
+ var OK: boolean;
+ begin
+ OK:=false;
+ if assigned(def.rettype.def) then
+ if UpcaseStr(GetDefinitionStr(def.rettype.def))<>'VOID' then
+ OK:=true;
+ retdefassigned:=OK;
+ end;
+ function GetAbsProcParmDefStr(def: tabstractprocdef): string;
+ var Name: string;
+ dc: tparavarsym;
+ i,
+ Count: integer;
+ CurName: string;
+ begin
+ Name:='';
+ Count:=0;
+ for i:=0 to def.paras.count-1 do
+ begin
+ dc:=tparavarsym(def.paras[i]);
+ if i=0 then
+ CurName:=''
+ else
+ CurName:=', '+CurName;
+ case dc.varspez of
+ vs_Value : ;
+ vs_Const : CurName:=CurName+'const ';
+ vs_Var : CurName:=CurName+'var ';
+ end;
+ if assigned(dc.vartype.def) then
+ CurName:=CurName+GetDefinitionStr(dc.vartype.def);
+ Name:=CurName+Name;
+ Inc(Count);
+ end;
+ GetAbsProcParmDefStr:=Name;
+ end;
+ function GetAbsProcDefStr(def: tabstractprocdef): string;
+ var Name: string;
+ begin
+ Name:=GetAbsProcParmDefStr(def);
+ if Name<>'' then Name:='('+Name+')';
+ if retdefassigned(def) then
+ Name:='function'+Name+': '+GetDefinitionStr(def.rettype.def)
+ else
+ Name:='procedure'+Name;
+ GetAbsProcDefStr:=Name;
+ end;
+ function GetProcDefStr(def: tprocdef): string;
+ var DName: string;
+ {J: integer;}
+ begin
+{ DName:='';
+ if assigned(def) then
+ begin
+ if assigned(def.parast) then
+ begin
+ with def.parast^ do
+ for J:=1 to number_symbols do
+ begin
+ if J<>1 then DName:=DName+', ';
+ ParSym:=GetsymNr(J);
+ if ParSym=nil then Break;
+ DName:=DName+ParSym^.Name;
+ end;
+ end
+ end;}
+ DName:=GetAbsProcDefStr(def);
+ GetProcDefStr:=DName;
+ end;
+ function GetProcVarDefStr(def: tprocvardef): string;
+ begin
+ GetProcVarDefStr:=GetAbsProcDefStr(def);
+ end;
+ function GetSetDefStr(def: tsetdef): string;
+ var Name: string;
+ begin
+ Name:='';
+ case def.settype of
+ normset : Name:='set';
+ smallset : Name:='set';
+ varset : Name:='varset';
+ end;
+ Name:=Name+' of ';
+ Name:=Name+GetDefinitionStr(def.elementtype.def);
+ GetSetDefStr:=Name;
+ end;
+ function GetPointerDefStr(def: tpointerdef): string;
+ begin
+ GetPointerDefStr:='^'+GetDefinitionStr(def.pointertype.def);
+ end;
+ function GetDefinitionStr(def: tdef): string;
+ var Name: string;
+ begin
+ Name:='';
+ if def<>nil then
+ begin
+ if assigned(def.typesym) then
+ Name:=def.typesym.name;
+ if Name='' then
+ case def.deftype of
+ arraydef :
+ Name:=GetArrayDefStr(tarraydef(def));
+ stringdef :
+ Name:=GetStringDefStr(tstringdef(def));
+ enumdef :
+ Name:=GetEnumDefStr(tenumdef(def));
+ procdef :
+ Name:=GetProcDefStr(tprocdef(def));
+ procvardef :
+ Name:=GetProcVarDefStr(tprocvardef(def));
+ filedef :
+ Name:=GetFileDefStr(tfiledef(def));
+ setdef :
+ Name:=GetSetDefStr(tsetdef(def));
+ end;
+ end;
+ GetDefinitionStr:=Name;
+ end;
+ function GetEnumItemName(Sym: tenumsym): string;
+ var Name: string;
+ {ES: tenumsym;}
+ begin
+ Name:='';
+ if assigned(sym) and assigned(sym.definition) then
+ if assigned(sym.definition.typesym) then
+ begin
+{ ES:=sym.definition.First;
+ while (ES<>nil) and (ES^.Value<>sym.value) do
+ ES:=ES^.next;
+ if assigned(es) and (es^.value=sym.value) then
+ Name:=}
+ Name:=sym.definition.typesym.name;
+ if Name<>'' then
+ Name:=Name+'('+IntToStr(sym.value)+')';
+ end;
+ GetEnumItemName:=Name;
+ end;
+ function GetConstValueName(sym: tconstsym): string;
+ var Name: string;
+ begin
+ Name:='';
+ if Name='' then
+ case sym.consttyp of
+ constord :
+ begin
+ if sym.consttype.def.deftype=enumdef then
+ Name:=sym.consttype.def.typesym.name+'('+IntToStr(sym.value.valueord)+')'
+ else
+ if is_boolean(sym.consttype.def) then
+ Name:='Longbool('+IntToStr(sym.value.valueord)+')'
+ else
+ if is_char(sym.consttype.def) or
+ is_widechar(sym.consttype.def) then
+ Name:=''''+chr(sym.value.valueord)+''''
+ else
+ Name:=IntToStr(sym.value.valueord);
+ end;
+ constresourcestring,
+ conststring :
+ Name:=''''+StrPas(pchar(sym.value.valueptr))+'''';
+ constreal:
+ Name:=FloatToStr(PBestReal(sym.value.valueptr)^);
+ constset:
+{ Name:=SetToStr(pnormalset(sym.value.valueptr)) };
+ constnil: ;
+ end;
+ GetConstValueName:=Name;
+ end;
+ procedure ProcessDefIfStruct(definition: tdef);
+ begin
+ { still led to infinite recursions
+ only usefull for unamed types PM }
+ if assigned(definition) and not assigned(definition.typesym) then
+ begin
+ case definition.deftype of
+ recorddef :
+ if trecorddef(definition).symtable<>Table then
+ ProcessSymTable(Symbol,Symbol^.Items,trecorddef(definition).symtable);
+ objectdef :
+ if tobjectdef(definition).symtable<>Table then
+ ProcessSymTable(Symbol,Symbol^.Items,tobjectdef(definition).symtable);
+ { leads to infinite loops !!
+ pointerdef :
+ with tpointerdef(definition)^ do
+ if assigned(definition) then
+ if assigned(definition.sym) then
+ ProcessDefIfStruct(definition.sym.definition);}
+ end;
+ end;
+ end;
+ var MemInfo: TSymbolMemInfo;
+ ObjDef: tobjectdef;
+ begin
+ if not Assigned(Table) then
+ Exit;
+ if Owner=nil then
+ Owner:=New(PSortedSymbolCollection, Init(10,50));
+ sym:=tsym(Table.symindex.first);
+ while assigned(sym) do
+ begin
+ New(Symbol, Init(Sym.Name,Sym.Typ,'',nil));
+ case Sym.Typ of
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ with tabstractvarsym(sym) do
+ begin
+ if assigned(vartype.def) then
+ if assigned(vartype.def.typesym) then
+ SetVType(Symbol,vartype.def.typesym.name)
+ else
+ SetVType(Symbol,GetDefinitionStr(vartype.def));
+ ProcessDefIfStruct(vartype.def);
+ if assigned(vartype.def) then
+ if (vartype.def.deftype=pointerdef) and
+ assigned(tpointerdef(vartype.def).pointertype.def) then
+ begin
+ Symbol^.Flags:=(Symbol^.Flags or sfPointer);
+ Symbol^.RelatedTypeID:=Ptrint(tpointerdef(vartype.def).pointertype.def);
+ end;
+ if typ=fieldvarsym then
+ MemInfo.Addr:=tfieldvarsym(sym).fieldoffset
+ else
+ begin
+ if tabstractnormalvarsym(sym).localloc.loc=LOC_REFERENCE then
+ MemInfo.Addr:=tabstractnormalvarsym(sym).localloc.reference.offset
+ else
+ MemInfo.Addr:=0;
+ end;
+ if assigned(vartype.def) and (vartype.def.deftype=arraydef) then
+ begin
+ if tarraydef(vartype.def).highrange<tarraydef(vartype.def).lowrange then
+ MemInfo.Size:=-1
+ else
+ MemInfo.Size:=getsize;
+ end
+ else
+ MemInfo.Size:=getsize;
+ { this is not completely correct... }
+ MemInfo.PushSize:=paramanager.push_size(varspez,vartype.def,pocall_default);
+ Symbol^.SetMemInfo(MemInfo);
+ end;
+ fieldvarsym :
+ with tfieldvarsym(sym) do
+ begin
+ if assigned(vartype.def) and (vartype.def.deftype=arraydef) then
+ begin
+ if tarraydef(vartype.def).highrange<tarraydef(vartype.def).lowrange then
+ MemInfo.Size:=-1
+ else
+ MemInfo.Size:=getsize;
+ end
+ else
+ MemInfo.Size:=getsize;
+ Symbol^.SetMemInfo(MemInfo);
+ end;
+ constsym :
+ SetDType(Symbol,GetConstValueName(tconstsym(sym)));
+ enumsym :
+ if assigned(tenumsym(sym).definition) then
+ SetDType(Symbol,GetEnumItemName(tenumsym(sym)));
+ unitsym :
+ begin
+ { ProcessSymTable(Symbol^.Items,tunitsym(sym).unitsymtable);}
+ end;
+ syssym :
+{ if assigned(Table.Name) then
+ if Table.Name^='SYSTEM' then}
+ begin
+ Symbol^.Params:=TypeNames^.Add('...');
+ end;
+ procsym :
+ begin
+ with tprocsym(sym) do
+ if assigned(first_procdef) then
+ begin
+ if cs_local_browser in aktmoduleswitches then
+ ProcessSymTable(Symbol,Symbol^.Items,first_procdef.parast);
+ if assigned(first_procdef.parast) then
+ begin
+ Symbol^.Params:=TypeNames^.Add(GetAbsProcParmDefStr(first_procdef));
+ end
+ else { param-definition is NOT assigned }
+ if assigned(Table.Name) then
+ if Table.Name^='SYSTEM' then
+ begin
+ Symbol^.Params:=TypeNames^.Add('...');
+ end;
+ if cs_local_browser in aktmoduleswitches then
+ begin
+ if assigned(first_procdef.localst) and
+ (first_procdef.localst.symtabletype<>staticsymtable) then
+ ProcessSymTable(Symbol,Symbol^.Items,first_procdef.localst);
+ end;
+ end;
+ end;
+ typesym :
+ begin
+ with ttypesym(sym) do
+ if assigned(restype.def) then
+ begin
+ Symbol^.TypeID:=Ptrint(restype.def);
+ case restype.def.deftype of
+ arraydef :
+ SetDType(Symbol,GetArrayDefStr(tarraydef(restype.def)));
+ enumdef :
+ SetDType(Symbol,GetEnumDefStr(tenumdef(restype.def)));
+ procdef :
+ SetDType(Symbol,GetProcDefStr(tprocdef(restype.def)));
+ procvardef :
+ SetDType(Symbol,GetProcVarDefStr(tprocvardef(restype.def)));
+ objectdef :
+ with tobjectdef(restype.def) do
+ begin
+ ObjDef:=childof;
+ if ObjDef<>nil then
+ Symbol^.RelatedTypeID:=Ptrint(ObjDef);{TypeNames^.Add(S);}
+ Symbol^.Flags:=(Symbol^.Flags or sfObject);
+ if tobjectdef(restype.def).objecttype=odt_class then
+ Symbol^.Flags:=(Symbol^.Flags or sfClass);
+ ProcessSymTable(Symbol,Symbol^.Items,tobjectdef(restype.def).symtable);
+ end;
+ recorddef :
+ begin
+ Symbol^.Flags:=(Symbol^.Flags or sfRecord);
+ ProcessSymTable(Symbol,Symbol^.Items,trecorddef(restype.def).symtable);
+ end;
+ pointerdef :
+ begin
+ Symbol^.Flags:=(Symbol^.Flags or sfPointer);
+ Symbol^.RelatedTypeID:=Ptrint(tpointerdef(restype.def).pointertype.def);{TypeNames^.Add(S);}
+ SetDType(Symbol,GetPointerDefStr(tpointerdef(restype.def)));
+ end;
+
+ filedef :
+ SetDType(Symbol,GetFileDefStr(tfiledef(restype.def)));
+ setdef :
+ SetDType(Symbol,GetSetDefStr(tsetdef(restype.def)));
+ end;
+ end;
+ end;
+ end;
+ Ref:=tstoredsym(sym).defref;
+ while Assigned(Symbol) and assigned(Ref) do
+ begin
+ inputfile:=get_source_file(ref.moduleindex,ref.posinfo.fileindex);
+ if Assigned(inputfile) and Assigned(inputfile.name) then
+ begin
+ New(Reference, Init(ModuleNames^.Add(inputfile.name^),
+ ref.posinfo.line,ref.posinfo.column));
+ Symbol^.References^.Insert(Reference);
+ end;
+ Ref:=Ref.nextref;
+ end;
+ if Assigned(Symbol) then
+ begin
+ if not Owner^.Search(Symbol,J) then
+ Owner^.Insert(Symbol)
+ else
+ begin
+ Dispose(Symbol,done);
+ Symbol:=nil;
+ end;
+ end;
+ sym:=tsym(sym.indexnext);
+ end;
+ end;
+
+function SearchModule(const Name: string): PModuleSymbol;
+function Match(P: PModuleSymbol): boolean; {$ifndef FPC}far;{$endif}
+begin
+ Match:=CompareText(P^.GetName,Name)=0;
+end;
+var P: PModuleSymbol;
+begin
+ P:=nil;
+ if Assigned(Modules) then
+ P:=Modules^.FirstThat(@Match);
+ SearchModule:=P;
+end;
+
+procedure CreateBrowserCol;
+var
+ T: TSymTable;
+ UnitS,PM: PModuleSymbol;
+ hp : tmodule;
+ puu: tused_unit;
+ pdu: tdependent_unit;
+ pif: tinputfile;
+begin
+ DisposeBrowserCol;
+ if (cs_browser in aktmoduleswitches) then
+ NewBrowserCol;
+ hp:=tmodule(loaded_units.first);
+ if (cs_browser in aktmoduleswitches) then
+ while assigned(hp) do
+ begin
+ t:=tsymtable(hp.globalsymtable);
+ if assigned(t) then
+ begin
+ New(UnitS, Init(T.Name^,hp.mainsource^));
+ if Assigned(hp.loaded_from) then
+ if assigned(hp.loaded_from.globalsymtable) then
+ UnitS^.SetLoadedFrom(tsymtable(hp.loaded_from.globalsymtable).name^);
+{ pimportlist(current_module^.imports^.first);}
+
+ if assigned(hp.sourcefiles) then
+ begin
+ pif:=hp.sourcefiles.files;
+ while (pif<>nil) do
+ begin
+ UnitS^.AddSourceFile(pif.path^+pif.name^);
+ pif:=pif.next;
+ end;
+ end;
+
+ Modules^.Insert(UnitS);
+ ProcessSymTable(UnitS,UnitS^.Items,T);
+ if cs_local_browser in aktmoduleswitches then
+ begin
+ t:=tsymtable(hp.localsymtable);
+ if assigned(t) then
+ ProcessSymTable(UnitS,UnitS^.Items,T);
+ end;
+ end;
+ hp:=tmodule(hp.next);
+ end;
+
+ hp:=tmodule(loaded_units.first);
+ if (cs_browser in aktmoduleswitches) then
+ while assigned(hp) do
+ begin
+ t:=tsymtable(hp.globalsymtable);
+ if assigned(t) then
+ begin
+ UnitS:=SearchModule(T.Name^);
+ puu:=tused_unit(hp.used_units.first);
+ while (puu<>nil) do
+ begin
+ PM:=SearchModule(puu.u.modulename^);
+ if Assigned(PM) then
+ UnitS^.AddUsedUnit(PM);
+ puu:=tused_unit(puu.next);
+ end;
+ pdu:=tdependent_unit(hp.dependent_units.first);
+ while (pdu<>nil) do
+ begin
+ PM:=SearchModule(tsymtable(pdu.u.globalsymtable).name^);
+ if Assigned(PM) then
+ UnitS^.AddDependentUnit(PM);
+ pdu:=tdependent_unit(pdu.next);
+ end;
+ end;
+ hp:=tmodule(hp.next);
+ end;
+
+ if (cs_browser in aktmoduleswitches) then
+ BuildObjectInfo;
+ { can allways be done
+ needed to know when recompilation of sources is necessary }
+ BuildSourceList;
+end;
+
+procedure BuildObjectInfo;
+var C,D: PIDSortedSymbolCollection;
+ E : PCollection;
+ ObjectC: PObjectSymbolCollection;
+ ObjectsSymbol: PObjectSymbol;
+procedure InsertSymbolCollection(Symbols: PSymbolCollection);
+var I: sw_integer;
+ P: PSymbol;
+begin
+ for I:=0 to Symbols^.Count-1 do
+ begin
+ P:=Symbols^.At(I);
+ if (P^.Flags and sfObject)<>0 then
+ C^.Insert(P);
+ if (P^.typ=typesym) then
+ D^.Insert(P);
+ if (P^.typ in [globalvarsym,localvarsym,paravarsym]) and ((P^.flags and sfPointer)<>0) then
+ E^.Insert(P);
+ if P^.Items<>nil then
+ InsertSymbolCollection(P^.Items);
+ end;
+end;
+function SearchObjectForSym(O: PSymbol): PObjectSymbol;
+var I: sw_integer;
+ OS,P: PObjectSymbol;
+begin
+ P:=nil;
+ for I:=0 to ObjectC^.Count-1 do
+ begin
+ OS:=ObjectC^.At(I);
+ if OS^.Symbol=O then
+ begin P:=OS; Break; end;
+ end;
+ SearchObjectForSym:=P;
+end;
+procedure BuildTree;
+var I: sw_integer;
+ Symbol: PSymbol;
+ Parent,OS: PObjectSymbol;
+begin
+ I:=0;
+ while (I<C^.Count) do
+ begin
+ Symbol:=C^.At(I);
+ if Symbol^.Ancestor=nil then
+ Parent:=ObjectsSymbol
+ else
+ Parent:=SearchObjectForSym(Symbol^.Ancestor);
+ if Parent<>nil then
+ begin
+ New(OS, Init(Parent, Symbol));
+ Parent^.AddDescendant(OS);
+ ObjectC^.Insert(OS);
+ C^.AtDelete(I);
+ end
+ else
+ Inc(I);
+ end;
+end;
+var Pass: integer;
+ I: sw_integer;
+ P: PSymbol;
+begin
+ New(C, Init(1000,5000));
+ New(D, Init(1000,5000));
+ New(E, Init(1000,5000));
+ InsertSymbolCollection(Modules);
+
+ { --- Resolve ancestor<->descendant references --- }
+ for I:=0 to C^.Count-1 do
+ begin
+ P:=C^.At(I);
+ if P^.RelatedTypeID<>0 then
+ P^.Ancestor:=C^.SearchSymbolByID(P^.RelatedTypeID);
+ end;
+
+ { --- Resolve pointer definition references --- }
+ for I:=0 to D^.Count-1 do
+ begin
+ P:=D^.At(I);
+ if P^.RelatedTypeID<>0 then
+ P^.Ancestor:=D^.SearchSymbolByID(P^.RelatedTypeID);
+ end;
+
+ { --- Resolve pointer var definition references --- }
+ for I:=0 to E^.Count-1 do
+ begin
+ P:=PSymbol(E^.At(I));
+ if P^.RelatedTypeID<>0 then
+ P^.Ancestor:=D^.SearchSymbolByID(P^.RelatedTypeID);
+ end;
+
+ { E is not needed anymore }
+ E^.DeleteAll;
+ Dispose(E,Done);
+
+ { D is not needed anymore }
+ D^.DeleteAll;
+ Dispose(D,Done);
+
+ { --- Build object tree --- }
+ if assigned(ObjectTree) then
+ Dispose(ObjectTree, Done);
+ New(ObjectsSymbol, InitName('Objects'));
+ ObjectTree:=ObjectsSymbol;
+
+ New(ObjectC, Init(C^.Count,100));
+
+ Pass:=0;
+ if C^.Count>0 then
+ repeat
+ BuildTree;
+ Inc(Pass);
+ until (C^.Count=0) or (Pass>20); { more than 20 levels ? - then there must be a bug }
+
+ ObjectC^.DeleteAll; Dispose(ObjectC, Done);
+ C^.DeleteAll; Dispose(C, Done);
+end;
+
+function SearchObjectForSymbol(O: PSymbol): PObjectSymbol;
+function ScanObjectCollection(Parent: PObjectSymbol): PObjectSymbol;
+var I: sw_integer;
+ OS,P: PObjectSymbol;
+ ObjectC: PObjectSymbolCollection;
+begin
+ P:=nil;
+ if Parent<>nil then
+ if Parent^.Descendants<>nil then
+ begin
+ ObjectC:=Parent^.Descendants;
+ for I:=0 to ObjectC^.Count-1 do
+ begin
+ OS:=ObjectC^.At(I);
+ if OS^.Symbol=O then
+ begin P:=OS; Break; end;
+ if OS^.Descendants<>nil then
+ begin
+ P:=ScanObjectCollection(OS);
+ if P<>nil then Break;
+ end;
+ end;
+ end;
+ ScanObjectCollection:=P;
+end;
+begin
+ SearchObjectForSymbol:=ScanObjectCollection(ObjectTree);
+end;
+
+procedure BuildSourceList;
+var m: tmodule;
+ s: tinputfile;
+ p: cutils.pstring;
+ ppu,obj: string;
+ source: string;
+begin
+ if Assigned(SourceFiles) then
+ begin
+ Dispose(SourceFiles, Done);
+ SourceFiles:=nil;
+ end;
+ if assigned(loaded_units.first) then
+ begin
+ New(SourceFiles, Init(50,10));
+ m:=tmodule(loaded_units.first);
+ while assigned(m) do
+ begin
+ obj:=fexpand(m.objfilename^);
+ ppu:=''; source:='';
+ if m.is_unit then
+ ppu:=fexpand(m.ppufilename^);
+ if (m.is_unit=false) and (m.islibrary=false) then
+ ppu:=fexpand(m.exefilename^);
+ if assigned(m.sourcefiles) then
+ begin
+ s:=m.sourcefiles.files;
+ while assigned(s) do
+ begin
+ source:='';
+ p:=s.path;
+ if assigned(p) then
+ source:=source+p^;
+ p:=s.name;
+ if assigned(p) then
+ source:=source+p^;
+ source:=fexpand(source);
+
+ sourcefiles^.Insert(New(PSourceFile, Init(source,obj,ppu)));
+ s:=s.ref_next;
+ end;
+ end;
+ m:=tmodule(m.next);
+ end;
+ end;
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+
+
+var
+ oldexit : pointer;
+
+procedure browcol_exit;{$ifndef FPC}far;{$endif}
+begin
+ exitproc:=oldexit;
+ DisposeBrowserCol;
+ if Assigned(SourceFiles) then
+ begin
+ Dispose(SourceFiles, Done);
+ SourceFiles:=nil;
+ end;
+ if assigned(ObjectTree) then
+ begin
+ Dispose(ObjectTree, Done);
+ ObjectTree:=nil;
+ end;
+end;
+
+
+procedure InitBrowserCol;
+begin
+end;
+
+
+procedure DoneBrowserCol;
+begin
+ { nothing, the collections are freed in the exitproc - ??? }
+ { nothing? then why do we've this routine for ? IMHO, either we should
+ remove this, or it should destroy the browser info when it's called. - BG }
+end;
+
+type
+ PPointerXRef = ^TPointerXRef;
+ TPointerXRef = record
+ PtrValue : pointer;
+ DataPtr : pointer;
+ end;
+
+ PPointerDictionary = ^TPointerDictionary;
+ TPointerDictionary = object(TSortedCollection)
+ function At(Index: sw_Integer): PPointerXRef;
+ function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
+ procedure FreeItem(Item: Pointer); virtual;
+ function SearchXRef(PtrValue: pointer): PPointerXRef;
+ function AddPtr(PtrValue, DataPtr: pointer): PPointerXRef;
+ procedure Resolve(var P);
+ end;
+
+function NewPointerXRef(APtrValue, ADataPtr: pointer): PPointerXRef;
+var P: PPointerXRef;
+begin
+ New(P); FillChar(P^,SizeOf(P^),0);
+ with P^ do begin PtrValue:=APtrValue; DataPtr:=ADataPtr; end;
+ NewPointerXRef:=P;
+end;
+
+procedure DisposePointerXRef(P: PPointerXRef);
+begin
+ if Assigned(P) then Dispose(P);
+end;
+
+function TPointerDictionary.At(Index: sw_Integer): PPointerXRef;
+begin
+ At:=inherited At(Index);
+end;
+
+function TPointerDictionary.Compare(Key1, Key2: Pointer): sw_Integer;
+var K1: PPointerXRef absolute Key1;
+ K2: PPointerXRef absolute Key2;
+ R: integer;
+begin
+ if Ptrint(K1^.PtrValue)<Ptrint(K2^.PtrValue) then R:=-1 else
+ if Ptrint(K1^.PtrValue)>Ptrint(K2^.PtrValue) then R:= 1 else
+ R:=0;
+ Compare:=R;
+end;
+
+procedure TPointerDictionary.FreeItem(Item: Pointer);
+begin
+ if Assigned(Item) then DisposePointerXRef(Item);
+end;
+
+function TPointerDictionary.SearchXRef(PtrValue: pointer): PPointerXRef;
+var P: PPointerXRef;
+ T: TPointerXRef;
+ Index: sw_integer;
+begin
+ T.PtrValue:=PtrValue;
+ if Search(@T,Index)=false then P:=nil else
+ P:=At(Index);
+ SearchXRef:=P;
+end;
+
+function TPointerDictionary.AddPtr(PtrValue, DataPtr: pointer): PPointerXRef;
+var P: PPointerXRef;
+begin
+ P:=SearchXRef(PtrValue);
+ if P=nil then
+ begin
+ P:=NewPointerXRef(PtrValue,DataPtr);
+ Insert(P);
+{$ifdef DEBUG}
+ end
+ else
+ begin
+ if P^.DataPtr<>DataPtr then
+ InternalError(987654);
+{$endif DEBUG}
+ end;
+ AddPtr:=P;
+end;
+
+procedure TPointerDictionary.Resolve(var P);
+var X: PPointerXRef;
+ V: pointer;
+begin
+ Move(P,V,SizeOf(V));
+ X:=SearchXRef(V);
+ if X=nil then V:=nil else
+ V:=X^.DataPtr;
+ Move(V,P,SizeOf(V));
+end;
+
+procedure ReadPointers(S: PStream; C: PCollection; D: PPointerDictionary);
+var W,I: sw_integer;
+ P: pointer;
+begin
+ S^.Read(W,SizeOf(W));
+ for I:=0 to W-1 do
+ begin
+ S^.Read(P,SizeOf(P));
+ D^.AddPtr(P,C^.At(I));
+ end;
+end;
+
+function LoadBrowserCol(S: PStream): boolean;
+var PD: PPointerDictionary;
+procedure FixupPointers;
+procedure FixupReference(P: PReference); {$ifndef FPC}far;{$endif}
+begin
+ PD^.Resolve(P^.FileName);
+end;
+procedure FixupSymbol(P: PSymbol); {$ifndef FPC}far;{$endif}
+var I: sw_integer;
+begin
+ PD^.Resolve(P^.DType);
+ PD^.Resolve(P^.VType);
+ PD^.Resolve(P^.Params);
+ if Assigned(P^.References) then
+ with P^.References^ do
+ for I:=0 to Count-1 do
+ FixupReference(At(I));
+ if Assigned(P^.Items) then
+ with P^.Items^ do
+ for I:=0 to Count-1 do
+ FixupSymbol(At(I));
+end;
+begin
+ Modules^.ForEach(@FixupSymbol);
+end;
+procedure ReadSymbolPointers(P: PSymbol); {$ifndef FPC}far;{$endif}
+var I: sw_integer;
+ PV: pointer;
+begin
+ S^.Read(PV, SizeOf(PV));
+ PD^.AddPtr(PV,P);
+ if Assigned(P^.Items) then
+ with P^.Items^ do
+ for I:=0 to Count-1 do
+ ReadSymbolPointers(At(I));
+end;
+begin
+ DisposeBrowserCol;
+
+ New(ModuleNames, Load(S^));
+ New(TypeNames, Load(S^));
+ New(Modules, Load(S^));
+
+ New(PD, Init(4000,1000));
+ ReadPointers(S,ModuleNames,PD);
+ ReadPointers(S,TypeNames,PD);
+ ReadPointers(S,Modules,PD);
+ Modules^.ForEach(@ReadSymbolPointers);
+ FixupPointers;
+ Dispose(PD, Done);
+
+ BuildObjectInfo;
+ LoadBrowserCol:=(S^.Status=stOK);
+end;
+
+procedure StorePointers(S: PStream; C: PCollection);
+var W,I: sw_integer;
+ P: pointer;
+begin
+ W:=C^.Count;
+ S^.Write(W,SizeOf(W));
+ for I:=0 to W-1 do
+ begin
+ P:=C^.At(I);
+ S^.Write(P,SizeOf(P));
+ end;
+end;
+
+function StoreBrowserCol(S: PStream) : boolean;
+procedure WriteSymbolPointers(P: PSymbol); {$ifndef FPC}far;{$endif}
+var I: sw_integer;
+begin
+ S^.Write(P, SizeOf(P));
+ if Assigned(P^.Items) then
+ with P^.Items^ do
+ for I:=0 to Count-1 do
+ WriteSymbolPointers(At(I));
+end;
+begin
+ ModuleNames^.Store(S^);
+ TypeNames^.Store(S^);
+ Modules^.Store(S^);
+
+ StorePointers(S,ModuleNames);
+ StorePointers(S,TypeNames);
+ StorePointers(S,Modules);
+ Modules^.ForEach(@WriteSymbolPointers);
+ StoreBrowserCol:=(S^.Status=stOK);
+end;
+
+procedure RegisterSymbols;
+begin
+ RegisterType(RModuleNameCollection);
+ RegisterType(RTypeNameCollection);
+ RegisterType(RReference);
+ RegisterType(RSymbol);
+ RegisterType(RObjectSymbol);
+ RegisterType(RSymbolCollection);
+ RegisterType(RSortedSymbolCollection);
+ RegisterType(RIDSortedSymbolCollection);
+ RegisterType(RObjectSymbolCollection);
+ RegisterType(RReferenceCollection);
+ RegisterType(RModuleSymbol);
+end;
+
+begin
+ oldexit:=exitproc;
+ exitproc:=@browcol_exit;
+end.
diff --git a/compiler/browlog.pas b/compiler/browlog.pas
new file mode 100644
index 0000000000..1dc68ea703
--- /dev/null
+++ b/compiler/browlog.pas
@@ -0,0 +1,515 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Pierre Muller
+
+ Support routines for creating the browser log
+
+ 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 browlog;
+
+{$i fpcdefs.inc}
+
+interface
+uses
+ cclasses,
+ globtype,
+ fmodule,finput,
+ symbase,symconst,symtype,symsym,symdef,symtable;
+
+const
+ logbufsize = 16384;
+
+type
+ pbrowserlog=^tbrowserlog;
+ tbrowserlog=object
+ fname : string;
+ logopen : boolean;
+ stderrlog : boolean;
+ f : file;
+ elements_to_list : tstringlist;
+ buf : pchar;
+ bufidx : longint;
+ identidx : longint;
+ constructor init;
+ destructor done;
+ procedure setfilename(const fn:string);
+ procedure createlog;
+ procedure flushlog;
+ procedure addlog(const s:string);
+ procedure addlogrefs(p:tref);
+ procedure closelog;
+ procedure ident;
+ procedure unident;
+ procedure browse_symbol(const sr : string);
+ procedure list_elements;
+ procedure list_debug_infos;
+ end;
+
+var
+ browserlog : tbrowserlog;
+
+ procedure WriteBrowserLog;
+
+ procedure InitBrowserLog;
+ procedure DoneBrowserLog;
+
+
+implementation
+
+ uses
+ cutils,comphook,
+ globals,systems,
+ ppu;
+
+ function get_file_line(ref:tref): string;
+ var
+ inputfile : tinputfile;
+ begin
+ get_file_line:='';
+ with ref do
+ begin
+ inputfile:=get_source_file(moduleindex,posinfo.fileindex);
+ if assigned(inputfile) then
+ if status.use_gccoutput then
+ { for use with rhide
+ add warning so that it does not interpret
+ this as an error !! }
+ get_file_line:=lower(inputfile.name^)
+ +':'+tostr(posinfo.line)+': warning: '+tostr(posinfo.column)+':'
+ else
+ get_file_line:=inputfile.name^
+ +'('+tostr(posinfo.line)+','+tostr(posinfo.column)+')'
+ else
+ if status.use_gccoutput then
+ get_file_line:='file_unknown:'
+ +tostr(posinfo.line)+': warning: '+tostr(posinfo.column)+':'
+ else
+ get_file_line:='file_unknown('
+ +tostr(posinfo.line)+','+tostr(posinfo.column)+')'
+ end;
+ end;
+
+{****************************************************************************
+ TBrowser
+****************************************************************************}
+
+ constructor tbrowserlog.init;
+ begin
+ fname:=FixFileName('browser.log');
+ logopen:=false;
+ elements_to_list:=TStringList.Create;
+ end;
+
+
+ destructor tbrowserlog.done;
+ begin
+ if logopen then
+ closelog;
+ elements_to_list.free;
+ end;
+
+
+ procedure tbrowserlog.setfilename(const fn:string);
+ begin
+ fname:=FixFileName(fn);
+ end;
+
+
+ procedure tbrowserlog.createlog;
+ begin
+ if logopen then
+ closelog;
+ assign(f,fname);
+ {$I-}
+ rewrite(f,1);
+ {$I+}
+ if ioresult<>0 then
+ exit;
+ logopen:=true;
+ getmem(buf,logbufsize);
+ bufidx:=0;
+ identidx:=0;
+ end;
+
+
+ procedure tbrowserlog.flushlog;
+ begin
+ if logopen then
+ if not stderrlog then
+ blockwrite(f,buf^,bufidx)
+ else
+ begin
+ buf[bufidx]:=#0;
+{$ifdef FPC}
+ write(stderr,buf);
+{$else FPC}
+ write(buf);
+{$endif FPC}
+ end;
+ bufidx:=0;
+ end;
+
+
+ procedure tbrowserlog.closelog;
+ begin
+ if logopen then
+ begin
+ flushlog;
+ close(f);
+ freemem(buf,logbufsize);
+ logopen:=false;
+ end;
+ end;
+
+ procedure tbrowserlog.list_elements;
+
+ begin
+
+ stderrlog:=true;
+ getmem(buf,logbufsize);
+ logopen:=true;
+ while not elements_to_list.empty do
+ browse_symbol(elements_to_list.getfirst);
+ flushlog;
+ logopen:=false;
+ freemem(buf,logbufsize);
+ stderrlog:=false;
+ end;
+
+ procedure tbrowserlog.list_debug_infos;
+{$ifndef debug}
+ begin
+ end;
+{$else debug}
+ var
+ hp : tmodule;
+ ff : tinputfile;
+ begin
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ addlog('Unit '+hp.modulename^+' has index '+tostr(hp.unit_index));
+ ff:=hp.sourcefiles.files;
+ while assigned(ff) do
+ begin
+ addlog('File '+ff.name^+' index '+tostr(ff.ref_index));
+ ff:=ff.ref_next;
+ end;
+ hp:=tmodule(hp.next);
+ end;
+ end;
+{$endif debug}
+
+ procedure tbrowserlog.addlog(const s:string);
+ begin
+ if not logopen then
+ exit;
+ { add ident }
+ if (identidx>0) and not stderrlog then
+ begin
+ if bufidx+identidx>logbufsize then
+ flushlog;
+ fillchar(buf[bufidx],identidx,' ');
+ inc(bufidx,identidx);
+ end;
+ { add text }
+ if bufidx+length(s)>logbufsize-2 then
+ flushlog;
+ move(s[1],buf[bufidx],length(s));
+ inc(bufidx,length(s));
+ { add crlf }
+ buf[bufidx]:=target_info.newline[1];
+ inc(bufidx);
+ if length(target_info.newline)=2 then
+ begin
+ buf[bufidx]:=target_info.newline[2];
+ inc(bufidx);
+ end;
+ end;
+
+
+ procedure tbrowserlog.addlogrefs(p:tref);
+ var
+ ref : tref;
+ begin
+ ref:=p;
+ Ident;
+ while assigned(ref) do
+ begin
+ Browserlog.AddLog(get_file_line(ref));
+ ref:=ref.nextref;
+ end;
+ Unident;
+ end;
+
+
+ procedure tbrowserlog.browse_symbol(const sr : string);
+ var
+ sym : tsym;
+ symb : tstoredsym;
+ symt : tsymtable;
+ hp : tmodule;
+ s,ss : string;
+ p : byte;
+
+ procedure next_substring;
+ begin
+ p:=pos('.',s);
+ if p>0 then
+ begin
+ ss:=copy(s,1,p-1);
+ s:=copy(s,p+1,255);
+ end
+ else
+ begin
+ ss:=s;
+ s:='';
+ end;
+ addlog('substring : '+ss);
+ end;
+ begin
+ { don't create a new reference when
+ looking for the symbol !! }
+ make_ref:=false;
+ s:=sr;
+ symt:=symtablestack;
+ next_substring;
+ if assigned(symt) then
+ begin
+ sym:=tstoredsym(symt.search(ss));
+ if sym=nil then
+ sym:=tstoredsym(symt.search(upper(ss)));
+ end
+ else
+ sym:=nil;
+ if assigned(sym) and (sym.typ=unitsym) and (s<>'') then
+ begin
+ addlog('Unitsym found !');
+ symt:=tunitsym(sym).unitsymtable;
+ if assigned(symt) then
+ begin
+ next_substring;
+ sym:=tstoredsym(symt.search(ss));
+ end
+ else
+ sym:=nil;
+ end;
+ if not assigned(sym) then
+ begin
+ symt:=nil;
+ { try all loaded_units }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.modulename^=upper(ss) then
+ begin
+ symt:=hp.globalsymtable;
+ break;
+ end;
+ hp:=tmodule(hp.next);
+ end;
+ if not assigned(symt) then
+ begin
+ addlog('!!!Symbol '+ss+' not found !!!');
+ make_ref:=true;
+ exit;
+ end
+ else
+ begin
+ next_substring;
+ sym:=tstoredsym(symt.search(ss));
+ if sym=nil then
+ sym:=tstoredsym(symt.search(upper(ss)));
+ end;
+ end;
+
+ while assigned(sym) and (s<>'') do
+ begin
+ next_substring;
+ case sym.typ of
+ typesym :
+ begin
+ if ttypesym(sym).restype.def.deftype in [recorddef,objectdef] then
+ begin
+ if ttypesym(sym).restype.def.deftype=recorddef then
+ symt:=trecorddef(ttypesym(sym).restype.def).symtable
+ else
+ symt:=tobjectdef(ttypesym(sym).restype.def).symtable;
+ sym:=tstoredsym(symt.search(ss));
+ if sym=nil then
+ sym:=tstoredsym(symt.search(upper(ss)));
+ end;
+ end;
+ globalvarsym,
+ localvarsym,
+ paravarsym,
+ fieldvarsym :
+ begin
+ if tabstractvarsym(sym).vartype.def.deftype in [recorddef,objectdef] then
+ begin
+ symt:=tabstractvarsym(sym).vartype.def.getsymtable(gs_record);
+ sym:=tstoredsym(symt.search(ss));
+ if sym=nil then
+ sym:=tstoredsym(symt.search(upper(ss)));
+ end;
+ end;
+ procsym :
+ begin
+ symt:=tprocsym(sym).first_procdef.parast;
+ symb:=tstoredsym(symt.search(ss));
+ if symb=nil then
+ symb:=tstoredsym(symt.search(upper(ss)));
+ if not assigned(symb) then
+ begin
+ symt:=tprocsym(sym).first_procdef.localst;
+ sym:=tstoredsym(symt.search(ss));
+ if symb=nil then
+ symb:=tstoredsym(symt.search(upper(ss)));
+ end
+ else
+ sym:=symb;
+ end;
+ end;
+ end;
+ if assigned(sym) then
+ begin
+ if assigned(sym.defref) then
+ begin
+ browserlog.AddLog('***'+sym.name+'***');
+ browserlog.AddLogRefs(sym.defref);
+ end;
+ end
+ else
+ addlog('!!!Symbol '+ss+' not found !!!');
+ make_ref:=true;
+ end;
+
+ procedure tbrowserlog.ident;
+ begin
+ inc(identidx,2);
+ end;
+
+
+ procedure tbrowserlog.unident;
+ begin
+ dec(identidx,2);
+ end;
+
+ procedure writesymtable(p:Tsymtable);forward;
+
+ procedure writelocalsymtables(p:Tprocdef;arg:pointer);
+
+ begin
+ if assigned(p.defref) then
+ begin
+ browserlog.AddLog('***'+p.mangledname);
+ browserlog.AddLogRefs(p.defref);
+ if (current_module.flags and uf_local_browser)<>0 then
+ begin
+ if assigned(p.parast) then
+ writesymtable(p.parast);
+ if assigned(p.localst) then
+ writesymtable(p.localst);
+ end;
+ end;
+ end;
+
+
+ procedure writesymtable(p:tsymtable);
+ var
+ hp : tsym;
+ prdef : pprocdeflist;
+ begin
+ if cs_browser in aktmoduleswitches then
+ begin
+ if assigned(p.name) then
+ Browserlog.AddLog('---Symtable '+p.name^)
+ else
+ begin
+ if (p.symtabletype=recordsymtable) and
+ assigned(tdef(p.defowner).typesym) then
+ Browserlog.AddLog('---Symtable '+tdef(p.defowner).typesym.name)
+ else
+ Browserlog.AddLog('---Symtable with no name');
+ end;
+ Browserlog.Ident;
+ hp:=tstoredsym(p.symindex.first);
+ while assigned(hp) do
+ begin
+ if assigned(hp.defref) then
+ begin
+ browserlog.AddLog('***'+hp.name+'***');
+ browserlog.AddLogRefs(hp.defref);
+ end;
+ case hp.typ of
+ typesym :
+ begin
+ if (ttypesym(hp).restype.def.deftype=recorddef) then
+ writesymtable(trecorddef(ttypesym(hp).restype.def).symtable);
+ if (ttypesym(hp).restype.def.deftype=objectdef) then
+ writesymtable(tobjectdef(ttypesym(hp).restype.def).symtable);
+ end;
+ procsym :
+ Tprocsym(hp).foreach_procdef_static(@writelocalsymtables,nil);
+ end;
+ hp:=tstoredsym(hp.indexnext);
+ end;
+ browserlog.Unident;
+ end;
+ end;
+
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ procedure WriteBrowserLog;
+ var
+ p : tstoredsymtable;
+ hp : tmodule;
+ begin
+ browserlog.CreateLog;
+ browserlog.list_debug_infos;
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ p:=tstoredsymtable(hp.globalsymtable);
+ if assigned(p) then
+ writesymtable(p);
+ if cs_local_browser in aktmoduleswitches then
+ begin
+ p:=tstoredsymtable(hp.localsymtable);
+ if assigned(p) then
+ writesymtable(p);
+ end;
+ hp:=tmodule(hp.next);
+ end;
+ browserlog.CloseLog;
+ end;
+
+
+ procedure InitBrowserLog;
+ begin
+ browserlog.init;
+ end;
+
+ procedure DoneBrowserLog;
+ begin
+ browserlog.done;
+ end;
+
+end.
diff --git a/compiler/bsdcompile b/compiler/bsdcompile
new file mode 100644
index 0000000000..1260d53da6
--- /dev/null
+++ b/compiler/bsdcompile
@@ -0,0 +1,3 @@
+#!/bin/sh
+ppc386 -OG3p3 -Ch8000000 -dI386 -dGDB -dBROWSERLOG -Sg pp.pas -a -s -g %1 %2 %3 %4 %5 %6 %7 %8 %9
+
diff --git a/compiler/catch.pas b/compiler/catch.pas
new file mode 100644
index 0000000000..794680de40
--- /dev/null
+++ b/compiler/catch.pas
@@ -0,0 +1,92 @@
+{
+ Copyright (c) 1998-2002 by Michael Van Canneyt
+
+ Unit to catch segmentation faults and Ctrl-C and exit gracefully
+ under linux and go32v2
+
+ 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 catch;
+
+{$i fpcdefs.inc}
+
+{$ifdef DEBUG}
+ {$define NOCATCH}
+{$endif DEBUG}
+
+interface
+uses
+{$ifdef unix}
+ {$ifndef beos}
+ {$define has_signal}
+ {$ifdef havelinuxrtl10}
+ Linux,
+ {$else}
+ BaseUnix,Unix,
+ {$endif}
+ {$endif}
+{$endif}
+{$ifdef go32v2}
+{$define has_signal}
+ dpmiexcp,
+{$endif}
+{$ifdef watcom}
+ {$define has_signal}
+ dpmiexcp,
+{$endif}
+ verbose;
+
+{$ifdef has_signal}
+Var
+ NewSignal,
+ OldSigInt : SignalHandler;
+{$endif}
+
+Const in_const_evaluation : boolean = false;
+
+Implementation
+
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+uses
+ comphook;
+{$ENDIF MACOS_USE_FAKE_SYSUTILS}
+
+{$ifdef has_signal}
+{$ifdef unix}
+Procedure CatchSignal(Sig : Longint);cdecl;
+{$else}
+Function CatchSignal(Sig : longint):longint;
+{$endif}
+begin
+ case Sig of
+ SIGINT :
+ raise EControlCAbort.Create;
+ end;
+{$ifndef unix}
+ CatchSignal:=0;
+{$endif}
+end;
+{$endif def has_signal}
+
+begin
+{$ifndef nocatch}
+ {$ifdef has_signal}
+ NewSignal:=SignalHandler(@CatchSignal);
+ OldSigInt:={$ifdef havelinuxrtl10}Signal{$else}{$ifdef Unix}fpSignal{$else}Signal{$endif}{$endif} (SIGINT,NewSignal);
+ {$endif}
+{$endif nocatch}
+end.
diff --git a/compiler/cclasses.pas b/compiler/cclasses.pas
new file mode 100644
index 0000000000..94b1259839
--- /dev/null
+++ b/compiler/cclasses.pas
@@ -0,0 +1,2352 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ This module provides some basic classes
+
+ 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 cclasses;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cstreams;
+
+{********************************************
+ TMemDebug
+********************************************}
+
+ type
+ tmemdebug = class
+ private
+ totalmem,
+ startmem : integer;
+ infostr : string[40];
+ public
+ constructor Create(const s:string);
+ destructor Destroy;override;
+ procedure show;
+ procedure start;
+ procedure stop;
+ end;
+
+{*******************************************************
+ TList (Copied from FCL, exception handling stripped)
+********************************************************}
+
+const
+ MaxListSize = Maxint div 16;
+ SListIndexError = 'List index exceeds bounds (%d)';
+ SListCapacityError = 'The maximum list capacity is reached (%d)';
+ SListCountError = 'List count too large (%d)';
+type
+{ TList class }
+
+ PPointerList = ^TPointerList;
+ TPointerList = array[0..MaxListSize - 1] of Pointer;
+ TListSortCompare = function (Item1, Item2: Pointer): Integer;
+
+ TList = class(TObject)
+ private
+ FList: PPointerList;
+ FCount: Integer;
+ FCapacity: Integer;
+ protected
+ function Get(Index: Integer): Pointer;
+ procedure Grow; virtual;
+ procedure Put(Index: Integer; Item: Pointer);
+ procedure SetCapacity(NewCapacity: Integer);
+ procedure SetCount(NewCount: Integer);
+ public
+ destructor Destroy; override;
+ function Add(Item: Pointer): Integer;
+ procedure Clear; dynamic;
+ procedure Delete(Index: Integer);
+ class procedure Error(const Msg: string; Data: Integer); virtual;
+ procedure Exchange(Index1, Index2: Integer);
+ function Expand: TList;
+ function Extract(item: Pointer): Pointer;
+ function First: Pointer;
+ procedure Assign(Obj:TList);
+ function IndexOf(Item: Pointer): Integer;
+ procedure Insert(Index: Integer; Item: Pointer);
+ function Last: Pointer;
+ procedure Move(CurIndex, NewIndex: Integer);
+ function Remove(Item: Pointer): Integer;
+ procedure Pack;
+ procedure Sort(Compare: TListSortCompare);
+ property Capacity: Integer read FCapacity write SetCapacity;
+ property Count: Integer read FCount write SetCount;
+ property Items[Index: Integer]: Pointer read Get write Put; default;
+ property List: PPointerList read FList;
+ end;
+
+{********************************************
+ TLinkedList
+********************************************}
+
+ type
+ TLinkedListItem = class
+ public
+ Previous,
+ Next : TLinkedListItem;
+ Constructor Create;
+ Destructor Destroy;override;
+ Function GetCopy:TLinkedListItem;virtual;
+ end;
+
+ TLinkedListItemClass = class of TLinkedListItem;
+
+ TLinkedList = class
+ private
+ FCount : integer;
+ FFirst,
+ FLast : TLinkedListItem;
+ FNoClear : boolean;
+ public
+ constructor Create;
+ destructor Destroy;override;
+ { true when the List is empty }
+ function Empty:boolean;
+ { deletes all Items }
+ procedure Clear;
+ { inserts an Item }
+ procedure Insert(Item:TLinkedListItem);
+ { inserts an Item before Loc }
+ procedure InsertBefore(Item,Loc : TLinkedListItem);
+ { inserts an Item after Loc }
+ procedure InsertAfter(Item,Loc : TLinkedListItem);virtual;
+ { concats an Item }
+ procedure Concat(Item:TLinkedListItem);
+ { deletes an Item }
+ procedure Remove(Item:TLinkedListItem);
+ { Gets First Item }
+ function GetFirst:TLinkedListItem;
+ { Gets last Item }
+ function GetLast:TLinkedListItem;
+ { inserts another List at the begin and make this List empty }
+ procedure insertList(p : TLinkedList);
+ { inserts another List before the provided item and make this List empty }
+ procedure insertListBefore(Item:TLinkedListItem;p : TLinkedList);
+ { inserts another List after the provided item and make this List empty }
+ procedure insertListAfter(Item:TLinkedListItem;p : TLinkedList);
+ { concats another List at the end and make this List empty }
+ procedure concatList(p : TLinkedList);
+ { concats another List at the start and makes a copy
+ the list is ordered in reverse.
+ }
+ procedure insertListcopy(p : TLinkedList);
+ { concats another List at the end and makes a copy }
+ procedure concatListcopy(p : TLinkedList);
+ property First:TLinkedListItem read FFirst;
+ property Last:TLinkedListItem read FLast;
+ property Count:Integer read FCount;
+ property NoClear:boolean write FNoClear;
+ end;
+
+{********************************************
+ TStringList
+********************************************}
+
+ { string containerItem }
+ TStringListItem = class(TLinkedListItem)
+ FPStr : PString;
+ public
+ constructor Create(const s:string);
+ destructor Destroy;override;
+ function GetCopy:TLinkedListItem;override;
+ function Str:string;
+ end;
+
+ { string container }
+ TStringList = class(TLinkedList)
+ private
+ FDoubles : boolean; { if this is set to true, doubles are allowed }
+ public
+ constructor Create;
+ constructor Create_No_Double;
+ { inserts an Item }
+ procedure Insert(const s:string);
+ { concats an Item }
+ procedure Concat(const s:string);
+ { deletes an Item }
+ procedure Remove(const s:string);
+ { Gets First Item }
+ function GetFirst:string;
+ { Gets last Item }
+ function GetLast:string;
+ { true if string is in the container, compare case sensitive }
+ function FindCase(const s:string):TStringListItem;
+ { true if string is in the container }
+ function Find(const s:string):TStringListItem;
+ { inserts an item }
+ procedure InsertItem(item:TStringListItem);
+ { concats an item }
+ procedure ConcatItem(item:TStringListItem);
+ property Doubles:boolean read FDoubles write FDoubles;
+ end;
+
+
+{********************************************
+ Dictionary
+********************************************}
+
+ const
+ { the real size will be [0..hasharray-1] ! }
+ hasharraysize = 512;
+
+ type
+ { namedindexobect for use with dictionary and indexarray }
+ TNamedIndexItem=class
+ private
+ { indexarray }
+ FIndexNr : integer;
+ FIndexNext : TNamedIndexItem;
+ { dictionary }
+ FLeft,
+ FRight : TNamedIndexItem;
+ FSpeedValue : cardinal;
+ { singleList }
+ FListNext : TNamedIndexItem;
+ FName : Pstring;
+ protected
+ function GetName:string;virtual;
+ procedure SetName(const n:string);virtual;
+ public
+ constructor Create;
+ constructor CreateName(const n:string);
+ destructor Destroy;override;
+ property IndexNr:integer read FIndexNr write FIndexNr;
+ property IndexNext:TNamedIndexItem read FIndexNext write FIndexNext;
+ property Name:string read GetName write SetName;
+ property SpeedValue:cardinal read FSpeedValue;
+ property ListNext:TNamedIndexItem read FListNext;
+ property Left:TNamedIndexItem read FLeft write FLeft;
+ property Right:TNamedIndexItem read FRight write FRight;
+ end;
+
+ Pdictionaryhasharray=^Tdictionaryhasharray;
+ Tdictionaryhasharray=array[0..hasharraysize-1] of TNamedIndexItem;
+
+ TnamedIndexCallback = procedure(p:TNamedIndexItem;arg:pointer) of object;
+ TnamedIndexStaticCallback = procedure(p:TNamedIndexItem;arg:pointer);
+
+ Tdictionary=class
+ private
+ FRoot : TNamedIndexItem;
+ FCount : longint;
+ FHashArray : Pdictionaryhasharray;
+ procedure cleartree(var obj:TNamedIndexItem);
+ function insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
+ procedure inserttree(currtree,currroot:TNamedIndexItem);
+ public
+ noclear : boolean;
+ delete_doubles : boolean;
+ constructor Create;
+ destructor Destroy;override;
+ procedure usehash;
+ procedure clear;
+ function delete(const s:string):TNamedIndexItem;
+ function empty:boolean;
+ procedure foreach(proc2call:TNamedIndexcallback;arg:pointer);
+ procedure foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
+ function insert(obj:TNamedIndexItem):TNamedIndexItem;
+ function replace(oldobj,newobj:TNamedIndexItem):boolean;
+ function rename(const olds,News : string):TNamedIndexItem;
+ function search(const s:string):TNamedIndexItem;
+ function speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
+ property Items[const s:string]:TNamedIndexItem read Search;default;
+ property Count:longint read FCount;
+ end;
+
+ tsingleList=class
+ First,
+ last : TNamedIndexItem;
+ constructor Create;
+ procedure reset;
+ procedure clear;
+ procedure insert(p:TNamedIndexItem);
+ end;
+
+ tindexobjectarray=array[1..16000] of TNamedIndexItem;
+ pnamedindexobjectarray=^tindexobjectarray;
+
+ tindexarray=class
+ noclear : boolean;
+ First : TNamedIndexItem;
+ count : integer;
+ constructor Create(Agrowsize:integer);
+ destructor destroy;override;
+ procedure clear;
+ procedure foreach(proc2call : Tnamedindexcallback;arg:pointer);
+ procedure foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
+ procedure deleteindex(p:TNamedIndexItem);
+ procedure delete(var p:TNamedIndexItem);
+ procedure insert(p:TNamedIndexItem);
+ procedure replace(oldp,newp:TNamedIndexItem);
+ function search(nr:integer):TNamedIndexItem;
+ private
+ growsize,
+ size : integer;
+ data : pnamedindexobjectarray;
+ procedure grow(gsize:integer);
+ end;
+
+
+{********************************************
+ DynamicArray
+********************************************}
+
+ const
+ dynamicblockbasesize = 12;
+
+ type
+ pdynamicblock = ^tdynamicblock;
+ tdynamicblock = record
+ pos,
+ used : integer;
+ Next : pdynamicblock;
+ { can't use sizeof(integer) because it crashes gdb }
+ data : array[0..1024*1024] of byte;
+ end;
+
+ tdynamicarray = class
+ private
+ FPosn : integer;
+ FPosnblock : pdynamicblock;
+ FBlocksize : integer;
+ FFirstblock,
+ FLastblock : pdynamicblock;
+ procedure grow;
+ public
+ constructor Create(Ablocksize:integer);
+ destructor Destroy;override;
+ procedure reset;
+ function size:integer;
+ procedure align(i:integer);
+ procedure seek(i:integer);
+ function read(var d;len:integer):integer;
+ procedure write(const d;len:integer);
+ procedure writestr(const s:string);
+ procedure readstream(f:TCStream;maxlen:longint);
+ procedure writestream(f:TCStream);
+ property BlockSize : integer read FBlocksize;
+ property FirstBlock : PDynamicBlock read FFirstBlock;
+ property Pos : integer read FPosn;
+ end;
+
+
+implementation
+
+{*****************************************************************************
+ Memory debug
+*****************************************************************************}
+
+ constructor tmemdebug.create(const s:string);
+ begin
+ infostr:=s;
+ totalmem:=0;
+ Start;
+ end;
+
+
+ procedure tmemdebug.start;
+
+ var
+ status : TFPCHeapStatus;
+
+ begin
+ status:=GetFPCHeapStatus;
+ startmem:=status.CurrHeapUsed;
+ end;
+
+
+ procedure tmemdebug.stop;
+ var
+ status : TFPCHeapStatus;
+ begin
+ if startmem<>0 then
+ begin
+ status:=GetFPCHeapStatus;
+ inc(TotalMem,startmem-status.CurrHeapUsed);
+ startmem:=0;
+ end;
+ end;
+
+
+ destructor tmemdebug.destroy;
+ begin
+ Stop;
+ show;
+ end;
+
+
+ procedure tmemdebug.show;
+ begin
+ write('memory [',infostr,'] ');
+ if TotalMem>0 then
+ writeln(DStr(TotalMem shr 10),' Kb released')
+ else
+ writeln(DStr((-TotalMem) shr 10),' Kb allocated');
+ end;
+
+
+{*****************************************************************************
+ TList
+*****************************************************************************}
+
+Const
+ // Ratio of Pointer and Word Size.
+ WordRatio = SizeOf(Pointer) Div SizeOf(Word);
+
+function TList.Get(Index: Integer): Pointer;
+
+begin
+ If (Index<0) or (Index>=FCount) then
+ Error(SListIndexError,Index);
+ Result:=FList^[Index];
+end;
+
+
+
+procedure TList.Grow;
+
+begin
+ // Only for compatibility with Delphi. Not needed.
+end;
+
+
+
+procedure TList.Put(Index: Integer; Item: Pointer);
+
+begin
+ if (Index<0) or (Index>=FCount) then
+ Error(SListIndexError,Index);
+ Flist^[Index]:=Item;
+end;
+
+
+function TList.Extract(item: Pointer): Pointer;
+var
+ i : Integer;
+begin
+ result:=nil;
+ i:=IndexOf(item);
+ if i>=0 then
+ begin
+ Result:=item;
+ FList^[i]:=nil;
+ Delete(i);
+ end;
+end;
+
+
+procedure TList.SetCapacity(NewCapacity: Integer);
+begin
+ If (NewCapacity<0) or (NewCapacity>MaxListSize) then
+ Error (SListCapacityError,NewCapacity);
+ if NewCapacity=FCapacity then
+ exit;
+ ReallocMem(FList,SizeOf(Pointer)*NewCapacity);
+ if NewCapacity > FCapacity then
+ FillChar (FList^ [FCapacity],
+ (NewCapacity - FCapacity) * SizeOf (pointer), 0);
+ FCapacity:=NewCapacity;
+end;
+
+
+
+procedure TList.SetCount(NewCount: Integer);
+
+begin
+ If (NewCount<0) or (NewCount>MaxListSize)then
+ Error(SListCountError,NewCount);
+ If NewCount<FCount then
+ FCount:=NewCount
+ else If NewCount>FCount then
+ begin
+ If NewCount>FCapacity then
+ SetCapacity (NewCount);
+ If FCount<NewCount then
+ FillWord (Flist^[FCount],(NewCount-FCount)* WordRatio ,0);
+ FCount:=Newcount;
+ end;
+end;
+
+
+
+destructor TList.Destroy;
+
+begin
+ Self.Clear;
+ inherited Destroy;
+end;
+
+
+Function TList.Add(Item: Pointer): Integer;
+
+begin
+ Self.Insert (Count,Item);
+ Result:=Count-1;
+end;
+
+
+
+Procedure TList.Clear;
+
+begin
+ If Assigned(FList) then
+ begin
+ FreeMem (Flist,FCapacity*SizeOf(Pointer));
+ FList:=Nil;
+ FCapacity:=0;
+ FCount:=0;
+ end;
+end;
+
+
+Procedure TList.Delete(Index: Integer);
+begin
+ If (Index<0) or (Index>=FCount) then
+ Error (SListIndexError,Index);
+ FCount:=FCount-1;
+ System.Move (FList^[Index+1],FList^[Index],(FCount-Index)*SizeOf(Pointer));
+ // Shrink the list if appropiate
+ if (FCapacity > 256) and (FCount < FCapacity shr 2) then
+ begin
+ FCapacity := FCapacity shr 1;
+ ReallocMem(FList, SizeOf(Pointer) * FCapacity);
+ end;
+end;
+
+
+class procedure TList.Error(const Msg: string; Data: Integer);
+{$ifdef EXTDEBUG}
+var
+ s : string;
+{$endif EXTDEBUG}
+begin
+{$ifdef EXTDEBUG}
+ s:=Msg;
+ Replace(s,'%d',ToStr(Data));
+ writeln(s);
+{$endif EXTDEBUG}
+ internalerrorproc(200411151);
+end;
+
+procedure TList.Exchange(Index1, Index2: Integer);
+
+var Temp : Pointer;
+
+begin
+ If ((Index1>=FCount) or (Index1<0)) then
+ Error(SListIndexError,Index1);
+ If ((Index2>=FCount) or (Index2<0)) then
+ Error(SListIndexError,Index2);
+ Temp:=FList^[Index1];
+ FList^[Index1]:=FList^[Index2];
+ FList^[Index2]:=Temp;
+end;
+
+
+
+function TList.Expand: TList;
+
+Var IncSize : Longint;
+
+begin
+ if FCount<FCapacity then exit;
+ IncSize:=4;
+ if FCapacity>3 then IncSize:=IncSize+4;
+ if FCapacity>8 then IncSize:=IncSize+8;
+ if FCapacity>127 then Inc(IncSize, FCapacity shr 2);
+ SetCapacity(FCapacity+IncSize);
+ Result:=Self;
+end;
+
+
+function TList.First: Pointer;
+
+begin
+ If FCount=0 then
+ Result:=Nil
+ else
+ Result:=Items[0];
+end;
+
+
+
+function TList.IndexOf(Item: Pointer): Integer;
+
+begin
+ Result:=0;
+ While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
+ If Result=FCount then Result:=-1;
+end;
+
+
+
+procedure TList.Insert(Index: Integer; Item: Pointer);
+
+begin
+ If (Index<0) or (Index>FCount )then
+ Error(SlistIndexError,Index);
+ IF FCount=FCapacity Then Self.Expand;
+ If Index<FCount then
+ System.Move(Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
+ FList^[Index]:=Item;
+ FCount:=FCount+1;
+end;
+
+
+
+function TList.Last: Pointer;
+
+begin
+ // Wouldn't it be better to return nil if the count is zero ?
+ If FCount=0 then
+ Result:=Nil
+ else
+ Result:=Items[FCount-1];
+end;
+
+
+procedure TList.Move(CurIndex, NewIndex: Integer);
+
+Var Temp : Pointer;
+
+begin
+ If ((CurIndex<0) or (CurIndex>Count-1)) then
+ Error(SListIndexError,CurIndex);
+ If (NewINdex<0) then
+ Error(SlistIndexError,NewIndex);
+ Temp:=FList^[CurIndex];
+ FList^[CurIndex]:=Nil;
+ Self.Delete(CurIndex);
+ // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
+ // Newindex changes when deleting ??
+ Self.Insert (NewIndex,Nil);
+ FList^[NewIndex]:=Temp;
+end;
+
+
+function TList.Remove(Item: Pointer): Integer;
+
+begin
+ Result:=IndexOf(Item);
+ If Result<>-1 then
+ Self.Delete (Result);
+end;
+
+
+
+Procedure TList.Pack;
+
+Var {Last,I,J,}Runner : Longint;
+
+begin
+ // Not the fastest; but surely correct
+ For Runner:=Fcount-1 downto 0 do
+ if Items[Runner]=Nil then Self.Delete(Runner);
+{ The following may be faster in case of large and defragmented lists
+ If count=0 then exit;
+ Runner:=0;I:=0;
+ TheLast:=Count;
+ while runner<count do
+ begin
+ // Find first Nil
+ While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
+ if Runner<Count do
+ begin
+ // Start searching for non-nil from last known nil+1
+ if i<Runner then I:=Runner+1;
+ While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
+ // Start looking for last non-nil of block.
+ J:=I+1;
+ While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
+ // Move block and zero out
+ Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
+ FillWord (Flist^[I],(J-I)*WordRatio,0);
+ // Update Runner and Last to point behind last block
+ TheLast:=Runner+(J-I);
+ If J=Count then
+ begin
+ // Shortcut, when J=Count we checked all pointers
+ Runner:=Count
+ else
+ begin
+ Runner:=TheLast;
+ I:=j;
+ end;
+ end;
+ Count:=TheLast;
+}
+end;
+
+// Needed by Sort method.
+
+Procedure QuickSort (Flist : PPointerList; L,R : Longint;
+ Compare : TListSortCompare);
+
+Var I,J : Longint;
+ P,Q : Pointer;
+
+begin
+ Repeat
+ I:=L;
+ J:=R;
+ P:=FList^[ (L+R) div 2 ];
+ repeat
+ While Compare(P,FList^[i])>0 Do I:=I+1;
+ While Compare(P,FList^[J])<0 Do J:=J-1;
+ If I<=J then
+ begin
+ Q:=Flist^[I];
+ Flist^[I]:=FList^[J];
+ FList^[J]:=Q;
+ I:=I+1;
+ J:=j-1;
+ end;
+ Until I>J;
+ If L<J then QuickSort (FList,L,J,Compare);
+ L:=I;
+ Until I>=R;
+end;
+
+procedure TList.Sort(Compare: TListSortCompare);
+
+begin
+ If Not Assigned(FList) or (FCount<2) then exit;
+ QuickSort (Flist, 0, FCount-1,Compare);
+end;
+
+procedure TList.Assign(Obj:TList);
+// Principle copied from TCollection
+
+var i : Integer;
+begin
+ Clear;
+ For I:=0 To Obj.Count-1 Do
+ Add(Obj[i]);
+end;
+
+
+{****************************************************************************
+ TLinkedListItem
+ ****************************************************************************}
+
+ constructor TLinkedListItem.Create;
+ begin
+ Previous:=nil;
+ Next:=nil;
+ end;
+
+
+ destructor TLinkedListItem.Destroy;
+ begin
+ end;
+
+
+ function TLinkedListItem.GetCopy:TLinkedListItem;
+ var
+ p : TLinkedListItem;
+ l : integer;
+ begin
+ p:=TLinkedListItemClass(ClassType).Create;
+ l:=InstanceSize;
+ Move(pointer(self)^,pointer(p)^,l);
+ Result:=p;
+ end;
+
+
+{****************************************************************************
+ TLinkedList
+ ****************************************************************************}
+
+ constructor TLinkedList.Create;
+ begin
+ FFirst:=nil;
+ Flast:=nil;
+ FCount:=0;
+ FNoClear:=False;
+ end;
+
+
+ destructor TLinkedList.destroy;
+ begin
+ if not FNoClear then
+ Clear;
+ end;
+
+
+ function TLinkedList.empty:boolean;
+ begin
+ Empty:=(FFirst=nil);
+ end;
+
+
+ procedure TLinkedList.Insert(Item:TLinkedListItem);
+ begin
+ if FFirst=nil then
+ begin
+ FLast:=Item;
+ Item.Previous:=nil;
+ Item.Next:=nil;
+ end
+ else
+ begin
+ FFirst.Previous:=Item;
+ Item.Previous:=nil;
+ Item.Next:=FFirst;
+ end;
+ FFirst:=Item;
+ inc(FCount);
+ end;
+
+
+ procedure TLinkedList.InsertBefore(Item,Loc : TLinkedListItem);
+ begin
+ Item.Previous:=Loc.Previous;
+ Item.Next:=Loc;
+ Loc.Previous:=Item;
+ if assigned(Item.Previous) then
+ Item.Previous.Next:=Item
+ else
+ { if we've no next item, we've to adjust FFist }
+ FFirst:=Item;
+ inc(FCount);
+ end;
+
+
+ procedure TLinkedList.InsertAfter(Item,Loc : TLinkedListItem);
+ begin
+ Item.Next:=Loc.Next;
+ Loc.Next:=Item;
+ Item.Previous:=Loc;
+ if assigned(Item.Next) then
+ Item.Next.Previous:=Item
+ else
+ { if we've no next item, we've to adjust FLast }
+ FLast:=Item;
+ inc(FCount);
+ end;
+
+
+ procedure TLinkedList.Concat(Item:TLinkedListItem);
+ begin
+ if FFirst=nil then
+ begin
+ FFirst:=Item;
+ Item.Previous:=nil;
+ Item.Next:=nil;
+ end
+ else
+ begin
+ Flast.Next:=Item;
+ Item.Previous:=Flast;
+ Item.Next:=nil;
+ end;
+ Flast:=Item;
+ inc(FCount);
+ end;
+
+
+ procedure TLinkedList.remove(Item:TLinkedListItem);
+ begin
+ if Item=nil then
+ exit;
+ if (FFirst=Item) and (Flast=Item) then
+ begin
+ FFirst:=nil;
+ Flast:=nil;
+ end
+ else if FFirst=Item then
+ begin
+ FFirst:=Item.Next;
+ if assigned(FFirst) then
+ FFirst.Previous:=nil;
+ end
+ else if Flast=Item then
+ begin
+ Flast:=Flast.Previous;
+ if assigned(Flast) then
+ Flast.Next:=nil;
+ end
+ else
+ begin
+ Item.Previous.Next:=Item.Next;
+ Item.Next.Previous:=Item.Previous;
+ end;
+ Item.Next:=nil;
+ Item.Previous:=nil;
+ dec(FCount);
+ end;
+
+
+ procedure TLinkedList.clear;
+ var
+ NewNode : TLinkedListItem;
+ begin
+ NewNode:=FFirst;
+ while assigned(NewNode) do
+ begin
+ FFirst:=NewNode.Next;
+ NewNode.Free;
+ NewNode:=FFirst;
+ end;
+ FLast:=nil;
+ FFirst:=nil;
+ FCount:=0;
+ end;
+
+
+ function TLinkedList.GetFirst:TLinkedListItem;
+ begin
+ if FFirst=nil then
+ GetFirst:=nil
+ else
+ begin
+ GetFirst:=FFirst;
+ if FFirst=FLast then
+ FLast:=nil;
+ FFirst:=FFirst.Next;
+ dec(FCount);
+ end;
+ end;
+
+
+ function TLinkedList.GetLast:TLinkedListItem;
+ begin
+ if FLast=nil then
+ Getlast:=nil
+ else
+ begin
+ Getlast:=FLast;
+ if FLast=FFirst then
+ FFirst:=nil;
+ FLast:=FLast.Previous;
+ dec(FCount);
+ end;
+ end;
+
+
+ procedure TLinkedList.insertList(p : TLinkedList);
+ begin
+ { empty List ? }
+ if (p.FFirst=nil) then
+ exit;
+ p.Flast.Next:=FFirst;
+ { we have a double Linked List }
+ if assigned(FFirst) then
+ FFirst.Previous:=p.Flast;
+ FFirst:=p.FFirst;
+ if (FLast=nil) then
+ Flast:=p.Flast;
+ inc(FCount,p.FCount);
+ { p becomes empty }
+ p.FFirst:=nil;
+ p.Flast:=nil;
+ p.FCount:=0;
+ end;
+
+
+ procedure TLinkedList.insertListBefore(Item:TLinkedListItem;p : TLinkedList);
+ begin
+ { empty List ? }
+ if (p.FFirst=nil) then
+ exit;
+ if (Item=nil) then
+ begin
+ { Insert at begin }
+ InsertList(p);
+ exit;
+ end
+ else
+ begin
+ p.FLast.Next:=Item;
+ p.FFirst.Previous:=Item.Previous;
+ if assigned(Item.Previous) then
+ Item.Previous.Next:=p.FFirst
+ else
+ FFirst:=p.FFirst;
+ Item.Previous:=p.FLast;
+ inc(FCount,p.FCount);
+ end;
+ { p becomes empty }
+ p.FFirst:=nil;
+ p.Flast:=nil;
+ p.FCount:=0;
+ end;
+
+
+ procedure TLinkedList.insertListAfter(Item:TLinkedListItem;p : TLinkedList);
+ begin
+ { empty List ? }
+ if (p.FFirst=nil) then
+ exit;
+ if (Item=nil) then
+ begin
+ { Insert at begin }
+ InsertList(p);
+ exit;
+ end
+ else
+ begin
+ p.FFirst.Previous:=Item;
+ p.FLast.Next:=Item.Next;
+ if assigned(Item.Next) then
+ Item.Next.Previous:=p.FLast
+ else
+ FLast:=p.FLast;
+ Item.Next:=p.FFirst;
+ inc(FCount,p.FCount);
+ end;
+ { p becomes empty }
+ p.FFirst:=nil;
+ p.Flast:=nil;
+ p.FCount:=0;
+ end;
+
+
+ procedure TLinkedList.concatList(p : TLinkedList);
+ begin
+ if (p.FFirst=nil) then
+ exit;
+ if FFirst=nil then
+ FFirst:=p.FFirst
+ else
+ begin
+ FLast.Next:=p.FFirst;
+ p.FFirst.Previous:=Flast;
+ end;
+ Flast:=p.Flast;
+ inc(FCount,p.FCount);
+ { make p empty }
+ p.Flast:=nil;
+ p.FFirst:=nil;
+ p.FCount:=0;
+ end;
+
+
+ procedure TLinkedList.insertListcopy(p : TLinkedList);
+ var
+ NewNode,NewNode2 : TLinkedListItem;
+ begin
+ NewNode:=p.First;
+ while assigned(NewNode) do
+ begin
+ NewNode2:=NewNode.Getcopy;
+ if assigned(NewNode2) then
+ Insert(NewNode2);
+ NewNode:=NewNode.Next;
+ end;
+ end;
+
+
+ procedure TLinkedList.concatListcopy(p : TLinkedList);
+ var
+ NewNode,NewNode2 : TLinkedListItem;
+ begin
+ NewNode:=p.First;
+ while assigned(NewNode) do
+ begin
+ NewNode2:=NewNode.Getcopy;
+ if assigned(NewNode2) then
+ Concat(NewNode2);
+ NewNode:=NewNode.Next;
+ end;
+ end;
+
+
+{****************************************************************************
+ TStringListItem
+ ****************************************************************************}
+
+ constructor TStringListItem.Create(const s:string);
+ begin
+ inherited Create;
+ FPStr:=stringdup(s);
+ end;
+
+
+ destructor TStringListItem.Destroy;
+ begin
+ stringdispose(FPStr);
+ end;
+
+
+ function TStringListItem.Str:string;
+ begin
+ Str:=FPStr^;
+ end;
+
+
+ function TStringListItem.GetCopy:TLinkedListItem;
+ begin
+ Result:=(inherited GetCopy);
+ TStringListItem(Result).FPStr:=stringdup(FPstr^);
+ end;
+
+
+{****************************************************************************
+ TSTRINGList
+ ****************************************************************************}
+
+ constructor tstringList.Create;
+ begin
+ inherited Create;
+ FDoubles:=true;
+ end;
+
+
+ constructor tstringList.Create_no_double;
+ begin
+ inherited Create;
+ FDoubles:=false;
+ end;
+
+
+ procedure tstringList.insert(const s : string);
+ begin
+ if (s='') or
+ ((not FDoubles) and (find(s)<>nil)) then
+ exit;
+ inherited insert(tstringListItem.create(s));
+ end;
+
+
+ procedure tstringList.concat(const s : string);
+ begin
+ if (s='') or
+ ((not FDoubles) and (find(s)<>nil)) then
+ exit;
+ inherited concat(tstringListItem.create(s));
+ end;
+
+
+ procedure tstringList.remove(const s : string);
+ var
+ p : tstringListItem;
+ begin
+ if s='' then
+ exit;
+ p:=find(s);
+ if assigned(p) then
+ begin
+ inherited Remove(p);
+ p.Free;
+ end;
+ end;
+
+
+ function tstringList.GetFirst : string;
+ var
+ p : tstringListItem;
+ begin
+ p:=tstringListItem(inherited GetFirst);
+ if p=nil then
+ GetFirst:=''
+ else
+ begin
+ GetFirst:=p.FPStr^;
+ p.free;
+ end;
+ end;
+
+
+ function tstringList.Getlast : string;
+ var
+ p : tstringListItem;
+ begin
+ p:=tstringListItem(inherited Getlast);
+ if p=nil then
+ Getlast:=''
+ else
+ begin
+ Getlast:=p.FPStr^;
+ p.free;
+ end;
+ end;
+
+
+ function tstringList.FindCase(const s:string):TstringListItem;
+ var
+ NewNode : tstringListItem;
+ begin
+ result:=nil;
+ if s='' then
+ exit;
+ NewNode:=tstringListItem(FFirst);
+ while assigned(NewNode) do
+ begin
+ if NewNode.FPStr^=s then
+ begin
+ result:=NewNode;
+ exit;
+ end;
+ NewNode:=tstringListItem(NewNode.Next);
+ end;
+ end;
+
+
+ function tstringList.Find(const s:string):TstringListItem;
+ var
+ NewNode : tstringListItem;
+ ups : string;
+ begin
+ result:=nil;
+ if s='' then
+ exit;
+ ups:=upper(s);
+ NewNode:=tstringListItem(FFirst);
+ while assigned(NewNode) do
+ begin
+ if upper(NewNode.FPStr^)=ups then
+ begin
+ result:=NewNode;
+ exit;
+ end;
+ NewNode:=tstringListItem(NewNode.Next);
+ end;
+ end;
+
+
+ procedure TStringList.InsertItem(item:TStringListItem);
+ begin
+ inherited Insert(item);
+ end;
+
+
+ procedure TStringList.ConcatItem(item:TStringListItem);
+ begin
+ inherited Concat(item);
+ end;
+
+
+{****************************************************************************
+ TNamedIndexItem
+ ****************************************************************************}
+
+ constructor TNamedIndexItem.Create;
+ begin
+ { index }
+ Findexnr:=-1;
+ FindexNext:=nil;
+ { dictionary }
+ Fleft:=nil;
+ Fright:=nil;
+ FName:=nil;
+ Fspeedvalue:=cardinal($ffffffff);
+ { List }
+ FListNext:=nil;
+ end;
+
+ constructor TNamedIndexItem.Createname(const n:string);
+ begin
+ { index }
+ Findexnr:=-1;
+ FindexNext:=nil;
+ { dictionary }
+ Fleft:=nil;
+ Fright:=nil;
+ fspeedvalue:=getspeedvalue(n);
+ {$ifdef compress}
+ FName:=stringdup(minilzw_encode(n));
+ {$else}
+ FName:=stringdup(n);
+ {$endif}
+ { List }
+ FListNext:=nil;
+ end;
+
+
+ destructor TNamedIndexItem.destroy;
+ begin
+ stringdispose(FName);
+ end;
+
+
+ procedure TNamedIndexItem.setname(const n:string);
+ begin
+ if assigned(FName) then
+ stringdispose(FName);
+ fspeedvalue:=getspeedvalue(n);
+ {$ifdef compress}
+ FName:=stringdup(minilzw_encode(n));
+ {$else}
+ FName:=stringdup(n);
+ {$endif}
+ end;
+
+
+ function TNamedIndexItem.GetName:string;
+ begin
+ if assigned(FName) then
+ {$ifdef compress}
+ Getname:=minilzw_decode(FName^)
+ {$else}
+ Getname:=FName^
+ {$endif}
+ else
+ Getname:='';
+ end;
+
+
+{****************************************************************************
+ TDICTIONARY
+****************************************************************************}
+
+ constructor Tdictionary.Create;
+ begin
+ FRoot:=nil;
+ FHashArray:=nil;
+ noclear:=false;
+ delete_doubles:=false;
+ end;
+
+
+ procedure Tdictionary.usehash;
+ begin
+ if not(assigned(FRoot)) and
+ not(assigned(FHashArray)) then
+ begin
+ New(FHashArray);
+ fillchar(FHashArray^,sizeof(FHashArray^),0);
+ end;
+ end;
+
+
+ function counttree(p: tnamedindexitem): longint;
+ begin
+ counttree:=0;
+ if not assigned(p) then
+ exit;
+ result := 1;
+ inc(result,counttree(p.fleft));
+ inc(result,counttree(p.fright));
+ end;
+
+ destructor Tdictionary.destroy;
+ begin
+ if not noclear then
+ clear;
+ if assigned(FHashArray) then
+ begin
+ dispose(FHashArray);
+ end;
+ end;
+
+
+ procedure Tdictionary.cleartree(var obj:TNamedIndexItem);
+ begin
+ if assigned(obj.Fleft) then
+ cleartree(obj.FLeft);
+ if assigned(obj.FRight) then
+ cleartree(obj.FRight);
+ obj.free;
+ obj:=nil;
+ end;
+
+
+ procedure Tdictionary.clear;
+ var
+ w : integer;
+ begin
+ if assigned(FRoot) then
+ cleartree(FRoot);
+ if assigned(FHashArray) then
+ for w:= low(FHashArray^) to high(FHashArray^) do
+ if assigned(FHashArray^[w]) then
+ cleartree(FHashArray^[w]);
+ end;
+
+
+ function Tdictionary.delete(const s:string):TNamedIndexItem;
+ var
+ p,SpeedValue : cardinal;
+ n : TNamedIndexItem;
+ {$ifdef compress}
+ senc:string;
+ {$else}
+ senc:string absolute s;
+ {$endif}
+
+ procedure insert_right_bottom(var root,Atree:TNamedIndexItem);
+ begin
+ while root.FRight<>nil do
+ root:=root.FRight;
+ root.FRight:=Atree;
+ end;
+
+ function delete_from_tree(root:TNamedIndexItem):TNamedIndexItem;
+ type
+ leftright=(left,right);
+ var
+ lr : leftright;
+ oldroot : TNamedIndexItem;
+ begin
+ oldroot:=nil;
+ while (root<>nil) and (root.SpeedValue<>SpeedValue) do
+ begin
+ oldroot:=root;
+ if SpeedValue<root.SpeedValue then
+ begin
+ root:=root.FRight;
+ lr:=right;
+ end
+ else
+ begin
+ root:=root.FLeft;
+ lr:=left;
+ end;
+ end;
+ while (root<>nil) and (root.FName^<>senc) do
+ begin
+ oldroot:=root;
+ if senc<root.FName^ then
+ begin
+ root:=root.FRight;
+ lr:=right;
+ end
+ else
+ begin
+ root:=root.FLeft;
+ lr:=left;
+ end;
+ end;
+ if root<>nil then
+ begin
+ dec(FCount);
+ if root.FLeft<>nil then
+ begin
+ { Now the Node pointing to root must point to the left
+ subtree of root. The right subtree of root must be
+ connected to the right bottom of the left subtree.}
+ if lr=left then
+ oldroot.FLeft:=root.FLeft
+ else
+ oldroot.FRight:=root.FLeft;
+ if root.FRight<>nil then
+ insert_right_bottom(root.FLeft,root.FRight);
+ end
+ else
+ begin
+ { There is no left subtree. So we can just replace the Node to
+ delete with the right subtree.}
+ if lr=left then
+ oldroot.FLeft:=root.FRight
+ else
+ oldroot.FRight:=root.FRight;
+ end;
+ end;
+ delete_from_tree:=root;
+ end;
+
+ begin
+ {$ifdef compress}
+ senc:=minilzw_encode(s);
+ {$endif}
+ SpeedValue:=GetSpeedValue(s);
+ n:=FRoot;
+ if assigned(FHashArray) then
+ begin
+ { First, check if the Node to delete directly located under
+ the hasharray.}
+ p:=SpeedValue mod hasharraysize;
+ n:=FHashArray^[p];
+ if (n<>nil) and (n.SpeedValue=SpeedValue) and
+ (n.FName^=senc) then
+ begin
+ { The Node to delete is directly located under the
+ hasharray. Make the hasharray point to the left
+ subtree of the Node and place the right subtree on
+ the right-bottom of the left subtree.}
+ if n.FLeft<>nil then
+ begin
+ FHashArray^[p]:=n.FLeft;
+ if n.FRight<>nil then
+ insert_right_bottom(n.FLeft,n.FRight);
+ end
+ else
+ FHashArray^[p]:=n.FRight;
+ delete:=n;
+ dec(FCount);
+ exit;
+ end;
+ end
+ else
+ begin
+ { First check if the Node to delete is the root.}
+ if (FRoot<>nil) and (n.SpeedValue=SpeedValue) and
+ (n.FName^=senc) then
+ begin
+ if n.FLeft<>nil then
+ begin
+ FRoot:=n.FLeft;
+ if n.FRight<>nil then
+ insert_right_bottom(n.FLeft,n.FRight);
+ end
+ else
+ FRoot:=n.FRight;
+ delete:=n;
+ dec(FCount);
+ exit;
+ end;
+ end;
+ delete:=delete_from_tree(n);
+ end;
+
+ function Tdictionary.empty:boolean;
+ var
+ w : integer;
+ begin
+ if assigned(FHashArray) then
+ begin
+ empty:=false;
+ for w:=low(FHashArray^) to high(FHashArray^) do
+ if assigned(FHashArray^[w]) then
+ exit;
+ empty:=true;
+ end
+ else
+ empty:=(FRoot=nil);
+ end;
+
+
+ procedure Tdictionary.foreach(proc2call:TNamedIndexcallback;arg:pointer);
+
+ procedure a(p:TNamedIndexItem;arg:pointer);
+ begin
+ proc2call(p,arg);
+ if assigned(p.FLeft) then
+ a(p.FLeft,arg);
+ if assigned(p.FRight) then
+ a(p.FRight,arg);
+ end;
+
+ var
+ i : integer;
+ begin
+ if assigned(FHashArray) then
+ begin
+ for i:=low(FHashArray^) to high(FHashArray^) do
+ if assigned(FHashArray^[i]) then
+ a(FHashArray^[i],arg);
+ end
+ else
+ if assigned(FRoot) then
+ a(FRoot,arg);
+ end;
+
+
+ procedure Tdictionary.foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
+
+ procedure a(p:TNamedIndexItem;arg:pointer);
+ begin
+ proc2call(p,arg);
+ if assigned(p.FLeft) then
+ a(p.FLeft,arg);
+ if assigned(p.FRight) then
+ a(p.FRight,arg);
+ end;
+
+ var
+ i : integer;
+ begin
+ if assigned(FHashArray) then
+ begin
+ for i:=low(FHashArray^) to high(FHashArray^) do
+ if assigned(FHashArray^[i]) then
+ a(FHashArray^[i],arg);
+ end
+ else
+ if assigned(FRoot) then
+ a(FRoot,arg);
+ end;
+
+
+ function Tdictionary.replace(oldobj,newobj:TNamedIndexItem):boolean;
+ var
+ hp : TNamedIndexItem;
+ begin
+ hp:=nil;
+ Replace:=false;
+ { must be the same name and hash }
+ if (oldobj.FSpeedValue<>newobj.FSpeedValue) or
+ (oldobj.FName^<>newobj.FName^) then
+ exit;
+ { copy tree info }
+ newobj.FLeft:=oldobj.FLeft;
+ newobj.FRight:=oldobj.FRight;
+ { update treeroot }
+ if assigned(FHashArray) then
+ begin
+ hp:=FHashArray^[newobj.FSpeedValue mod hasharraysize];
+ if hp=oldobj then
+ begin
+ FHashArray^[newobj.FSpeedValue mod hasharraysize]:=newobj;
+ hp:=nil;
+ end;
+ end
+ else
+ begin
+ hp:=FRoot;
+ if hp=oldobj then
+ begin
+ FRoot:=newobj;
+ hp:=nil;
+ end;
+ end;
+ { update parent entry }
+ while assigned(hp) do
+ begin
+ { is the node to replace the left or right, then
+ update this node and stop }
+ if hp.FLeft=oldobj then
+ begin
+ hp.FLeft:=newobj;
+ break;
+ end;
+ if hp.FRight=oldobj then
+ begin
+ hp.FRight:=newobj;
+ break;
+ end;
+ { First check SpeedValue, to allow a fast insert }
+ if hp.SpeedValue>oldobj.SpeedValue then
+ hp:=hp.FRight
+ else
+ if hp.SpeedValue<oldobj.SpeedValue then
+ hp:=hp.FLeft
+ else
+ begin
+ if (hp.FName^=oldobj.FName^) then
+ begin
+ { this can never happend, return error }
+ exit;
+ end
+ else
+ if oldobj.FName^>hp.FName^ then
+ hp:=hp.FLeft
+ else
+ hp:=hp.FRight;
+ end;
+ end;
+ Replace:=true;
+ end;
+
+
+ function Tdictionary.insert(obj:TNamedIndexItem):TNamedIndexItem;
+ begin
+ inc(FCount);
+ if assigned(FHashArray) then
+ insert:=insertNode(obj,FHashArray^[obj.SpeedValue mod hasharraysize])
+ else
+ insert:=insertNode(obj,FRoot);
+ end;
+
+
+ function tdictionary.insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
+ begin
+ if currNode=nil then
+ begin
+ currNode:=NewNode;
+ insertNode:=NewNode;
+ end
+ { First check SpeedValue, to allow a fast insert }
+ else
+ if currNode.SpeedValue>NewNode.SpeedValue then
+ insertNode:=insertNode(NewNode,currNode.FRight)
+ else
+ if currNode.SpeedValue<NewNode.SpeedValue then
+ insertNode:=insertNode(NewNode,currNode.FLeft)
+ else
+ begin
+ if currNode.FName^>NewNode.FName^ then
+ insertNode:=insertNode(NewNode,currNode.FRight)
+ else
+ if currNode.FName^<NewNode.FName^ then
+ insertNode:=insertNode(NewNode,currNode.FLeft)
+ else
+ begin
+ if (delete_doubles) and
+ assigned(currNode) then
+ begin
+ NewNode.FLeft:=currNode.FLeft;
+ NewNode.FRight:=currNode.FRight;
+ if delete_doubles then
+ begin
+ currnode.FLeft:=nil;
+ currnode.FRight:=nil;
+ currnode.free;
+ end;
+ currNode:=NewNode;
+ insertNode:=NewNode;
+ end
+ else
+ insertNode:=currNode;
+ end;
+ end;
+ end;
+
+
+ procedure tdictionary.inserttree(currtree,currroot:TNamedIndexItem);
+ begin
+ if assigned(currtree) then
+ begin
+ inserttree(currtree.FLeft,currroot);
+ inserttree(currtree.FRight,currroot);
+ currtree.FRight:=nil;
+ currtree.FLeft:=nil;
+ insertNode(currtree,currroot);
+ end;
+ end;
+
+
+ function tdictionary.rename(const olds,News : string):TNamedIndexItem;
+ var
+ spdval : cardinal;
+ lasthp,
+ hp,hp2,hp3 : TNamedIndexItem;
+ {$ifdef compress}
+ oldsenc,newsenc:string;
+ {$else}
+ oldsenc:string absolute olds;
+ newsenc:string absolute news;
+ {$endif}
+ begin
+ {$ifdef compress}
+ oldsenc:=minilzw_encode(olds);
+ newsenc:=minilzw_encode(news);
+ {$endif}
+ spdval:=GetSpeedValue(olds);
+ if assigned(FHashArray) then
+ hp:=FHashArray^[spdval mod hasharraysize]
+ else
+ hp:=FRoot;
+ lasthp:=nil;
+ while assigned(hp) do
+ begin
+ if spdval>hp.SpeedValue then
+ begin
+ lasthp:=hp;
+ hp:=hp.FLeft
+ end
+ else
+ if spdval<hp.SpeedValue then
+ begin
+ lasthp:=hp;
+ hp:=hp.FRight
+ end
+ else
+ begin
+ if (hp.FName^=oldsenc) then
+ begin
+ { Get in hp2 the replacer for the root or hasharr }
+ hp2:=hp.FLeft;
+ hp3:=hp.FRight;
+ if not assigned(hp2) then
+ begin
+ hp2:=hp.FRight;
+ hp3:=hp.FLeft;
+ end;
+ { remove entry from the tree }
+ if assigned(lasthp) then
+ begin
+ if lasthp.FLeft=hp then
+ lasthp.FLeft:=hp2
+ else
+ lasthp.FRight:=hp2;
+ end
+ else
+ begin
+ if assigned(FHashArray) then
+ FHashArray^[spdval mod hasharraysize]:=hp2
+ else
+ FRoot:=hp2;
+ end;
+ { reinsert the hp3 in the tree from hp2 }
+ inserttree(hp3,hp2);
+ { reset Node with New values }
+ hp.FLeft:=nil;
+ hp.FRight:=nil;
+ stringdispose(hp.FName);
+ hp.FName:=stringdup(newsenc);
+ hp.FSpeedValue:=GetSpeedValue(news);
+ { reinsert }
+ if assigned(FHashArray) then
+ rename:=insertNode(hp,FHashArray^[hp.SpeedValue mod hasharraysize])
+ else
+ rename:=insertNode(hp,FRoot);
+ exit;
+ end
+ else
+ if oldsenc>hp.FName^ then
+ begin
+ lasthp:=hp;
+ hp:=hp.FLeft
+ end
+ else
+ begin
+ lasthp:=hp;
+ hp:=hp.FRight;
+ end;
+ end;
+ end;
+ result := nil;
+ end;
+
+
+ function Tdictionary.search(const s:string):TNamedIndexItem;
+
+ begin
+ search:=speedsearch(s,getspeedvalue(s));
+ end;
+
+
+ function Tdictionary.speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
+ var
+ NewNode:TNamedIndexItem;
+ {$ifdef compress}
+ decn:string;
+ {$endif}
+ begin
+ if assigned(FHashArray) then
+ NewNode:=FHashArray^[SpeedValue mod hasharraysize]
+ else
+ NewNode:=FRoot;
+ while assigned(NewNode) do
+ begin
+ if SpeedValue>NewNode.SpeedValue then
+ NewNode:=NewNode.FLeft
+ else
+ if SpeedValue<NewNode.SpeedValue then
+ NewNode:=NewNode.FRight
+ else
+ begin
+ {$ifdef compress}
+ decn:=minilzw_decode(newnode.fname^);
+ if (decn=s) then
+ begin
+ speedsearch:=NewNode;
+ exit;
+ end
+ else
+ if s>decn then
+ NewNode:=NewNode.FLeft
+ else
+ NewNode:=NewNode.FRight;
+ {$else}
+ if (NewNode.FName^=s) then
+ begin
+ speedsearch:=NewNode;
+ exit;
+ end
+ else
+ if s>NewNode.FName^ then
+ NewNode:=NewNode.FLeft
+ else
+ NewNode:=NewNode.FRight;
+ {$endif}
+ end;
+ end;
+ speedsearch:=nil;
+ end;
+
+{****************************************************************************
+ tsingleList
+ ****************************************************************************}
+
+ constructor tsingleList.create;
+ begin
+ First:=nil;
+ last:=nil;
+ end;
+
+
+ procedure tsingleList.reset;
+ begin
+ First:=nil;
+ last:=nil;
+ end;
+
+
+ procedure tsingleList.clear;
+ var
+ hp,hp2 : TNamedIndexItem;
+ begin
+ hp:=First;
+ while assigned(hp) do
+ begin
+ hp2:=hp;
+ hp:=hp.FListNext;
+ hp2.free;
+ end;
+ First:=nil;
+ last:=nil;
+ end;
+
+
+ procedure tsingleList.insert(p:TNamedIndexItem);
+ begin
+ if not assigned(First) then
+ First:=p
+ else
+ last.FListNext:=p;
+ last:=p;
+ p.FListNext:=nil;
+ end;
+
+
+{****************************************************************************
+ tindexarray
+ ****************************************************************************}
+
+ constructor tindexarray.create(Agrowsize:integer);
+ begin
+ growsize:=Agrowsize;
+ size:=0;
+ count:=0;
+ data:=nil;
+ First:=nil;
+ noclear:=false;
+ end;
+
+
+ destructor tindexarray.destroy;
+ begin
+ if assigned(data) then
+ begin
+ if not noclear then
+ clear;
+ freemem(data);
+ data:=nil;
+ end;
+ end;
+
+
+ function tindexarray.search(nr:integer):TNamedIndexItem;
+ begin
+ if nr<=count then
+ search:=data^[nr]
+ else
+ search:=nil;
+ end;
+
+
+ procedure tindexarray.clear;
+ var
+ i : integer;
+ begin
+ for i:=1 to count do
+ if assigned(data^[i]) then
+ begin
+ data^[i].free;
+ data^[i]:=nil;
+ end;
+ count:=0;
+ First:=nil;
+ end;
+
+
+ procedure tindexarray.foreach(proc2call : Tnamedindexcallback;arg:pointer);
+ var
+ i : integer;
+ begin
+ for i:=1 to count do
+ if assigned(data^[i]) then
+ proc2call(data^[i],arg);
+ end;
+
+
+ procedure tindexarray.foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
+ var
+ i : integer;
+ begin
+ for i:=1 to count do
+ if assigned(data^[i]) then
+ proc2call(data^[i],arg);
+ end;
+
+
+ procedure tindexarray.grow(gsize:integer);
+ var
+ osize : integer;
+ begin
+ osize:=size;
+ inc(size,gsize);
+ reallocmem(data,size*sizeof(pointer));
+ fillchar(data^[osize+1],gsize*sizeof(pointer),0);
+ end;
+
+
+ procedure tindexarray.deleteindex(p:TNamedIndexItem);
+ var
+ i : integer;
+ begin
+ i:=p.Findexnr;
+ { update counter }
+ if i=count then
+ dec(count);
+ { update Linked List }
+ while (i>0) do
+ begin
+ dec(i);
+ if (i>0) and assigned(data^[i]) then
+ begin
+ data^[i].FindexNext:=data^[p.Findexnr].FindexNext;
+ break;
+ end;
+ end;
+ if i=0 then
+ First:=p.FindexNext;
+ data^[p.FIndexnr]:=nil;
+ { clear entry }
+ p.FIndexnr:=-1;
+ p.FIndexNext:=nil;
+ end;
+
+
+ procedure tindexarray.delete(var p:TNamedIndexItem);
+ begin
+ deleteindex(p);
+ p.free;
+ p:=nil;
+ end;
+
+
+ procedure tindexarray.insert(p:TNamedIndexItem);
+ var
+ i : integer;
+ begin
+ if p.FIndexnr=-1 then
+ begin
+ inc(count);
+ p.FIndexnr:=count;
+ end;
+ if p.FIndexnr>count then
+ count:=p.FIndexnr;
+ if count>size then
+ grow(((count div growsize)+1)*growsize);
+ Assert(not assigned(data^[p.FIndexnr]) or (p=data^[p.FIndexnr]));
+ data^[p.FIndexnr]:=p;
+ { update Linked List backward }
+ i:=p.FIndexnr;
+ while (i>0) do
+ begin
+ dec(i);
+ if (i>0) and assigned(data^[i]) then
+ begin
+ data^[i].FIndexNext:=p;
+ break;
+ end;
+ end;
+ if i=0 then
+ First:=p;
+ { update Linked List forward }
+ i:=p.FIndexnr;
+ while (i<=count) do
+ begin
+ inc(i);
+ if (i<=count) and assigned(data^[i]) then
+ begin
+ p.FIndexNext:=data^[i];
+ exit;
+ end;
+ end;
+ if i>count then
+ p.FIndexNext:=nil;
+ end;
+
+
+ procedure tindexarray.replace(oldp,newp:TNamedIndexItem);
+ var
+ i : integer;
+ begin
+ newp.FIndexnr:=oldp.FIndexnr;
+ newp.FIndexNext:=oldp.FIndexNext;
+ data^[newp.FIndexnr]:=newp;
+ if First=oldp then
+ First:=newp;
+ { update Linked List backward }
+ i:=newp.FIndexnr;
+ while (i>0) do
+ begin
+ dec(i);
+ if (i>0) and assigned(data^[i]) then
+ begin
+ data^[i].FIndexNext:=newp;
+ break;
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ tdynamicarray
+****************************************************************************}
+
+ constructor tdynamicarray.create(Ablocksize:integer);
+ begin
+ FPosn:=0;
+ FPosnblock:=nil;
+ FFirstblock:=nil;
+ FLastblock:=nil;
+ Fblocksize:=Ablocksize;
+ grow;
+ end;
+
+
+ destructor tdynamicarray.destroy;
+ var
+ hp : pdynamicblock;
+ begin
+ while assigned(FFirstblock) do
+ begin
+ hp:=FFirstblock;
+ FFirstblock:=FFirstblock^.Next;
+ Freemem(hp);
+ end;
+ end;
+
+
+ function tdynamicarray.size:integer;
+ begin
+ if assigned(FLastblock) then
+ size:=FLastblock^.pos+FLastblock^.used
+ else
+ size:=0;
+ end;
+
+
+ procedure tdynamicarray.reset;
+ var
+ hp : pdynamicblock;
+ begin
+ while assigned(FFirstblock) do
+ begin
+ hp:=FFirstblock;
+ FFirstblock:=FFirstblock^.Next;
+ Freemem(hp);
+ end;
+ FPosn:=0;
+ FPosnblock:=nil;
+ FFirstblock:=nil;
+ FLastblock:=nil;
+ grow;
+ end;
+
+
+ procedure tdynamicarray.grow;
+ var
+ nblock : pdynamicblock;
+ begin
+ Getmem(nblock,blocksize+dynamicblockbasesize);
+ if not assigned(FFirstblock) then
+ begin
+ FFirstblock:=nblock;
+ FPosnblock:=nblock;
+ nblock^.pos:=0;
+ end
+ else
+ begin
+ FLastblock^.Next:=nblock;
+ nblock^.pos:=FLastblock^.pos+FLastblock^.used;
+ end;
+ nblock^.used:=0;
+ nblock^.Next:=nil;
+ fillchar(nblock^.data,blocksize,0);
+ FLastblock:=nblock;
+ end;
+
+
+ procedure tdynamicarray.align(i:integer);
+ var
+ j : integer;
+ begin
+ j:=(FPosn mod i);
+ if j<>0 then
+ begin
+ j:=i-j;
+ if FPosnblock^.used+j>blocksize then
+ begin
+ dec(j,blocksize-FPosnblock^.used);
+ FPosnblock^.used:=blocksize;
+ grow;
+ FPosnblock:=FLastblock;
+ end;
+ inc(FPosnblock^.used,j);
+ inc(FPosn,j);
+ end;
+ end;
+
+
+ procedure tdynamicarray.seek(i:integer);
+ begin
+ if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+blocksize) then
+ begin
+ { set FPosnblock correct if the size is bigger then
+ the current block }
+ if FPosnblock^.pos>i then
+ FPosnblock:=FFirstblock;
+ while assigned(FPosnblock) do
+ begin
+ if FPosnblock^.pos+blocksize>i then
+ break;
+ FPosnblock:=FPosnblock^.Next;
+ end;
+ { not found ? then increase blocks }
+ if not assigned(FPosnblock) then
+ begin
+ repeat
+ { the current FLastblock is now also fully used }
+ FLastblock^.used:=blocksize;
+ grow;
+ FPosnblock:=FLastblock;
+ until FPosnblock^.pos+blocksize>=i;
+ end;
+ end;
+ FPosn:=i;
+ if FPosn mod blocksize>FPosnblock^.used then
+ FPosnblock^.used:=FPosn mod blocksize;
+ end;
+
+
+ procedure tdynamicarray.write(const d;len:integer);
+ var
+ p : pchar;
+ i,j : integer;
+ begin
+ p:=pchar(@d);
+ while (len>0) do
+ begin
+ i:=FPosn mod blocksize;
+ if i+len>=blocksize then
+ begin
+ j:=blocksize-i;
+ move(p^,FPosnblock^.data[i],j);
+ inc(p,j);
+ inc(FPosn,j);
+ dec(len,j);
+ FPosnblock^.used:=blocksize;
+ if assigned(FPosnblock^.Next) then
+ FPosnblock:=FPosnblock^.Next
+ else
+ begin
+ grow;
+ FPosnblock:=FLastblock;
+ end;
+ end
+ else
+ begin
+ move(p^,FPosnblock^.data[i],len);
+ inc(p,len);
+ inc(FPosn,len);
+ i:=FPosn mod blocksize;
+ if i>FPosnblock^.used then
+ FPosnblock^.used:=i;
+ len:=0;
+ end;
+ end;
+ end;
+
+
+ procedure tdynamicarray.writestr(const s:string);
+ begin
+ write(s[1],length(s));
+ end;
+
+
+ function tdynamicarray.read(var d;len:integer):integer;
+ var
+ p : pchar;
+ i,j,res : integer;
+ begin
+ res:=0;
+ p:=pchar(@d);
+ while (len>0) do
+ begin
+ i:=FPosn mod blocksize;
+ if i+len>=FPosnblock^.used then
+ begin
+ j:=FPosnblock^.used-i;
+ move(FPosnblock^.data[i],p^,j);
+ inc(p,j);
+ inc(FPosn,j);
+ inc(res,j);
+ dec(len,j);
+ if assigned(FPosnblock^.Next) then
+ FPosnblock:=FPosnblock^.Next
+ else
+ break;
+ end
+ else
+ begin
+ move(FPosnblock^.data[i],p^,len);
+ inc(p,len);
+ inc(FPosn,len);
+ inc(res,len);
+ len:=0;
+ end;
+ end;
+ read:=res;
+ end;
+
+
+ procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
+ var
+ i,left : integer;
+ begin
+ if maxlen=-1 then
+ maxlen:=maxlongint;
+ repeat
+ left:=blocksize-FPosnblock^.used;
+ if left>maxlen then
+ left:=maxlen;
+ i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
+ dec(maxlen,i);
+ inc(FPosnblock^.used,i);
+ if FPosnblock^.used=blocksize then
+ begin
+ if assigned(FPosnblock^.Next) then
+ FPosnblock:=FPosnblock^.Next
+ else
+ begin
+ grow;
+ FPosnblock:=FLastblock;
+ end;
+ end;
+ until (i<left) or (maxlen=0);
+ end;
+
+
+ procedure tdynamicarray.writestream(f:TCStream);
+ var
+ hp : pdynamicblock;
+ begin
+ hp:=FFirstblock;
+ while assigned(hp) do
+ begin
+ f.Write(hp^.data,hp^.used);
+ hp:=hp^.Next;
+ end;
+ end;
+
+
+end.
diff --git a/compiler/cg64f32.pas b/compiler/cg64f32.pas
new file mode 100644
index 0000000000..e80e4cad7f
--- /dev/null
+++ b/compiler/cg64f32.pas
@@ -0,0 +1,791 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+ Member of the Free Pascal development team
+
+ This unit implements the code generation for 64 bit int
+ arithmethics on 32 bit processors
+
+ 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 generation for 64 bit int arithmethics on
+ 32 bit processors.
+}
+unit cg64f32;
+
+ {$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,cpupara,
+ cgbase,cgobj,parabase,cgutils,
+ symtype
+ ;
+
+ type
+ {# Defines all the methods required on 32-bit processors
+ to handle 64-bit integers.
+ }
+ tcg64f32 = class(tcg64)
+ procedure a_load64_const_ref(list : taasmoutput;value : int64;const ref : treference);override;
+ procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);override;
+ procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);override;
+ procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);override;
+ procedure a_load64_const_reg(list : taasmoutput;value: int64;reg : tregister64);override;
+ procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);override;
+ procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);override;
+ procedure a_load64_const_loc(list : taasmoutput;value : int64;const l : tlocation);override;
+ procedure a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);override;
+
+ procedure a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);override;
+ procedure a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);override;
+ procedure a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);override;
+ procedure a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);override;
+ procedure a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);override;
+ procedure a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);override;
+
+ procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
+ procedure a_op64_reg_ref(list : taasmoutput;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);override;
+ procedure a_op64_const_loc(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);override;
+ procedure a_op64_reg_loc(list : taasmoutput;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);override;
+ procedure a_op64_loc_reg(list : taasmoutput;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);override;
+ procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
+
+ procedure a_param64_reg(list : taasmoutput;reg : tregister64;const paraloc : tcgpara);override;
+ procedure a_param64_const(list : taasmoutput;value : int64;const paraloc : tcgpara);override;
+ procedure a_param64_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);override;
+ procedure a_param64_loc(list : taasmoutput;const l : tlocation;const paraloc : tcgpara);override;
+
+ {# This routine tries to optimize the a_op64_const_reg operation, by
+ removing superfluous opcodes. Returns TRUE if normal processing
+ must continue in op64_const_reg, otherwise, everything is processed
+ entirely in this routine, by emitting the appropriate 32-bit opcodes.
+ }
+ function optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : int64; var reg: tregister64): boolean;override;
+
+ procedure g_rangecheck64(list: taasmoutput; const l:tlocation;fromdef,todef: tdef); override;
+ end;
+
+ {# Creates a tregister64 record from 2 32 Bit registers. }
+ function joinreg64(reglo,reghi : tregister) : tregister64;
+
+ implementation
+
+ uses
+ globtype,systems,
+ verbose,
+ symbase,symconst,symdef,defutil,paramgr;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ function joinreg64(reglo,reghi : tregister) : tregister64;
+ begin
+ result.reglo:=reglo;
+ result.reghi:=reghi;
+ end;
+
+
+ procedure swap64(var q : int64);
+ begin
+ q:=(int64(lo(q)) shl 32) or hi(q);
+ end;
+
+
+ procedure splitparaloc64(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
+ var
+ paraloclo,
+ paralochi : pcgparalocation;
+ begin
+ if not(cgpara.size in [OS_64,OS_S64]) then
+ internalerror(200408231);
+ if not assigned(cgpara.location) then
+ internalerror(200408201);
+ { init lo/hi para }
+ cgparahi.reset;
+ if cgpara.size=OS_S64 then
+ cgparahi.size:=OS_S32
+ else
+ cgparahi.size:=OS_32;
+ cgparahi.intsize:=4;
+ cgparahi.alignment:=cgpara.alignment;
+ paralochi:=cgparahi.add_location;
+ cgparalo.reset;
+ cgparalo.size:=OS_32;
+ cgparalo.intsize:=4;
+ cgparalo.alignment:=cgpara.alignment;
+ paraloclo:=cgparalo.add_location;
+ { 2 parameter fields? }
+ if assigned(cgpara.location^.next) then
+ begin
+ { Order for multiple locations is always
+ paraloc^ -> high
+ paraloc^.next -> low }
+ if (target_info.endian=ENDIAN_BIG) then
+ begin
+ { paraloc^ -> high
+ paraloc^.next -> low }
+ move(cgpara.location^,paralochi^,sizeof(paralochi^));
+ move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
+ end
+ else
+ begin
+ { paraloc^ -> low
+ paraloc^.next -> high }
+ move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
+ move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
+ end;
+ end
+ else
+ begin
+ { single parameter, this can only be in memory }
+ if cgpara.location^.loc<>LOC_REFERENCE then
+ internalerror(200408282);
+ move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
+ move(cgpara.location^,paralochi^,sizeof(paralochi^));
+ { for big endian low is at +4, for little endian high }
+ if target_info.endian = endian_big then
+ inc(cgparalo.location^.reference.offset,4)
+ else
+ inc(cgparahi.location^.reference.offset,4);
+ end;
+ { fix size }
+ paraloclo^.size:=cgparalo.size;
+ paraloclo^.next:=nil;
+ paralochi^.size:=cgparahi.size;
+ paralochi^.next:=nil;
+ end;
+
+
+{****************************************************************************
+ TCG64F32
+****************************************************************************}
+
+ procedure tcg64f32.a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);
+ var
+ tmpreg: tregister;
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ begin
+ tmpreg:=reg.reglo;
+ reg.reglo:=reg.reghi;
+ reg.reghi:=tmpreg;
+ end;
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,ref);
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
+ end;
+
+
+ procedure tcg64f32.a_load64_const_ref(list : taasmoutput;value : int64;const ref : treference);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ swap64(value);
+ cg.a_load_const_ref(list,OS_32,aint(lo(value)),ref);
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_const_ref(list,OS_32,aint(hi(value)),tmpref);
+ end;
+
+
+ procedure tcg64f32.a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);
+ var
+ tmpreg: tregister;
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ begin
+ tmpreg := reg.reglo;
+ reg.reglo := reg.reghi;
+ reg.reghi := tmpreg;
+ end;
+ tmpref := ref;
+ if (tmpref.base=reg.reglo) then
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
+ tmpref.base:=tmpreg;
+ end
+ else
+ { this works only for the i386, thus the i386 needs to override }
+ { this method and this method must be replaced by a more generic }
+ { implementation FK }
+ if (tmpref.index=reg.reglo) then
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
+ tmpref.index:=tmpreg;
+ end;
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
+ inc(tmpref.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
+ end;
+
+
+ procedure tcg64f32.a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);
+
+ begin
+ cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
+ cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
+ end;
+
+
+ procedure tcg64f32.a_load64_const_reg(list : taasmoutput;value : int64;reg : tregister64);
+
+ begin
+ cg.a_load_const_reg(list,OS_32,aint(lo(value)),reg.reglo);
+ cg.a_load_const_reg(list,OS_32,aint(hi(value)),reg.reghi);
+ end;
+
+
+ procedure tcg64f32.a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);
+
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_load64_ref_reg(list,l.reference,reg);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_reg_reg(list,l.register64,reg);
+ LOC_CONSTANT :
+ a_load64_const_reg(list,l.value64,reg);
+ else
+ internalerror(200112292);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);
+ begin
+ case l.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_reg_ref(list,l.register64,ref);
+ LOC_CONSTANT :
+ a_load64_const_ref(list,l.value64,ref);
+ else
+ internalerror(200203288);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64_const_loc(list : taasmoutput;value : int64;const l : tlocation);
+
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_load64_const_ref(list,value,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_const_reg(list,value,l.register64);
+ else
+ internalerror(200112293);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);
+
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_load64_reg_ref(list,reg,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_reg_reg(list,reg,l.register64);
+ else
+ internalerror(200112293);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
+ else
+ begin
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
+ end;
+ end;
+
+ procedure tcg64f32.a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_little then
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
+ else
+ begin
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
+ else
+ begin
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_little then
+ cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
+ else
+ begin
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
+ begin
+ case l.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ a_load64low_ref_reg(list,l.reference,reg);
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reglo,reg);
+ LOC_CONSTANT :
+ cg.a_load_const_reg(list,OS_32,aint(lo(l.value64)),reg);
+ else
+ internalerror(200203244);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);
+ begin
+ case l.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ a_load64high_ref_reg(list,l.reference,reg);
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reghi,reg);
+ LOC_CONSTANT :
+ cg.a_load_const_reg(list,OS_32,hi(l.value64),reg);
+ else
+ internalerror(200203244);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_op64_const_loc(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op64_const_ref(list,op,size,value,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_op64_const_reg(list,op,size,value,l.register64);
+ else
+ internalerror(200203292);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_op64_reg_loc(list : taasmoutput;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op64_reg_ref(list,op,size,reg,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_op64_reg_reg(list,op,size,reg,l.register64);
+ else
+ internalerror(2002032422);
+ end;
+ end;
+
+
+
+ procedure tcg64f32.a_op64_loc_reg(list : taasmoutput;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op64_ref_reg(list,op,size,l.reference,reg);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_op64_reg_reg(list,op,size,l.register64,reg);
+ LOC_CONSTANT :
+ a_op64_const_reg(list,op,size,l.value64,reg);
+ else
+ internalerror(200203242);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_op64_ref_reg(list : taasmoutput;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
+ var
+ tempreg: tregister64;
+ begin
+ tempreg.reghi:=cg.getintregister(list,OS_32);
+ tempreg.reglo:=cg.getintregister(list,OS_32);
+ a_load64_ref_reg(list,ref,tempreg);
+ a_op64_reg_reg(list,op,size,tempreg,reg);
+ end;
+
+
+ procedure tcg64f32.a_op64_reg_ref(list : taasmoutput;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);
+ var
+ tempreg: tregister64;
+ begin
+ tempreg.reghi:=cg.getintregister(list,OS_32);
+ tempreg.reglo:=cg.getintregister(list,OS_32);
+ a_load64_ref_reg(list,ref,tempreg);
+ a_op64_reg_reg(list,op,size,reg,tempreg);
+ a_load64_reg_ref(list,tempreg,ref);
+ end;
+
+
+ procedure tcg64f32.a_op64_const_ref(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
+ var
+ tempreg: tregister64;
+ begin
+ tempreg.reghi:=cg.getintregister(list,OS_32);
+ tempreg.reglo:=cg.getintregister(list,OS_32);
+ a_load64_ref_reg(list,ref,tempreg);
+ a_op64_const_reg(list,op,size,value,tempreg);
+ a_load64_reg_ref(list,tempreg,ref);
+ end;
+
+
+ procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const paraloc : tcgpara);
+ var
+ tmplochi,tmploclo: tcgpara;
+ begin
+ tmploclo.init;
+ tmplochi.init;
+ splitparaloc64(paraloc,tmploclo,tmplochi);
+ { Keep this order of first hi before lo to have
+ the correct push order for i386 }
+ cg.a_param_reg(list,OS_32,reg.reghi,tmplochi);
+ cg.a_param_reg(list,OS_32,reg.reglo,tmploclo);
+ tmploclo.done;
+ tmplochi.done;
+ end;
+
+
+ procedure tcg64f32.a_param64_const(list : taasmoutput;value : int64;const paraloc : tcgpara);
+ var
+ tmplochi,tmploclo: tcgpara;
+ begin
+ tmploclo.init;
+ tmplochi.init;
+ splitparaloc64(paraloc,tmploclo,tmplochi);
+ { Keep this order of first hi before lo to have
+ the correct push order for i386 }
+ cg.a_param_const(list,OS_32,aint(hi(value)),tmplochi);
+ cg.a_param_const(list,OS_32,aint(lo(value)),tmploclo);
+ tmploclo.done;
+ tmplochi.done;
+ end;
+
+
+ procedure tcg64f32.a_param64_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);
+ var
+ tmprefhi,tmpreflo : treference;
+ tmploclo,tmplochi : tcgpara;
+ begin
+ tmploclo.init;
+ tmplochi.init;
+ splitparaloc64(paraloc,tmploclo,tmplochi);
+ tmprefhi:=r;
+ tmpreflo:=r;
+ if target_info.endian=endian_big then
+ inc(tmpreflo.offset,4)
+ else
+ inc(tmprefhi.offset,4);
+ { Keep this order of first hi before lo to have
+ the correct push order for i386 }
+ cg.a_param_ref(list,OS_32,tmprefhi,tmplochi);
+ cg.a_param_ref(list,OS_32,tmpreflo,tmploclo);
+ tmploclo.done;
+ tmplochi.done;
+ end;
+
+
+ procedure tcg64f32.a_param64_loc(list : taasmoutput;const l:tlocation;const paraloc : tcgpara);
+ begin
+ case l.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ a_param64_reg(list,l.register64,paraloc);
+ LOC_CONSTANT :
+ a_param64_const(list,l.value64,paraloc);
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ a_param64_ref(list,l.reference,paraloc);
+ else
+ internalerror(200203287);
+ end;
+ end;
+
+
+ procedure tcg64f32.g_rangecheck64(list : taasmoutput;const l:tlocation;fromdef,todef:tdef);
+
+ var
+ neglabel,
+ poslabel,
+ endlabel: tasmlabel;
+ hreg : tregister;
+ hdef : torddef;
+ opsize : tcgsize;
+ oldregisterdef: boolean;
+ from_signed,to_signed: boolean;
+ temploc : tlocation;
+
+ begin
+ from_signed := is_signed(fromdef);
+ to_signed := is_signed(todef);
+
+ if not is_64bit(todef) then
+ begin
+ oldregisterdef := registerdef;
+ registerdef := false;
+
+ { get the high dword in a register }
+ if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ begin
+ hreg := l.register64.reghi;
+ end
+ else
+ begin
+ hreg:=cg.getintregister(list,OS_32);
+ a_load64high_ref_reg(list,l.reference,hreg);
+ end;
+ objectlibrary.getjumplabel(poslabel);
+
+ { check high dword, must be 0 (for positive numbers) }
+ cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
+
+ { It can also be $ffffffff, but only for negative numbers }
+ if from_signed and to_signed then
+ begin
+ objectlibrary.getjumplabel(neglabel);
+ cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
+ end;
+ { For all other values we have a range check error }
+ cg.a_call_name(list,'FPC_RANGEERROR');
+
+ { if the high dword = 0, the low dword can be considered a }
+ { simple cardinal }
+ cg.a_label(list,poslabel);
+ hdef:=torddef.create(u32bit,0,$ffffffff);
+
+ location_copy(temploc,l);
+ temploc.size:=OS_32;
+
+ if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
+ (target_info.endian = endian_big) then
+ inc(temploc.reference.offset,4);
+
+ cg.g_rangecheck(list,temploc,hdef,todef);
+ hdef.free;
+
+ if from_signed and to_signed then
+ begin
+ objectlibrary.getjumplabel(endlabel);
+ cg.a_jmp_always(list,endlabel);
+ { if the high dword = $ffffffff, then the low dword (when }
+ { considered as a longint) must be < 0 }
+ cg.a_label(list,neglabel);
+ if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ begin
+ hreg := l.register64.reglo;
+ end
+ else
+ begin
+ hreg:=cg.getintregister(list,OS_32);
+ a_load64low_ref_reg(list,l.reference,hreg);
+ end;
+ { get a new neglabel (JM) }
+ objectlibrary.getjumplabel(neglabel);
+ cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
+
+ cg.a_call_name(list,'FPC_RANGEERROR');
+
+ { if we get here, the 64bit value lies between }
+ { longint($80000000) and -1 (JM) }
+ cg.a_label(list,neglabel);
+ hdef:=torddef.create(s32bit,longint($80000000),-1);
+ location_copy(temploc,l);
+ temploc.size:=OS_32;
+ cg.g_rangecheck(list,temploc,hdef,todef);
+ hdef.free;
+ cg.a_label(list,endlabel);
+ end;
+ registerdef := oldregisterdef;
+ end
+ else
+ { todef = 64bit int }
+ { no 64bit subranges supported, so only a small check is necessary }
+
+ { if both are signed or both are unsigned, no problem! }
+ if (from_signed xor to_signed) and
+ { also not if the fromdef is unsigned and < 64bit, since that will }
+ { always fit in a 64bit int (todef is 64bit) }
+ (from_signed or
+ (torddef(fromdef).typ = u64bit)) then
+ begin
+ { in all cases, there is only a problem if the higest bit is set }
+ if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ begin
+ if is_64bit(fromdef) then
+ begin
+ hreg := l.register64.reghi;
+ opsize := OS_32;
+ end
+ else
+ begin
+ hreg := l.register;
+ opsize := def_cgsize(fromdef);
+ end;
+ end
+ else
+ begin
+ hreg:=cg.getintregister(list,OS_32);
+
+ opsize := def_cgsize(fromdef);
+ if opsize in [OS_64,OS_S64] then
+ a_load64high_ref_reg(list,l.reference,hreg)
+ else
+ cg.a_load_ref_reg(list,opsize,OS_32,l.reference,hreg);
+ end;
+ objectlibrary.getjumplabel(poslabel);
+ cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
+
+ cg.a_call_name(list,'FPC_RANGEERROR');
+ cg.a_label(list,poslabel);
+ end;
+ end;
+
+
+ function tcg64f32.optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : int64; var reg: tregister64): boolean;
+ var
+ lowvalue, highvalue : longint;
+ hreg: tregister;
+ begin
+ lowvalue := longint(a);
+ highvalue:= longint(a shr 32);
+ { assume it will be optimized out }
+ optimize64_op_const_reg := true;
+ case op of
+ OP_ADD:
+ begin
+ if a = 0 then
+ exit;
+ end;
+ OP_AND:
+ begin
+ if lowvalue <> -1 then
+ cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
+ if highvalue <> -1 then
+ cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
+ { already emitted correctly }
+ exit;
+ end;
+ OP_OR:
+ begin
+ if lowvalue <> 0 then
+ cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
+ if highvalue <> 0 then
+ cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
+ { already emitted correctly }
+ exit;
+ end;
+ OP_SUB:
+ begin
+ if a = 0 then
+ exit;
+ end;
+ OP_XOR:
+ begin
+ end;
+ OP_SHL:
+ begin
+ if a = 0 then
+ exit;
+ { simply clear low-register
+ and shift the rest and swap
+ registers.
+ }
+ if (a > 31) then
+ begin
+ cg.a_load_const_reg(list,OS_32,0,reg.reglo);
+ cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
+ { swap the registers }
+ hreg := reg.reghi;
+ reg.reghi := reg.reglo;
+ reg.reglo := hreg;
+ exit;
+ end;
+ end;
+ OP_SHR:
+ begin
+ if a = 0 then exit;
+ { simply clear high-register
+ and shift the rest and swap
+ registers.
+ }
+ if (a > 31) then
+ begin
+ cg.a_load_const_reg(list,OS_32,0,reg.reghi);
+ cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
+ { swap the registers }
+ hreg := reg.reghi;
+ reg.reghi := reg.reglo;
+ reg.reglo := hreg;
+ exit;
+ end;
+ end;
+ OP_IMUL,OP_MUL:
+ begin
+ if a = 1 then exit;
+ end;
+ OP_IDIV,OP_DIV:
+ begin
+ if a = 1 then exit;
+ end;
+ else
+ internalerror(20020817);
+ end;
+ optimize64_op_const_reg := false;
+ end;
+
+end.
diff --git a/compiler/cgbase.pas b/compiler/cgbase.pas
new file mode 100644
index 0000000000..6f1a241028
--- /dev/null
+++ b/compiler/cgbase.pas
@@ -0,0 +1,605 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Some basic types and constants for the code generation
+
+ 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 exports some types which are used across the code generator }
+unit cgbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ symconst;
+
+ type
+ { Location types where value can be stored }
+ TCGLoc=(
+ LOC_INVALID, { added for tracking problems}
+ LOC_VOID, { no value is available }
+ LOC_CONSTANT, { constant value }
+ LOC_JUMP, { boolean results only, jump to false or true label }
+ LOC_FLAGS, { boolean results only, flags are set }
+ LOC_CREFERENCE, { in memory constant value reference (cannot change) }
+ LOC_REFERENCE, { in memory value }
+ LOC_REGISTER, { in a processor register }
+ LOC_CREGISTER, { Constant register which shouldn't be modified }
+ LOC_FPUREGISTER, { FPU stack }
+ LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
+ LOC_MMXREGISTER, { MMX register }
+ { MMX register variable }
+ LOC_CMMXREGISTER,
+ { multimedia register }
+ LOC_MMREGISTER,
+ { Constant multimedia reg which shouldn't be modified }
+ LOC_CMMREGISTER
+ );
+
+ { since we have only 16bit offsets, we need to be able to specify the high
+ and lower 16 bits of the address of a symbol of up to 64 bit }
+ trefaddr = (
+ addr_no,
+ addr_full,
+ {$IFNDEF POWERPC64}
+ addr_hi,
+ addr_lo,
+ {$ENDIF}
+ addr_pic
+ {$IFDEF POWERPC64}
+ ,
+ addr_low, // bits 48-63
+ addr_high, // bits 32-47
+ addr_higher, // bits 16-31
+ addr_highest, // bits 00-15
+ addr_higha, // bits 16-31, adjusted
+ addr_highera, // bits 32-47, adjusted
+ addr_highesta // bits 48-63, adjusted
+ {$ENDIF}
+ );
+
+
+ {# Generic opcodes, which must be supported by all processors
+ }
+ topcg =
+ (
+ OP_NONE,
+ OP_ADD, { simple addition }
+ OP_AND, { simple logical and }
+ OP_DIV, { simple unsigned division }
+ OP_IDIV, { simple signed division }
+ OP_IMUL, { simple signed multiply }
+ OP_MUL, { simple unsigned multiply }
+ OP_NEG, { simple negate }
+ OP_NOT, { simple logical not }
+ OP_OR, { simple logical or }
+ OP_SAR, { arithmetic shift-right }
+ OP_SHL, { logical shift left }
+ OP_SHR, { logical shift right }
+ OP_SUB, { simple subtraction }
+ OP_XOR { simple exclusive or }
+ );
+
+ {# Generic flag values - used for jump locations }
+ TOpCmp =
+ (
+ OC_NONE,
+ OC_EQ, { equality comparison }
+ OC_GT, { greater than (signed) }
+ OC_LT, { less than (signed) }
+ OC_GTE, { greater or equal than (signed) }
+ OC_LTE, { less or equal than (signed) }
+ OC_NE, { not equal }
+ OC_BE, { less or equal than (unsigned) }
+ OC_B, { less than (unsigned) }
+ OC_AE, { greater or equal than (unsigned) }
+ OC_A { greater than (unsigned) }
+ );
+
+ { OS_NO is also used memory references with large data that can
+ not be loaded in a register directly }
+ TCgSize = (OS_NO,
+ { integer registers }
+ OS_8,OS_16,OS_32,OS_64,OS_128,OS_S8,OS_S16,OS_S32,OS_S64,OS_S128,
+ { single,double,extended,comp,float128 }
+ OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,
+ { multi-media sizes: split in byte, word, dword, ... }
+ { entities, then the signed counterparts }
+ OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,
+ OS_MS8,OS_MS16,OS_MS32,OS_MS64,OS_MS128);
+
+ { Register types }
+ TRegisterType = (
+ R_INVALIDREGISTER, { = 0 }
+ R_INTREGISTER, { = 1 }
+ R_FPUREGISTER, { = 2 }
+ { used by Intel only }
+ R_MMXREGISTER, { = 3 }
+ R_MMREGISTER, { = 4 }
+ R_SPECIALREGISTER, { = 5 }
+ R_ADDRESSREGISTER { = 6 }
+ );
+
+ { Sub registers }
+ TSubRegister = (
+ R_SUBNONE, { = 0; no sub register possible }
+ R_SUBL, { = 1; 8 bits, Like AL }
+ R_SUBH, { = 2; 8 bits, Like AH }
+ R_SUBW, { = 3; 16 bits, Like AX }
+ R_SUBD, { = 4; 32 bits, Like EAX }
+ R_SUBQ, { = 5; 64 bits, Like RAX }
+ { For Sparc floats that use F0:F1 to store doubles }
+ R_SUBFS, { = 6; Float that allocates 1 FPU register }
+ R_SUBFD, { = 7; Float that allocates 2 FPU registers }
+ R_SUBFQ, { = 8; Float that allocates 4 FPU registers }
+ R_SUBMMS, { = 9; single scalar in multi media register }
+ R_SUBMMD { = 10; double scalar in multi media register }
+ );
+
+ TSuperRegister = type word;
+
+ {
+ The new register coding:
+
+ SuperRegister (bits 0..15)
+ Subregister (bits 16..23)
+ Register type (bits 24..31)
+
+ TRegister is defined as an enum to make it incompatible
+ with TSuperRegister to avoid mixing them
+ }
+ TRegister = (
+ TRegisterLowEnum := Low(longint),
+ TRegisterHighEnum := High(longint)
+ );
+ TRegisterRec=packed record
+{$ifdef FPC_BIG_ENDIAN}
+ regtype : Tregistertype;
+ subreg : Tsubregister;
+ supreg : Tsuperregister;
+{$else FPC_BIG_ENDIAN}
+ supreg : Tsuperregister;
+ subreg : Tsubregister;
+ regtype : Tregistertype;
+{$endif FPC_BIG_ENDIAN}
+ end;
+
+ { A type to store register locations for 64 Bit values. }
+{$ifdef cpu64bit}
+ tregister64 = tregister;
+{$else cpu64bit}
+ tregister64 = record
+ reglo,reghi : tregister;
+ end;
+{$endif cpu64bit}
+
+ Tregistermmxset = record
+ reg0,reg1,reg2,reg3:Tregister
+ end;
+
+ { Set type definition for registers }
+ tcpuregisterset = set of byte;
+ tsuperregisterset = array[byte] of set of byte;
+
+ pmmshuffle = ^tmmshuffle;
+
+ { this record describes shuffle operations for mm operations; if a pointer a shuffle record
+ passed to an mm operation is nil, it means that the whole location is moved }
+ tmmshuffle = record
+ { describes how many shuffles are actually described, if len=0 then
+ moving the scalar with index 0 to the scalar with index 0 is meant }
+ len : byte;
+ { lower nibble of each entry of this array describes index of the source data index while
+ the upper nibble describes the destination index }
+ shuffles : array[1..1] of byte;
+ end;
+
+ Tsuperregisterarray=array[0..$ffff] of Tsuperregister;
+ Psuperregisterarray=^Tsuperregisterarray;
+
+ Tsuperregisterworklist=object
+ buflength,
+ buflengthinc,
+ length:word;
+ buf:Psuperregisterarray;
+ constructor init;
+ constructor copyfrom(const x:Tsuperregisterworklist);
+ destructor done;
+ procedure clear;
+ procedure add(s:tsuperregister);
+ function get:tsuperregister;
+ procedure deleteidx(i:word);
+ function delete(s:tsuperregister):boolean;
+ end;
+ psuperregisterworklist=^tsuperregisterworklist;
+
+ const
+ { alias for easier understanding }
+ R_SSEREGISTER = R_MMREGISTER;
+
+ { Invalid register number }
+ RS_INVALID = high(tsuperregister);
+
+ { Maximum number of cpu registers per register type,
+ this must fit in tcpuregisterset }
+ maxcpuregister = 32;
+
+ tcgsize2size : Array[tcgsize] of integer =
+ { integer values }
+ (0,1,2,4,8,16,1,2,4,8,16,
+ { floating point values }
+ 4,8,10,8,16,
+ { multimedia values }
+ 1,2,4,8,16,1,2,4,8,16);
+
+ tfloat2tcgsize: array[tfloattype] of tcgsize =
+ (OS_F32,OS_F64,OS_F80,OS_C64,OS_C64,OS_F128);
+
+ tcgsize2tfloat: array[OS_F32..OS_C64] of tfloattype =
+ (s32real,s64real,s80real,s64comp);
+
+ { Table to convert tcgsize variables to the correspondending
+ unsigned types }
+ tcgsize2unsigned : array[tcgsize] of tcgsize = (OS_NO,
+ OS_8,OS_16,OS_32,OS_64,OS_128,OS_8,OS_16,OS_32,OS_64,OS_128,
+ OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,
+ OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,OS_M8,OS_M16,OS_M32,
+ OS_M64,OS_M128);
+
+ tcgloc2str : array[TCGLoc] of string[11] = (
+ 'LOC_INVALID',
+ 'LOC_VOID',
+ 'LOC_CONST',
+ 'LOC_JUMP',
+ 'LOC_FLAGS',
+ 'LOC_CREF',
+ 'LOC_REF',
+ 'LOC_REG',
+ 'LOC_CREG',
+ 'LOC_FPUREG',
+ 'LOC_CFPUREG',
+ 'LOC_MMXREG',
+ 'LOC_CMMXREG',
+ 'LOC_MMREG',
+ 'LOC_CMMREG');
+
+ var
+ mms_movescalar : pmmshuffle;
+
+ procedure supregset_reset(var regs:tsuperregisterset;setall:boolean;
+ maxreg:Tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ procedure supregset_include(var regs:tsuperregisterset;s:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ procedure supregset_exclude(var regs:tsuperregisterset;s:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ function supregset_in(const regs:tsuperregisterset;s:tsuperregister):boolean;{$ifdef USEINLINE}inline;{$endif}
+
+ function newreg(rt:tregistertype;sr:tsuperregister;sb:tsubregister):tregister;{$ifdef USEINLINE}inline;{$endif}
+ function getsubreg(r:tregister):tsubregister;{$ifdef USEINLINE}inline;{$endif}
+ function getsupreg(r:tregister):tsuperregister;{$ifdef USEINLINE}inline;{$endif}
+ function getregtype(r:tregister):tregistertype;{$ifdef USEINLINE}inline;{$endif}
+ procedure setsubreg(var r:tregister;sr:tsubregister);{$ifdef USEINLINE}inline;{$endif}
+ procedure setsupreg(var r:tregister;sr:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ function generic_regname(r:tregister):string;
+
+ {# From a constant numeric value, return the abstract code generator
+ size.
+ }
+ function int_cgsize(const a: aint): tcgsize;{$ifdef USEINLINE}inline;{$endif}
+
+ { return the inverse condition of opcmp }
+ function inverse_opcmp(opcmp: topcmp): topcmp;{$ifdef USEINLINE}inline;{$endif}
+
+ { return whether op is commutative }
+ function commutativeop(op: topcg): boolean;{$ifdef USEINLINE}inline;{$endif}
+
+ { returns true, if shuffle describes a real shuffle operation and not only a move }
+ function realshuffle(shuffle : pmmshuffle) : boolean;
+
+ { returns true, if the shuffle describes only a move of the scalar at index 0 }
+ function shufflescalar(shuffle : pmmshuffle) : boolean;
+
+ { removes shuffling from shuffle, this means that the destenation index of each shuffle is copied to
+ the source }
+ procedure removeshuffles(var shuffle : tmmshuffle);
+
+implementation
+
+ uses
+ verbose;
+
+{******************************************************************************
+ tsuperregisterworklist
+******************************************************************************}
+
+ constructor tsuperregisterworklist.init;
+
+ begin
+ length:=0;
+ buflength:=0;
+ buflengthinc:=16;
+ buf:=nil;
+ end;
+
+ constructor Tsuperregisterworklist.copyfrom(const x:Tsuperregisterworklist);
+
+ begin
+ self:=x;
+ if x.buf<>nil then
+ begin
+ getmem(buf,buflength*sizeof(Tsuperregister));
+ move(x.buf^,buf^,length*sizeof(Tsuperregister));
+ end;
+ end;
+
+ destructor tsuperregisterworklist.done;
+
+ begin
+ if assigned(buf) then
+ freemem(buf);
+ end;
+
+
+ procedure tsuperregisterworklist.add(s:tsuperregister);
+
+ begin
+ inc(length);
+ { Need to increase buffer length? }
+ if length>=buflength then
+ begin
+ inc(buflength,buflengthinc);
+ buflengthinc:=buflengthinc*2;
+ if buflengthinc>256 then
+ buflengthinc:=256;
+ reallocmem(buf,buflength*sizeof(Tsuperregister));
+ end;
+ buf^[length-1]:=s;
+ end;
+
+
+ procedure tsuperregisterworklist.clear;
+
+ begin
+ length:=0;
+ end;
+
+
+ procedure tsuperregisterworklist.deleteidx(i:word);
+
+ begin
+ if length=0 then
+ internalerror(200310144);
+ buf^[i]:=buf^[length-1];
+ dec(length);
+ end;
+
+
+ function tsuperregisterworklist.get:tsuperregister;
+
+ begin
+ if length=0 then
+ internalerror(200310142);
+ get:=buf^[0];
+ buf^[0]:=buf^[length-1];
+ dec(length);
+ end;
+
+
+ function tsuperregisterworklist.delete(s:tsuperregister):boolean;
+
+ var
+ i:longint;
+
+ begin
+ delete:=false;
+ { indexword in 1.0.x and 1.9.4 is broken }
+ i:=indexword(buf^,length,s);
+ if i<>-1 then
+ begin
+ deleteidx(i);
+ delete := true;
+ end;
+ end;
+
+
+ procedure supregset_reset(var regs:tsuperregisterset;setall:boolean;
+ maxreg:Tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+
+ begin
+ fillchar(regs,(maxreg+7) shr 3,-byte(setall));
+ end;
+
+
+ procedure supregset_include(var regs:tsuperregisterset;s:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ include(regs[s shr 8],(s and $ff));
+ end;
+
+
+ procedure supregset_exclude(var regs:tsuperregisterset;s:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ exclude(regs[s shr 8],(s and $ff));
+ end;
+
+
+ function supregset_in(const regs:tsuperregisterset;s:tsuperregister):boolean;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=(s and $ff) in regs[s shr 8];
+ end;
+
+
+ function newreg(rt:tregistertype;sr:tsuperregister;sb:tsubregister):tregister;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ tregisterrec(result).regtype:=rt;
+ tregisterrec(result).supreg:=sr;
+ tregisterrec(result).subreg:=sb;
+ end;
+
+
+ function getsubreg(r:tregister):tsubregister;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=tregisterrec(r).subreg;
+ end;
+
+
+ function getsupreg(r:tregister):tsuperregister;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=tregisterrec(r).supreg;
+ end;
+
+
+ function getregtype(r:tregister):tregistertype;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=tregisterrec(r).regtype;
+ end;
+
+
+ procedure setsubreg(var r:tregister;sr:tsubregister);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ tregisterrec(r).subreg:=sr;
+ end;
+
+
+ procedure setsupreg(var r:tregister;sr:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ tregisterrec(r).supreg:=sr;
+ end;
+
+
+ function generic_regname(r:tregister):string;
+ var
+ nr : string[12];
+ begin
+ str(getsupreg(r),nr);
+ case getregtype(r) of
+ R_INTREGISTER:
+ result:='ireg'+nr;
+ R_FPUREGISTER:
+ result:='freg'+nr;
+ R_MMREGISTER:
+ result:='mreg'+nr;
+ R_MMXREGISTER:
+ result:='xreg'+nr;
+ else
+ begin
+ result:='INVALID';
+ exit;
+ end;
+ end;
+ case getsubreg(r) of
+ R_SUBNONE:
+ ;
+ R_SUBL:
+ result:=result+'l';
+ R_SUBH:
+ result:=result+'h';
+ R_SUBW:
+ result:=result+'w';
+ R_SUBD:
+ result:=result+'d';
+ R_SUBQ:
+ result:=result+'q';
+ R_SUBFS:
+ result:=result+'fs';
+ R_SUBFD:
+ result:=result+'fd';
+ R_SUBMMD:
+ result:=result+'md';
+ R_SUBMMS:
+ result:=result+'ms';
+ else
+ internalerror(200308252);
+ end;
+ end;
+
+
+ function int_cgsize(const a: aint): tcgsize;{$ifdef USEINLINE}inline;{$endif}
+ const
+ size2cgsize : array[0..8] of tcgsize = (
+ OS_NO,OS_8,OS_16,OS_32,OS_32,OS_64,OS_64,OS_64,OS_64
+ );
+ begin
+ if a>8 then
+ result:=OS_NO
+ else
+ result:=size2cgsize[a];
+ end;
+
+
+ function inverse_opcmp(opcmp: topcmp): topcmp;{$ifdef USEINLINE}inline;{$endif}
+ const
+ list: array[TOpCmp] of TOpCmp =
+ (OC_NONE,OC_NE,OC_LTE,OC_GTE,OC_LT,OC_GT,OC_EQ,OC_A,OC_AE,
+ OC_B,OC_BE);
+ begin
+ inverse_opcmp := list[opcmp];
+ end;
+
+
+ function commutativeop(op: topcg): boolean;{$ifdef USEINLINE}inline;{$endif}
+ const
+ list: array[topcg] of boolean =
+ (true,true,true,false,false,true,true,false,false,
+ true,false,false,false,false,true);
+ begin
+ commutativeop := list[op];
+ end;
+
+
+ function realshuffle(shuffle : pmmshuffle) : boolean;
+ var
+ i : longint;
+ begin
+ realshuffle:=true;
+ if (shuffle=nil) or (shuffle^.len=0) then
+ realshuffle:=false
+ else
+ begin
+ for i:=1 to shuffle^.len do
+ begin
+ if (shuffle^.shuffles[i] and $f)<>((shuffle^.shuffles[i] and $f0) shr 8) then
+ exit;
+ end;
+ realshuffle:=false;
+ end;
+ end;
+
+
+ function shufflescalar(shuffle : pmmshuffle) : boolean;
+ begin
+ result:=shuffle^.len=0;
+ end;
+
+
+ procedure removeshuffles(var shuffle : tmmshuffle);
+ var
+ i : longint;
+ begin
+ if shuffle.len=0 then
+ exit;
+ for i:=1 to shuffle.len do
+ shuffle.shuffles[i]:=(shuffle.shuffles[i] and $f0) or ((shuffle.shuffles[i] and $f0) shr 8);
+ end;
+
+
+initialization
+ new(mms_movescalar);
+ mms_movescalar^.len:=0;
+finalization
+ dispose(mms_movescalar);
+end.
diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas
new file mode 100644
index 0000000000..c51bcc1b56
--- /dev/null
+++ b/compiler/cgobj.pas
@@ -0,0 +1,2090 @@
+{
+ Copyright (c) 1998-2005 by Florian Klaempfl
+ Member of the Free Pascal development team
+
+ This unit implements the basic code generator object
+
+ 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.
+
+ ****************************************************************************
+}
+{# @abstract(Abstract code generator unit)
+ Abstreact code generator unit. This contains the base class
+ to implement for all new supported processors.
+
+ WARNING: None of the routines implemented in these modules,
+ or their descendants, should use the temp. allocator, as
+ these routines may be called inside genentrycode, and the
+ stack frame is already setup!
+}
+unit cgobj;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,globtype,
+ cpubase,cgbase,cgutils,parabase,
+ aasmbase,aasmtai,aasmcpu,
+ symconst,symbase,symtype,symdef,symtable,rgobj
+ ;
+
+ type
+ talignment = (AM_NATURAL,AM_NONE,AM_2BYTE,AM_4BYTE,AM_8BYTE);
+
+ {# @abstract(Abstract code generator)
+ This class implements an abstract instruction generator. Some of
+ the methods of this class are generic, while others must
+ be overriden for all new processors which will be supported
+ by Free Pascal. For 32-bit processors, the base class
+ sould be @link(tcg64f32) and not @var(tcg).
+ }
+ tcg = class
+ public
+ alignment : talignment;
+ rg : array[tregistertype] of trgobj;
+ t_times : longint;
+ {$ifdef flowgraph}
+ aktflownode:word;
+ {$endif}
+ {************************************************}
+ { basic routines }
+ constructor create;
+
+ {# Initialize the register allocators needed for the codegenerator.}
+ procedure init_register_allocators;virtual;
+ {# Clean up the register allocators needed for the codegenerator.}
+ procedure done_register_allocators;virtual;
+
+ {$ifdef flowgraph}
+ procedure init_flowgraph;
+ procedure done_flowgraph;
+ {$endif}
+ {# Gets a register suitable to do integer operations on.}
+ function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;
+ {# Gets a register suitable to do integer operations on.}
+ function getaddressregister(list:Taasmoutput):Tregister;virtual;
+ function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;
+ function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;
+ function getflagregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;abstract;
+ {Does the generic cg need SIMD registers, like getmmxregister? Or should
+ the cpu specific child cg object have such a method?}
+
+ procedure add_reg_instruction(instr:Tai;r:tregister);virtual;
+ procedure add_move_instruction(instr:Taicpu);virtual;
+
+ function uses_registers(rt:Tregistertype):boolean;virtual;
+ {# Get a specific register.}
+ procedure getcpuregister(list:Taasmoutput;r:Tregister);virtual;
+ procedure ungetcpuregister(list:Taasmoutput;r:Tregister);virtual;
+ {# Get multiple registers specified.}
+ procedure alloccpuregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);virtual;
+ {# Free multiple registers specified.}
+ procedure dealloccpuregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);virtual;
+
+ procedure allocallcpuregisters(list:Taasmoutput);virtual;
+ procedure deallocallcpuregisters(list:Taasmoutput);virtual;
+ procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
+
+ function makeregsize(list:Taasmoutput;reg:Tregister;size:Tcgsize):Tregister;
+
+ {# Emit a label to the instruction stream. }
+ procedure a_label(list : taasmoutput;l : tasmlabel);virtual;
+
+ {# Allocates register r by inserting a pai_realloc record }
+ procedure a_reg_alloc(list : taasmoutput;r : tregister);
+ {# Deallocates register r by inserting a pa_regdealloc record}
+ procedure a_reg_dealloc(list : taasmoutput;r : tregister);
+ { Synchronize register, make sure it is still valid }
+ procedure a_reg_sync(list : taasmoutput;r : tregister);
+
+ {# Pass a parameter, which is located in a register, to a routine.
+
+ This routine should push/send the parameter to the routine, as
+ required by the specific processor ABI and routine modifiers.
+ This must be overriden for each CPU target.
+
+ @param(size size of the operand in the register)
+ @param(r register source of the operand)
+ @param(cgpara where the parameter will be stored)
+ }
+ procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : TCGPara);virtual;
+ {# Pass a parameter, which is a constant, to a routine.
+
+ A generic version is provided. This routine should
+ be overriden for optimization purposes if the cpu
+ permits directly sending this type of parameter.
+
+ @param(size size of the operand in constant)
+ @param(a value of constant to send)
+ @param(cgpara where the parameter will be stored)
+ }
+ procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : TCGPara);virtual;
+ {# Pass the value of a parameter, which is located in memory, to a routine.
+
+ A generic version is provided. This routine should
+ be overriden for optimization purposes if the cpu
+ permits directly sending this type of parameter.
+
+ @param(size size of the operand in constant)
+ @param(r Memory reference of value to send)
+ @param(cgpara where the parameter will be stored)
+ }
+ procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : TCGPara);virtual;
+ {# Pass the value of a parameter, which can be located either in a register or memory location,
+ to a routine.
+
+ A generic version is provided.
+
+ @param(l location of the operand to send)
+ @param(nr parameter number (starting from one) of routine (from left to right))
+ @param(cgpara where the parameter will be stored)
+ }
+ procedure a_param_loc(list : taasmoutput;const l : tlocation;const cgpara : TCGPara);
+ {# Pass the address of a reference to a routine. This routine
+ will calculate the address of the reference, and pass this
+ calculated address as a parameter.
+
+ A generic version is provided. This routine should
+ be overriden for optimization purposes if the cpu
+ permits directly sending this type of parameter.
+
+ @param(r reference to get address from)
+ @param(nr parameter number (starting from one) of routine (from left to right))
+ }
+ procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const cgpara : TCGPara);virtual;
+
+ { Remarks:
+ * If a method specifies a size you have only to take care
+ of that number of bits, i.e. load_const_reg with OP_8 must
+ only load the lower 8 bit of the specified register
+ the rest of the register can be undefined
+ if necessary the compiler will call a method
+ to zero or sign extend the register
+ * The a_load_XX_XX with OP_64 needn't to be
+ implemented for 32 bit
+ processors, the code generator takes care of that
+ * the addr size is for work with the natural pointer
+ size
+ * the procedures without fpu/mm are only for integer usage
+ * normally the first location is the source and the
+ second the destination
+ }
+
+ {# Emits instruction to call the method specified by symbol name.
+ This routine must be overriden for each new target cpu.
+
+ There is no a_call_ref because loading the reference will use
+ a temp register on most cpu's resulting in conflicts with the
+ registers used for the parameters (PFV)
+ }
+ procedure a_call_name(list : taasmoutput;const s : string);virtual; abstract;
+ procedure a_call_reg(list : taasmoutput;reg : tregister);virtual;abstract;
+
+ { move instructions }
+ procedure a_load_const_reg(list : taasmoutput;size : tcgsize;a : aint;register : tregister);virtual; abstract;
+ procedure a_load_const_ref(list : taasmoutput;size : tcgsize;a : aint;const ref : treference);virtual;
+ procedure a_load_const_loc(list : taasmoutput;a : aint;const loc : tlocation);
+ procedure a_load_reg_ref(list : taasmoutput;fromsize,tosize : tcgsize;register : tregister;const ref : treference);virtual; abstract;
+ procedure a_load_reg_reg(list : taasmoutput;fromsize,tosize : tcgsize;reg1,reg2 : tregister);virtual; abstract;
+ procedure a_load_reg_loc(list : taasmoutput;fromsize : tcgsize;reg : tregister;const loc: tlocation);
+ procedure a_load_ref_reg(list : taasmoutput;fromsize,tosize : tcgsize;const ref : treference;register : tregister);virtual; abstract;
+ procedure a_load_ref_ref(list : taasmoutput;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);virtual;
+ procedure a_load_loc_reg(list : taasmoutput;tosize: tcgsize; const loc: tlocation; reg : tregister);
+ procedure a_load_loc_ref(list : taasmoutput;tosize: tcgsize; const loc: tlocation; const ref : treference);
+ procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);virtual; abstract;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: taasmoutput; size:tcgsize; reg1, reg2: tregister); virtual; abstract;
+ procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); virtual; abstract;
+ procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); virtual; abstract;
+ procedure a_loadfpu_loc_reg(list: taasmoutput; const loc: tlocation; const reg: tregister);
+ procedure a_loadfpu_reg_loc(list: taasmoutput; size: tcgsize; const reg: tregister; const loc: tlocation);
+ procedure a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const cgpara : TCGPara);virtual;
+ procedure a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const cgpara : TCGPara);virtual;
+
+ { vector register move instructions }
+ procedure a_loadmm_reg_reg(list: taasmoutput; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); virtual; abstract;
+ procedure a_loadmm_ref_reg(list: taasmoutput; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); virtual; abstract;
+ procedure a_loadmm_reg_ref(list: taasmoutput; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle); virtual; abstract;
+ procedure a_loadmm_loc_reg(list: taasmoutput; size: tcgsize; const loc: tlocation; const reg: tregister;shuffle : pmmshuffle);
+ procedure a_loadmm_reg_loc(list: taasmoutput; size: tcgsize; const reg: tregister; const loc: tlocation;shuffle : pmmshuffle);
+ procedure a_parammm_reg(list: taasmoutput; size: tcgsize; reg: tregister;const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
+ procedure a_parammm_ref(list: taasmoutput; size: tcgsize; const ref: treference;const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
+ procedure a_parammm_loc(list: taasmoutput; const loc: tlocation; const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
+ procedure a_opmm_reg_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle); virtual;abstract;
+ procedure a_opmm_ref_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); virtual;
+ procedure a_opmm_loc_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const loc: tlocation; reg: tregister;shuffle : pmmshuffle); virtual;
+ procedure a_opmm_reg_ref(list: taasmoutput; Op: TOpCG; size : tcgsize;reg: tregister;const ref: treference; shuffle : pmmshuffle); virtual;
+
+ { basic arithmetic operations }
+ { note: for operators which require only one argument (not, neg), use }
+ { the op_reg_reg, op_reg_ref or op_reg_loc methods and keep in mind }
+ { that in this case the *second* operand is used as both source and }
+ { destination (JM) }
+ procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: Aint; reg: TRegister); virtual; abstract;
+ procedure a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: Aint; const ref: TReference); virtual;
+ procedure a_op_const_loc(list : taasmoutput; Op: TOpCG; a: Aint; const loc: tlocation);
+ procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister); virtual; abstract;
+ procedure a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; reg: TRegister; const ref: TReference); virtual;
+ procedure a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); virtual;
+ procedure a_op_reg_loc(list : taasmoutput; Op: TOpCG; reg: tregister; const loc: tlocation);
+ procedure a_op_ref_loc(list : taasmoutput; Op: TOpCG; const ref: TReference; const loc: tlocation);
+
+ { trinary operations for processors that support them, 'emulated' }
+ { on others. None with "ref" arguments since I don't think there }
+ { are any processors that support it (JM) }
+ procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister); virtual;
+ procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); virtual;
+ procedure a_op_const_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation); virtual;
+ procedure a_op_reg_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation); virtual;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);virtual; abstract;
+ procedure a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;const ref : treference;
+ l : tasmlabel); virtual;
+ procedure a_cmp_const_loc_label(list: taasmoutput; size: tcgsize;cmp_op: topcmp; a: aint; const loc: tlocation;
+ l : tasmlabel);
+ procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); virtual; abstract;
+ procedure a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const ref: treference; reg : tregister; l : tasmlabel); virtual;
+ procedure a_cmp_reg_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg : tregister; const ref: treference; l : tasmlabel); virtual;
+ procedure a_cmp_loc_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
+ procedure a_cmp_ref_loc_label(list: taasmoutput; size: tcgsize;cmp_op: topcmp; const ref: treference; const loc: tlocation;
+ l : tasmlabel);
+
+ procedure a_jmp_name(list : taasmoutput;const s : string); virtual; abstract;
+ procedure a_jmp_always(list : taasmoutput;l: tasmlabel); virtual; abstract;
+ procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); virtual; abstract;
+
+ {# Depending on the value to check in the flags, either sets the register reg to one (if the flag is set)
+ or zero (if the flag is cleared). The size parameter indicates the destination size register.
+ }
+ procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister); virtual; abstract;
+ procedure g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref:TReference); virtual;
+
+ {
+ This routine tries to optimize the const_reg opcode, and should be
+ called at the start of a_op_const_reg. It returns the actual opcode
+ to emit, and the constant value to emit. If this routine returns
+ TRUE, @var(no) instruction should be emitted (.eg : imul reg by 1 )
+
+ @param(op The opcode to emit, returns the opcode which must be emitted)
+ @param(a The constant which should be emitted, returns the constant which must
+ be emitted)
+ @param(reg The register to emit the opcode with, returns the register with
+ which the opcode will be emitted)
+ }
+ function optimize_op_const_reg(list: taasmoutput; var op: topcg; var a : aint; var reg: tregister): boolean;virtual;
+
+ {#
+ This routine is used in exception management nodes. It should
+ save the exception reason currently in the FUNCTION_RETURN_REG. The
+ save should be done either to a temp (pointed to by href).
+ or on the stack (pushing the value on the stack).
+
+ The size of the value to save is OS_S32. The default version
+ saves the exception reason to a temp. memory area.
+ }
+ procedure g_exception_reason_save(list : taasmoutput; const href : treference);virtual;
+ {#
+ This routine is used in exception management nodes. It should
+ save the exception reason constant. The
+ save should be done either to a temp (pointed to by href).
+ or on the stack (pushing the value on the stack).
+
+ The size of the value to save is OS_S32. The default version
+ saves the exception reason to a temp. memory area.
+ }
+ procedure g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aint);virtual;
+ {#
+ This routine is used in exception management nodes. It should
+ load the exception reason to the FUNCTION_RETURN_REG. The saved value
+ should either be in the temp. area (pointed to by href , href should
+ *NOT* be freed) or on the stack (the value should be popped).
+
+ The size of the value to save is OS_S32. The default version
+ saves the exception reason to a temp. memory area.
+ }
+ procedure g_exception_reason_load(list : taasmoutput; const href : treference);virtual;
+
+ procedure g_maybe_testself(list : taasmoutput;reg:tregister);
+ procedure g_maybe_testvmt(list : taasmoutput;reg:tregister;objdef:tobjectdef);
+ {# This should emit the opcode to copy len bytes from the source
+ to destination.
+
+ It must be overriden for each new target processor.
+
+ @param(source Source reference of copy)
+ @param(dest Destination reference of copy)
+
+ }
+ procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);virtual; abstract;
+ {# This should emit the opcode to copy len bytes from the an unaligned source
+ to destination.
+
+ It must be overriden for each new target processor.
+
+ @param(source Source reference of copy)
+ @param(dest Destination reference of copy)
+
+ }
+ procedure g_concatcopy_unaligned(list : taasmoutput;const source,dest : treference;len : aint);virtual;
+ {# This should emit the opcode to a shortrstring from the source
+ to destination.
+
+ @param(source Source reference of copy)
+ @param(dest Destination reference of copy)
+
+ }
+ procedure g_copyshortstring(list : taasmoutput;const source,dest : treference;len:byte);
+
+ procedure g_incrrefcount(list : taasmoutput;t: tdef; const ref: treference);
+ procedure g_decrrefcount(list : taasmoutput;t: tdef; const ref: treference);
+ procedure g_initialize(list : taasmoutput;t : tdef;const ref : treference);
+ procedure g_finalize(list : taasmoutput;t : tdef;const ref : treference);
+
+ {# Generates range checking code. It is to note
+ that this routine does not need to be overriden,
+ as it takes care of everything.
+
+ @param(p Node which contains the value to check)
+ @param(todef Type definition of node to range check)
+ }
+ procedure g_rangecheck(list: taasmoutput; const l:tlocation; fromdef,todef: tdef); virtual;
+
+ {# Generates overflow checking code for a node }
+ procedure g_overflowcheck(list: taasmoutput; const Loc:tlocation; def:tdef); virtual;abstract;
+ procedure g_overflowCheck_loc(List:TAasmOutput;const Loc:TLocation;def:TDef;ovloc : tlocation);virtual;
+
+ procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);virtual;
+ procedure g_releasevaluepara_openarray(list : taasmoutput;const l:tlocation);virtual;
+
+ {# Emits instructions when compilation is done in profile
+ mode (this is set as a command line option). The default
+ behavior does nothing, should be overriden as required.
+ }
+ procedure g_profilecode(list : taasmoutput);virtual;
+ {# Emits instruction for allocating @var(size) bytes at the stackpointer
+
+ @param(size Number of bytes to allocate)
+ }
+ procedure g_stackpointer_alloc(list : taasmoutput;size : longint);virtual; abstract;
+ {# Emits instruction for allocating the locals in entry
+ code of a routine. This is one of the first
+ routine called in @var(genentrycode).
+
+ @param(localsize Number of bytes to allocate as locals)
+ }
+ procedure g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);virtual; abstract;
+ {# Emits instructions for returning from a subroutine.
+ Should also restore the framepointer and stack.
+
+ @param(parasize Number of bytes of parameters to deallocate from stack)
+ }
+ procedure g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);virtual;abstract;
+ {# This routine is called when generating the code for the entry point
+ of a routine. It should save all registers which are not used in this
+ routine, and which should be declared as saved in the std_saved_registers
+ set.
+
+ This routine is mainly used when linking to code which is generated
+ by ABI-compliant compilers (like GCC), to make sure that the reserved
+ registers of that ABI are not clobbered.
+
+ @param(usedinproc Registers which are used in the code of this routine)
+ }
+ procedure g_save_standard_registers(list:Taasmoutput);virtual;
+ {# This routine is called when generating the code for the exit point
+ of a routine. It should restore all registers which were previously
+ saved in @var(g_save_standard_registers).
+
+ @param(usedinproc Registers which are used in the code of this routine)
+ }
+ procedure g_restore_standard_registers(list:Taasmoutput);virtual;
+ procedure g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);virtual;abstract;
+ procedure g_adjust_self_value(list:taasmoutput;procdef: tprocdef;ioffset: aint);virtual;
+ end;
+
+{$ifndef cpu64bit}
+ {# @abstract(Abstract code generator for 64 Bit operations)
+ This class implements an abstract code generator class
+ for 64 Bit operations.
+ }
+ tcg64 = class
+ procedure a_load64_const_ref(list : taasmoutput;value : int64;const ref : treference);virtual;abstract;
+ procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);virtual;abstract;
+ procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);virtual;abstract;
+ procedure a_load64_reg_reg(list : taasmoutput;regsrc,regdst : tregister64);virtual;abstract;
+ procedure a_load64_const_reg(list : taasmoutput;value : int64;reg : tregister64);virtual;abstract;
+ procedure a_load64_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister64);virtual;abstract;
+ procedure a_load64_loc_ref(list : taasmoutput;const l : tlocation;const ref : treference);virtual;abstract;
+ procedure a_load64_const_loc(list : taasmoutput;value : int64;const l : tlocation);virtual;abstract;
+ procedure a_load64_reg_loc(list : taasmoutput;reg : tregister64;const l : tlocation);virtual;abstract;
+
+ procedure a_load64high_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);virtual;abstract;
+ procedure a_load64low_reg_ref(list : taasmoutput;reg : tregister;const ref : treference);virtual;abstract;
+ procedure a_load64high_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);virtual;abstract;
+ procedure a_load64low_ref_reg(list : taasmoutput;const ref : treference;reg : tregister);virtual;abstract;
+ procedure a_load64high_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);virtual;abstract;
+ procedure a_load64low_loc_reg(list : taasmoutput;const l : tlocation;reg : tregister);virtual;abstract;
+
+ procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);virtual;abstract;
+ procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);virtual;abstract;
+ procedure a_op64_reg_ref(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc : tregister64;const ref : treference);virtual;abstract;
+ procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;regdst : tregister64);virtual;abstract;
+ procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;const ref : treference);virtual;abstract;
+ procedure a_op64_const_loc(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);virtual;abstract;
+ procedure a_op64_reg_loc(list : taasmoutput;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);virtual;abstract;
+ procedure a_op64_loc_reg(list : taasmoutput;op:TOpCG;size : tcgsize;const l : tlocation;reg64 : tregister64);virtual;abstract;
+ procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);virtual;
+ procedure a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);virtual;
+ procedure a_op64_const_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);virtual;
+ procedure a_op64_reg_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);virtual;
+
+ procedure a_param64_reg(list : taasmoutput;reg64 : tregister64;const loc : TCGPara);virtual;abstract;
+ procedure a_param64_const(list : taasmoutput;value : int64;const loc : TCGPara);virtual;abstract;
+ procedure a_param64_ref(list : taasmoutput;const r : treference;const loc : TCGPara);virtual;abstract;
+ procedure a_param64_loc(list : taasmoutput;const l : tlocation;const loc : TCGPara);virtual;abstract;
+
+ {
+ This routine tries to optimize the const_reg opcode, and should be
+ called at the start of a_op64_const_reg. It returns the actual opcode
+ to emit, and the constant value to emit. If this routine returns
+ TRUE, @var(no) instruction should be emitted (.eg : imul reg by 1 )
+
+ @param(op The opcode to emit, returns the opcode which must be emitted)
+ @param(a The constant which should be emitted, returns the constant which must
+ be emitted)
+ @param(reg The register to emit the opcode with, returns the register with
+ which the opcode will be emitted)
+ }
+ function optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : int64; var reg: tregister64): boolean;virtual;abstract;
+
+
+ { override to catch 64bit rangechecks }
+ procedure g_rangecheck64(list: taasmoutput; const l:tlocation; fromdef,todef: tdef);virtual;abstract;
+ end;
+{$endif cpu64bit}
+
+ var
+ {# Main code generator class }
+ cg : tcg;
+{$ifndef cpu64bit}
+ {# Code generator class for all operations working with 64-Bit operands }
+ cg64 : tcg64;
+{$endif cpu64bit}
+
+
+implementation
+
+ uses
+ globals,options,systems,
+ verbose,defutil,paramgr,symsym,
+ tgobj,cutils,procinfo;
+
+ const
+ { Please leave this here, this module should NOT use
+ exprasmlist, the lists are always passed as arguments.
+ Declaring it as string here results in an error when compiling (PFV) }
+ exprasmlist = 'error';
+
+
+{*****************************************************************************
+ basic functionallity
+******************************************************************************}
+
+ constructor tcg.create;
+ begin
+ end;
+
+
+{*****************************************************************************
+ register allocation
+******************************************************************************}
+
+
+ procedure tcg.init_register_allocators;
+ begin
+ fillchar(rg,sizeof(rg),0);
+ add_reg_instruction_hook:=@add_reg_instruction;
+ end;
+
+
+ procedure tcg.done_register_allocators;
+ begin
+ { Safety }
+ fillchar(rg,sizeof(rg),0);
+ add_reg_instruction_hook:=nil;
+ end;
+
+ {$ifdef flowgraph}
+ procedure Tcg.init_flowgraph;
+
+ begin
+ aktflownode:=0;
+ end;
+
+ procedure Tcg.done_flowgraph;
+
+ begin
+ end;
+ {$endif}
+
+ function tcg.getintregister(list:Taasmoutput;size:Tcgsize):Tregister;
+ begin
+ if not assigned(rg[R_INTREGISTER]) then
+ internalerror(200312122);
+ result:=rg[R_INTREGISTER].getregister(list,cgsize2subreg(size));
+ end;
+
+
+ function tcg.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
+ begin
+ if not assigned(rg[R_FPUREGISTER]) then
+ internalerror(200312123);
+ result:=rg[R_FPUREGISTER].getregister(list,cgsize2subreg(size));
+ end;
+
+
+ function tcg.getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;
+ begin
+ if not assigned(rg[R_MMREGISTER]) then
+ internalerror(2003121214);
+ result:=rg[R_MMREGISTER].getregister(list,cgsize2subreg(size));
+ end;
+
+
+ function tcg.getaddressregister(list:Taasmoutput):Tregister;
+ begin
+ if assigned(rg[R_ADDRESSREGISTER]) then
+ result:=rg[R_ADDRESSREGISTER].getregister(list,R_SUBWHOLE)
+ else
+ begin
+ if not assigned(rg[R_INTREGISTER]) then
+ internalerror(200312121);
+ result:=rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ end;
+ end;
+
+
+ function Tcg.makeregsize(list:Taasmoutput;reg:Tregister;size:Tcgsize):Tregister;
+ var
+ subreg:Tsubregister;
+ begin
+ subreg:=cgsize2subreg(size);
+ result:=reg;
+ setsubreg(result,subreg);
+ { notify RA }
+ if result<>reg then
+ list.concat(tai_regalloc.resize(result));
+ end;
+
+
+ procedure tcg.getcpuregister(list:Taasmoutput;r:Tregister);
+ begin
+ if not assigned(rg[getregtype(r)]) then
+ internalerror(200312125);
+ rg[getregtype(r)].getcpuregister(list,r);
+ end;
+
+
+ procedure tcg.ungetcpuregister(list:Taasmoutput;r:Tregister);
+ begin
+ if not assigned(rg[getregtype(r)]) then
+ internalerror(200312126);
+ rg[getregtype(r)].ungetcpuregister(list,r);
+ end;
+
+
+ procedure tcg.alloccpuregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
+ begin
+ if assigned(rg[rt]) then
+ rg[rt].alloccpuregisters(list,r)
+ else
+ internalerror(200310092);
+ end;
+
+
+ procedure tcg.allocallcpuregisters(list:Taasmoutput);
+ begin
+ alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+{$ifndef i386}
+ alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+{$ifdef cpumm}
+ alloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
+{$endif cpumm}
+{$endif i386}
+ end;
+
+
+ procedure tcg.dealloccpuregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
+ begin
+ if assigned(rg[rt]) then
+ rg[rt].dealloccpuregisters(list,r)
+ else
+ internalerror(200310093);
+ end;
+
+
+ procedure tcg.deallocallcpuregisters(list:Taasmoutput);
+ begin
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+{$ifndef i386}
+ dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+{$ifdef cpumm}
+ dealloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
+{$endif cpumm}
+{$endif i386}
+ end;
+
+
+ function tcg.uses_registers(rt:Tregistertype):boolean;
+ begin
+ if assigned(rg[rt]) then
+ result:=rg[rt].uses_registers
+ else
+ result:=false;
+ end;
+
+
+ procedure tcg.add_reg_instruction(instr:Tai;r:tregister);
+ var
+ rt : tregistertype;
+ begin
+ rt:=getregtype(r);
+ { Only add it when a register allocator is configured.
+ No IE can be generated, because the VMT is written
+ without a valid rg[] }
+ if assigned(rg[rt]) then
+ rg[rt].add_reg_instruction(instr,r);
+ end;
+
+
+ procedure tcg.add_move_instruction(instr:Taicpu);
+ var
+ rt : tregistertype;
+ begin
+ rt:=getregtype(instr.oper[O_MOV_SOURCE]^.reg);
+ if assigned(rg[rt]) then
+ rg[rt].add_move_instruction(instr)
+ else
+ internalerror(200310095);
+ end;
+
+
+ procedure tcg.do_register_allocation(list:Taasmoutput;headertai:tai);
+ var
+ rt : tregistertype;
+ begin
+ for rt:=R_FPUREGISTER to R_SPECIALREGISTER do
+ begin
+ if assigned(rg[rt]) then
+ rg[rt].do_register_allocation(list,headertai);
+ end;
+ { running the other register allocator passes could require addition int/addr. registers
+ when spilling so run int/addr register allocation at the end }
+ if assigned(rg[R_INTREGISTER]) then
+ rg[R_INTREGISTER].do_register_allocation(list,headertai);
+ if assigned(rg[R_ADDRESSREGISTER]) then
+ rg[R_ADDRESSREGISTER].do_register_allocation(list,headertai);
+ end;
+
+
+ procedure tcg.a_reg_alloc(list : taasmoutput;r : tregister);
+ begin
+ list.concat(tai_regalloc.alloc(r,nil));
+ end;
+
+
+ procedure tcg.a_reg_dealloc(list : taasmoutput;r : tregister);
+ begin
+ list.concat(tai_regalloc.dealloc(r,nil));
+ end;
+
+
+ procedure tcg.a_reg_sync(list : taasmoutput;r : tregister);
+ var
+ instr : tai;
+ begin
+ instr:=tai_regalloc.sync(r);
+ list.concat(instr);
+ add_reg_instruction(instr,r);
+ end;
+
+
+ procedure tcg.a_label(list : taasmoutput;l : tasmlabel);
+ begin
+ list.concat(tai_label.create(l));
+ end;
+
+
+{*****************************************************************************
+ for better code generation these methods should be overridden
+******************************************************************************}
+
+ procedure tcg.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : TCGPara);
+ var
+ ref : treference;
+ begin
+ cgpara.check_simple_location;
+ case cgpara.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_reg(list,size,cgpara.location^.size,r,cgpara.location^.register);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
+ a_load_reg_ref(list,size,cgpara.location^.size,r,ref);
+ end
+ else
+ internalerror(2002071004);
+ end;
+ end;
+
+
+ procedure tcg.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : TCGPara);
+ var
+ ref : treference;
+ begin
+ cgpara.check_simple_location;
+ case cgpara.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,cgpara.location^.size,a,cgpara.location^.register);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
+ a_load_const_ref(list,cgpara.location^.size,a,ref);
+ end
+ else
+ internalerror(2002071004);
+ end;
+ end;
+
+
+ procedure tcg.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : TCGPara);
+ var
+ ref : treference;
+ begin
+ cgpara.check_simple_location;
+ case cgpara.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_ref_reg(list,size,cgpara.location^.size,r,cgpara.location^.register);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ reference_reset(ref);
+ ref.base:=cgpara.location^.reference.index;
+ ref.offset:=cgpara.location^.reference.offset;
+ { use concatcopy, because it can also be a float which fails when
+ load_ref_ref is used }
+ g_concatcopy(list,r,ref,tcgsize2size[size]);
+ end
+ else
+ internalerror(2002071004);
+ end;
+ end;
+
+
+ procedure tcg.a_param_loc(list : taasmoutput;const l:tlocation;const cgpara : TCGPara);
+ begin
+ case l.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ a_param_reg(list,l.size,l.register,cgpara);
+ LOC_CONSTANT :
+ a_param_const(list,l.size,l.value,cgpara);
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ a_param_ref(list,l.size,l.reference,cgpara);
+ else
+ internalerror(2002032211);
+ end;
+ end;
+
+
+ procedure tcg.a_paramaddr_ref(list : taasmoutput;const r : treference;const cgpara : TCGPara);
+ var
+ hr : tregister;
+ begin
+ cgpara.check_simple_location;
+ hr:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,r,hr);
+ a_param_reg(list,OS_ADDR,hr,cgpara);
+ end;
+
+
+{****************************************************************************
+ some generic implementations
+****************************************************************************}
+
+ procedure tcg.a_load_ref_ref(list : taasmoutput;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
+ var
+ tmpreg: tregister;
+ begin
+ { verify if we have the same reference }
+ if references_equal(sref,dref) then
+ exit;
+ tmpreg:=getintregister(list,tosize);
+ a_load_ref_reg(list,fromsize,tosize,sref,tmpreg);
+ a_load_reg_ref(list,tosize,tosize,tmpreg,dref);
+ end;
+
+
+ procedure tcg.a_load_const_ref(list : taasmoutput;size : tcgsize;a : aint;const ref : treference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_load_reg_ref(list,size,size,tmpreg,ref);
+ end;
+
+
+ procedure tcg.a_load_const_loc(list : taasmoutput;a : aint;const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_const_ref(list,loc.size,a,loc.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,loc.size,a,loc.register);
+ else
+ internalerror(200203272);
+ end;
+ end;
+
+
+ procedure tcg.a_load_reg_loc(list : taasmoutput;fromsize : tcgsize;reg : tregister;const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_reg_ref(list,fromsize,loc.size,reg,loc.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_reg(list,fromsize,loc.size,reg,loc.register);
+ else
+ internalerror(200203271);
+ end;
+ end;
+
+
+ procedure tcg.a_load_loc_reg(list : taasmoutput; tosize: tcgsize; const loc: tlocation; reg : tregister);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_ref_reg(list,loc.size,tosize,loc.reference,reg);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_reg(list,loc.size,tosize,loc.register,reg);
+ LOC_CONSTANT:
+ a_load_const_reg(list,tosize,loc.value,reg);
+ else
+ internalerror(200109092);
+ end;
+ end;
+
+
+ procedure tcg.a_load_loc_ref(list : taasmoutput;tosize: tcgsize; const loc: tlocation; const ref : treference);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_ref_ref(list,loc.size,tosize,loc.reference,ref);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_ref(list,loc.size,tosize,loc.register,ref);
+ LOC_CONSTANT:
+ a_load_const_ref(list,tosize,loc.value,ref);
+ else
+ internalerror(200109302);
+ end;
+ end;
+
+
+ function tcg.optimize_op_const_reg(list: taasmoutput; var op: topcg; var a : aint; var reg:tregister): boolean;
+ var
+ powerval : longint;
+ begin
+ optimize_op_const_reg := false;
+ case op of
+ { or with zero returns same result }
+ OP_OR : if a = 0 then optimize_op_const_reg := true;
+ { and with max returns same result }
+ OP_AND : if (a = high(a)) then optimize_op_const_reg := true;
+ { division by 1 returns result }
+ OP_DIV :
+ begin
+ if a = 1 then
+ optimize_op_const_reg := true
+ else if ispowerof2(int64(a), powerval) then
+ begin
+ a := powerval;
+ op:= OP_SHR;
+ end;
+ exit;
+ end;
+ OP_IDIV:
+ begin
+ if a = 1 then
+ optimize_op_const_reg := true
+ else if ispowerof2(int64(a), powerval) then
+ begin
+ a := powerval;
+ op:= OP_SAR;
+ end;
+ exit;
+ end;
+ OP_MUL,OP_IMUL:
+ begin
+ if a = 1 then
+ optimize_op_const_reg := true
+ else if ispowerof2(int64(a), powerval) then
+ begin
+ a := powerval;
+ op:= OP_SHL;
+ end;
+ exit;
+ end;
+ OP_SAR,OP_SHL,OP_SHR:
+ begin
+ if a = 0 then
+ optimize_op_const_reg := true;
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure tcg.a_loadfpu_loc_reg(list: taasmoutput; const loc: tlocation; const reg: tregister);
+ begin
+ case loc.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_loadfpu_ref_reg(list,loc.size,loc.reference,reg);
+ LOC_FPUREGISTER, LOC_CFPUREGISTER:
+ a_loadfpu_reg_reg(list,loc.size,loc.register,reg);
+ else
+ internalerror(200203301);
+ end;
+ end;
+
+
+ procedure tcg.a_loadfpu_reg_loc(list: taasmoutput; size: tcgsize; const reg: tregister; const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_loadfpu_reg_ref(list,size,reg,loc.reference);
+ LOC_FPUREGISTER, LOC_CFPUREGISTER:
+ a_loadfpu_reg_reg(list,size,reg,loc.register);
+ else
+ internalerror(48991);
+ end;
+ end;
+
+
+ procedure tcg.a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const cgpara : TCGPara);
+ var
+ ref : treference;
+ begin
+ case cgpara.location^.loc of
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ begin
+ cgpara.check_simple_location;
+ a_loadfpu_reg_reg(list,size,r,cgpara.location^.register);
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ cgpara.check_simple_location;
+ reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
+ a_loadfpu_reg_ref(list,size,r,ref);
+ end;
+ LOC_REGISTER,LOC_CREGISTER:
+ begin
+ { paramfpu_ref does the check_simpe_location check here if necessary }
+ tg.GetTemp(list,TCGSize2Size[size],tt_normal,ref);
+ a_loadfpu_reg_ref(list,size,r,ref);
+ a_paramfpu_ref(list,size,ref,cgpara);
+ tg.Ungettemp(list,ref);
+ end;
+ else
+ internalerror(2002071004);
+ end;
+ end;
+
+
+ procedure tcg.a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const cgpara : TCGPara);
+ var
+ href : treference;
+ begin
+ cgpara.check_simple_location;
+ case cgpara.location^.loc of
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ a_loadfpu_ref_reg(list,size,ref,cgpara.location^.register);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset);
+ { concatcopy should choose the best way to copy the data }
+ g_concatcopy(list,ref,href,tcgsize2size[size]);
+ end;
+ else
+ internalerror(200402201);
+ end;
+ end;
+
+
+ procedure tcg.a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; const ref: TReference);
+ var
+ tmpreg : tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_op_const_reg(list,op,size,a,tmpreg);
+ a_load_reg_ref(list,size,size,tmpreg,ref);
+ end;
+
+
+ procedure tcg.a_op_const_loc(list : taasmoutput; Op: TOpCG; a: aint; const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_op_const_reg(list,op,loc.size,a,loc.register);
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op_const_ref(list,op,loc.size,a,loc.reference);
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure tcg.a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
+ var
+ tmpreg : tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_op_reg_reg(list,op,size,reg,tmpreg);
+ a_load_reg_ref(list,size,size,tmpreg,ref);
+ end;
+
+
+ procedure tcg.a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister);
+
+ var
+ tmpreg: tregister;
+
+ begin
+ case op of
+ OP_NOT,OP_NEG:
+ { handle it as "load ref,reg; op reg" }
+ begin
+ a_load_ref_reg(list,size,size,ref,reg);
+ a_op_reg_reg(list,op,size,reg,reg);
+ end;
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_op_reg_reg(list,op,size,tmpreg,reg);
+ end;
+ end;
+ end;
+
+
+ procedure tcg.a_op_reg_loc(list : taasmoutput; Op: TOpCG; reg: tregister; const loc: tlocation);
+
+ begin
+ case loc.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_op_reg_reg(list,op,loc.size,reg,loc.register);
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op_reg_ref(list,op,loc.size,reg,loc.reference);
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure tcg.a_op_ref_loc(list : taasmoutput; Op: TOpCG; const ref: TReference; const loc: tlocation);
+
+ var
+ tmpreg: tregister;
+
+ begin
+ case loc.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_op_ref_reg(list,op,loc.size,ref,loc.register);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ tmpreg:=getintregister(list,loc.size);
+ a_load_ref_reg(list,loc.size,loc.size,ref,tmpreg);
+ a_op_reg_ref(list,op,loc.size,tmpreg,loc.reference);
+ end;
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+ procedure Tcg.a_op_const_reg_reg(list:Taasmoutput;op:Topcg;size:Tcgsize;
+ a:aint;src,dst:Tregister);
+
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ a_op_const_reg(list,op,size,a,dst);
+ end;
+
+ procedure tcg.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister);
+ var
+ tmpreg: tregister;
+ begin
+ if (dst<>src1) then
+ begin
+ a_load_reg_reg(list,size,size,src2,dst);
+ a_op_reg_reg(list,op,size,src1,dst);
+ end
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,src2,tmpreg);
+ a_op_reg_reg(list,op,size,src1,tmpreg);
+ a_load_reg_reg(list,size,size,tmpreg,dst);
+ end;
+ end;
+
+
+ procedure tcg.a_op_const_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ begin
+ a_op_const_reg_reg(list,op,size,a,src,dst);
+ ovloc.loc:=LOC_VOID;
+ end;
+
+
+ procedure tcg.a_op_reg_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ begin
+ a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+ ovloc.loc:=LOC_VOID;
+ end;
+
+
+ procedure tcg.a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;const ref : treference;
+ l : tasmlabel);
+
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
+ end;
+
+
+ procedure tcg.a_cmp_const_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;const loc : tlocation;
+ l : tasmlabel);
+
+ begin
+ case loc.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_cmp_const_reg_label(list,size,cmp_op,a,loc.register,l);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_cmp_const_ref_label(list,size,cmp_op,a,loc.reference,l);
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure tcg.a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const ref: treference; reg : tregister; l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
+ end;
+
+
+ procedure tcg.a_cmp_reg_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; reg : tregister; const ref: treference; l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_cmp_reg_reg_label(list,size,cmp_op,reg,tmpreg,l);
+ end;
+
+
+ procedure tcg.a_cmp_loc_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
+ begin
+ case loc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ a_cmp_reg_reg_label(list,size,cmp_op,loc.register,reg,l);
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ a_cmp_ref_reg_label(list,size,cmp_op,loc.reference,reg,l);
+ LOC_CONSTANT:
+ a_cmp_const_reg_label(list,size,cmp_op,loc.value,reg,l);
+ else
+ internalerror(200203231);
+ end;
+ end;
+
+
+ procedure tcg.a_cmp_ref_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference;const loc : tlocation;
+ l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ case loc.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,loc.reference,tmpreg);
+ a_cmp_ref_reg_label(list,size,cmp_op,ref,tmpreg,l);
+ end
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure tcg.a_loadmm_loc_reg(list: taasmoutput; size: tcgsize; const loc: tlocation; const reg: tregister;shuffle : pmmshuffle);
+ begin
+ case loc.loc of
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_reg_reg(list,loc.size,size,loc.register,reg,shuffle);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_loadmm_ref_reg(list,loc.size,size,loc.reference,reg,shuffle);
+ else
+ internalerror(200310121);
+ end;
+ end;
+
+
+ procedure tcg.a_loadmm_reg_loc(list: taasmoutput; size: tcgsize; const reg: tregister; const loc: tlocation;shuffle : pmmshuffle);
+ begin
+ case loc.loc of
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_reg_reg(list,size,loc.size,reg,loc.register,shuffle);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_loadmm_reg_ref(list,size,loc.size,reg,loc.reference,shuffle);
+ else
+ internalerror(200310122);
+ end;
+ end;
+
+
+ procedure tcg.a_parammm_reg(list: taasmoutput; size: tcgsize; reg: tregister;const cgpara : TCGPara;shuffle : pmmshuffle);
+ var
+ href : treference;
+ begin
+ cgpara.check_simple_location;
+ case cgpara.location^.loc of
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_reg_reg(list,size,cgpara.location^.size,reg,cgpara.location^.register,shuffle);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset);
+ a_loadmm_reg_ref(list,size,cgpara.location^.size,reg,href,shuffle);
+ end
+ else
+ internalerror(200310123);
+ end;
+ end;
+
+
+ procedure tcg.a_parammm_ref(list: taasmoutput; size: tcgsize;const ref: treference;const cgpara : TCGPara;shuffle : pmmshuffle);
+ var
+ hr : tregister;
+ hs : tmmshuffle;
+ begin
+ cgpara.check_simple_location;
+ hr:=getmmregister(list,cgpara.location^.size);
+ a_loadmm_ref_reg(list,size,cgpara.location^.size,ref,hr,shuffle);
+ if realshuffle(shuffle) then
+ begin
+ hs:=shuffle^;
+ removeshuffles(hs);
+ a_parammm_reg(list,cgpara.location^.size,hr,cgpara,@hs);
+ end
+ else
+ a_parammm_reg(list,cgpara.location^.size,hr,cgpara,shuffle);
+ end;
+
+
+ procedure tcg.a_parammm_loc(list: taasmoutput;const loc: tlocation; const cgpara : TCGPara;shuffle : pmmshuffle);
+ begin
+ case loc.loc of
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_parammm_reg(list,loc.size,loc.register,cgpara,shuffle);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_parammm_ref(list,loc.size,loc.reference,cgpara,shuffle);
+ else
+ internalerror(200310123);
+ end;
+ end;
+
+
+ procedure tcg.a_opmm_ref_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle);
+ var
+ hr : tregister;
+ hs : tmmshuffle;
+ begin
+ hr:=getmmregister(list,size);
+ a_loadmm_ref_reg(list,size,size,ref,hr,shuffle);
+ if realshuffle(shuffle) then
+ begin
+ hs:=shuffle^;
+ removeshuffles(hs);
+ a_opmm_reg_reg(list,op,size,hr,reg,@hs);
+ end
+ else
+ a_opmm_reg_reg(list,op,size,hr,reg,shuffle);
+ end;
+
+
+ procedure tcg.a_opmm_reg_ref(list: taasmoutput; Op: TOpCG; size : tcgsize;reg: tregister; const ref: treference; shuffle : pmmshuffle);
+ var
+ hr : tregister;
+ hs : tmmshuffle;
+ begin
+ hr:=getmmregister(list,size);
+ a_loadmm_ref_reg(list,size,size,ref,hr,shuffle);
+ if realshuffle(shuffle) then
+ begin
+ hs:=shuffle^;
+ removeshuffles(hs);
+ a_opmm_reg_reg(list,op,size,reg,hr,@hs);
+ a_loadmm_reg_ref(list,size,size,hr,ref,@hs);
+ end
+ else
+ begin
+ a_opmm_reg_reg(list,op,size,reg,hr,shuffle);
+ a_loadmm_reg_ref(list,size,size,hr,ref,shuffle);
+ end;
+ end;
+
+
+ procedure tcg.a_opmm_loc_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const loc: tlocation; reg: tregister;shuffle : pmmshuffle);
+ begin
+ case loc.loc of
+ LOC_CMMREGISTER,LOC_MMREGISTER:
+ a_opmm_reg_reg(list,op,size,loc.register,reg,shuffle);
+ LOC_CREFERENCE,LOC_REFERENCE:
+ a_opmm_ref_reg(list,op,size,loc.reference,reg,shuffle);
+ else
+ internalerror(200312232);
+ end;
+ end;
+
+
+ procedure tcg.g_concatcopy_unaligned(list : taasmoutput;const source,dest : treference;len : aint);
+ begin
+ g_concatcopy(list,source,dest,len);
+ end;
+
+
+ procedure tcg.g_copyshortstring(list : taasmoutput;const source,dest : treference;len:byte);
+ var
+ cgpara1,cgpara2,cgpara3 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ cgpara3.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ paramanager.getintparaloc(pocall_default,3,cgpara3);
+ paramanager.allocparaloc(list,cgpara3);
+ a_paramaddr_ref(list,dest,cgpara3);
+ paramanager.allocparaloc(list,cgpara2);
+ a_paramaddr_ref(list,source,cgpara2);
+ paramanager.allocparaloc(list,cgpara1);
+ a_param_const(list,OS_INT,len,cgpara1);
+ paramanager.freeparaloc(list,cgpara3);
+ paramanager.freeparaloc(list,cgpara2);
+ paramanager.freeparaloc(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_SHORTSTR_ASSIGN');
+ deallocallcpuregisters(list);
+ cgpara3.done;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_incrrefcount(list : taasmoutput;t: tdef; const ref: treference);
+ var
+ href : treference;
+ incrfunc : string;
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ if is_interfacecom(t) then
+ incrfunc:='FPC_INTF_INCR_REF'
+ else if is_ansistring(t) then
+ {$ifdef ansistring_bits}
+ begin
+ case Tstringdef(t).string_typ of
+ st_ansistring16:
+ incrfunc:='FPC_ANSISTR16_INCR_REF';
+ st_ansistring32:
+ incrfunc:='FPC_ANSISTR32_INCR_REF';
+ st_ansistring64:
+ incrfunc:='FPC_ANSISTR64_INCR_REF';
+ end;
+ end
+ {$else}
+ incrfunc:='FPC_ANSISTR_INCR_REF'
+ {$endif}
+ else if is_widestring(t) then
+ incrfunc:='FPC_WIDESTR_INCR_REF'
+ else if is_dynamic_array(t) then
+ incrfunc:='FPC_DYNARRAY_INCR_REF'
+ else
+ incrfunc:='';
+ { call the special incr function or the generic addref }
+ if incrfunc<>'' then
+ begin
+ paramanager.allocparaloc(list,cgpara1);
+ { these functions get the pointer by value }
+ a_param_ref(list,OS_ADDR,ref,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,incrfunc);
+ deallocallcpuregisters(list);
+ end
+ else
+ begin
+ reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
+ paramanager.allocparaloc(list,cgpara2);
+ a_paramaddr_ref(list,href,cgpara2);
+ paramanager.allocparaloc(list,cgpara1);
+ a_paramaddr_ref(list,ref,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ paramanager.freeparaloc(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_ADDREF');
+ deallocallcpuregisters(list);
+ end;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_decrrefcount(list : taasmoutput;t: tdef; const ref: treference);
+ var
+ href : treference;
+ decrfunc : string;
+ needrtti : boolean;
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ needrtti:=false;
+ if is_interfacecom(t) then
+ decrfunc:='FPC_INTF_DECR_REF'
+ else if is_ansistring(t) then
+ {$ifdef ansistring_bits}
+ begin
+ case Tstringdef(t).string_typ of
+ st_ansistring16:
+ decrfunc:='FPC_ANSISTR16_DECR_REF';
+ st_ansistring32:
+ decrfunc:='FPC_ANSISTR32_DECR_REF';
+ st_ansistring64:
+ decrfunc:='FPC_ANSISTR64_DECR_REF';
+ end;
+ end
+ {$else}
+ decrfunc:='FPC_ANSISTR_DECR_REF'
+ {$endif}
+ else if is_widestring(t) then
+ decrfunc:='FPC_WIDESTR_DECR_REF'
+ else if is_dynamic_array(t) then
+ begin
+ decrfunc:='FPC_DYNARRAY_DECR_REF';
+ needrtti:=true;
+ end
+ else
+ decrfunc:='';
+ { call the special decr function or the generic decref }
+ if decrfunc<>'' then
+ begin
+ if needrtti then
+ begin
+ reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
+ paramanager.allocparaloc(list,cgpara2);
+ a_paramaddr_ref(list,href,cgpara2);
+ end;
+ paramanager.allocparaloc(list,cgpara1);
+ a_paramaddr_ref(list,ref,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ if needrtti then
+ paramanager.freeparaloc(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,decrfunc);
+ deallocallcpuregisters(list);
+ end
+ else
+ begin
+ reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
+ paramanager.allocparaloc(list,cgpara2);
+ a_paramaddr_ref(list,href,cgpara2);
+ paramanager.allocparaloc(list,cgpara1);
+ a_paramaddr_ref(list,ref,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ paramanager.freeparaloc(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_DECREF');
+ deallocallcpuregisters(list);
+ end;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_initialize(list : taasmoutput;t : tdef;const ref : treference);
+ var
+ href : treference;
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ if is_ansistring(t) or
+ is_widestring(t) or
+ is_interfacecom(t) or
+ is_dynamic_array(t) then
+ a_load_const_ref(list,OS_ADDR,0,ref)
+ else
+ begin
+ reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
+ paramanager.allocparaloc(list,cgpara2);
+ a_paramaddr_ref(list,href,cgpara2);
+ paramanager.allocparaloc(list,cgpara1);
+ a_paramaddr_ref(list,ref,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ paramanager.freeparaloc(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_INITIALIZE');
+ deallocallcpuregisters(list);
+ end;
+ cgpara1.done;
+ cgpara2.done;
+ end;
+
+
+ procedure tcg.g_finalize(list : taasmoutput;t : tdef;const ref : treference);
+ var
+ href : treference;
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ if is_ansistring(t) or
+ is_widestring(t) or
+ is_interfacecom(t) then
+ begin
+ g_decrrefcount(list,t,ref);
+ a_load_const_ref(list,OS_ADDR,0,ref);
+ end
+ else
+ begin
+ reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
+ paramanager.allocparaloc(list,cgpara2);
+ a_paramaddr_ref(list,href,cgpara2);
+ paramanager.allocparaloc(list,cgpara1);
+ a_paramaddr_ref(list,ref,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ paramanager.freeparaloc(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_FINALIZE');
+ deallocallcpuregisters(list);
+ end;
+ cgpara1.done;
+ cgpara2.done;
+ end;
+
+
+ procedure tcg.g_rangecheck(list: taasmoutput; const l:tlocation;fromdef,todef: tdef);
+ { generate range checking code for the value at location p. The type }
+ { type used is checked against todefs ranges. fromdef (p.resulttype.def) }
+ { is the original type used at that location. When both defs are equal }
+ { the check is also insert (needed for succ,pref,inc,dec) }
+ const
+ aintmax=high(aint);
+ var
+ neglabel : tasmlabel;
+ hreg : tregister;
+ lto,hto,
+ lfrom,hfrom : TConstExprInt;
+ from_signed: boolean;
+ begin
+ { range checking on and range checkable value? }
+ if not(cs_check_range in aktlocalswitches) or
+ not(fromdef.deftype in [orddef,enumdef,arraydef]) then
+ exit;
+{$ifndef cpu64bit}
+ { handle 64bit rangechecks separate for 32bit processors }
+ if is_64bit(fromdef) or is_64bit(todef) then
+ begin
+ cg64.g_rangecheck64(list,l,fromdef,todef);
+ exit;
+ end;
+{$endif cpu64bit}
+ { only check when assigning to scalar, subranges are different, }
+ { when todef=fromdef then the check is always generated }
+ getrange(fromdef,lfrom,hfrom);
+ getrange(todef,lto,hto);
+ from_signed := is_signed(fromdef);
+ { no range check if from and to are equal and are both longint/dword }
+ { (if we have a 32bit processor) or int64/qword, since such }
+ { operations can at most cause overflows (JM) }
+ { Note that these checks are mostly processor independent, they only }
+ { have to be changed once we introduce 64bit subrange types }
+{$ifdef cpu64bit}
+ if (fromdef = todef) and
+ (fromdef.deftype=orddef) and
+ (((((torddef(fromdef).typ = s64bit) and
+ (lfrom = low(int64)) and
+ (hfrom = high(int64))) or
+ ((torddef(fromdef).typ = u64bit) and
+ (lfrom = low(qword)) and
+ (hfrom = high(qword)))))) then
+ exit;
+{$else cpu64bit}
+ if (fromdef = todef) and
+ (fromdef.deftype=orddef) and
+ (((((torddef(fromdef).typ = s32bit) and
+ (lfrom = low(longint)) and
+ (hfrom = high(longint))) or
+ ((torddef(fromdef).typ = u32bit) and
+ (lfrom = low(cardinal)) and
+ (hfrom = high(cardinal)))))) then
+ exit;
+{$endif cpu64bit}
+
+ { if the from-range falls completely in the to-range, no check }
+ { is necessary. Don't do this conversion for the largest unsigned type }
+ if (todef<>fromdef) and
+ (from_signed or (hfrom>=0)) and
+ (lto<=lfrom) and (hto>=hfrom) then
+ exit;
+
+ { generate the rangecheck code for the def where we are going to }
+ { store the result }
+
+ { use the trick that }
+ { a <= x <= b <=> 0 <= x-a <= b-a <=> unsigned(x-a) <= unsigned(b-a) }
+
+ { To be able to do that, we have to make sure however that either }
+ { fromdef and todef are both signed or unsigned, or that we leave }
+ { the parts < 0 and > maxlongint out }
+
+ { is_signed now also works for arrays (it checks the rangetype) (JM) }
+ if from_signed xor is_signed(todef) then
+ begin
+ if from_signed then
+ { from is signed, to is unsigned }
+ begin
+ { if high(from) < 0 -> always range error }
+ if (hfrom < 0) or
+ { if low(to) > maxlongint also range error }
+ (lto > aintmax) then
+ begin
+ a_call_name(list,'FPC_RANGEERROR');
+ exit
+ end;
+ { from is signed and to is unsigned -> when looking at to }
+ { as an signed value, it must be < maxaint (otherwise }
+ { it will become negative, which is invalid since "to" is unsigned) }
+ if hto > aintmax then
+ hto := aintmax;
+ end
+ else
+ { from is unsigned, to is signed }
+ begin
+ if (lfrom > aintmax) or
+ (hto < 0) then
+ begin
+ a_call_name(list,'FPC_RANGEERROR');
+ exit
+ end;
+ { from is unsigned and to is signed -> when looking at to }
+ { as an unsigned value, it must be >= 0 (since negative }
+ { values are the same as values > maxlongint) }
+ if lto < 0 then
+ lto := 0;
+ end;
+ end;
+ hreg:=getintregister(list,OS_INT);
+ a_load_loc_reg(list,OS_INT,l,hreg);
+ a_op_const_reg(list,OP_SUB,OS_INT,aint(lto),hreg);
+ objectlibrary.getjumplabel(neglabel);
+ {
+ if from_signed then
+ a_cmp_const_reg_label(list,OS_INT,OC_GTE,aint(hto-lto),hreg,neglabel)
+ else
+ }
+{$ifdef cpu64bit}
+ if qword(hto-lto)>qword(aintmax) then
+ a_cmp_const_reg_label(list,OS_INT,OC_BE,aintmax,hreg,neglabel)
+ else
+{$endif cpu64bit}
+ a_cmp_const_reg_label(list,OS_INT,OC_BE,aint(hto-lto),hreg,neglabel);
+ a_call_name(list,'FPC_RANGEERROR');
+ a_label(list,neglabel);
+ end;
+
+
+ procedure tcg.g_overflowCheck_loc(List:TAasmOutput;const Loc:TLocation;def:TDef;ovloc : tlocation);
+ begin
+ g_overflowCheck(list,loc,def);
+ end;
+
+
+ procedure tcg.g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref:TReference);
+
+ var
+ tmpreg : tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ g_flags2reg(list,size,f,tmpreg);
+ a_load_reg_ref(list,size,size,tmpreg,ref);
+ end;
+
+
+ procedure tcg.g_maybe_testself(list : taasmoutput;reg:tregister);
+ var
+ OKLabel : tasmlabel;
+ cgpara1 : TCGPara;
+ begin
+ if (cs_check_object in aktlocalswitches) or
+ (cs_check_range in aktlocalswitches) then
+ begin
+ objectlibrary.getjumplabel(oklabel);
+ a_cmp_const_reg_label(list,OS_ADDR,OC_NE,0,reg,oklabel);
+ cgpara1.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.allocparaloc(list,cgpara1);
+ a_param_const(list,OS_INT,210,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ a_call_name(list,'FPC_HANDLEERROR');
+ a_label(list,oklabel);
+ cgpara1.done;
+ end;
+ end;
+
+
+ procedure tcg.g_maybe_testvmt(list : taasmoutput;reg:tregister;objdef:tobjectdef);
+ var
+ hrefvmt : treference;
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ if (cs_check_object in aktlocalswitches) then
+ begin
+ reference_reset_symbol(hrefvmt,objectlibrary.newasmsymbol(objdef.vmt_mangledname,AB_EXTERNAL,AT_DATA),0);
+ paramanager.allocparaloc(list,cgpara2);
+ a_paramaddr_ref(list,hrefvmt,cgpara2);
+ paramanager.allocparaloc(list,cgpara1);
+ a_param_reg(list,OS_ADDR,reg,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ paramanager.freeparaloc(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_CHECK_OBJECT_EXT');
+ deallocallcpuregisters(list);
+ end
+ else
+ if (cs_check_range in aktlocalswitches) then
+ begin
+ paramanager.allocparaloc(list,cgpara1);
+ a_param_reg(list,OS_ADDR,reg,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_CHECK_OBJECT');
+ deallocallcpuregisters(list);
+ end;
+ cgpara1.done;
+ cgpara2.done;
+ end;
+
+
+{*****************************************************************************
+ Entry/Exit Code Functions
+*****************************************************************************}
+
+ procedure tcg.g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);
+ var
+ sizereg,sourcereg,lenreg : tregister;
+ cgpara1,cgpara2,cgpara3 : TCGPara;
+ begin
+ { because some abis don't support dynamic stack allocation properly
+ open array value parameters are copied onto the heap
+ }
+
+ { calculate necessary memory }
+
+ { read/write operations on one register make the life of the register allocator hard }
+ if not(lenloc.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ begin
+ lenreg:=getintregister(list,OS_INT);
+ a_load_loc_reg(list,OS_INT,lenloc,lenreg);
+ end
+ else
+ lenreg:=lenloc.register;
+
+ sizereg:=getintregister(list,OS_INT);
+ a_op_const_reg_reg(list,OP_ADD,OS_INT,1,lenreg,sizereg);
+ a_op_const_reg(list,OP_IMUL,OS_INT,elesize,sizereg);
+ { load source }
+ sourcereg:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,ref,sourcereg);
+
+ { do getmem call }
+ cgpara1.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.allocparaloc(list,cgpara1);
+ a_param_reg(list,OS_INT,sizereg,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_GETMEM');
+ deallocallcpuregisters(list);
+ cgpara1.done;
+ { return the new address }
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,destreg);
+
+ { do move call }
+ cgpara1.init;
+ cgpara2.init;
+ cgpara3.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ paramanager.getintparaloc(pocall_default,3,cgpara3);
+ { load size }
+ paramanager.allocparaloc(list,cgpara3);
+ a_param_reg(list,OS_INT,sizereg,cgpara3);
+ { load destination }
+ paramanager.allocparaloc(list,cgpara2);
+ a_param_reg(list,OS_ADDR,destreg,cgpara2);
+ { load source }
+ paramanager.allocparaloc(list,cgpara1);
+ a_param_reg(list,OS_ADDR,sourcereg,cgpara1);
+ paramanager.freeparaloc(list,cgpara3);
+ paramanager.freeparaloc(list,cgpara2);
+ paramanager.freeparaloc(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_MOVE');
+ deallocallcpuregisters(list);
+ cgpara3.done;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_releasevaluepara_openarray(list : taasmoutput;const l:tlocation);
+ var
+ cgpara1 : TCGPara;
+ begin
+ { do move call }
+ cgpara1.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ { load source }
+ paramanager.allocparaloc(list,cgpara1);
+ a_param_loc(list,l,cgpara1);
+ paramanager.freeparaloc(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_FREEMEM');
+ deallocallcpuregisters(list);
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_save_standard_registers(list:Taasmoutput);
+ var
+ href : treference;
+ size : longint;
+ r : integer;
+ begin
+ { Get temp }
+ size:=0;
+ for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+ if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+ inc(size,sizeof(aint));
+ if size>0 then
+ begin
+ tg.GetTemp(list,size,tt_noreuse,current_procinfo.save_regs_ref);
+ { Copy registers to temp }
+ href:=current_procinfo.save_regs_ref;
+
+ for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+ begin
+ if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+ begin
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE),href);
+ inc(href.offset,sizeof(aint));
+ end;
+ include(rg[R_INTREGISTER].preserved_by_proc,saved_standard_registers[r]);
+ end;
+ end;
+ end;
+
+
+ procedure tcg.g_restore_standard_registers(list:Taasmoutput);
+ var
+ href : treference;
+ r : integer;
+ hreg : tregister;
+ begin
+ { Copy registers from temp }
+ href:=current_procinfo.save_regs_ref;
+ for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+ if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+ begin
+ hreg:=newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE);
+ { Allocate register so the optimizer does remove the load }
+ a_reg_alloc(list,hreg);
+ a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,hreg);
+ inc(href.offset,sizeof(aint));
+ end;
+ tg.UnGetTemp(list,current_procinfo.save_regs_ref);
+ end;
+
+
+ procedure tcg.g_profilecode(list : taasmoutput);
+ begin
+ end;
+
+
+ procedure tcg.g_exception_reason_save(list : taasmoutput; const href : treference);
+ begin
+ a_load_reg_ref(list, OS_INT, OS_INT, NR_FUNCTION_RESULT_REG, href);
+ end;
+
+
+ procedure tcg.g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aint);
+ begin
+ a_load_const_ref(list, OS_INT, a, href);
+ end;
+
+
+ procedure tcg.g_exception_reason_load(list : taasmoutput; const href : treference);
+ begin
+ a_load_ref_reg(list, OS_INT, OS_INT, href, NR_FUNCTION_RESULT_REG);
+ end;
+
+
+ procedure tcg.g_adjust_self_value(list:taasmoutput;procdef: tprocdef;ioffset: aint);
+ var
+ hsym : tsym;
+ href : treference;
+ paraloc : tcgparalocation;
+ begin
+ { calculate the parameter info for the procdef }
+ if not procdef.has_paraloc_info then
+ begin
+ procdef.requiredargarea:=paramanager.create_paraloc_info(procdef,callerside);
+ procdef.has_paraloc_info:=true;
+ end;
+ hsym:=tsym(procdef.parast.search('self'));
+ if not(assigned(hsym) and
+ (hsym.typ=paravarsym)) then
+ internalerror(200305251);
+ paraloc:=tparavarsym(hsym).paraloc[callerside].location^;
+ case paraloc.loc of
+ LOC_REGISTER:
+ cg.a_op_const_reg(list,OP_SUB,paraloc.size,ioffset,paraloc.register);
+ LOC_REFERENCE:
+ begin
+ { offset in the wrapper needs to be adjusted for the stored
+ return address }
+ reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset+sizeof(aint));
+ cg.a_op_const_ref(list,OP_SUB,paraloc.size,ioffset,href);
+ end
+ else
+ internalerror(200309189);
+ end;
+ end;
+
+{*****************************************************************************
+ TCG64
+*****************************************************************************}
+
+{$ifndef cpu64bit}
+ procedure tcg64.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64; regsrc,regdst : tregister64);
+ begin
+ a_load64_reg_reg(list,regsrc,regdst);
+ a_op64_const_reg(list,op,size,value,regdst);
+ end;
+
+
+ procedure tcg64.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ var
+ tmpreg64 : tregister64;
+ begin
+ { when src1=dst then we need to first create a temp to prevent
+ overwriting src1 with src2 }
+ if (regsrc1.reghi=regdst.reghi) or
+ (regsrc1.reglo=regdst.reghi) or
+ (regsrc1.reghi=regdst.reglo) or
+ (regsrc1.reglo=regdst.reglo) then
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_reg_reg(list,regsrc2,tmpreg64);
+ a_op64_reg_reg(list,op,size,regsrc1,tmpreg64);
+ a_load64_reg_reg(list,tmpreg64,regdst);
+ end
+ else
+ begin
+ a_load64_reg_reg(list,regsrc2,regdst);
+ a_op64_reg_reg(list,op,size,regsrc1,regdst);
+ end;
+ end;
+
+
+ procedure tcg64.a_op64_const_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ begin
+ a_op64_const_reg_reg(list,op,size,value,regsrc,regdst);
+ ovloc.loc:=LOC_VOID;
+ end;
+
+
+ procedure tcg64.a_op64_reg_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ begin
+ a_op64_reg_reg_reg(list,op,size,regsrc1,regsrc2,regdst);
+ ovloc.loc:=LOC_VOID;
+ end;
+
+
+{$endif cpu64bit}
+
+
+
+initialization
+ ;
+finalization
+ cg.free;
+{$ifndef cpu64bit}
+ cg64.free;
+{$endif cpu64bit}
+end.
diff --git a/compiler/cgutils.pas b/compiler/cgutils.pas
new file mode 100644
index 0000000000..0e8c94f316
--- /dev/null
+++ b/compiler/cgutils.pas
@@ -0,0 +1,186 @@
+{
+ Copyright (c) 1998-2004 by Florian Klaempfl
+
+ Some basic types and constants for the code generation
+
+ 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 exports some helper routines which are used across the code generator }
+unit cgutils;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cclasses,
+ aasmbase,
+ cpubase,cgbase;
+
+ type
+ { reference record, reordered for best alignment }
+ preference = ^treference;
+ treference = record
+ offset : aint;
+ symbol,
+ relsymbol : tasmsymbol;
+ segment,
+ base,
+ index : tregister;
+ refaddr : trefaddr;
+ scalefactor : byte;
+{$ifdef arm}
+ symboldata : tlinkedlistitem;
+ signindex : shortint;
+ shiftimm : byte;
+ addressmode : taddressmode;
+ shiftmode : tshiftmode;
+{$endif arm}
+{$ifdef m68k}
+ { indexed increment and decrement mode }
+ { (An)+ and -(An) }
+ direction : tdirection;
+{$endif m68k}
+ end;
+
+ tlocation = record
+ loc : TCGLoc;
+ size : TCGSize;
+ case TCGLoc of
+ LOC_FLAGS : (resflags : tresflags);
+ LOC_CONSTANT : (
+ case longint of
+{$ifdef FPC_BIG_ENDIAN}
+ 1 : (_valuedummy,value : aint);
+{$else FPC_BIG_ENDIAN}
+ 1 : (value : aint);
+{$endif FPC_BIG_ENDIAN}
+ 2 : (value64 : Int64);
+ );
+ LOC_CREFERENCE,
+ LOC_REFERENCE : (reference : treference);
+ { segment in reference at the same place as in loc_register }
+ LOC_REGISTER,
+ LOC_CREGISTER : (
+ case longint of
+ 1 : (register : tregister;
+{$ifdef m68k}
+ { some m68k OSes require that the result is returned in d0 and a0
+ the second location must be stored here }
+ registeralias : tregister;
+{$endif m68k}
+ );
+{$ifndef cpu64bit}
+ { overlay a 64 Bit register type }
+ 2 : (register64 : tregister64);
+{$endif cpu64bit}
+ );
+ end;
+
+
+ { trerefence handling }
+
+ {# Clear to zero a treference }
+ procedure reference_reset(var ref : treference);
+ {# Clear to zero a treference, and set is base address
+ to base register.
+ }
+ procedure reference_reset_base(var ref : treference;base : tregister;offset : longint);
+ procedure reference_reset_symbol(var ref : treference;sym : tasmsymbol;offset : longint);
+ { This routine verifies if two references are the same, and
+ if so, returns TRUE, otherwise returns false.
+ }
+ function references_equal(sref : treference;dref : treference) : boolean;
+
+ { tlocation handling }
+
+ procedure location_reset(var l : tlocation;lt:TCGLoc;lsize:TCGSize);
+ procedure location_copy(var destloc:tlocation; const sourceloc : tlocation);
+ procedure location_swap(var destloc,sourceloc : tlocation);
+
+implementation
+
+{****************************************************************************
+ TReference
+****************************************************************************}
+
+ procedure reference_reset(var ref : treference);
+ begin
+ FillChar(ref,sizeof(treference),0);
+{$ifdef arm}
+ ref.signindex:=1;
+{$endif arm}
+ end;
+
+
+ procedure reference_reset_base(var ref : treference;base : tregister;offset : longint);
+ begin
+ reference_reset(ref);
+ ref.base:=base;
+ ref.offset:=offset;
+ end;
+
+
+ procedure reference_reset_symbol(var ref : treference;sym : tasmsymbol;offset : longint);
+ begin
+ reference_reset(ref);
+ ref.symbol:=sym;
+ ref.offset:=offset;
+ end;
+
+
+ function references_equal(sref : treference;dref : treference):boolean;
+ begin
+ references_equal:=CompareByte(sref,dref,sizeof(treference))=0;
+ end;
+
+
+{****************************************************************************
+ TLocation
+****************************************************************************}
+
+ procedure location_reset(var l : tlocation;lt:TCGLoc;lsize:TCGSize);
+ begin
+ FillChar(l,sizeof(tlocation),0);
+ l.loc:=lt;
+ l.size:=lsize;
+{$ifdef arm}
+ if l.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ l.reference.signindex:=1;
+{$endif arm}
+ end;
+
+
+ procedure location_copy(var destloc:tlocation; const sourceloc : tlocation);
+ begin
+ destloc:=sourceloc;
+ end;
+
+
+ procedure location_swap(var destloc,sourceloc : tlocation);
+ var
+ swapl : tlocation;
+ begin
+ swapl := destloc;
+ destloc := sourceloc;
+ sourceloc := swapl;
+ end;
+
+
+
+end.
diff --git a/compiler/charset.pas b/compiler/charset.pas
new file mode 100644
index 0000000000..348581c48c
--- /dev/null
+++ b/compiler/charset.pas
@@ -0,0 +1,252 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2000 by Florian Klaempfl
+ member of the Free Pascal development team.
+
+ This unit implements several classes for charset conversions
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************
+}
+unit charset;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ type
+ tunicodechar = word;
+ tunicodestring = ^tunicodechar;
+
+ tcsconvert = class
+ // !!!!!!1constructor create;
+ end;
+
+ tunicodecharmappingflag = (umf_noinfo,umf_leadbyte,umf_undefined,
+ umf_unused);
+
+ punicodecharmapping = ^tunicodecharmapping;
+ tunicodecharmapping = record
+ unicode : tunicodechar;
+ flag : tunicodecharmappingflag;
+ reserved : byte;
+ end;
+
+ punicodemap = ^tunicodemap;
+ tunicodemap = record
+ cpname : string[20];
+ map : punicodecharmapping;
+ lastchar : longint;
+ next : punicodemap;
+ internalmap : boolean;
+ end;
+
+ tcp2unicode = class(tcsconvert)
+ end;
+
+ function loadunicodemapping(const cpname,f : string) : punicodemap;
+ procedure registermapping(p : punicodemap);
+ function getmap(const s : string) : punicodemap;
+ function mappingavailable(const s : string) : boolean;
+ function getunicode(c : char;p : punicodemap) : tunicodechar;
+ function getascii(c : tunicodechar;p : punicodemap) : string;
+
+ implementation
+
+ var
+ mappings : punicodemap;
+
+ function loadunicodemapping(const cpname,f : string) : punicodemap;
+
+ var
+ data : punicodecharmapping;
+ datasize : longint;
+ t : text;
+ s,hs : string;
+ scanpos,charpos,unicodevalue : longint;
+ code : integer;
+ flag : tunicodecharmappingflag;
+ p : punicodemap;
+ lastchar : longint;
+
+ begin
+ lastchar:=-1;
+ loadunicodemapping:=nil;
+ datasize:=256;
+ getmem(data,sizeof(tunicodecharmapping)*datasize);
+ assign(t,f);
+ {$I-}
+ reset(t);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ freemem(data,sizeof(tunicodecharmapping)*datasize);
+ exit;
+ end;
+ while not(eof(t)) do
+ begin
+ readln(t,s);
+ if (s[1]='0') and (s[2]='x') then
+ begin
+ flag:=umf_unused;
+ scanpos:=3;
+ hs:='$';
+ while s[scanpos] in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ hs:=hs+s[scanpos];
+ inc(scanpos);
+ end;
+ val(hs,charpos,code);
+ if code<>0 then
+ begin
+ freemem(data,sizeof(tunicodecharmapping)*datasize);
+ close(t);
+ exit;
+ end;
+ while not(s[scanpos] in ['0','#']) do
+ inc(scanpos);
+ if s[scanpos]='#' then
+ begin
+ { special char }
+ unicodevalue:=$ffff;
+ hs:=copy(s,scanpos,length(s)-scanpos+1);
+ if hs='#DBCS LEAD BYTE' then
+ flag:=umf_leadbyte;
+ end
+ else
+ begin
+ { C hex prefix }
+ inc(scanpos,2);
+ hs:='$';
+ while s[scanpos] in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ hs:=hs+s[scanpos];
+ inc(scanpos);
+ end;
+ val(hs,unicodevalue,code);
+ if code<>0 then
+ begin
+ freemem(data,sizeof(tunicodecharmapping)*datasize);
+ close(t);
+ exit;
+ end;
+ if charpos>datasize then
+ begin
+ { allocate 1024 bytes more because }
+ { if we need more than 256 entries it's }
+ { probably a mbcs with a lot of }
+ { entries }
+ datasize:=charpos+1024;
+ reallocmem(data,sizeof(tunicodecharmapping)*datasize);
+ end;
+ flag:=umf_noinfo;
+ end;
+ data[charpos].flag:=flag;
+ data[charpos].unicode:=unicodevalue;
+ if charpos>lastchar then
+ lastchar:=charpos;
+ end;
+ end;
+ close(t);
+ new(p);
+ p^.lastchar:=lastchar;
+ p^.cpname:=cpname;
+ p^.internalmap:=false;
+ p^.next:=nil;
+ p^.map:=data;
+ loadunicodemapping:=p;
+ end;
+
+ procedure registermapping(p : punicodemap);
+
+ begin
+ p^.next:=mappings;
+ mappings:=p;
+ end;
+
+ function getmap(const s : string) : punicodemap;
+
+ var
+ hp : punicodemap;
+
+ const
+ mapcachep : punicodemap = nil;
+
+ begin
+ if assigned(mapcachep) and
+ (mapcachep^.cpname=s) then
+ begin
+ getmap:=mapcachep;
+ exit;
+ end;
+ hp:=mappings;
+ while assigned(hp) do
+ begin
+ if hp^.cpname=s then
+ begin
+ getmap:=hp;
+ mapcachep:=hp;
+ exit;
+ end;
+ hp:=hp^.next;
+ end;
+ getmap:=nil;
+ end;
+
+ function mappingavailable(const s : string) : boolean;
+
+ begin
+ mappingavailable:=getmap(s)<>nil;
+ end;
+
+ function getunicode(c : char;p : punicodemap) : tunicodechar;
+
+ begin
+ if ord(c)<=p^.lastchar then
+ getunicode:=p^.map[ord(c)].unicode
+ else
+ getunicode:=0;
+ end;
+
+ function getascii(c : tunicodechar;p : punicodemap) : string;
+
+ var
+ i : longint;
+
+ begin
+ { at least map to space }
+ getascii:=#32;
+ for i:=0 to p^.lastchar do
+ if p^.map[i].unicode=c then
+ begin
+ if i<256 then
+ getascii:=chr(i)
+ else
+ getascii:=chr(i div 256)+chr(i mod 256);
+ exit;
+ end;
+ end;
+
+ var
+ hp : punicodemap;
+
+initialization
+ mappings:=nil;
+finalization
+ while assigned(mappings) do
+ begin
+ hp:=mappings^.next;
+ if not(mappings^.internalmap) then
+ begin
+ freemem(mappings^.map);
+ dispose(mappings);
+ end;
+ mappings:=hp;
+ end;
+end.
diff --git a/compiler/cmsgs.pas b/compiler/cmsgs.pas
new file mode 100644
index 0000000000..899ed0e7d4
--- /dev/null
+++ b/compiler/cmsgs.pas
@@ -0,0 +1,413 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements the message object
+
+ 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 cmsgs;
+
+{$i fpcdefs.inc}
+
+interface
+
+const
+ maxmsgidxparts = 20;
+
+type
+ ppchar=^pchar;
+
+ TArrayOfPChar = array[0..1000] of pchar;
+ PArrayOfPChar = ^TArrayOfPChar;
+
+ PMessage=^TMessage;
+ TMessage=object
+ msgfilename : string;
+ msgintern : boolean;
+ msgallocsize,
+ msgsize,
+ msgparts,
+ msgs : longint;
+ msgtxt : pchar;
+ msgidx : array[1..maxmsgidxparts] of PArrayOfPChar;
+ msgidxmax : array[1..maxmsgidxparts] of longint;
+ constructor Init(n:longint;const idxmax:array of longint);
+ destructor Done;
+ function LoadIntern(p:pointer;n:longint):boolean;
+ function LoadExtern(const fn:string):boolean;
+ procedure ClearIdx;
+ procedure CreateIdx;
+ function GetPChar(nr:longint):pchar;
+ function Get(nr:longint;const args:array of string):string;
+ end;
+
+{ this will read a line until #10 or #0 and also increase p }
+function GetMsgLine(var p:pchar):string;
+
+
+implementation
+
+uses
+ cutils,
+ strings;
+
+
+function MsgReplace(const s:string;const args:array of string):string;
+var
+ last,
+ i : longint;
+ hs : string;
+
+begin
+ if s='' then
+ begin
+ MsgReplace:='';
+ exit;
+ end;
+ hs:='';
+ i:=0;
+ last:=0;
+ while (i<length(s)-1) do
+ begin
+ inc(i);
+ if (s[i]='$') and (s[i+1] in ['1'..'9']) then
+ begin
+ hs:=hs+copy(s,last+1,i-last-1)+args[byte(s[i+1])-byte('1')];
+ inc(i);
+ last:=i;
+ end;
+ end;
+ MsgReplace:=hs+copy(s,last+1,length(s)-last);;
+end;
+
+
+
+constructor TMessage.Init(n:longint;const idxmax:array of longint);
+var
+ i : longint;
+begin
+ msgtxt:=nil;
+ msgsize:=0;
+ msgparts:=n;
+ if n<>high(idxmax)+1 then
+ fail;
+ for i:=1 to n do
+ begin
+ msgidxmax[i]:=idxmax[i-1];
+ getmem(msgidx[i],msgidxmax[i]*sizeof(pointer));
+ fillchar(msgidx[i]^,msgidxmax[i]*sizeof(pointer),0);
+ end;
+end;
+
+
+destructor TMessage.Done;
+var
+ i : longint;
+begin
+ for i:=1 to msgparts do
+ freemem(msgidx[i],msgidxmax[i]*sizeof(pointer));
+ if msgallocsize>0 then
+ begin
+ freemem(msgtxt,msgsize);
+ msgallocsize:=0;
+ end;
+ msgtxt:=nil;
+ msgsize:=0;
+ msgparts:=0;
+end;
+
+
+function TMessage.LoadIntern(p:pointer;n:longint):boolean;
+begin
+ msgtxt:=pchar(p);
+ msgsize:=n;
+ msgallocsize:=0;
+ msgintern:=true;
+ ClearIdx;
+ CreateIdx;
+ LoadIntern:=true;
+end;
+
+
+function TMessage.LoadExtern(const fn:string):boolean;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+const
+ bufsize=8192;
+var
+ f : text;
+ error,multiline : boolean;
+ line,i,j : longint;
+ ptxt : pchar;
+ s,s1 : string;
+ buf : pointer;
+
+ procedure err(const msgstr:string);
+ begin
+ writeln('*** PPC, file ',fn,', error in line ',line,': ',msgstr);
+ error:=true;
+ end;
+
+begin
+ LoadExtern:=false;
+ getmem(buf,bufsize);
+ { Read the message file }
+ assign(f,fn);
+ {$I-}
+ reset(f);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ WriteLn('*** PPC, can not open message file ',fn);
+ exit;
+ end;
+ settextbuf(f,buf^,bufsize);
+ { First parse the file and count bytes needed }
+ error:=false;
+ line:=0;
+ multiline:=false;
+ msgsize:=0;
+ while not eof(f) do
+ begin
+ readln(f,s);
+ inc(line);
+ if multiline then
+ begin
+ if s=']' then
+ multiline:=false
+ else
+ inc(msgsize,length(s)+1); { +1 for linebreak }
+ end
+ else
+ begin
+ if (s<>'') and not(s[1] in ['#',';','%']) then
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ j:=i+1;
+ if not(s[j] in ['0'..'9']) then
+ err('no number found')
+ else
+ begin
+ while (s[j] in ['0'..'9']) do
+ inc(j);
+ end;
+ if j-i-1<>5 then
+ err('number length is not 5');
+ if s[j+1]='[' then
+ begin
+ inc(msgsize,j-i);
+ multiline:=true
+ end
+ else
+ inc(msgsize,length(s)-i+1);
+ end
+ else
+ err('no = found');
+ end;
+ end;
+ end;
+ if multiline then
+ err('still in multiline mode');
+ if error then
+ begin
+ freemem(buf,bufsize);
+ close(f);
+ exit;
+ end;
+ { now read the buffer in mem }
+ msgallocsize:=msgsize;
+ getmem(msgtxt,msgallocsize);
+ ptxt:=msgtxt;
+ reset(f);
+ while not eof(f) do
+ begin
+ readln(f,s);
+ if multiline then
+ begin
+ if s=']' then
+ begin
+ multiline:=false;
+ { overwrite last eol }
+ dec(ptxt);
+ ptxt^:=#0;
+ inc(ptxt);
+ end
+ else
+ begin
+ move(s[1],ptxt^,length(s));
+ inc(ptxt,length(s));
+ ptxt^:=#10;
+ inc(ptxt);
+ end;
+ end
+ else
+ begin
+ if (s<>'') and not(s[1] in ['#',';','%']) then
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ j:=i+1;
+ while (s[j] in ['0'..'9']) do
+ inc(j);
+ { multiline start then no txt }
+ if s[j+1]='[' then
+ begin
+ s1:=Copy(s,i+1,j-i);
+ move(s1[1],ptxt^,length(s1));
+ inc(ptxt,length(s1));
+ multiline:=true;
+ end
+ else
+ begin
+ { txt including number }
+ s1:=Copy(s,i+1,255);
+ move(s1[1],ptxt^,length(s1));
+ inc(ptxt,length(s1));
+ ptxt^:=#0;
+ inc(ptxt);
+ end;
+ end;
+ end;
+ end;
+ end;
+ close(f);
+ freemem(buf,bufsize);
+{ now we can create the index, clear if the previous load was also
+ an external file, because those can't be reused }
+ if not msgintern then
+ ClearIdx;
+ CreateIdx;
+{ set that we've loaded an external file }
+ msgintern:=false;
+ LoadExtern:=true;
+end;
+
+
+procedure TMessage.ClearIdx;
+var
+ i : longint;
+begin
+ { clear }
+ for i:=1 to msgparts do
+ fillchar(msgidx[i]^,msgidxmax[i]*sizeof(pointer),0);
+end;
+
+
+procedure TMessage.CreateIdx;
+var
+ hp1,
+ hp,hpend : pchar;
+ code : integer;
+ num : longint;
+ number : string[5];
+ i : longint;
+ numpart,numidx : longint;
+begin
+ { process msgtxt buffer }
+ number:='00000';
+ hp:=msgtxt;
+ hpend:=@msgtxt[msgsize];
+ while (hp<hpend) do
+ begin
+ hp1:=hp;
+ for i:=1 to 5 do
+ begin
+ number[i]:=hp1^;
+ inc(hp1);
+ end;
+ val(number,num,code);
+ numpart:=num div 1000;
+ numidx:=num mod 1000;
+ { check range }
+ if (numpart <= msgparts) and (numidx < msgidxmax[numpart]) then
+ begin
+ { skip _ }
+ inc(hp1);
+ { put the address in the idx, the numbers are already checked }
+ msgidx[numpart]^[numidx]:=hp1;
+ end;
+ { next string }
+ hp:=pchar(@hp[strlen(hp)+1]);
+ end;
+end;
+
+
+function GetMsgLine(var p:pchar):string;
+var
+ i : longint;
+begin
+ i:=0;
+ while not(p^ in [#0,#10]) and (i<255) do
+ begin
+ inc(i);
+ GetMsgLine[i]:=p^;
+ inc(p);
+ end;
+ { skip #10 }
+ if p^=#10 then
+ inc(p);
+ { if #0 then set p to nil }
+ if p^=#0 then
+ p:=nil;
+ { return string }
+ GetMsgLine[0]:=chr(i);
+end;
+
+
+function TMessage.GetPChar(nr:longint):pchar;
+begin
+ GetPChar:=msgidx[nr div 1000]^[nr mod 1000];
+end;
+
+
+function TMessage.Get(nr:longint;const args:array of string):string;
+var
+ hp : pchar;
+begin
+ hp:=msgidx[nr div 1000]^[nr mod 1000];
+ if hp=nil then
+ Get:='msg nr '+tostr(nr)
+ else
+ Get:=MsgReplace(strpas(hp),args);
+end;
+
+end.
diff --git a/compiler/comphook.pas b/compiler/comphook.pas
new file mode 100644
index 0000000000..48bab69da5
--- /dev/null
+++ b/compiler/comphook.pas
@@ -0,0 +1,413 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit handles the compilerhooks for output to external programs
+
+ 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 comphook;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+ SysUtils,
+{$ELSE}
+ globals,
+{$ENDIF}
+ finput;
+
+Const
+ { Levels }
+ V_None = $0;
+ V_Fatal = $1;
+ V_Error = $2;
+ V_Normal = $4; { doesn't show a text like Error: }
+ V_Warning = $8;
+ V_Note = $10;
+ V_Hint = $20;
+ V_LineInfoMask = $fff;
+ { From here by default no line info }
+ V_Info = $1000;
+ V_Status = $2000;
+ V_Used = $4000;
+ V_Tried = $8000;
+ V_Conditional = $10000;
+ V_Debug = $20000;
+ V_Executable = $40000;
+ V_LevelMask = $fffffff;
+ V_All = V_LevelMask;
+ V_Default = V_Fatal + V_Error + V_Normal;
+ { Flags }
+ V_LineInfo = $10000000;
+
+const
+ { RHIDE expect gcc like error output }
+ fatalstr : string[20] = 'Fatal:';
+ errorstr : string[20] = 'Error:';
+ warningstr : string[20] = 'Warning:';
+ notestr : string[20] = 'Note:';
+ hintstr : string[20] = 'Hint:';
+
+type
+ PCompilerStatus = ^TCompilerStatus;
+ TCompilerStatus = record
+ { Current status }
+ currentmodule,
+ currentsourcepath,
+ currentsource : string; { filename }
+ currentline,
+ currentcolumn : longint; { current line and column }
+ { Total Status }
+ compiledlines : longint; { the number of lines which are compiled }
+ errorcount : longint; { number of generated errors }
+ { program info }
+ isexe,
+ islibrary : boolean;
+ { Settings for the output }
+ verbosity : longint;
+ maxerrorcount : longint;
+ errorwarning,
+ errornote,
+ errorhint,
+ skip_error,
+ use_stderr,
+ use_redir,
+ use_bugreport,
+ use_gccoutput,
+ print_source_path,
+ compiling_current : boolean;
+ { Redirection support }
+ redirfile : text;
+ { Special file for bug report }
+ reportbugfile : text;
+ end;
+var
+ status : tcompilerstatus;
+
+ type
+ EControlCAbort=class(Exception)
+ constructor Create;
+ end;
+ ECompilerAbort=class(Exception)
+ constructor Create;
+ end;
+ ECompilerAbortSilent=class(Exception)
+ constructor Create;
+ end;
+
+{ Default Functions }
+Function def_status:boolean;
+Function def_comment(Level:Longint;const s:string):boolean;
+function def_internalerror(i:longint):boolean;
+procedure def_initsymbolinfo;
+procedure def_donesymbolinfo;
+procedure def_extractsymbolinfo;
+function def_openinputfile(const filename: string): tinputfile;
+Function def_getnamedfiletime(Const F : String) : Longint;
+{ Function redirecting for IDE support }
+type
+ tstopprocedure = procedure(err:longint);
+ tstatusfunction = function:boolean;
+ tcommentfunction = function(Level:Longint;const s:string):boolean;
+ tinternalerrorfunction = function(i:longint):boolean;
+
+ tinitsymbolinfoproc = procedure;
+ tdonesymbolinfoproc = procedure;
+ textractsymbolinfoproc = procedure;
+ topeninputfilefunc = function(const filename: string): tinputfile;
+ tgetnamedfiletimefunc = function(const filename: string): longint;
+
+const
+ do_status : tstatusfunction = @def_status;
+ do_comment : tcommentfunction = @def_comment;
+ do_internalerror : tinternalerrorfunction = @def_internalerror;
+
+ do_initsymbolinfo : tinitsymbolinfoproc = @def_initsymbolinfo;
+ do_donesymbolinfo : tdonesymbolinfoproc = @def_donesymbolinfo;
+ do_extractsymbolinfo : textractsymbolinfoproc = @def_extractsymbolinfo;
+
+ do_openinputfile : topeninputfilefunc = @def_openinputfile;
+ do_getnamedfiletime : tgetnamedfiletimefunc = @def_getnamedfiletime;
+
+implementation
+
+ uses
+{$IFNDEF USE_SYSUTILS}
+ dos,
+{$ENDIF USE_SYSUTILS}
+ cutils
+ ;
+
+{****************************************************************************
+ Helper Routines
+****************************************************************************}
+
+function gccfilename(const s : string) : string;
+var
+ i : longint;
+begin
+ for i:=1to length(s) do
+ begin
+ case s[i] of
+ '\' : gccfilename[i]:='/';
+ 'A'..'Z' : gccfilename[i]:=chr(ord(s[i])+32);
+ else
+ gccfilename[i]:=s[i];
+ end;
+ end;
+ gccfilename[0]:=s[0];
+end;
+
+
+function tostr(i : longint) : string;
+var
+ hs : string;
+begin
+ str(i,hs);
+ tostr:=hs;
+end;
+
+
+{****************************************************************************
+ Stopping the compiler
+****************************************************************************}
+
+ constructor EControlCAbort.Create;
+ begin
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+ inherited Create('Ctrl-C Signaled!');
+{$ELSE}
+ inherited Create;
+{$ENDIF}
+ end;
+
+
+ constructor ECompilerAbort.Create;
+ begin
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+ inherited Create('Compilation Aborted');
+{$ELSE}
+ inherited Create;
+{$ENDIF}
+ end;
+
+
+ constructor ECompilerAbortSilent.Create;
+ begin
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+ inherited Create('Compilation Aborted');
+{$ELSE}
+ inherited Create;
+{$ENDIF}
+ end;
+
+
+{****************************************************************************
+ Predefined default Handlers
+****************************************************************************}
+
+function def_status:boolean;
+var
+ hstatus : TFPCHeapStatus;
+begin
+ def_status:=false; { never stop }
+{ Status info?, Called every line }
+ if ((status.verbosity and V_Status)<>0) then
+ begin
+ if (status.compiledlines=1) or
+ (status.currentline mod 100=0) then
+ begin
+ if status.currentline>0 then
+ Write(status.currentline,' ');
+ hstatus:=GetFPCHeapStatus;
+ WriteLn(DStr(hstatus.CurrHeapUsed shr 10),'/',DStr(hstatus.CurrHeapSize shr 10),' Kb Used');
+ end;
+ end;
+{$ifdef macos}
+ Yield;
+{$endif}
+end;
+
+
+Function def_comment(Level:Longint;const s:string):boolean;
+const
+ rh_errorstr = 'error:';
+ rh_warningstr = 'warning:';
+var
+ hs : string;
+begin
+ def_comment:=false; { never stop }
+ hs:='';
+ if not(status.use_gccoutput) then
+ begin
+ if (status.verbosity and Level)=V_Hint then
+ hs:=hintstr;
+ if (status.verbosity and Level)=V_Note then
+ hs:=notestr;
+ if (status.verbosity and Level)=V_Warning then
+ hs:=warningstr;
+ if (status.verbosity and Level)=V_Error then
+ hs:=errorstr;
+ if (status.verbosity and Level)=V_Fatal then
+ hs:=fatalstr;
+ if (status.verbosity and Level)=V_Used then
+ hs:=PadSpace('('+status.currentmodule+')',10);
+ end
+ else
+ begin
+ if (status.verbosity and Level)=V_Hint then
+ hs:=rh_warningstr;
+ if (status.verbosity and Level)=V_Note then
+ hs:=rh_warningstr;
+ if (status.verbosity and Level)=V_Warning then
+ hs:=rh_warningstr;
+ if (status.verbosity and Level)=V_Error then
+ hs:=rh_errorstr;
+ if (status.verbosity and Level)=V_Fatal then
+ hs:=rh_errorstr;
+ end;
+ { Generate line prefix }
+ if ((Level and V_LineInfo)=V_LineInfo) and
+ (status.currentsource<>'') and
+ (status.currentline>0) then
+ begin
+ {$ifndef macos}
+ { Adding the column should not confuse RHIDE,
+ even if it does not yet use it PM
+ but only if it is after error or warning !! PM }
+ if status.currentcolumn>0 then
+ begin
+ if status.use_gccoutput then
+ hs:=gccfilename(status.currentsource)+':'+tostr(status.currentline)+': '+hs+' '+
+ tostr(status.currentcolumn)+': '+s
+ else
+ begin
+ hs:=status.currentsource+'('+tostr(status.currentline)+
+ ','+tostr(status.currentcolumn)+') '+hs+' '+s;
+ if status.print_source_path then
+ hs:=status.currentsourcepath+hs;
+ end;
+ end
+ else
+ begin
+ if status.use_gccoutput then
+ hs:=gccfilename(status.currentsource)+': '+hs+' '+tostr(status.currentline)+': '+s
+ else
+ hs:=status.currentsource+'('+tostr(status.currentline)+') '+hs+' '+s;
+ end;
+ {$else}
+ {MPW style error}
+ if status.currentcolumn>0 then
+ hs:='File "'+status.currentsourcepath+status.currentsource+'"; Line '+tostr(status.currentline)+
+ ' #[' + tostr(status.currentcolumn) + '] ' +hs+' '+s
+ else
+ hs:='File "'+status.currentsourcepath+status.currentsource+'"; Line '+tostr(status.currentline)+' # '+hs+' '+s;
+ {$endif}
+ end
+ else
+ begin
+ if hs<>'' then
+ hs:=hs+' '+s
+ else
+ hs:=s;
+ end;
+
+ { Display line }
+ if ((status.verbosity and (Level and V_LevelMask))=(Level and V_LevelMask)) then
+ begin
+{$ifdef FPC}
+ if status.use_stderr then
+ begin
+ writeln(stderr,hs);
+ flush(stderr);
+ end
+ else
+{$endif}
+ begin
+ if status.use_redir then
+ writeln(status.redirfile,hs)
+ else
+ writeln(hs);
+ end;
+ end;
+ { include everything in the bugreport file }
+ if status.use_bugreport then
+ begin
+{$ifdef FPC}
+ Write(status.reportbugfile,hexstr(level,8)+':');
+ Writeln(status.reportbugfile,hs);
+{$endif}
+ end;
+end;
+
+
+function def_internalerror(i : longint) : boolean;
+begin
+ do_comment(V_Fatal+V_LineInfo,'Internal error '+tostr(i));
+{$ifdef EXTDEBUG}
+ {$ifdef FPC}
+ { Internalerror() and def_internalerror() do not
+ have a stackframe }
+ dump_stack(stdout,get_caller_frame(get_frame));
+ {$endif FPC}
+{$endif EXTDEBUG}
+ def_internalerror:=true;
+end;
+
+procedure def_initsymbolinfo;
+begin
+end;
+
+procedure def_donesymbolinfo;
+begin
+end;
+
+procedure def_extractsymbolinfo;
+begin
+end;
+
+function def_openinputfile(const filename: string): tinputfile;
+begin
+ def_openinputfile:=tdosinputfile.create(filename);
+end;
+
+
+Function def_GetNamedFileTime (Const F : String) : Longint;
+var
+{$IFDEF USE_SYSUTILS}
+ fh : THandle;
+{$ELSE USE_SYSUTILS}
+ info : SearchRec;
+{$ENDIF USE_SYSUTILS}
+begin
+ Result := -1;
+{$IFDEF USE_SYSUTILS}
+ fh := FileOpen(f, faArchive+faReadOnly+faHidden);
+ Result := FileGetDate(fh);
+ FileClose(fh);
+{$ELSE USE_SYSUTILS}
+ FindFirst (F,archive+readonly+hidden,info);
+ if DosError=0 then
+ Result := info.time;
+ FindClose(info);
+{$ENDIF USE_SYSUTILS}
+end;
+
+end.
diff --git a/compiler/compiler.pas b/compiler/compiler.pas
new file mode 100644
index 0000000000..ed6d64ac0d
--- /dev/null
+++ b/compiler/compiler.pas
@@ -0,0 +1,450 @@
+{
+ This unit is the interface of the compiler which can be used by
+ external programs to link in the compiler
+
+ Copyright (c) 1998-2005 by Florian Klaempfl
+
+ 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 compiler;
+
+{$i fpcdefs.inc}
+
+{$ifdef FPC}
+ { One of Alpha, I386 or M68K must be defined }
+ {$UNDEF CPUOK}
+
+ {$ifdef I386}
+ {$define CPUOK}
+ {$endif}
+
+ {$ifdef M68K}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif}
+ {$endif}
+
+ {$ifdef alpha}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif}
+ {$endif}
+
+ {$ifdef vis}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif}
+ {$endif}
+
+
+ {$ifdef powerpc}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif}
+ {$endif}
+
+ {$ifdef POWERPC64}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif}
+ {$endif}
+
+ {$ifdef ia64}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif}
+ {$endif}
+
+ {$ifdef SPARC}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif}
+ {$endif}
+
+ {$ifdef x86_64}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif}
+ {$endif}
+
+ {$ifdef ARM}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif ARM}
+ {$endif ARM}
+
+
+ {$ifdef MIPS}
+ {$ifndef CPUOK}
+ {$DEFINE CPUOK}
+ {$else}
+ {$fatal cannot define two CPU switches}
+ {$endif MIPS}
+ {$endif MIPS}
+
+ {$ifndef CPUOK}
+ {$fatal One of the switches I386, iA64, Alpha, PowerPC or M68K must be defined}
+ {$endif}
+
+ {$ifdef support_mmx}
+ {$ifndef i386}
+ {$fatal I386 switch must be on for MMX support}
+ {$endif i386}
+ {$endif support_mmx}
+{$endif}
+
+interface
+
+uses
+{$ifdef fpc}
+ {$ifdef GO32V2}
+ emu387,
+ {$endif GO32V2}
+ {$ifdef WATCOM} // wiktor: pewnie nie potrzeba
+ emu387,
+{ dpmiexcp, }
+ {$endif WATCOM}
+{$endif}
+{$ifdef BrowserLog}
+ browlog,
+{$endif BrowserLog}
+{$IFDEF USE_SYSUTILS}
+{$ELSE USE_SYSUTILS}
+ dos,
+{$ENDIF USE_SYSUTILS}
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+ sysutils,
+{$ENDIF MACOS_USE_FAKE_SYSUTILS}
+ verbose,comphook,systems,
+ cutils,cclasses,globals,options,fmodule,parser,symtable,
+ assemble,link,dbgbase,import,export,tokens,pass_1
+ { cpu specific commandline options }
+ ,cpuswtch
+ { cpu parameter handling }
+ ,cpupara
+ { procinfo stuff }
+ ,cpupi
+ { cpu codegenerator }
+ ,cgcpu
+{$ifndef NOPASS2}
+ ,cpunode
+{$endif}
+ { cpu targets }
+ ,cputarg
+ { system information for source system }
+ { the information about the target os }
+ { are pulled in by the t_* units }
+{$ifdef amiga}
+ ,i_amiga
+{$endif amiga}
+{$ifdef atari}
+ ,i_atari
+{$endif atari}
+{$ifdef beos}
+ ,i_beos
+{$endif beos}
+{$ifdef fbsd}
+ ,i_fbsd
+{$endif fbsd}
+{$ifdef gba}
+ ,i_gba
+{$endif gba}
+{$ifdef go32v2}
+ ,i_go32v2
+{$endif go32v2}
+{$ifdef linux}
+ ,i_linux
+{$endif linux}
+{$ifdef macos}
+ ,i_macos
+{$endif macos}
+{$ifdef nwm}
+ ,i_nwm
+{$endif nwm}
+{$ifdef nwl}
+ ,i_nwl
+{$endif nwm}
+{$ifdef os2}
+ {$ifdef emx}
+ ,i_emx
+ {$else emx}
+ ,i_os2
+ {$endif emx}
+{$endif os2}
+{$ifdef palmos}
+ ,i_palmos
+{$endif palmos}
+{$ifdef solaris}
+ ,i_sunos
+{$endif solaris}
+{$ifdef wdosx}
+ ,i_wdosx
+{$endif wdosx}
+{$ifdef win32}
+ ,i_win
+{$endif win32}
+ ;
+
+function Compile(const cmd:string):longint;
+
+
+implementation
+
+uses
+ aasmcpu;
+
+{$ifdef EXTDEBUG}
+ {$define SHOWUSEDMEM}
+{$endif}
+{$ifdef MEMDEBUG}
+ {$define SHOWUSEDMEM}
+{$endif}
+
+var
+ CompilerInitedAfterArgs,
+ CompilerInited : boolean;
+
+
+{****************************************************************************
+ Compiler
+****************************************************************************}
+
+procedure DoneCompiler;
+begin
+ if not CompilerInited then
+ exit;
+{ Free compiler if args are read }
+{$ifdef BrowserLog}
+ DoneBrowserLog;
+{$endif BrowserLog}
+{$ifdef BrowserCol}
+ do_doneSymbolInfo;
+{$endif BrowserCol}
+ if CompilerInitedAfterArgs then
+ begin
+ CompilerInitedAfterArgs:=false;
+ DoneParser;
+ DoneImport;
+ DoneExport;
+ DoneDebuginfo;
+ DoneLinker;
+ DoneAssembler;
+ DoneAsm;
+ end;
+{ Free memory for the others }
+ CompilerInited:=false;
+ DoneSymtable;
+ DoneGlobals;
+ donetokens;
+end;
+
+
+procedure InitCompiler(const cmd:string);
+begin
+ if CompilerInited then
+ DoneCompiler;
+{ inits which need to be done before the arguments are parsed }
+ InitSystems;
+ { globals depends on source_info so it must be after systems }
+ InitGlobals;
+ { verbose depends on exe_path and must be after globals }
+ InitVerbose;
+{$ifdef BrowserLog}
+ InitBrowserLog;
+{$endif BrowserLog}
+{$ifdef BrowserCol}
+ do_initSymbolInfo;
+{$endif BrowserCol}
+ inittokens;
+ InitSymtable; {Must come before read_arguments, to enable macrosymstack}
+ CompilerInited:=true;
+{ this is needed here for the IDE
+ in case of compilation failure
+ at the previous compile }
+ current_module:=nil;
+{ read the arguments }
+ read_arguments(cmd);
+{ inits which depend on arguments }
+ InitParser;
+ InitImport;
+ InitExport;
+ InitLinker;
+ InitAssembler;
+ InitDebugInfo;
+ InitAsm;
+ CompilerInitedAfterArgs:=true;
+end;
+
+
+function Compile(const cmd:string):longint;
+
+{$ifdef fpc}
+{$maxfpuregisters 0}
+{$endif fpc}
+
+ procedure writepathlist(w:longint;l:TSearchPathList);
+ var
+ hp : tstringlistitem;
+ begin
+ hp:=tstringlistitem(l.first);
+ while assigned(hp) do
+ begin
+ Message1(w,hp.str);
+ hp:=tstringlistitem(hp.next);
+ end;
+ end;
+
+ function getrealtime : real;
+ var
+{$IFDEF USE_SYSUTILS}
+ h,m,s,s1000 : word;
+{$ELSE USE_SYSUTILS}
+ h,m,s,s100 : word;
+{$ENDIF USE_SYSUTILS}
+ begin
+{$IFDEF USE_SYSUTILS}
+ DecodeTime(Time,h,m,s,s1000);
+ getrealtime:=h*3600.0+m*60.0+s+s1000/1000.0;
+{$ELSE USE_SYSUTILS}
+ gettime(h,m,s,s100);
+ getrealtime:=h*3600.0+m*60.0+s+s100/100.0;
+{$ENDIF USE_SYSUTILS}
+ end;
+
+var
+ starttime : real;
+{$ifdef SHOWUSEDMEM}
+ hstatus : TFPCHeapStatus;
+{$endif SHOWUSEDMEM}
+begin
+ try
+ try
+ { Initialize the compiler }
+ InitCompiler(cmd);
+
+ { show some info }
+ Message1(general_t_compilername,FixFileName(system.paramstr(0)));
+ Message1(general_d_sourceos,source_info.name);
+ Message1(general_i_targetos,target_info.name);
+ Message1(general_t_exepath,exepath);
+ WritePathList(general_t_unitpath,unitsearchpath);
+ WritePathList(general_t_includepath,includesearchpath);
+ WritePathList(general_t_librarypath,librarysearchpath);
+ WritePathList(general_t_objectpath,objectsearchpath);
+
+ starttime:=getrealtime;
+
+ { Compile the program }
+ {$ifdef PREPROCWRITE}
+ if parapreprocess then
+ parser.preprocess(inputdir+inputfile+inputextension)
+ else
+ {$endif PREPROCWRITE}
+ parser.compile(inputdir+inputfile+inputextension);
+
+ { Show statistics }
+ if status.errorcount=0 then
+ begin
+ starttime:=getrealtime-starttime;
+ if starttime<0 then
+ starttime:=starttime+3600.0*24.0;
+ Message2(general_i_abslines_compiled,tostr(status.compiledlines),tostr(trunc(starttime))+
+ '.'+tostr(trunc(frac(starttime)*10)));
+ end;
+ finally
+ { no message possible after this !! }
+ DoneCompiler;
+ end;
+ except
+
+ on EControlCAbort do
+ begin
+ try
+ { in case of 50 errors, this could cause another exception,
+ suppress this exception
+ }
+ Message(general_f_compilation_aborted);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ end;
+ on ECompilerAbort do
+ begin
+ try
+ { in case of 50 errors, this could cause another exception,
+ suppress this exception
+ }
+ Message(general_f_compilation_aborted);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ end;
+ on ECompilerAbortSilent do
+ begin
+ DoneVerbose;
+ end;
+ on Exception do
+ begin
+ { General catchall, normally not used }
+ try
+ { in case of 50 errors, this could cause another exception,
+ suppress this exception
+ }
+ Message(general_f_compilation_aborted);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ Raise;
+ end;
+ end;
+{$ifdef SHOWUSEDMEM}
+ hstatus:=GetFPCHeapStatus;
+ Writeln('Max Memory used/heapsize: ',DStr(hstatus.MaxHeapUsed shr 10),'/',DStr(hstatus.MaxHeapSize shr 10),' Kb');
+{$endif SHOWUSEDMEM}
+
+ { Set the return value if an error has occurred }
+ if status.errorcount=0 then
+ result:=0
+ else
+ result:=1;
+end;
+
+end.
diff --git a/compiler/compinnr.inc b/compiler/compinnr.inc
new file mode 100644
index 0000000000..90f8f87854
--- /dev/null
+++ b/compiler/compinnr.inc
@@ -0,0 +1,107 @@
+{
+ This file is part of the Free Pascal run time library and compiler.
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Internal Function/Constant Evaluator numbers
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+const
+{ Internal functions }
+ in_lo_word = 1;
+ in_hi_word = 2;
+ in_lo_long = 3;
+ in_hi_long = 4;
+ in_ord_x = 5;
+ in_length_x = 6;
+ in_chr_byte = 7;
+ in_write_x = 14;
+ in_writeln_x = 15;
+ in_read_x = 16;
+ in_readln_x = 17;
+ in_concat_x = 18;
+ in_assigned_x = 19;
+ in_str_x_string = 20;
+ in_ofs_x = 21;
+ in_sizeof_x = 22;
+ in_typeof_x = 23;
+ in_val_x = 24;
+ in_reset_x = 25;
+ in_rewrite_x = 26;
+ in_low_x = 27;
+ in_high_x = 28;
+ in_seg_x = 29;
+ in_pred_x = 30;
+ in_succ_x = 31;
+ in_reset_typedfile = 32;
+ in_rewrite_typedfile = 33;
+ in_settextbuf_file_x = 34;
+ in_inc_x = 35;
+ in_dec_x = 36;
+ in_include_x_y = 37;
+ in_exclude_x_y = 38;
+ in_break = 39;
+ in_continue = 40;
+ in_assert_x_y = 41;
+ in_addr_x = 42;
+ in_typeinfo_x = 43;
+ in_setlength_x = 44;
+ in_finalize_x = 45;
+ in_new_x = 46;
+ in_dispose_x = 47;
+ in_exit = 48;
+ in_copy_x = 49;
+ in_initialize_x = 50;
+ in_leave = 51; {macpas}
+ in_cycle = 52; {macpas}
+ in_slice_x = 53;
+
+{ Internal constant functions }
+ in_const_sqr = 100;
+ in_const_abs = 101;
+ in_const_odd = 102;
+ in_const_ptr = 103;
+ in_const_swap_word = 104;
+ in_const_swap_long = 105;
+ in_lo_qword = 106;
+ in_hi_qword = 107;
+ in_const_swap_qword = 108;
+ in_prefetch_var = 109;
+
+{ FPU functions }
+ in_trunc_real = 120;
+ in_round_real = 121;
+ in_frac_real = 122;
+ in_int_real = 123;
+ in_exp_real = 124;
+ in_cos_real = 125;
+ in_pi_real = 126;
+ in_abs_real = 127;
+ in_sqr_real = 128;
+ in_sqrt_real = 129;
+ in_arctan_real = 130;
+ in_ln_real = 131;
+ in_sin_real = 132;
+
+{ MMX functions }
+ { these contants are used by the mmx unit }
+
+ { MMX }
+ in_mmx_pcmpeqb = 200;
+ in_mmx_pcmpeqw = 201;
+ in_mmx_pcmpeqd = 202;
+ in_mmx_pcmpgtb = 203;
+ in_mmx_pcmpgtw = 204;
+ in_mmx_pcmpgtd = 205;
+
+ { 3DNow }
+
+ { SSE }
+
diff --git a/compiler/comprsrc.pas b/compiler/comprsrc.pas
new file mode 100644
index 0000000000..35910d176e
--- /dev/null
+++ b/compiler/comprsrc.pas
@@ -0,0 +1,185 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Handles the resource files handling
+
+ 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 comprsrc;
+
+{$i fpcdefs.inc}
+
+interface
+
+type
+ presourcefile=^tresourcefile;
+ tresourcefile=object
+ private
+ fname : string;
+ public
+ constructor Init(const fn:string);
+ destructor Done;
+ procedure Compile;virtual;
+ end;
+
+procedure CompileResourceFiles;
+
+
+implementation
+
+uses
+{$IFDEF USE_SYSUTILS}
+ SysUtils,
+{$ELSE USE_SYSUTILS}
+ dos,
+{$ENDIF USE_SYSUTILS}
+ Systems,cutils,Globtype,Globals,Verbose,Fmodule,
+ Script;
+
+{****************************************************************************
+ TRESOURCEFILE
+****************************************************************************}
+
+constructor tresourcefile.init(const fn:string);
+begin
+ fname:=fn;
+end;
+
+
+destructor tresourcefile.done;
+begin
+end;
+
+
+procedure tresourcefile.compile;
+var
+ respath,
+ srcfilepath : dirstr;
+ n : namestr;
+{$IFDEF USE_SYSUTILS}
+{$ELSE USE_SYSUTILS}
+ e : extstr;
+{$ENDIF USE_SYSUTILS}
+ s,
+ resobj,
+ resbin : string;
+ resfound,
+ objused : boolean;
+begin
+ resbin:='';
+ resfound:=false;
+ if utilsdirectory<>'' then
+ resfound:=FindFile(utilsprefix+target_res.resbin+source_info.exeext,utilsdirectory,resbin);
+ if not resfound then
+ resfound:=FindExe(utilsprefix+target_res.resbin,resbin);
+ { get also the path to be searched for the windres.h }
+{$IFDEF USE_SYSUTILS}
+ respath := SplitPath(resbin);
+{$ELSE USE_SYSUTILS}
+ fsplit(resbin,respath,n,e);
+{$ENDIF USE_SYSUTILS}
+ if (not resfound) and not(cs_link_extern in aktglobalswitches) then
+ begin
+ Message(exec_e_res_not_found);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ end;
+{$IFDEF USE_SYSUTILS}
+ srcfilepath := SplitPath(current_module.mainsource^);
+{$ELSE USE_SYSUTILS}
+ fsplit(current_module.mainsource^,srcfilepath,n,e);
+{$ENDIF USE_SYSUTILS}
+ if not path_absolute(fname) then
+ fname:=srcfilepath+fname;
+ resobj:=ForceExtension(fname,target_info.resobjext);
+ s:=target_res.rescmd;
+ ObjUsed:=(pos('$OBJ',s)>0);
+ Replace(s,'$OBJ',maybequoted(resobj));
+ Replace(s,'$RES',maybequoted(fname));
+ { windres doesn't like empty include paths }
+ if respath='' then
+ respath:='.';
+ Replace(s,'$INC',maybequoted(respath));
+ if (target_info.system = system_i386_win32) and
+ (srcfilepath<>'') then
+ s:=s+' --include '+maybequoted(srcfilepath);
+{ Execute the command }
+ if not (cs_link_extern in aktglobalswitches) then
+ begin
+ Message1(exec_i_compilingresource,fname);
+ Message2(exec_d_resbin_params,resbin,s);
+{$IFDEF USE_SYSUTILS}
+ try
+ if ExecuteProcess(resbin,s) <> 0 then
+ begin
+ Message(exec_e_error_while_linking);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ end;
+ except
+ on E:EOSError do
+ begin
+ Message(exec_e_cant_call_linker);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ end
+ end;
+{$ELSE USE_SYSUTILS}
+ swapvectors;
+ exec(resbin,s);
+ swapvectors;
+ if (doserror<>0) then
+ begin
+ Message(exec_e_cant_call_linker);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ end
+ else
+ if (dosexitcode<>0) then
+ begin
+ Message(exec_e_error_while_linking);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ end;
+{$ENDIF USE_SYSUTILS}
+ end;
+ { Update asmres when externmode is set }
+ if cs_link_extern in aktglobalswitches then
+ AsmRes.AddLinkCommand(resbin,s,'');
+ if ObjUsed then
+ current_module.linkotherofiles.add(resobj,link_allways);
+end;
+
+
+procedure CompileResourceFiles;
+var
+ hr : presourcefile;
+begin
+ { OS/2 (EMX) must be processed elsewhere (in the linking/binding stage).
+ same with MacOS}
+ if not (target_info.system in [system_i386_os2,
+ system_i386_emx,system_powerpc_macos]) then
+ While not current_module.ResourceFiles.Empty do
+ begin
+ if target_info.res<>res_none then
+ begin
+ hr:=new(presourcefile,init(current_module.ResourceFiles.getfirst));
+ hr^.compile;
+ dispose(hr,done);
+ end
+ else
+ Message(scan_e_resourcefiles_not_supported);
+ end;
+end;
+
+
+end.
diff --git a/compiler/cp437.pas b/compiler/cp437.pas
new file mode 100644
index 0000000000..a7fcdd48b5
--- /dev/null
+++ b/compiler/cp437.pas
@@ -0,0 +1,281 @@
+{ This is an automatically created file, so don't edit it }
+unit cp437;
+
+ interface
+
+ implementation
+
+ uses
+ charset;
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 199; flag : umf_noinfo; reserved : 0),
+ (unicode : 252; flag : umf_noinfo; reserved : 0),
+ (unicode : 233; flag : umf_noinfo; reserved : 0),
+ (unicode : 226; flag : umf_noinfo; reserved : 0),
+ (unicode : 228; flag : umf_noinfo; reserved : 0),
+ (unicode : 224; flag : umf_noinfo; reserved : 0),
+ (unicode : 229; flag : umf_noinfo; reserved : 0),
+ (unicode : 231; flag : umf_noinfo; reserved : 0),
+ (unicode : 234; flag : umf_noinfo; reserved : 0),
+ (unicode : 235; flag : umf_noinfo; reserved : 0),
+ (unicode : 232; flag : umf_noinfo; reserved : 0),
+ (unicode : 239; flag : umf_noinfo; reserved : 0),
+ (unicode : 238; flag : umf_noinfo; reserved : 0),
+ (unicode : 236; flag : umf_noinfo; reserved : 0),
+ (unicode : 196; flag : umf_noinfo; reserved : 0),
+ (unicode : 197; flag : umf_noinfo; reserved : 0),
+ (unicode : 201; flag : umf_noinfo; reserved : 0),
+ (unicode : 230; flag : umf_noinfo; reserved : 0),
+ (unicode : 198; flag : umf_noinfo; reserved : 0),
+ (unicode : 244; flag : umf_noinfo; reserved : 0),
+ (unicode : 246; flag : umf_noinfo; reserved : 0),
+ (unicode : 242; flag : umf_noinfo; reserved : 0),
+ (unicode : 251; flag : umf_noinfo; reserved : 0),
+ (unicode : 249; flag : umf_noinfo; reserved : 0),
+ (unicode : 255; flag : umf_noinfo; reserved : 0),
+ (unicode : 214; flag : umf_noinfo; reserved : 0),
+ (unicode : 220; flag : umf_noinfo; reserved : 0),
+ (unicode : 162; flag : umf_noinfo; reserved : 0),
+ (unicode : 163; flag : umf_noinfo; reserved : 0),
+ (unicode : 165; flag : umf_noinfo; reserved : 0),
+ (unicode : 8359; flag : umf_noinfo; reserved : 0),
+ (unicode : 402; flag : umf_noinfo; reserved : 0),
+ (unicode : 225; flag : umf_noinfo; reserved : 0),
+ (unicode : 237; flag : umf_noinfo; reserved : 0),
+ (unicode : 243; flag : umf_noinfo; reserved : 0),
+ (unicode : 250; flag : umf_noinfo; reserved : 0),
+ (unicode : 241; flag : umf_noinfo; reserved : 0),
+ (unicode : 209; flag : umf_noinfo; reserved : 0),
+ (unicode : 170; flag : umf_noinfo; reserved : 0),
+ (unicode : 186; flag : umf_noinfo; reserved : 0),
+ (unicode : 191; flag : umf_noinfo; reserved : 0),
+ (unicode : 8976; flag : umf_noinfo; reserved : 0),
+ (unicode : 172; flag : umf_noinfo; reserved : 0),
+ (unicode : 189; flag : umf_noinfo; reserved : 0),
+ (unicode : 188; flag : umf_noinfo; reserved : 0),
+ (unicode : 161; flag : umf_noinfo; reserved : 0),
+ (unicode : 171; flag : umf_noinfo; reserved : 0),
+ (unicode : 187; flag : umf_noinfo; reserved : 0),
+ (unicode : 9617; flag : umf_noinfo; reserved : 0),
+ (unicode : 9618; flag : umf_noinfo; reserved : 0),
+ (unicode : 9619; flag : umf_noinfo; reserved : 0),
+ (unicode : 9474; flag : umf_noinfo; reserved : 0),
+ (unicode : 9508; flag : umf_noinfo; reserved : 0),
+ (unicode : 9569; flag : umf_noinfo; reserved : 0),
+ (unicode : 9570; flag : umf_noinfo; reserved : 0),
+ (unicode : 9558; flag : umf_noinfo; reserved : 0),
+ (unicode : 9557; flag : umf_noinfo; reserved : 0),
+ (unicode : 9571; flag : umf_noinfo; reserved : 0),
+ (unicode : 9553; flag : umf_noinfo; reserved : 0),
+ (unicode : 9559; flag : umf_noinfo; reserved : 0),
+ (unicode : 9565; flag : umf_noinfo; reserved : 0),
+ (unicode : 9564; flag : umf_noinfo; reserved : 0),
+ (unicode : 9563; flag : umf_noinfo; reserved : 0),
+ (unicode : 9488; flag : umf_noinfo; reserved : 0),
+ (unicode : 9492; flag : umf_noinfo; reserved : 0),
+ (unicode : 9524; flag : umf_noinfo; reserved : 0),
+ (unicode : 9516; flag : umf_noinfo; reserved : 0),
+ (unicode : 9500; flag : umf_noinfo; reserved : 0),
+ (unicode : 9472; flag : umf_noinfo; reserved : 0),
+ (unicode : 9532; flag : umf_noinfo; reserved : 0),
+ (unicode : 9566; flag : umf_noinfo; reserved : 0),
+ (unicode : 9567; flag : umf_noinfo; reserved : 0),
+ (unicode : 9562; flag : umf_noinfo; reserved : 0),
+ (unicode : 9556; flag : umf_noinfo; reserved : 0),
+ (unicode : 9577; flag : umf_noinfo; reserved : 0),
+ (unicode : 9574; flag : umf_noinfo; reserved : 0),
+ (unicode : 9568; flag : umf_noinfo; reserved : 0),
+ (unicode : 9552; flag : umf_noinfo; reserved : 0),
+ (unicode : 9580; flag : umf_noinfo; reserved : 0),
+ (unicode : 9575; flag : umf_noinfo; reserved : 0),
+ (unicode : 9576; flag : umf_noinfo; reserved : 0),
+ (unicode : 9572; flag : umf_noinfo; reserved : 0),
+ (unicode : 9573; flag : umf_noinfo; reserved : 0),
+ (unicode : 9561; flag : umf_noinfo; reserved : 0),
+ (unicode : 9560; flag : umf_noinfo; reserved : 0),
+ (unicode : 9554; flag : umf_noinfo; reserved : 0),
+ (unicode : 9555; flag : umf_noinfo; reserved : 0),
+ (unicode : 9579; flag : umf_noinfo; reserved : 0),
+ (unicode : 9578; flag : umf_noinfo; reserved : 0),
+ (unicode : 9496; flag : umf_noinfo; reserved : 0),
+ (unicode : 9484; flag : umf_noinfo; reserved : 0),
+ (unicode : 9608; flag : umf_noinfo; reserved : 0),
+ (unicode : 9604; flag : umf_noinfo; reserved : 0),
+ (unicode : 9612; flag : umf_noinfo; reserved : 0),
+ (unicode : 9616; flag : umf_noinfo; reserved : 0),
+ (unicode : 9600; flag : umf_noinfo; reserved : 0),
+ (unicode : 945; flag : umf_noinfo; reserved : 0),
+ (unicode : 223; flag : umf_noinfo; reserved : 0),
+ (unicode : 915; flag : umf_noinfo; reserved : 0),
+ (unicode : 960; flag : umf_noinfo; reserved : 0),
+ (unicode : 931; flag : umf_noinfo; reserved : 0),
+ (unicode : 963; flag : umf_noinfo; reserved : 0),
+ (unicode : 181; flag : umf_noinfo; reserved : 0),
+ (unicode : 964; flag : umf_noinfo; reserved : 0),
+ (unicode : 934; flag : umf_noinfo; reserved : 0),
+ (unicode : 920; flag : umf_noinfo; reserved : 0),
+ (unicode : 937; flag : umf_noinfo; reserved : 0),
+ (unicode : 948; flag : umf_noinfo; reserved : 0),
+ (unicode : 8734; flag : umf_noinfo; reserved : 0),
+ (unicode : 966; flag : umf_noinfo; reserved : 0),
+ (unicode : 949; flag : umf_noinfo; reserved : 0),
+ (unicode : 8745; flag : umf_noinfo; reserved : 0),
+ (unicode : 8801; flag : umf_noinfo; reserved : 0),
+ (unicode : 177; flag : umf_noinfo; reserved : 0),
+ (unicode : 8805; flag : umf_noinfo; reserved : 0),
+ (unicode : 8804; flag : umf_noinfo; reserved : 0),
+ (unicode : 8992; flag : umf_noinfo; reserved : 0),
+ (unicode : 8993; flag : umf_noinfo; reserved : 0),
+ (unicode : 247; flag : umf_noinfo; reserved : 0),
+ (unicode : 8776; flag : umf_noinfo; reserved : 0),
+ (unicode : 176; flag : umf_noinfo; reserved : 0),
+ (unicode : 8729; flag : umf_noinfo; reserved : 0),
+ (unicode : 183; flag : umf_noinfo; reserved : 0),
+ (unicode : 8730; flag : umf_noinfo; reserved : 0),
+ (unicode : 8319; flag : umf_noinfo; reserved : 0),
+ (unicode : 178; flag : umf_noinfo; reserved : 0),
+ (unicode : 9632; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : 'cp437';
+ map : @map;
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/compiler/cp850.pas b/compiler/cp850.pas
new file mode 100644
index 0000000000..bf9a920dfa
--- /dev/null
+++ b/compiler/cp850.pas
@@ -0,0 +1,281 @@
+{ This is an automatically created file, so don't edit it }
+unit cp850;
+
+ interface
+
+ implementation
+
+ uses
+ charset;
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 199; flag : umf_noinfo; reserved : 0),
+ (unicode : 252; flag : umf_noinfo; reserved : 0),
+ (unicode : 233; flag : umf_noinfo; reserved : 0),
+ (unicode : 226; flag : umf_noinfo; reserved : 0),
+ (unicode : 228; flag : umf_noinfo; reserved : 0),
+ (unicode : 224; flag : umf_noinfo; reserved : 0),
+ (unicode : 229; flag : umf_noinfo; reserved : 0),
+ (unicode : 231; flag : umf_noinfo; reserved : 0),
+ (unicode : 234; flag : umf_noinfo; reserved : 0),
+ (unicode : 235; flag : umf_noinfo; reserved : 0),
+ (unicode : 232; flag : umf_noinfo; reserved : 0),
+ (unicode : 239; flag : umf_noinfo; reserved : 0),
+ (unicode : 238; flag : umf_noinfo; reserved : 0),
+ (unicode : 236; flag : umf_noinfo; reserved : 0),
+ (unicode : 196; flag : umf_noinfo; reserved : 0),
+ (unicode : 197; flag : umf_noinfo; reserved : 0),
+ (unicode : 201; flag : umf_noinfo; reserved : 0),
+ (unicode : 230; flag : umf_noinfo; reserved : 0),
+ (unicode : 198; flag : umf_noinfo; reserved : 0),
+ (unicode : 244; flag : umf_noinfo; reserved : 0),
+ (unicode : 246; flag : umf_noinfo; reserved : 0),
+ (unicode : 242; flag : umf_noinfo; reserved : 0),
+ (unicode : 251; flag : umf_noinfo; reserved : 0),
+ (unicode : 249; flag : umf_noinfo; reserved : 0),
+ (unicode : 255; flag : umf_noinfo; reserved : 0),
+ (unicode : 214; flag : umf_noinfo; reserved : 0),
+ (unicode : 220; flag : umf_noinfo; reserved : 0),
+ (unicode : 248; flag : umf_noinfo; reserved : 0),
+ (unicode : 163; flag : umf_noinfo; reserved : 0),
+ (unicode : 216; flag : umf_noinfo; reserved : 0),
+ (unicode : 215; flag : umf_noinfo; reserved : 0),
+ (unicode : 402; flag : umf_noinfo; reserved : 0),
+ (unicode : 225; flag : umf_noinfo; reserved : 0),
+ (unicode : 237; flag : umf_noinfo; reserved : 0),
+ (unicode : 243; flag : umf_noinfo; reserved : 0),
+ (unicode : 250; flag : umf_noinfo; reserved : 0),
+ (unicode : 241; flag : umf_noinfo; reserved : 0),
+ (unicode : 209; flag : umf_noinfo; reserved : 0),
+ (unicode : 170; flag : umf_noinfo; reserved : 0),
+ (unicode : 186; flag : umf_noinfo; reserved : 0),
+ (unicode : 191; flag : umf_noinfo; reserved : 0),
+ (unicode : 174; flag : umf_noinfo; reserved : 0),
+ (unicode : 172; flag : umf_noinfo; reserved : 0),
+ (unicode : 189; flag : umf_noinfo; reserved : 0),
+ (unicode : 188; flag : umf_noinfo; reserved : 0),
+ (unicode : 161; flag : umf_noinfo; reserved : 0),
+ (unicode : 171; flag : umf_noinfo; reserved : 0),
+ (unicode : 187; flag : umf_noinfo; reserved : 0),
+ (unicode : 9617; flag : umf_noinfo; reserved : 0),
+ (unicode : 9618; flag : umf_noinfo; reserved : 0),
+ (unicode : 9619; flag : umf_noinfo; reserved : 0),
+ (unicode : 9474; flag : umf_noinfo; reserved : 0),
+ (unicode : 9508; flag : umf_noinfo; reserved : 0),
+ (unicode : 193; flag : umf_noinfo; reserved : 0),
+ (unicode : 194; flag : umf_noinfo; reserved : 0),
+ (unicode : 192; flag : umf_noinfo; reserved : 0),
+ (unicode : 169; flag : umf_noinfo; reserved : 0),
+ (unicode : 9571; flag : umf_noinfo; reserved : 0),
+ (unicode : 9553; flag : umf_noinfo; reserved : 0),
+ (unicode : 9559; flag : umf_noinfo; reserved : 0),
+ (unicode : 9565; flag : umf_noinfo; reserved : 0),
+ (unicode : 162; flag : umf_noinfo; reserved : 0),
+ (unicode : 165; flag : umf_noinfo; reserved : 0),
+ (unicode : 9488; flag : umf_noinfo; reserved : 0),
+ (unicode : 9492; flag : umf_noinfo; reserved : 0),
+ (unicode : 9524; flag : umf_noinfo; reserved : 0),
+ (unicode : 9516; flag : umf_noinfo; reserved : 0),
+ (unicode : 9500; flag : umf_noinfo; reserved : 0),
+ (unicode : 9472; flag : umf_noinfo; reserved : 0),
+ (unicode : 9532; flag : umf_noinfo; reserved : 0),
+ (unicode : 227; flag : umf_noinfo; reserved : 0),
+ (unicode : 195; flag : umf_noinfo; reserved : 0),
+ (unicode : 9562; flag : umf_noinfo; reserved : 0),
+ (unicode : 9556; flag : umf_noinfo; reserved : 0),
+ (unicode : 9577; flag : umf_noinfo; reserved : 0),
+ (unicode : 9574; flag : umf_noinfo; reserved : 0),
+ (unicode : 9568; flag : umf_noinfo; reserved : 0),
+ (unicode : 9552; flag : umf_noinfo; reserved : 0),
+ (unicode : 9580; flag : umf_noinfo; reserved : 0),
+ (unicode : 164; flag : umf_noinfo; reserved : 0),
+ (unicode : 240; flag : umf_noinfo; reserved : 0),
+ (unicode : 208; flag : umf_noinfo; reserved : 0),
+ (unicode : 202; flag : umf_noinfo; reserved : 0),
+ (unicode : 203; flag : umf_noinfo; reserved : 0),
+ (unicode : 200; flag : umf_noinfo; reserved : 0),
+ (unicode : 305; flag : umf_noinfo; reserved : 0),
+ (unicode : 205; flag : umf_noinfo; reserved : 0),
+ (unicode : 206; flag : umf_noinfo; reserved : 0),
+ (unicode : 207; flag : umf_noinfo; reserved : 0),
+ (unicode : 9496; flag : umf_noinfo; reserved : 0),
+ (unicode : 9484; flag : umf_noinfo; reserved : 0),
+ (unicode : 9608; flag : umf_noinfo; reserved : 0),
+ (unicode : 9604; flag : umf_noinfo; reserved : 0),
+ (unicode : 166; flag : umf_noinfo; reserved : 0),
+ (unicode : 204; flag : umf_noinfo; reserved : 0),
+ (unicode : 9600; flag : umf_noinfo; reserved : 0),
+ (unicode : 211; flag : umf_noinfo; reserved : 0),
+ (unicode : 223; flag : umf_noinfo; reserved : 0),
+ (unicode : 212; flag : umf_noinfo; reserved : 0),
+ (unicode : 210; flag : umf_noinfo; reserved : 0),
+ (unicode : 245; flag : umf_noinfo; reserved : 0),
+ (unicode : 213; flag : umf_noinfo; reserved : 0),
+ (unicode : 181; flag : umf_noinfo; reserved : 0),
+ (unicode : 254; flag : umf_noinfo; reserved : 0),
+ (unicode : 222; flag : umf_noinfo; reserved : 0),
+ (unicode : 218; flag : umf_noinfo; reserved : 0),
+ (unicode : 219; flag : umf_noinfo; reserved : 0),
+ (unicode : 217; flag : umf_noinfo; reserved : 0),
+ (unicode : 253; flag : umf_noinfo; reserved : 0),
+ (unicode : 221; flag : umf_noinfo; reserved : 0),
+ (unicode : 175; flag : umf_noinfo; reserved : 0),
+ (unicode : 180; flag : umf_noinfo; reserved : 0),
+ (unicode : 173; flag : umf_noinfo; reserved : 0),
+ (unicode : 177; flag : umf_noinfo; reserved : 0),
+ (unicode : 8215; flag : umf_noinfo; reserved : 0),
+ (unicode : 190; flag : umf_noinfo; reserved : 0),
+ (unicode : 182; flag : umf_noinfo; reserved : 0),
+ (unicode : 167; flag : umf_noinfo; reserved : 0),
+ (unicode : 247; flag : umf_noinfo; reserved : 0),
+ (unicode : 184; flag : umf_noinfo; reserved : 0),
+ (unicode : 176; flag : umf_noinfo; reserved : 0),
+ (unicode : 168; flag : umf_noinfo; reserved : 0),
+ (unicode : 183; flag : umf_noinfo; reserved : 0),
+ (unicode : 185; flag : umf_noinfo; reserved : 0),
+ (unicode : 179; flag : umf_noinfo; reserved : 0),
+ (unicode : 178; flag : umf_noinfo; reserved : 0),
+ (unicode : 9632; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : 'cp850';
+ map : @map;
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/compiler/cp8859_1.pas b/compiler/cp8859_1.pas
new file mode 100644
index 0000000000..a157109754
--- /dev/null
+++ b/compiler/cp8859_1.pas
@@ -0,0 +1,281 @@
+{ This is an automatically created file, so don't edit it }
+unit cp8859_1;
+
+ interface
+
+ implementation
+
+ uses
+ charset;
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 128; flag : umf_noinfo; reserved : 0),
+ (unicode : 129; flag : umf_noinfo; reserved : 0),
+ (unicode : 130; flag : umf_noinfo; reserved : 0),
+ (unicode : 131; flag : umf_noinfo; reserved : 0),
+ (unicode : 132; flag : umf_noinfo; reserved : 0),
+ (unicode : 133; flag : umf_noinfo; reserved : 0),
+ (unicode : 134; flag : umf_noinfo; reserved : 0),
+ (unicode : 135; flag : umf_noinfo; reserved : 0),
+ (unicode : 136; flag : umf_noinfo; reserved : 0),
+ (unicode : 137; flag : umf_noinfo; reserved : 0),
+ (unicode : 138; flag : umf_noinfo; reserved : 0),
+ (unicode : 139; flag : umf_noinfo; reserved : 0),
+ (unicode : 140; flag : umf_noinfo; reserved : 0),
+ (unicode : 141; flag : umf_noinfo; reserved : 0),
+ (unicode : 142; flag : umf_noinfo; reserved : 0),
+ (unicode : 143; flag : umf_noinfo; reserved : 0),
+ (unicode : 144; flag : umf_noinfo; reserved : 0),
+ (unicode : 145; flag : umf_noinfo; reserved : 0),
+ (unicode : 146; flag : umf_noinfo; reserved : 0),
+ (unicode : 147; flag : umf_noinfo; reserved : 0),
+ (unicode : 148; flag : umf_noinfo; reserved : 0),
+ (unicode : 149; flag : umf_noinfo; reserved : 0),
+ (unicode : 150; flag : umf_noinfo; reserved : 0),
+ (unicode : 151; flag : umf_noinfo; reserved : 0),
+ (unicode : 152; flag : umf_noinfo; reserved : 0),
+ (unicode : 153; flag : umf_noinfo; reserved : 0),
+ (unicode : 154; flag : umf_noinfo; reserved : 0),
+ (unicode : 155; flag : umf_noinfo; reserved : 0),
+ (unicode : 156; flag : umf_noinfo; reserved : 0),
+ (unicode : 157; flag : umf_noinfo; reserved : 0),
+ (unicode : 158; flag : umf_noinfo; reserved : 0),
+ (unicode : 159; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0),
+ (unicode : 161; flag : umf_noinfo; reserved : 0),
+ (unicode : 162; flag : umf_noinfo; reserved : 0),
+ (unicode : 163; flag : umf_noinfo; reserved : 0),
+ (unicode : 164; flag : umf_noinfo; reserved : 0),
+ (unicode : 165; flag : umf_noinfo; reserved : 0),
+ (unicode : 166; flag : umf_noinfo; reserved : 0),
+ (unicode : 167; flag : umf_noinfo; reserved : 0),
+ (unicode : 168; flag : umf_noinfo; reserved : 0),
+ (unicode : 169; flag : umf_noinfo; reserved : 0),
+ (unicode : 170; flag : umf_noinfo; reserved : 0),
+ (unicode : 171; flag : umf_noinfo; reserved : 0),
+ (unicode : 172; flag : umf_noinfo; reserved : 0),
+ (unicode : 173; flag : umf_noinfo; reserved : 0),
+ (unicode : 174; flag : umf_noinfo; reserved : 0),
+ (unicode : 175; flag : umf_noinfo; reserved : 0),
+ (unicode : 176; flag : umf_noinfo; reserved : 0),
+ (unicode : 177; flag : umf_noinfo; reserved : 0),
+ (unicode : 178; flag : umf_noinfo; reserved : 0),
+ (unicode : 179; flag : umf_noinfo; reserved : 0),
+ (unicode : 180; flag : umf_noinfo; reserved : 0),
+ (unicode : 181; flag : umf_noinfo; reserved : 0),
+ (unicode : 182; flag : umf_noinfo; reserved : 0),
+ (unicode : 183; flag : umf_noinfo; reserved : 0),
+ (unicode : 184; flag : umf_noinfo; reserved : 0),
+ (unicode : 185; flag : umf_noinfo; reserved : 0),
+ (unicode : 186; flag : umf_noinfo; reserved : 0),
+ (unicode : 187; flag : umf_noinfo; reserved : 0),
+ (unicode : 188; flag : umf_noinfo; reserved : 0),
+ (unicode : 189; flag : umf_noinfo; reserved : 0),
+ (unicode : 190; flag : umf_noinfo; reserved : 0),
+ (unicode : 191; flag : umf_noinfo; reserved : 0),
+ (unicode : 192; flag : umf_noinfo; reserved : 0),
+ (unicode : 193; flag : umf_noinfo; reserved : 0),
+ (unicode : 194; flag : umf_noinfo; reserved : 0),
+ (unicode : 195; flag : umf_noinfo; reserved : 0),
+ (unicode : 196; flag : umf_noinfo; reserved : 0),
+ (unicode : 197; flag : umf_noinfo; reserved : 0),
+ (unicode : 198; flag : umf_noinfo; reserved : 0),
+ (unicode : 199; flag : umf_noinfo; reserved : 0),
+ (unicode : 200; flag : umf_noinfo; reserved : 0),
+ (unicode : 201; flag : umf_noinfo; reserved : 0),
+ (unicode : 202; flag : umf_noinfo; reserved : 0),
+ (unicode : 203; flag : umf_noinfo; reserved : 0),
+ (unicode : 204; flag : umf_noinfo; reserved : 0),
+ (unicode : 205; flag : umf_noinfo; reserved : 0),
+ (unicode : 206; flag : umf_noinfo; reserved : 0),
+ (unicode : 207; flag : umf_noinfo; reserved : 0),
+ (unicode : 208; flag : umf_noinfo; reserved : 0),
+ (unicode : 209; flag : umf_noinfo; reserved : 0),
+ (unicode : 210; flag : umf_noinfo; reserved : 0),
+ (unicode : 211; flag : umf_noinfo; reserved : 0),
+ (unicode : 212; flag : umf_noinfo; reserved : 0),
+ (unicode : 213; flag : umf_noinfo; reserved : 0),
+ (unicode : 214; flag : umf_noinfo; reserved : 0),
+ (unicode : 215; flag : umf_noinfo; reserved : 0),
+ (unicode : 216; flag : umf_noinfo; reserved : 0),
+ (unicode : 217; flag : umf_noinfo; reserved : 0),
+ (unicode : 218; flag : umf_noinfo; reserved : 0),
+ (unicode : 219; flag : umf_noinfo; reserved : 0),
+ (unicode : 220; flag : umf_noinfo; reserved : 0),
+ (unicode : 221; flag : umf_noinfo; reserved : 0),
+ (unicode : 222; flag : umf_noinfo; reserved : 0),
+ (unicode : 223; flag : umf_noinfo; reserved : 0),
+ (unicode : 224; flag : umf_noinfo; reserved : 0),
+ (unicode : 225; flag : umf_noinfo; reserved : 0),
+ (unicode : 226; flag : umf_noinfo; reserved : 0),
+ (unicode : 227; flag : umf_noinfo; reserved : 0),
+ (unicode : 228; flag : umf_noinfo; reserved : 0),
+ (unicode : 229; flag : umf_noinfo; reserved : 0),
+ (unicode : 230; flag : umf_noinfo; reserved : 0),
+ (unicode : 231; flag : umf_noinfo; reserved : 0),
+ (unicode : 232; flag : umf_noinfo; reserved : 0),
+ (unicode : 233; flag : umf_noinfo; reserved : 0),
+ (unicode : 234; flag : umf_noinfo; reserved : 0),
+ (unicode : 235; flag : umf_noinfo; reserved : 0),
+ (unicode : 236; flag : umf_noinfo; reserved : 0),
+ (unicode : 237; flag : umf_noinfo; reserved : 0),
+ (unicode : 238; flag : umf_noinfo; reserved : 0),
+ (unicode : 239; flag : umf_noinfo; reserved : 0),
+ (unicode : 240; flag : umf_noinfo; reserved : 0),
+ (unicode : 241; flag : umf_noinfo; reserved : 0),
+ (unicode : 242; flag : umf_noinfo; reserved : 0),
+ (unicode : 243; flag : umf_noinfo; reserved : 0),
+ (unicode : 244; flag : umf_noinfo; reserved : 0),
+ (unicode : 245; flag : umf_noinfo; reserved : 0),
+ (unicode : 246; flag : umf_noinfo; reserved : 0),
+ (unicode : 247; flag : umf_noinfo; reserved : 0),
+ (unicode : 248; flag : umf_noinfo; reserved : 0),
+ (unicode : 249; flag : umf_noinfo; reserved : 0),
+ (unicode : 250; flag : umf_noinfo; reserved : 0),
+ (unicode : 251; flag : umf_noinfo; reserved : 0),
+ (unicode : 252; flag : umf_noinfo; reserved : 0),
+ (unicode : 253; flag : umf_noinfo; reserved : 0),
+ (unicode : 254; flag : umf_noinfo; reserved : 0),
+ (unicode : 255; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : '8859-1';
+ map : @map;
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/compiler/crc.pas b/compiler/crc.pas
new file mode 100644
index 0000000000..439bf4d351
--- /dev/null
+++ b/compiler/crc.pas
@@ -0,0 +1,100 @@
+{
+ Copyright (c) 2000-2002 by Free Pascal Development Team
+
+ Routines to compute CRC values
+
+ 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 crc;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Function Crc32(Const HStr:String):cardinal;
+Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:integer):cardinal;
+Function UpdCrc32(InitCrc:cardinal;b:byte):cardinal;
+
+
+Implementation
+
+{*****************************************************************************
+ Crc 32
+*****************************************************************************}
+
+var
+ Crc32Tbl : array[0..255] of cardinal;
+
+procedure MakeCRC32Tbl;
+var
+ crc : cardinal;
+ i,n : integer;
+begin
+ for i:=0 to 255 do
+ begin
+ crc:=i;
+ for n:=1 to 8 do
+ if (crc and 1)<>0 then
+ crc:=(crc shr 1) xor cardinal($edb88320)
+ else
+ crc:=crc shr 1;
+ Crc32Tbl[i]:=crc;
+ end;
+end;
+
+
+Function Crc32(Const HStr:String):cardinal;
+var
+ i : integer;
+ InitCrc : cardinal;
+begin
+ if Crc32Tbl[1]=0 then
+ MakeCrc32Tbl;
+ InitCrc:=cardinal($ffffffff);
+ for i:=1 to Length(Hstr) do
+ InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(Hstr[i])] xor (InitCrc shr 8);
+ Crc32:=InitCrc;
+end;
+
+
+
+Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:Integer):cardinal;
+var
+ i : integer;
+ p : pchar;
+begin
+ if Crc32Tbl[1]=0 then
+ MakeCrc32Tbl;
+ p:=@InBuf;
+ for i:=1 to InLen do
+ begin
+ InitCrc:=Crc32Tbl[byte(InitCrc) xor byte(p^)] xor (InitCrc shr 8);
+ inc(p);
+ end;
+ UpdateCrc32:=InitCrc;
+end;
+
+
+
+Function UpdCrc32(InitCrc:cardinal;b:byte):cardinal;
+begin
+ if Crc32Tbl[1]=0 then
+ MakeCrc32Tbl;
+ UpdCrc32:=Crc32Tbl[byte(InitCrc) xor b] xor (InitCrc shr 8);
+end;
+
+end.
diff --git a/compiler/cresstr.pas b/compiler/cresstr.pas
new file mode 100644
index 0000000000..7cae976a23
--- /dev/null
+++ b/compiler/cresstr.pas
@@ -0,0 +1,294 @@
+{
+ Copyright (c) 1998-2002 by Michael van Canneyt
+
+ Handles resourcestrings
+
+ 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 cresstr;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses;
+
+Type
+ { These are used to form a singly-linked list, ordered by hash value }
+ TResourceStringItem = class(TLinkedListItem)
+ Name : String;
+ Value : Pchar;
+ Len : Longint;
+ hash : Cardinal;
+ constructor Create(const AName:string;AValue:pchar;ALen:longint);
+ destructor Destroy;override;
+ procedure CalcHash;
+ end;
+
+ Tresourcestrings=class
+ private
+ List : TLinkedList;
+ public
+ ResStrCount : longint;
+ constructor Create;
+ destructor Destroy;override;
+ function Register(Const name : string;p : pchar;len : longint) : longint;
+ procedure CreateResourceStringList;
+ Procedure WriteResourceFile(const FileName : String);
+ end;
+
+var
+ resourcestrings : Tresourcestrings;
+
+
+implementation
+
+uses
+ cutils,globtype,globals,
+ symdef,
+ verbose,fmodule,
+ aasmbase,aasmtai,
+ aasmcpu;
+
+
+{ ---------------------------------------------------------------------
+ Calculate hash value, based on the string
+ ---------------------------------------------------------------------}
+
+{ ---------------------------------------------------------------------
+ TRESOURCESTRING_ITEM
+ ---------------------------------------------------------------------}
+
+constructor TResourceStringItem.Create(const AName:string;AValue:pchar;ALen:longint);
+begin
+ inherited Create;
+ Name:=AName;
+ Len:=ALen;
+ GetMem(Value,Len);
+ Move(AValue^,Value^,Len);
+ CalcHash;
+end;
+
+
+destructor TResourceStringItem.Destroy;
+begin
+ FreeMem(Value,Len);
+end;
+
+procedure TResourceStringItem.CalcHash;
+Var
+ g : Cardinal;
+ I : longint;
+begin
+ hash:=0;
+ For I:=0 to Len-1 do { 0 terminated }
+ begin
+ hash:=hash shl 4;
+ inc(Hash,Ord(Value[i]));
+ g:=hash and ($f shl 28);
+ if g<>0 then
+ begin
+ hash:=hash xor (g shr 24);
+ hash:=hash xor g;
+ end;
+ end;
+ If Hash=0 then
+ Hash:=$ffffffff;
+end;
+
+
+{ ---------------------------------------------------------------------
+ Tresourcestrings
+ ---------------------------------------------------------------------}
+
+Constructor Tresourcestrings.Create;
+begin
+ List:=TStringList.Create;
+ ResStrCount:=0;
+end;
+
+
+Destructor Tresourcestrings.Destroy;
+begin
+ List.Free;
+end;
+
+
+{ ---------------------------------------------------------------------
+ Create the full asmlist for resourcestrings.
+ ---------------------------------------------------------------------}
+
+procedure Tresourcestrings.CreateResourceStringList;
+
+ Procedure AppendToAsmResList (P : TResourceStringItem);
+ Var
+ l1 : tasmlabel;
+ s : pchar;
+ l : longint;
+ begin
+ with p Do
+ begin
+ if (Value=nil) or (len=0) then
+ asmlist[al_resourcestrings].concat(tai_const.create_sym(nil))
+ else
+ begin
+ objectlibrary.getdatalabel(l1);
+ asmlist[al_resourcestrings].concat(tai_const.create_sym(l1));
+ maybe_new_object_file(asmlist[al_const]);
+ asmlist[al_const].concat(tai_align.Create(const_align(sizeof(aint))));
+ asmlist[al_const].concat(tai_const.create_aint(-1));
+ asmlist[al_const].concat(tai_const.create_aint(len));
+ asmlist[al_const].concat(tai_label.create(l1));
+ getmem(s,len+1);
+ move(value^,s^,len);
+ s[len]:=#0;
+ asmlist[al_const].concat(tai_string.create_pchar(s,len));
+ asmlist[al_const].concat(tai_const.create_8bit(0));
+ end;
+ { append Current value (nil) and hash...}
+ asmlist[al_resourcestrings].concat(tai_const.create_sym(nil));
+ asmlist[al_resourcestrings].concat(tai_const.create_32bit(longint(hash)));
+ { Append the name as a ansistring. }
+ objectlibrary.getdatalabel(l1);
+ l:=length(name);
+ asmlist[al_resourcestrings].concat(tai_const.create_sym(l1));
+ maybe_new_object_file(asmlist[al_const]);
+ asmlist[al_const].concat(tai_align.create(const_align(sizeof(aint))));
+ asmlist[al_const].concat(tai_const.create_aint(-1));
+ asmlist[al_const].concat(tai_const.create_aint(l));
+ asmlist[al_const].concat(tai_label.create(l1));
+ getmem(s,l+1);
+ move(Name[1],s^,l);
+ s[l]:=#0;
+ asmlist[al_const].concat(tai_string.create_pchar(s,l));
+ asmlist[al_const].concat(tai_const.create_8bit(0));
+ end;
+ end;
+
+Var
+ R : tresourceStringItem;
+begin
+ if asmlist[al_resourcestrings]=nil then
+ asmlist[al_resourcestrings]:=taasmoutput.create;
+ maybe_new_object_file(asmlist[al_resourcestrings]);
+ new_section(asmlist[al_resourcestrings],sec_data,'',4);
+ asmlist[al_resourcestrings].concat(tai_align.create(const_align(sizeof(aint))));
+ asmlist[al_resourcestrings].concat(tai_symbol.createname_global(
+ make_mangledname('RESOURCESTRINGLIST',current_module.localsymtable,''),AT_DATA,0));
+ asmlist[al_resourcestrings].concat(tai_const.create_32bit(resstrcount));
+ R:=TResourceStringItem(List.First);
+ while assigned(R) do
+ begin
+ AppendToAsmResList(R);
+ R:=TResourceStringItem(R.Next);
+ end;
+ asmlist[al_resourcestrings].concat(tai_symbol_end.createname(
+ current_module.modulename^+'_'+'RESOURCESTRINGLIST'));
+end;
+
+
+{ ---------------------------------------------------------------------
+ Insert 1 resource string in all tables.
+ ---------------------------------------------------------------------}
+
+function Tresourcestrings.Register(const name : string;p : pchar;len : longint) : longint;
+begin
+ List.Concat(tResourceStringItem.Create(lower(current_module.modulename^+'.'+Name),p,len));
+ Register:=ResStrCount;
+ inc(ResStrCount);
+end;
+
+
+Procedure Tresourcestrings.WriteResourceFile(const FileName : String);
+Type
+ TMode = (quoted,unquoted);
+Var
+ F : Text;
+ Mode : TMode;
+ R : TResourceStringItem;
+ C : char;
+ Col,i : longint;
+
+ Procedure Add(Const S : String);
+ begin
+ Write(F,S);
+ Col:=Col+length(s);
+ end;
+
+begin
+ If List.Empty then
+ exit;
+ message1 (general_i_writingresourcefile,SplitFileName(filename));
+ Assign(F,Filename);
+ {$i-}
+ Rewrite(f);
+ {$i+}
+ If IOresult<>0 then
+ begin
+ message1(general_e_errorwritingresourcefile,filename);
+ exit;
+ end;
+ R:=TResourceStringItem(List.First);
+ While assigned(R) do
+ begin
+ writeln(f);
+ Writeln(f,'# hash value = ',R.hash);
+ col:=0;
+ Add(R.Name+'=');
+ Mode:=unquoted;
+ For I:=0 to R.Len-1 do
+ begin
+ C:=R.Value[i];
+ If (ord(C)>31) and (Ord(c)<=128) and (c<>'''') then
+ begin
+ If mode=Quoted then
+ Add(c)
+ else
+ begin
+ Add(''''+c);
+ mode:=quoted
+ end;
+ end
+ else
+ begin
+ If Mode=quoted then
+ begin
+ Add('''');
+ mode:=unquoted;
+ end;
+ Add('#'+tostr(ord(c)));
+ end;
+ If Col>72 then
+ begin
+ if mode=quoted then
+ Write (F,'''');
+ Writeln(F,'+');
+ Col:=0;
+ Mode:=unQuoted;
+ end;
+ end;
+ if mode=quoted then
+ writeln (f,'''');
+ Writeln(f);
+ R:=TResourceStringItem(R.Next);
+ end;
+ close(f);
+end;
+
+
+end.
diff --git a/compiler/cstreams.pas b/compiler/cstreams.pas
new file mode 100644
index 0000000000..2595fcb755
--- /dev/null
+++ b/compiler/cstreams.pas
@@ -0,0 +1,613 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ This module provides stream classes
+
+ 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 cstreams;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils;
+
+
+{****************************************************************************
+ TCStream
+****************************************************************************}
+
+ {
+ TCStream is copied directly from classesh.inc from the FCL so
+ it's compatible with the normal Classes.TStream.
+
+ TCFileStream is a merge of THandleStream and TFileStream and updated
+ to have a 'file' type instead of Handle.
+
+ TCCustomMemoryStream and TCMemoryStream are direct copies.
+ }
+ const
+ { TCStream seek origins }
+ soFromBeginning = 0;
+ soFromCurrent = 1;
+ soFromEnd = 2;
+
+ { TCFileStream create mode }
+ fmCreate = $FFFF;
+ fmOpenRead = 0;
+ fmOpenWrite = 1;
+ fmOpenReadWrite = 2;
+
+var
+{ Used for Error reporting instead of exceptions }
+ CStreamError : longint;
+
+type
+{ Fake TComponent class, it isn't used any futher }
+ TCComponent = class(TObject)
+ end;
+
+{ TCStream abstract class }
+
+ TCStream = class(TObject)
+ private
+ function GetPosition: Longint;
+ procedure SetPosition(Pos: Longint);
+ function GetSize: Longint;
+ protected
+ procedure SetSize(NewSize: Longint); virtual;
+ public
+ function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
+ function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
+ function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;
+ procedure ReadBuffer(var Buffer; Count: Longint);
+ procedure WriteBuffer(const Buffer; Count: Longint);
+ function CopyFrom(Source: TCStream; Count: Longint): Longint;
+ function ReadComponent(Instance: TCComponent): TCComponent;
+ function ReadComponentRes(Instance: TCComponent): TCComponent;
+ procedure WriteComponent(Instance: TCComponent);
+ procedure WriteComponentRes(const ResName: string; Instance: TCComponent);
+ procedure WriteDescendent(Instance, Ancestor: TCComponent);
+ procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TCComponent);
+ procedure WriteResourceHeader(const ResName: string; {!!!:out} var FixupInfo: Integer);
+ procedure FixupResourceHeader(FixupInfo: Integer);
+ procedure ReadResHeader;
+ function ReadByte : Byte;
+ function ReadWord : Word;
+ function ReadDWord : Cardinal;
+ function ReadAnsiString : AnsiString;
+ procedure WriteByte(b : Byte);
+ procedure WriteWord(w : Word);
+ procedure WriteDWord(d : Cardinal);
+ Procedure WriteAnsiString (S : AnsiString);
+ property Position: Longint read GetPosition write SetPosition;
+ property Size: Longint read GetSize write SetSize;
+ end;
+
+{ TFileStream class }
+
+ TCFileStream = class(TCStream)
+ Private
+ FFileName : String;
+ FHandle: File;
+ protected
+ procedure SetSize(NewSize: Longint); override;
+ public
+ constructor Create(const AFileName: string; Mode: Word);
+ destructor Destroy; override;
+ function Read(var Buffer; Count: Longint): Longint; override;
+ function Write(const Buffer; Count: Longint): Longint; override;
+ function Seek(Offset: Longint; Origin: Word): Longint; override;
+ property FileName : String Read FFilename;
+ end;
+
+{ TCustomMemoryStream abstract class }
+
+ TCCustomMemoryStream = class(TCStream)
+ private
+ FMemory: Pointer;
+ FSize, FPosition: Longint;
+ protected
+ procedure SetPointer(Ptr: Pointer; ASize: Longint);
+ public
+ function Read(var Buffer; Count: Longint): Longint; override;
+ function Seek(Offset: Longint; Origin: Word): Longint; override;
+ procedure SaveToStream(Stream: TCStream);
+ procedure SaveToFile(const FileName: string);
+ property Memory: Pointer read FMemory;
+ end;
+
+{ TCMemoryStream }
+
+ TCMemoryStream = class(TCCustomMemoryStream)
+ private
+ FCapacity: Longint;
+ procedure SetCapacity(NewCapacity: Longint);
+ protected
+ function Realloc(var NewCapacity: Longint): Pointer; virtual;
+ property Capacity: Longint read FCapacity write SetCapacity;
+ public
+ destructor Destroy; override;
+ procedure Clear;
+ procedure LoadFromStream(Stream: TCStream);
+ procedure LoadFromFile(const FileName: string);
+ procedure SetSize(NewSize: Longint); override;
+ function Write(const Buffer; Count: Longint): Longint; override;
+ end;
+
+
+implementation
+
+ Type
+ PByte = ^Byte;
+
+{*****************************************************************************
+ TCStream
+*****************************************************************************}
+
+ function TCStream.GetPosition: Longint;
+
+ begin
+ Result:=Seek(0,soFromCurrent);
+ end;
+
+ procedure TCStream.SetPosition(Pos: Longint);
+
+ begin
+ Seek(pos,soFromBeginning);
+ end;
+
+ function TCStream.GetSize: Longint;
+
+ var
+ p : longint;
+
+ begin
+ p:=GetPosition;
+ GetSize:=Seek(0,soFromEnd);
+ Seek(p,soFromBeginning);
+ end;
+
+ procedure TCStream.SetSize(NewSize: Longint);
+
+ begin
+ // We do nothing. Pipe streams don't support this
+ // As wel as possible read-ony streams !!
+ end;
+
+ procedure TCStream.ReadBuffer(var Buffer; Count: Longint);
+
+ begin
+ CStreamError:=0;
+ if Read(Buffer,Count)<Count then
+ CStreamError:=102;
+ end;
+
+ procedure TCStream.WriteBuffer(const Buffer; Count: Longint);
+
+ begin
+ CStreamError:=0;
+ if Write(Buffer,Count)<Count then
+ CStreamError:=103;
+ end;
+
+ function TCStream.CopyFrom(Source: TCStream; Count: Longint): Longint;
+
+ var
+ i : longint;
+ buffer : array[0..1023] of byte;
+
+ begin
+ CStreamError:=0;
+ Result:=0;
+ while Count>0 do
+ begin
+ if (Count>sizeof(buffer)) then
+ i:=sizeof(Buffer)
+ else
+ i:=Count;
+ i:=Source.Read(buffer,i);
+ i:=Write(buffer,i);
+ dec(count,i);
+ inc(Result,i);
+ if i=0 then
+ exit;
+ end;
+ end;
+
+ function TCStream.ReadComponent(Instance: TCComponent): TCComponent;
+ begin
+ Result:=nil;
+ end;
+
+ function TCStream.ReadComponentRes(Instance: TCComponent): TCComponent;
+ begin
+ Result:=nil;
+ end;
+
+ procedure TCStream.WriteComponent(Instance: TCComponent);
+ begin
+ end;
+
+ procedure TCStream.WriteComponentRes(const ResName: string; Instance: TCComponent);
+ begin
+ end;
+
+ procedure TCStream.WriteDescendent(Instance, Ancestor: TCComponent);
+ begin
+ end;
+
+ procedure TCStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TCComponent);
+ begin
+ end;
+
+ procedure TCStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
+ begin
+ end;
+
+ procedure TCStream.FixupResourceHeader(FixupInfo: Integer);
+ begin
+ end;
+
+ procedure TCStream.ReadResHeader;
+ begin
+ end;
+
+ function TCStream.ReadByte : Byte;
+
+ var
+ b : Byte;
+
+ begin
+ ReadBuffer(b,1);
+ ReadByte:=b;
+ end;
+
+ function TCStream.ReadWord : Word;
+
+ var
+ w : Word;
+
+ begin
+ ReadBuffer(w,2);
+ ReadWord:=w;
+ end;
+
+ function TCStream.ReadDWord : Cardinal;
+
+ var
+ d : Cardinal;
+
+ begin
+ ReadBuffer(d,4);
+ ReadDWord:=d;
+ end;
+
+ Function TCStream.ReadAnsiString : AnsiString;
+ Var
+ TheSize : Longint;
+ P : PByte ;
+ begin
+ ReadBuffer (TheSize,SizeOf(TheSize));
+ SetLength(Result,TheSize);
+ // Illegal typecast if no AnsiStrings defined.
+ if TheSize>0 then
+ begin
+ ReadBuffer (Pointer(Result)^,TheSize);
+ P:=PByte(PtrInt(Result)+TheSize);
+ p^:=0;
+ end;
+ end;
+
+ Procedure TCStream.WriteAnsiString (S : AnsiString);
+
+ Var L : Longint;
+
+ begin
+ L:=Length(S);
+ WriteBuffer (L,SizeOf(L));
+ WriteBuffer (Pointer(S)^,L);
+ end;
+
+ procedure TCStream.WriteByte(b : Byte);
+
+ begin
+ WriteBuffer(b,1);
+ end;
+
+ procedure TCStream.WriteWord(w : Word);
+
+ begin
+ WriteBuffer(w,2);
+ end;
+
+ procedure TCStream.WriteDWord(d : Cardinal);
+
+ begin
+ WriteBuffer(d,4);
+ end;
+
+
+{****************************************************************************}
+{* TCFileStream *}
+{****************************************************************************}
+
+constructor TCFileStream.Create(const AFileName: string; Mode: Word);
+begin
+ FFileName:=AFileName;
+ If Mode=fmcreate then
+ begin
+ system.assign(FHandle,AFileName);
+ {$I-}
+ system.rewrite(FHandle,1);
+ {$I+}
+ CStreamError:=IOResult;
+ end
+ else
+ begin
+ system.assign(FHandle,AFileName);
+ {$I-}
+ system.reset(FHandle,1);
+ {$I+}
+ CStreamError:=IOResult;
+ end;
+end;
+
+
+destructor TCFileStream.Destroy;
+begin
+ {$I-}
+ System.Close(FHandle);
+ {$I+}
+ CStreamError:=IOResult;
+end;
+
+
+function TCFileStream.Read(var Buffer; Count: Longint): Longint;
+begin
+ CStreamError:=0;
+ BlockRead(FHandle,Buffer,Count,Result);
+ If Result=-1 then Result:=0;
+end;
+
+
+function TCFileStream.Write(const Buffer; Count: Longint): Longint;
+begin
+ CStreamError:=0;
+ BlockWrite (FHandle,(@Buffer)^,Count,Result);
+ If Result=-1 then Result:=0;
+end;
+
+
+Procedure TCFileStream.SetSize(NewSize: Longint);
+begin
+ {$I-}
+ System.Seek(FHandle,NewSize);
+ System.Truncate(FHandle);
+ {$I+}
+ CStreamError:=IOResult;
+end;
+
+
+function TCFileStream.Seek(Offset: Longint; Origin: Word): Longint;
+var
+ l : longint;
+begin
+ {$I-}
+ case Origin of
+ soFromBeginning :
+ System.Seek(FHandle,Offset);
+ soFromCurrent :
+ begin
+ l:=System.FilePos(FHandle);
+ inc(l,Offset);
+ System.Seek(FHandle,l);
+ end;
+ soFromEnd :
+ begin
+ l:=System.FileSize(FHandle);
+ dec(l,Offset);
+ if l<0 then
+ l:=0;
+ System.Seek(FHandle,l);
+ end;
+ end;
+ {$I+}
+ CStreamError:=IOResult;
+ Result:=CStreamError;
+end;
+
+
+{****************************************************************************}
+{* TCustomMemoryStream *}
+{****************************************************************************}
+
+procedure TCCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: Longint);
+
+begin
+ FMemory:=Ptr;
+ FSize:=ASize;
+end;
+
+
+function TCCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
+
+begin
+ Result:=0;
+ If (FSize>0) and (FPosition<Fsize) then
+ begin
+ Result:=FSize-FPosition;
+ If Result>Count then Result:=Count;
+ Move (Pointer(PtrInt(FMemory)+FPosition)^,Buffer,Result);
+ FPosition:=Fposition+Result;
+ end;
+end;
+
+
+function TCCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
+
+begin
+ Case Origin of
+ soFromBeginning : FPosition:=Offset;
+ soFromEnd : FPosition:=FSize+Offset;
+ soFromCurrent : FpoSition:=FPosition+Offset;
+ end;
+ Result:=FPosition;
+end;
+
+
+procedure TCCustomMemoryStream.SaveToStream(Stream: TCStream);
+
+begin
+ if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
+end;
+
+
+procedure TCCustomMemoryStream.SaveToFile(const FileName: string);
+
+Var S : TCFileStream;
+
+begin
+ Try
+ S:=TCFileStream.Create (FileName,fmCreate);
+ SaveToStream(S);
+ finally
+ S.free;
+ end;
+end;
+
+
+{****************************************************************************}
+{* TCMemoryStream *}
+{****************************************************************************}
+
+
+Const TMSGrow = 4096; { Use 4k blocks. }
+
+procedure TCMemoryStream.SetCapacity(NewCapacity: Longint);
+
+begin
+ SetPointer (Realloc(NewCapacity),Fsize);
+ FCapacity:=NewCapacity;
+end;
+
+
+function TCMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
+
+Var MoveSize : Longint;
+
+begin
+ CStreamError:=0;
+ If NewCapacity>0 Then // round off to block size.
+ NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
+ // Only now check !
+ If NewCapacity=FCapacity then
+ Result:=FMemory
+ else
+ If NewCapacity=0 then
+ FreeMem (FMemory,Fcapacity)
+ else
+ begin
+ GetMem (Result,NewCapacity);
+ If Result=Nil then
+ CStreamError:=204;
+ If FCapacity>0 then
+ begin
+ MoveSize:=FSize;
+ If MoveSize>NewCapacity then MoveSize:=NewCapacity;
+ Move (Fmemory^,Result^,MoveSize);
+ FreeMem (FMemory,FCapacity);
+ end;
+ end;
+end;
+
+
+destructor TCMemoryStream.Destroy;
+
+begin
+ Clear;
+ Inherited Destroy;
+end;
+
+
+procedure TCMemoryStream.Clear;
+
+begin
+ FSize:=0;
+ FPosition:=0;
+ SetCapacity (0);
+end;
+
+
+procedure TCMemoryStream.LoadFromStream(Stream: TCStream);
+
+begin
+ Stream.Position:=0;
+ SetSize(Stream.Size);
+ If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
+end;
+
+
+procedure TCMemoryStream.LoadFromFile(const FileName: string);
+
+Var S : TCFileStream;
+
+begin
+ Try
+ S:=TCFileStream.Create (FileName,fmOpenRead);
+ LoadFromStream(S);
+ finally
+ S.free;
+ end;
+end;
+
+
+procedure TCMemoryStream.SetSize(NewSize: Longint);
+
+begin
+ SetCapacity (NewSize);
+ FSize:=NewSize;
+ IF FPosition>FSize then
+ FPosition:=FSize;
+end;
+
+
+function TCMemoryStream.Write(const Buffer; Count: Longint): Longint;
+
+Var NewPos : Longint;
+
+begin
+ If Count=0 then
+ begin
+ Result:=0;
+ exit;
+ end;
+ NewPos:=FPosition+Count;
+ If NewPos>Fsize then
+ begin
+ IF NewPos>FCapacity then
+ SetCapacity (NewPos);
+ FSize:=Newpos;
+ end;
+ System.Move (Buffer,Pointer(Ptrint(FMemory)+FPosition)^,Count);
+ FPosition:=NewPos;
+ Result:=Count;
+end;
+
+end.
diff --git a/compiler/cutils.pas b/compiler/cutils.pas
new file mode 100644
index 0000000000..0f8392abed
--- /dev/null
+++ b/compiler/cutils.pas
@@ -0,0 +1,1081 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements some support functions
+
+ 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 contains some generic support functions which are used
+ in the different parts of the compiler.
+}
+unit cutils;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+ type
+ pstring = ^string;
+ Tcharset=set of char;
+
+ var
+ internalerrorproc : procedure(i:longint);
+
+
+ {# Returns the minimal value between @var(a) and @var(b) }
+ function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
+ function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
+ {# Returns the maximum value between @var(a) and @var(b) }
+ function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
+ function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
+ {# Returns the value in @var(x) swapped to different endian }
+ Function SwapInt64(x : int64): int64;{$ifdef USEINLINE}inline;{$endif}
+ {# Returns the value in @var(x) swapped to different endian }
+ function SwapLong(x : longint): longint;{$ifdef USEINLINE}inline;{$endif}
+ {# Returns the value in @va(x) swapped to different endian }
+ function SwapWord(x : word): word;{$ifdef USEINLINE}inline;{$endif}
+ {# Return value @var(i) aligned on @var(a) boundary }
+ function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
+
+ function used_align(varalign,minalign,maxalign:longint):longint;
+ function size_2_align(len : longint) : longint;
+ procedure Replace(var s:string;s1:string;const s2:string);
+ procedure Replace(var s:AnsiString;s1:string;const s2:string);
+ procedure ReplaceCase(var s:string;const s1,s2:string);
+ function upper(const s : string) : string;
+ function lower(const s : string) : string;
+ function trimbspace(const s:string):string;
+ function trimspace(const s:string):string;
+ function space (b : longint): string;
+ function PadSpace(const s:string;len:longint):string;
+ function GetToken(var s:string;endchar:char):string;
+ procedure uppervar(var s : string);
+ function hexstr(val : cardinal;cnt : cardinal) : string;
+ function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
+ function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
+ function DStr(l:longint):string;
+ {# Returns true if the string s is a number }
+ function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
+ {# Returns true if value is a power of 2, the actual
+ exponent value is returned in power.
+ }
+ function ispowerof2(value : int64;out power : longint) : boolean;
+ function backspace_quote(const s:string;const qchars:Tcharset):string;
+ function octal_quote(const s:string;const qchars:Tcharset):string;
+ function maybequoted(const s:string):string;
+
+ {# If the string is quoted, in accordance with pascal, it is
+ dequoted and returned in s, and the function returns true.
+ If it is not quoted, or if the quoting is bad, s is not touched,
+ and false is returned.
+ }
+ function DePascalQuote(var s: string): Boolean;
+ function CompareText(S1, S2: string): longint;
+
+ { releases the string p and assignes nil to p }
+ { if p=nil then freemem isn't called }
+ procedure stringdispose(var p : pstring);{$ifdef USEINLINE}inline;{$endif}
+
+
+ { allocates mem for a copy of s, copies s to this mem and returns }
+ { a pointer to this mem }
+ function stringdup(const s : string) : pstring;{$ifdef USEINLINE}inline;{$endif}
+
+ {# Allocates memory for the string @var(s) and copies s as zero
+ terminated string to that allocated memory and returns a pointer
+ to that mem
+ }
+ function strpnew(const s : string) : pchar;
+ procedure strdispose(var p : pchar);
+
+ {# makes the character @var(c) lowercase, with spanish, french and german
+ character set
+ }
+ function lowercase(c : char) : char;
+
+ { makes zero terminated string to a pascal string }
+ { the data in p is modified and p is returned }
+ function pchar2pstring(p : pchar) : pstring;
+
+ { ambivalent to pchar2pstring }
+ function pstring2pchar(p : pstring) : pchar;
+
+ { Speed/Hash value }
+ Function GetSpeedValue(Const s:String):cardinal;
+
+ { Ansistring (pchar+length) support }
+ procedure ansistringdispose(var p : pchar;length : longint);
+ function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
+ function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
+
+ {Lzw encode/decode to compress strings -> save memory.}
+ function minilzw_encode(const s:string):string;
+ function minilzw_decode(const s:string):string;
+
+
+implementation
+
+uses
+ strings
+ ;
+
+
+ var
+ uppertbl,
+ lowertbl : array[char] of char;
+
+
+ function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return the minimal of a and b
+ }
+ begin
+ if a>b then
+ min:=b
+ else
+ min:=a;
+ end;
+
+
+ function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return the minimal of a and b
+ }
+ begin
+ if a>b then
+ min:=b
+ else
+ min:=a;
+ end;
+
+
+ function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return the maximum of a and b
+ }
+ begin
+ if a<b then
+ max:=b
+ else
+ max:=a;
+ end;
+
+
+ function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return the maximum of a and b
+ }
+ begin
+ if a<b then
+ max:=b
+ else
+ max:=a;
+ end;
+
+
+ Function SwapLong(x : longint): longint;{$ifdef USEINLINE}inline;{$endif}
+ var
+ y : word;
+ z : word;
+ Begin
+ y := x shr 16;
+ y := word(longint(y) shl 8) or (y shr 8);
+ z := x and $FFFF;
+ z := word(longint(z) shl 8) or (z shr 8);
+ SwapLong := (longint(z) shl 16) or longint(y);
+ End;
+
+
+ Function SwapInt64(x : int64): int64;{$ifdef USEINLINE}inline;{$endif}
+ Begin
+ result:=swaplong(longint(hi(x)));
+ result:=result or (swaplong(longint(lo(x))) shl 32);
+ End;
+
+
+ Function SwapWord(x : word): word;{$ifdef USEINLINE}inline;{$endif}
+ var
+ z : byte;
+ Begin
+ z := x shr 8;
+ x := x and $ff;
+ x := (x shl 8);
+ SwapWord := x or z;
+ End;
+
+
+ function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return value <i> aligned <a> boundary
+ }
+ begin
+ { for 0 and 1 no aligning is needed }
+ if a<=1 then
+ result:=i
+ else
+ begin
+ if i<0 then
+ result:=((i-a+1) div a) * a
+ else
+ result:=((i+a-1) div a) * a;
+ end;
+ end;
+
+
+ function size_2_align(len : longint) : longint;
+ begin
+ if len>16 then
+ size_2_align:=32
+ else if len>8 then
+ size_2_align:=16
+ else if len>4 then
+ size_2_align:=8
+ else if len>2 then
+ size_2_align:=4
+ else if len>1 then
+ size_2_align:=2
+ else
+ size_2_align:=1;
+ end;
+
+
+ function used_align(varalign,minalign,maxalign:longint):longint;
+ begin
+ { varalign : minimum alignment required for the variable
+ minalign : Minimum alignment of this structure, 0 = undefined
+ maxalign : Maximum alignment of this structure, 0 = undefined }
+ if (minalign>0) and
+ (varalign<minalign) then
+ used_align:=minalign
+ else
+ begin
+ if (maxalign>0) and
+ (varalign>maxalign) then
+ used_align:=maxalign
+ else
+ used_align:=varalign;
+ end;
+ end;
+
+
+ procedure Replace(var s:string;s1:string;const s2:string);
+ var
+ last,
+ i : longint;
+ begin
+ s1:=upper(s1);
+ last:=0;
+ repeat
+ i:=pos(s1,upper(s));
+ if i=last then
+ i:=0;
+ if (i>0) then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ last:=i;
+ end;
+ until (i=0);
+ end;
+
+
+ procedure Replace(var s:AnsiString;s1:string;const s2:string);
+ var
+ last,
+ i : longint;
+ begin
+ s1:=upper(s1);
+ last:=0;
+ repeat
+ i:=pos(s1,upper(s));
+ if i=last then
+ i:=0;
+ if (i>0) then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ last:=i;
+ end;
+ until (i=0);
+ end;
+
+
+ procedure ReplaceCase(var s:string;const s1,s2:string);
+ var
+ last,
+ i : longint;
+ begin
+ last:=0;
+ repeat
+ i:=pos(s1,s);
+ if i=last then
+ i:=0;
+ if (i>0) then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ last:=i;
+ end;
+ until (i=0);
+ end;
+
+
+ function upper(const s : string) : string;
+ {
+ return uppercased string of s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ upper[i]:=uppertbl[s[i]];
+ upper[0]:=s[0];
+ end;
+
+
+ function lower(const s : string) : string;
+ {
+ return lowercased string of s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ lower[i]:=lowertbl[s[i]];
+ lower[0]:=s[0];
+ end;
+
+
+ procedure uppervar(var s : string);
+ {
+ uppercase string s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ s[i]:=uppertbl[s[i]];
+ end;
+
+
+ procedure initupperlower;
+ var
+ c : char;
+ begin
+ for c:=#0 to #255 do
+ begin
+ lowertbl[c]:=c;
+ uppertbl[c]:=c;
+ case c of
+ 'A'..'Z' :
+ lowertbl[c]:=char(byte(c)+32);
+ 'a'..'z' :
+ uppertbl[c]:=char(byte(c)-32);
+ end;
+ end;
+ end;
+
+
+ function hexstr(val : cardinal;cnt : cardinal) : string;
+ const
+ HexTbl : array[0..15] of char='0123456789ABCDEF';
+ var
+ i,j : cardinal;
+ begin
+ { calculate required length }
+ i:=0;
+ j:=val;
+ while (j>0) do
+ begin
+ inc(i);
+ j:=j shr 4;
+ end;
+ { generate fillers }
+ j:=0;
+ while (i+j<cnt) do
+ begin
+ inc(j);
+ hexstr[j]:='0';
+ end;
+ { generate hex }
+ inc(j,i);
+ hexstr[0]:=chr(j);
+ while (val>0) do
+ begin
+ hexstr[j]:=hextbl[val and $f];
+ dec(j);
+ val:=val shr 4;
+ end;
+ end;
+
+
+ function DStr(l:longint):string;
+ var
+ TmpStr : string[32];
+ i : longint;
+ begin
+ Str(l,TmpStr);
+ i:=Length(TmpStr);
+ while (i>3) do
+ begin
+ dec(i,3);
+ if TmpStr[i]<>'-' then
+ insert('.',TmpStr,i+1);
+ end;
+ DStr:=TmpStr;
+ end;
+
+
+ function trimbspace(const s:string):string;
+ {
+ return s with all leading spaces and tabs removed
+ }
+ var
+ i,j : longint;
+ begin
+ j:=1;
+ i:=length(s);
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ trimbspace:=Copy(s,j,i-j+1);
+ end;
+
+
+
+ function trimspace(const s:string):string;
+ {
+ return s with all leading and ending spaces and tabs removed
+ }
+ var
+ i,j : longint;
+ begin
+ i:=length(s);
+ while (i>0) and (s[i] in [#9,' ']) do
+ dec(i);
+ j:=1;
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ trimspace:=Copy(s,j,i-j+1);
+ end;
+
+
+ function space (b : longint): string;
+ var
+ s: string;
+ begin
+ space[0] := chr(b);
+ s[0] := chr(b);
+ FillChar (S[1],b,' ');
+ space:=s;
+ end;
+
+
+ function PadSpace(const s:string;len:longint):string;
+ {
+ return s with spaces add to the end
+ }
+ begin
+ if length(s)<len then
+ PadSpace:=s+Space(len-length(s))
+ else
+ PadSpace:=s;
+ end;
+
+
+ function GetToken(var s:string;endchar:char):string;
+ var
+ i : longint;
+ begin
+ GetToken:='';
+ s:=TrimSpace(s);
+ if (length(s)>0) and
+ (s[1]='''') then
+ begin
+ i:=1;
+ while (i<length(s)) do
+ begin
+ inc(i);
+ if s[i]='''' then
+ begin
+ { Remove double quote }
+ if (i<length(s)) and
+ (s[i+1]='''') then
+ begin
+ Delete(s,i,1);
+ inc(i);
+ end
+ else
+ begin
+ GetToken:=Copy(s,2,i-2);
+ Delete(s,1,i);
+ exit;
+ end;
+ end;
+ end;
+ GetToken:=s;
+ s:='';
+ end
+ else
+ begin
+ i:=pos(EndChar,s);
+ if i=0 then
+ begin
+ GetToken:=s;
+ s:='';
+ exit;
+ end
+ else
+ begin
+ GetToken:=Copy(s,1,i-1);
+ Delete(s,1,i);
+ exit;
+ end;
+ end;
+ end;
+
+
+ function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ str(e,result);
+ end;
+
+
+ function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ {
+ return string of value i
+ }
+ begin
+ str(i,result);
+ end;
+
+
+ function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ {
+ return string of value i
+ }
+ begin
+ str(i,result);
+ end;
+
+
+ function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ {
+ return string of value i
+ }
+ begin
+ str(i,result);
+ end;
+
+
+ function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return string of value i, but always include a + when i>=0
+ }
+ begin
+ str(i,result);
+ if i>=0 then
+ result:='+'+result;
+ end;
+
+
+ function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
+ {
+ is string a correct number ?
+ }
+ var
+ w : integer;
+ l : longint;
+ begin
+ val(s,l,w);
+ is_number:=(w=0);
+ end;
+
+
+ function ispowerof2(value : int64;out power : longint) : boolean;
+ {
+ return if value is a power of 2. And if correct return the power
+ }
+ var
+ hl : int64;
+ i : longint;
+ begin
+ if value and (value - 1) <> 0 then
+ begin
+ ispowerof2 := false;
+ exit
+ end;
+ hl:=1;
+ ispowerof2:=true;
+ for i:=0 to 63 do
+ begin
+ if hl=value then
+ begin
+ power:=i;
+ exit;
+ end;
+ hl:=hl shl 1;
+ end;
+ ispowerof2:=false;
+ end;
+
+
+ function backspace_quote(const s:string;const qchars:Tcharset):string;
+
+ var i:byte;
+
+ begin
+ backspace_quote:='';
+ for i:=1 to length(s) do
+ begin
+ if (s[i]=#10) and (#10 in qchars) then
+ backspace_quote:=backspace_quote+'\n'
+ else if (s[i]=#13) and (#13 in qchars) then
+ backspace_quote:=backspace_quote+'\r'
+ else
+ begin
+ if s[i] in qchars then
+ backspace_quote:=backspace_quote+'\';
+ backspace_quote:=backspace_quote+s[i];
+ end;
+ end;
+ end;
+
+ function octal_quote(const s:string;const qchars:Tcharset):string;
+
+ var i:byte;
+
+ begin
+ octal_quote:='';
+ for i:=1 to length(s) do
+ begin
+ if s[i] in qchars then
+ begin
+ if ord(s[i])<64 then
+ octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
+ else
+ octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
+ end
+ else
+ octal_quote:=octal_quote+s[i];
+ end;
+ end;
+
+ function maybequoted(const s:string):string;
+ var
+ s1 : string;
+ i : integer;
+ quoted : boolean;
+ begin
+ quoted:=false;
+ s1:='"';
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '"' :
+ begin
+ quoted:=true;
+ s1:=s1+'\"';
+ end;
+ ' ',
+ #128..#255 :
+ begin
+ quoted:=true;
+ s1:=s1+s[i];
+ end;
+ else
+ s1:=s1+s[i];
+ end;
+ end;
+ if quoted then
+ maybequoted:=s1+'"'
+ else
+ maybequoted:=s;
+ end;
+
+
+ function DePascalQuote(var s: string): Boolean;
+ var
+ destPos, sourcePos, len: Integer;
+ t: string;
+ ch: Char;
+ begin
+ DePascalQuote:= false;
+ len:= length(s);
+ if (len >= 1) and (s[1] = '''') then
+ begin
+ {Remove quotes, exchange '' against ' }
+ destPos := 0;
+ sourcepos:=1;
+ while (sourcepos<len) do
+ begin
+ inc(sourcePos);
+ ch := s[sourcePos];
+ if ch = '''' then
+ begin
+ inc(sourcePos);
+ if (sourcePos <= len) and (s[sourcePos] = '''') then
+ {Add the quote as part of string}
+ else
+ begin
+ SetLength(t, destPos);
+ s:= t;
+ Exit(true);
+ end;
+ end;
+ inc(destPos);
+ t[destPos] := ch;
+ end;
+ end;
+ end;
+
+
+ function pchar2pstring(p : pchar) : pstring;
+ var
+ w,i : longint;
+ begin
+ w:=strlen(p);
+ for i:=w-1 downto 0 do
+ p[i+1]:=p[i];
+ p[0]:=chr(w);
+ pchar2pstring:=pstring(p);
+ end;
+
+
+ function pstring2pchar(p : pstring) : pchar;
+ var
+ w,i : longint;
+ begin
+ w:=length(p^);
+ for i:=1 to w do
+ p^[i-1]:=p^[i];
+ p^[w]:=#0;
+ pstring2pchar:=pchar(p);
+ end;
+
+
+ function lowercase(c : char) : char;
+ begin
+ case c of
+ #65..#90 : c := chr(ord (c) + 32);
+ #154 : c:=#129; { german }
+ #142 : c:=#132; { german }
+ #153 : c:=#148; { german }
+ #144 : c:=#130; { french }
+ #128 : c:=#135; { french }
+ #143 : c:=#134; { swedish/norge (?) }
+ #165 : c:=#164; { spanish }
+ #228 : c:=#229; { greek }
+ #226 : c:=#231; { greek }
+ #232 : c:=#227; { greek }
+ end;
+ lowercase := c;
+ end;
+
+
+ function strpnew(const s : string) : pchar;
+ var
+ p : pchar;
+ begin
+ getmem(p,length(s)+1);
+ strpcopy(p,s);
+ strpnew:=p;
+ end;
+
+
+ procedure strdispose(var p : pchar);
+ begin
+ if assigned(p) then
+ begin
+ freemem(p,strlen(p)+1);
+ p:=nil;
+ end;
+ end;
+
+
+ procedure stringdispose(var p : pstring);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ if assigned(p) then
+ begin
+ freemem(p,length(p^)+1);
+ p:=nil;
+ end;
+ end;
+
+
+ function stringdup(const s : string) : pstring;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ getmem(result,length(s)+1);
+ result^:=s;
+ end;
+
+
+ function CompareText(S1, S2: string): longint;
+ begin
+ UpperVar(S1);
+ UpperVar(S2);
+ if S1<S2 then
+ CompareText:=-1
+ else
+ if S1>S2 then
+ CompareText:= 1
+ else
+ CompareText:=0;
+ end;
+
+
+{*****************************************************************************
+ GetSpeedValue
+*****************************************************************************}
+
+ var
+ Crc32Tbl : array[0..255] of cardinal;
+
+ procedure MakeCRC32Tbl;
+ var
+ crc : cardinal;
+ i,n : integer;
+ begin
+ for i:=0 to 255 do
+ begin
+ crc:=i;
+ for n:=1 to 8 do
+ if odd(longint(crc)) then
+ crc:=cardinal(crc shr 1) xor cardinal($edb88320)
+ else
+ crc:=cardinal(crc shr 1);
+ Crc32Tbl[i]:=crc;
+ end;
+ end;
+
+
+ Function GetSpeedValue(Const s:String):cardinal;
+ var
+ i : integer;
+ InitCrc : cardinal;
+ begin
+ InitCrc:=cardinal($ffffffff);
+ for i:=1 to Length(s) do
+ InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
+ GetSpeedValue:=InitCrc;
+ end;
+
+
+{*****************************************************************************
+ Ansistring (PChar+Length)
+*****************************************************************************}
+
+ procedure ansistringdispose(var p : pchar;length : longint);
+ begin
+ if assigned(p) then
+ begin
+ freemem(p,length+1);
+ p:=nil;
+ end;
+ end;
+
+
+ { enable ansistring comparison }
+ { 0 means equal }
+ { 1 means p1 > p2 }
+ { -1 means p1 < p2 }
+ function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
+ var
+ i,j : longint;
+ begin
+ compareansistrings:=0;
+ j:=min(length1,length2);
+ i:=0;
+ while (i<j) do
+ begin
+ if p1[i]>p2[i] then
+ begin
+ compareansistrings:=1;
+ exit;
+ end
+ else
+ if p1[i]<p2[i] then
+ begin
+ compareansistrings:=-1;
+ exit;
+ end;
+ inc(i);
+ end;
+ if length1>length2 then
+ compareansistrings:=1
+ else
+ if length1<length2 then
+ compareansistrings:=-1;
+ end;
+
+
+ function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
+ var
+ p : pchar;
+ begin
+ getmem(p,length1+length2+1);
+ move(p1[0],p[0],length1);
+ move(p2[0],p[length1],length2+1);
+ concatansistrings:=p;
+ end;
+
+
+{*****************************************************************************
+ Ultra basic KISS Lzw (de)compressor
+*****************************************************************************}
+
+ {This is an extremely basic implementation of the Lzw algorithm. It
+ compresses 7-bit ASCII strings into 8-bit compressed strings.
+ The Lzw dictionary is preinitialized with 0..127, therefore this
+ part of the dictionary does not need to be stored in the arrays.
+ The Lzw code size is allways 8 bit, so we do not need complex code
+ that can write partial bytes.}
+
+ function minilzw_encode(const s:string):string;
+
+ var t,u,i:byte;
+ c:char;
+ data:array[128..255] of char;
+ previous:array[128..255] of byte;
+ lzwptr:byte;
+ next_avail:set of 0..255;
+
+ label l1;
+
+ begin
+ minilzw_encode:='';
+ if s<>'' then
+ begin
+ lzwptr:=127;
+ t:=byte(s[1]);
+ i:=2;
+ u:=128;
+ next_avail:=[];
+ while i<=length(s) do
+ begin
+ c:=s[i];
+ if not(t in next_avail) or (u>lzwptr) then goto l1;
+ while (previous[u]<>t) or (data[u]<>c) do
+ begin
+ inc(u);
+ if u>lzwptr then goto l1;
+ end;
+ t:=u;
+ inc(i);
+ continue;
+ l1:
+ {It's a pity that we still need those awfull tricks
+ with this modern compiler. Without this performance
+ of the entire procedure drops about 3 times.}
+ inc(minilzw_encode[0]);
+ minilzw_encode[length(minilzw_encode)]:=char(t);
+ if lzwptr=255 then
+ begin
+ lzwptr:=127;
+ next_avail:=[];
+ end
+ else
+ begin
+ inc(lzwptr);
+ data[lzwptr]:=c;
+ previous[lzwptr]:=t;
+ include(next_avail,t);
+ end;
+ t:=byte(c);
+ u:=128;
+ inc(i);
+ end;
+ inc(minilzw_encode[0]);
+ minilzw_encode[length(minilzw_encode)]:=char(t);
+ end;
+ end;
+
+ function minilzw_decode(const s:string):string;
+
+ var oldc,newc,c:char;
+ i,j:byte;
+ data:array[128..255] of char;
+ previous:array[128..255] of byte;
+ lzwptr:byte;
+ t:string;
+
+ begin
+ minilzw_decode:='';
+ if s<>'' then
+ begin
+ lzwptr:=127;
+ oldc:=s[1];
+ c:=oldc;
+ i:=2;
+ minilzw_decode:=oldc;
+ while i<=length(s) do
+ begin
+ newc:=s[i];
+ if byte(newc)>lzwptr then
+ begin
+ t:=c;
+ c:=oldc;
+ end
+ else
+ begin
+ c:=newc;
+ t:='';
+ end;
+ while c>=#128 do
+ begin
+ inc(t[0]);
+ t[length(t)]:=data[byte(c)];
+ byte(c):=previous[byte(c)];
+ end;
+ inc(minilzw_decode[0]);
+ minilzw_decode[length(minilzw_decode)]:=c;
+ for j:=length(t) downto 1 do
+ begin
+ inc(minilzw_decode[0]);
+ minilzw_decode[length(minilzw_decode)]:=t[j];
+ end;
+ if lzwptr=255 then
+ lzwptr:=127
+ else
+ begin
+ inc(lzwptr);
+ previous[lzwptr]:=byte(oldc);
+ data[lzwptr]:=c;
+ end;
+ oldc:=newc;
+ inc(i);
+ end;
+ end;
+ end;
+
+
+ procedure defaulterror(i:longint);
+ begin
+ writeln('Internal error ',i);
+ runerror(255);
+ end;
+
+
+initialization
+ internalerrorproc:=@defaulterror;
+ makecrc32tbl;
+ initupperlower;
+end.
diff --git a/compiler/dbgbase.pas b/compiler/dbgbase.pas
new file mode 100644
index 0000000000..681230743d
--- /dev/null
+++ b/compiler/dbgbase.pas
@@ -0,0 +1,128 @@
+{
+ Copyright (c) 2003-2004 by Peter Vreman and Florian Klaempfl
+
+ This units contains support for debug info generation
+
+ 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 dbgbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ systems,
+ symdef,symtype,
+ symsym,
+ aasmtai;
+
+ type
+ TDebugInfo=class
+ constructor Create;virtual;
+ procedure inserttypeinfo;virtual;
+ procedure insertmoduleinfo;virtual;
+ procedure insertlineinfo(list:taasmoutput);virtual;
+ procedure referencesections(list:taasmoutput);virtual;
+ end;
+ TDebugInfoClass=class of TDebugInfo;
+
+ var
+ CDebugInfo : array[tdbg] of TDebugInfoClass;
+ DebugInfo : TDebugInfo;
+
+ procedure InitDebugInfo;
+ procedure DoneDebugInfo;
+ procedure RegisterDebugInfo(const r:tdbginfo;c:TDebugInfoClass);
+
+
+implementation
+
+ uses
+ verbose;
+
+
+ constructor tdebuginfo.Create;
+ begin
+ end;
+
+
+ procedure tdebuginfo.insertmoduleinfo;
+ begin
+ end;
+
+
+ procedure tdebuginfo.inserttypeinfo;
+ begin
+ end;
+
+
+ procedure tdebuginfo.insertlineinfo(list:taasmoutput);
+ begin
+ end;
+
+
+ procedure tdebuginfo.referencesections(list:taasmoutput);
+ begin
+ end;
+
+
+ procedure InitDebugInfo;
+ begin
+ if not assigned(CDebugInfo[target_dbg.id]) then
+ begin
+ Comment(V_Fatal,'cg_f_debuginfo_output_not_supported');
+ exit;
+ end;
+ DebugInfo:=CDebugInfo[target_dbg.id].Create;
+ end;
+
+
+ procedure DoneDebugInfo;
+ begin
+ if assigned(DebugInfo) then
+ begin
+ DebugInfo.Free;
+ DebugInfo:=nil;
+ end;
+ end;
+
+
+ procedure RegisterDebugInfo(const r:tdbginfo;c:TDebugInfoClass);
+ var
+ t : tdbg;
+ begin
+ t:=r.id;
+ if assigned(dbginfos[t]) then
+ writeln('Warning: DebugInfo is already registered!')
+ else
+ Getmem(dbginfos[t],sizeof(tdbginfo));
+ dbginfos[t]^:=r;
+ CDebugInfo[t]:=c;
+ end;
+
+
+ const
+ dbg_none_info : tdbginfo =
+ (
+ id : dbg_none;
+ idtxt : 'NONE';
+ );
+
+initialization
+ RegisterDebugInfo(dbg_none_info,tdebuginfo);
+end.
diff --git a/compiler/dbgdwarf.pas b/compiler/dbgdwarf.pas
new file mode 100644
index 0000000000..bab6d43069
--- /dev/null
+++ b/compiler/dbgdwarf.pas
@@ -0,0 +1,49 @@
+{
+ Copyright (c) 2003-2004 by Peter Vreman and Florian Klaempfl
+
+ This units contains support for DWARF debug info generation
+
+ 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 dbgdwarf;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ DbgBase;
+
+ type
+ TDebugInfoDwarf=class(TDebugInfo)
+ end;
+
+implementation
+
+ uses
+ Systems;
+
+ const
+ dbg_dwarf_info : tdbginfo =
+ (
+ id : dbg_dwarf;
+ idtxt : 'DWARF';
+ );
+
+initialization
+ RegisterDebugInfo(dbg_dwarf_info,TDebugInfoDwarf);
+end.
diff --git a/compiler/dbgstabs.pas b/compiler/dbgstabs.pas
new file mode 100644
index 0000000000..bfdd181c68
--- /dev/null
+++ b/compiler/dbgstabs.pas
@@ -0,0 +1,1589 @@
+{
+ Copyright (c) 2003-2004 by Peter Vreman and Florian Klaempfl
+
+ This units contains support for STABS debug info generation
+
+ 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 dbgstabs;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ dbgbase,
+ symtype,symdef,symsym,symtable,symbase,
+ aasmtai;
+
+ type
+ TDebugInfoStabs=class(TDebugInfo)
+ private
+ writing_def_stabs : boolean;
+ global_stab_number : word;
+ defnumberlist : tlist;
+ { tsym writing }
+ function sym_var_value(const s:string;arg:pointer):string;
+ function sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):Pchar;
+ procedure write_symtable_syms(list:taasmoutput;st:tsymtable);
+ { tdef writing }
+ function def_stab_number(def:tdef):string;
+ function def_stab_classnumber(def:tobjectdef):string;
+ function def_var_value(const s:string;arg:pointer):string;
+ function def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):Pchar;
+ procedure field_add_stabstr(p:Tnamedindexitem;arg:pointer);
+ procedure method_add_stabstr(p:Tnamedindexitem;arg:pointer);
+ function def_stabstr(def:tdef):pchar;
+ procedure write_def_stabstr(list:taasmoutput;def:tdef);
+ procedure field_write_defs(p:Tnamedindexitem;arg:pointer);
+ procedure method_write_defs(p :tnamedindexitem;arg:pointer);
+ procedure write_symtable_defs(list:taasmoutput;st:tsymtable);
+ procedure write_procdef(list:taasmoutput;pd:tprocdef);
+ procedure insertsym(list:taasmoutput;sym:tsym);
+ procedure insertdef(list:taasmoutput;def:tdef);
+ public
+ procedure inserttypeinfo;override;
+ procedure insertmoduleinfo;override;
+ procedure insertlineinfo(list:taasmoutput);override;
+ procedure referencesections(list:taasmoutput);override;
+ end;
+
+
+implementation
+
+ uses
+ strings,cutils,
+ systems,globals,globtype,verbose,
+ symconst,defutil,
+ cpuinfo,cpubase,cgbase,paramgr,
+ aasmbase,procinfo,
+ finput,fmodule,ppu;
+
+ const
+ memsizeinc = 512;
+
+ N_GSYM = $20;
+ N_STSYM = 38; { initialized const }
+ N_LCSYM = 40; { non initialized variable}
+ N_Function = $24; { function or const }
+ N_TextLine = $44;
+ N_DataLine = $46;
+ N_BssLine = $48;
+ N_RSYM = $40; { register variable }
+ N_LSYM = $80;
+ N_tsym = 160;
+ N_SourceFile = $64;
+ N_IncludeFile = $84;
+ N_BINCL = $82;
+ N_EINCL = $A2;
+ N_EXCL = $C2;
+
+ tagtypes = [
+ recorddef,
+ enumdef,
+ stringdef,
+ filedef,
+ objectdef
+ ];
+
+ type
+ get_var_value_proc=function(const s:string;arg:pointer):string of object;
+
+ Trecord_stabgen_state=record
+ stabstring:Pchar;
+ stabsize,staballoc,recoffset:integer;
+ end;
+ Precord_stabgen_state=^Trecord_stabgen_state;
+
+
+ function string_evaluate(s:string;get_var_value:get_var_value_proc;
+ get_var_value_arg:pointer;
+ const vars:array of string):Pchar;
+
+ (*
+ S contains a prototype of a result. Stabstr_evaluate will expand
+ variables and parameters.
+
+ Output is s in ASCIIZ format, with the following expanded:
+
+ ${varname} - The variable name is expanded.
+ $n - The parameter n is expanded.
+ $$ - Is expanded to $
+ *)
+
+ const maxvalue=9;
+ maxdata=1023;
+
+ var i,j:byte;
+ varname:string[63];
+ varno,varcounter:byte;
+ varvalues:array[0..9] of Pstring;
+ {1 kb of parameters is the limit. 256 extra bytes are allocated to
+ ensure buffer integrity.}
+ varvaluedata:array[0..maxdata+256] of char;
+ varptr:Pchar;
+ varidx : byte;
+ len:cardinal;
+ r:Pchar;
+
+ begin
+ {Two pass approach, first, calculate the length and receive variables.}
+ i:=1;
+ len:=0;
+ varcounter:=0;
+ varptr:=@varvaluedata;
+ while i<=length(s) do
+ begin
+ if (s[i]='$') and (i<length(s)) then
+ begin
+ if s[i+1]='$' then
+ begin
+ inc(len);
+ inc(i);
+ end
+ else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
+ begin
+ varname:='';
+ inc(i,2);
+ repeat
+ inc(varname[0]);
+ varname[length(varname)]:=s[i];
+ s[i]:=char(varcounter);
+ inc(i);
+ until s[i]='}';
+ varvalues[varcounter]:=Pstring(varptr);
+ if varptr>@varvaluedata+maxdata then
+ internalerrorproc(200411152);
+ Pstring(varptr)^:=get_var_value(varname,get_var_value_arg);
+ inc(len,length(Pstring(varptr)^));
+ inc(varptr,length(Pstring(varptr)^)+1);
+ inc(varcounter);
+ end
+ else if s[i+1] in ['1'..'9'] then
+ begin
+ varidx:=byte(s[i+1])-byte('1');
+ if varidx>high(vars) then
+ internalerror(200509263);
+ inc(len,length(vars[varidx]));
+ inc(i);
+ end;
+ end
+ else
+ inc(len);
+ inc(i);
+ end;
+
+ {Second pass, writeout result.}
+ getmem(r,len+1);
+ string_evaluate:=r;
+ i:=1;
+ while i<=length(s) do
+ begin
+ if (s[i]='$') and (i<length(s)) then
+ begin
+ if s[i+1]='$' then
+ begin
+ r^:='$';
+ inc(r);
+ inc(i);
+ end
+ else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
+ begin
+ varname:='';
+ inc(i,2);
+ varno:=byte(s[i]);
+ repeat
+ inc(i);
+ until s[i]='}';
+ for j:=1 to length(varvalues[varno]^) do
+ begin
+ r^:=varvalues[varno]^[j];
+ inc(r);
+ end;
+ end
+ else if s[i+1] in ['0'..'9'] then
+ begin
+ for j:=1 to length(vars[byte(s[i+1])-byte('1')]) do
+ begin
+ r^:=vars[byte(s[i+1])-byte('1')][j];
+ inc(r);
+ end;
+ inc(i);
+ end
+ end
+ else
+ begin
+ r^:=s[i];
+ inc(r);
+ end;
+ inc(i);
+ end;
+ r^:=#0;
+ end;
+
+
+{****************************************************************************
+ TDef support
+****************************************************************************}
+
+ function TDebugInfoStabs.def_stab_number(def:tdef):string;
+ begin
+ { procdefs only need a number, mark them as already written
+ so they won't be written implicitly }
+ if (def.deftype=procdef) then
+ def.stab_state:=stab_state_written;
+ { Stab must already be written, or we must be busy writing it }
+ if writing_def_stabs and
+ not(def.stab_state in [stab_state_writing,stab_state_written]) then
+ internalerror(200403091);
+ { Keep track of used stabs, this info is only usefull for stabs
+ referenced by the symbols. Definitions will always include all
+ required stabs }
+ if def.stab_state=stab_state_unused then
+ def.stab_state:=stab_state_used;
+ { Need a new number? }
+ if def.stab_number=0 then
+ begin
+ inc(global_stab_number);
+ { classes require 2 numbers }
+ if is_class(def) then
+ inc(global_stab_number);
+ def.stab_number:=global_stab_number;
+ if global_stab_number>=defnumberlist.count then
+ defnumberlist.count:=global_stab_number+250;
+ defnumberlist[global_stab_number]:=def;
+ end;
+ result:=tostr(def.stab_number);
+ end;
+
+
+ function TDebugInfoStabs.def_stab_classnumber(def:tobjectdef):string;
+ begin
+ if def.stab_number=0 then
+ def_stab_number(def);
+ result:=tostr(def.stab_number-1);
+ end;
+
+
+ function TDebugInfoStabs.def_var_value(const s:string;arg:pointer):string;
+ var
+ def : tdef;
+ begin
+ def:=tdef(arg);
+ result:='';
+ if s='numberstring' then
+ result:=def_stab_number(def)
+ else if s='sym_name' then
+ begin
+ if assigned(def.typesym) then
+ result:=Ttypesym(def.typesym).name;
+ end
+ else if s='N_LSYM' then
+ result:=tostr(N_LSYM)
+ else if s='savesize' then
+ result:=tostr(def.size);
+ end;
+
+
+ function TDebugInfoStabs.def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):Pchar;
+ begin
+ result:=string_evaluate(s,@def_var_value,def,vars);
+ end;
+
+
+ procedure TDebugInfoStabs.field_add_stabstr(p:Tnamedindexitem;arg:pointer);
+ var
+ newrec : Pchar;
+ spec : string[3];
+ varsize : aint;
+ state : Precord_stabgen_state;
+ begin
+ state:=arg;
+ { static variables from objects are like global objects }
+ if (Tsym(p).typ=fieldvarsym) and
+ not(sp_static in Tsym(p).symoptions) then
+ begin
+ if ([sp_protected,sp_strictprotected]*tsym(p).symoptions)<>[] then
+ spec:='/1'
+ else if ([sp_private,sp_strictprivate]*tsym(p).symoptions)<>[] then
+ spec:='/0'
+ else
+ spec:='';
+ varsize:=tfieldvarsym(p).vartype.def.size;
+ { open arrays made overflows !! }
+ if varsize>$fffffff then
+ varsize:=$fffffff;
+ newrec:=def_stabstr_evaluate(nil,'$1:$2,$3,$4;',[p.name,
+ spec+def_stab_number(tfieldvarsym(p).vartype.def),
+ tostr(tfieldvarsym(p).fieldoffset*8),tostr(varsize*8)]);
+ if state^.stabsize+strlen(newrec)>=state^.staballoc-256 then
+ begin
+ inc(state^.staballoc,strlen(newrec)+64);
+ reallocmem(state^.stabstring,state^.staballoc);
+ end;
+ strcopy(state^.stabstring+state^.stabsize,newrec);
+ inc(state^.stabsize,strlen(newrec));
+ strdispose(newrec);
+ {This should be used for case !!}
+ inc(state^.recoffset,Tfieldvarsym(p).vartype.def.size);
+ end;
+ end;
+
+
+ procedure TDebugInfoStabs.method_add_stabstr(p:Tnamedindexitem;arg:pointer);
+ var virtualind,argnames : string;
+ newrec : pchar;
+ pd : tprocdef;
+ lindex : longint;
+ arglength : byte;
+ sp : char;
+ state:^Trecord_stabgen_state;
+ olds:integer;
+ i : integer;
+ parasym : tparavarsym;
+ begin
+ state:=arg;
+ if tsym(p).typ = procsym then
+ begin
+ pd := tprocsym(p).first_procdef;
+ if (po_virtualmethod in pd.procoptions) then
+ begin
+ lindex := pd.extnumber;
+ {doesnt seem to be necessary
+ lindex := lindex or $80000000;}
+ virtualind := '*'+tostr(lindex)+';'+def_stab_classnumber(pd._class)+';'
+ end
+ else
+ virtualind := '.';
+
+ { used by gdbpas to recognize constructor and destructors }
+ if (pd.proctypeoption=potype_constructor) then
+ argnames:='__ct__'
+ else if (pd.proctypeoption=potype_destructor) then
+ argnames:='__dt__'
+ else
+ argnames := '';
+
+ { arguments are not listed here }
+ {we don't need another definition}
+ for i:=0 to pd.paras.count-1 do
+ begin
+ parasym:=tparavarsym(pd.paras[i]);
+ if Parasym.vartype.def.deftype = formaldef then
+ begin
+ case Parasym.varspez of
+ vs_var :
+ argnames := argnames+'3var';
+ vs_const :
+ argnames:=argnames+'5const';
+ vs_out :
+ argnames:=argnames+'3out';
+ end;
+ end
+ else
+ begin
+ { if the arg definition is like (v: ^byte;..
+ there is no sym attached to data !!! }
+ if assigned(Parasym.vartype.def.typesym) then
+ begin
+ arglength := length(Parasym.vartype.def.typesym.name);
+ argnames := argnames + tostr(arglength)+Parasym.vartype.def.typesym.name;
+ end
+ else
+ argnames:=argnames+'11unnamedtype';
+ end;
+ end;
+ { here 2A must be changed for private and protected }
+ { 0 is private 1 protected and 2 public }
+ if ([sp_private,sp_strictprivate]*tsym(p).symoptions)<>[] then
+ sp:='0'
+ else if ([sp_protected,sp_strictprotected]*tsym(p).symoptions)<>[] then
+ sp:='1'
+ else
+ sp:='2';
+ newrec:=def_stabstr_evaluate(nil,'$1::$2=##$3;:$4;$5A$6;',[p.name,def_stab_number(pd),
+ def_stab_number(pd.rettype.def),argnames,sp,
+ virtualind]);
+ { get spare place for a string at the end }
+ olds:=state^.stabsize;
+ inc(state^.stabsize,strlen(newrec));
+ if state^.stabsize>=state^.staballoc-256 then
+ begin
+ inc(state^.staballoc,strlen(newrec)+64);
+ reallocmem(state^.stabstring,state^.staballoc);
+ end;
+ strcopy(state^.stabstring+olds,newrec);
+ strdispose(newrec);
+ {This should be used for case !!
+ RecOffset := RecOffset + pd.size;}
+ end;
+ end;
+
+
+ function TDebugInfoStabs.def_stabstr(def:tdef):pchar;
+
+ function stringdef_stabstr(def:tstringdef):pchar;
+ var
+ slen : aint;
+ bytest,charst,longst : string;
+ begin
+ case def.string_typ of
+ st_shortstring:
+ begin
+ { fix length of openshortstring }
+ slen:=def.len;
+ if slen=0 then
+ slen:=255;
+ charst:=def_stab_number(cchartype.def);
+ bytest:=def_stab_number(u8inttype.def);
+ result:=def_stabstr_evaluate(def,'s$1length:$2,0,8;st:ar$2;1;$3;$4,8,$5;;',
+ [tostr(slen+1),bytest,tostr(slen),charst,tostr(slen*8)]);
+ end;
+ st_longstring:
+ begin
+ charst:=def_stab_number(cchartype.def);
+ bytest:=def_stab_number(u8inttype.def);
+ longst:=def_stab_number(u32inttype.def);
+ result:=def_stabstr_evaluate(def,'s$1length:$2,0,32;dummy:$6,32,8;st:ar$2;1;$3;$4,40,$5;;',
+ [tostr(def.len+5),longst,tostr(def.len),charst,tostr(def.len*8),bytest]);
+ end;
+ st_ansistring:
+ begin
+ { looks like a pchar }
+ charst:=def_stab_number(cchartype.def);
+ result:=strpnew('*'+charst);
+ end;
+ st_widestring:
+ begin
+ { looks like a pwidechar }
+ charst:=def_stab_number(cwidechartype.def);
+ result:=strpnew('*'+charst);
+ end;
+ end;
+ end;
+
+ function enumdef_stabstr(def:tenumdef):pchar;
+ var
+ st : Pchar;
+ p : Tenumsym;
+ s : string;
+ memsize,
+ stl : aint;
+ begin
+ memsize:=memsizeinc;
+ getmem(st,memsize);
+ { we can specify the size with @s<size>; prefix PM }
+ if def.size <> std_param_align then
+ strpcopy(st,'@s'+tostr(def.size*8)+';e')
+ else
+ strpcopy(st,'e');
+ p := tenumsym(def.firstenum);
+ stl:=strlen(st);
+ while assigned(p) do
+ begin
+ s :=p.name+':'+tostr(p.value)+',';
+ { place for the ending ';' also }
+ if (stl+length(s)+1>=memsize) then
+ begin
+ inc(memsize,memsizeinc);
+ reallocmem(st,memsize);
+ end;
+ strpcopy(st+stl,s);
+ inc(stl,length(s));
+ p:=p.nextenum;
+ end;
+ st[stl]:=';';
+ st[stl+1]:=#0;
+ reallocmem(st,stl+2);
+ result:=st;
+ end;
+
+ function orddef_stabstr(def:torddef):pchar;
+ begin
+ if cs_gdb_valgrind in aktglobalswitches then
+ begin
+ case def.typ of
+ uvoid :
+ result:=strpnew(def_stab_number(def));
+ bool8bit,
+ bool16bit,
+ bool32bit :
+ result:=def_stabstr_evaluate(def,'r${numberstring};0;255;',[]);
+ u32bit,
+ s64bit,
+ u64bit :
+ result:=def_stabstr_evaluate(def,'r${numberstring};0;-1;',[]);
+ else
+ result:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low)),tostr(longint(def.high))]);
+ end;
+ end
+ else
+ begin
+ case def.typ of
+ uvoid :
+ result:=strpnew(def_stab_number(def));
+ uchar :
+ result:=strpnew('-20;');
+ uwidechar :
+ result:=strpnew('-30;');
+ bool8bit :
+ result:=strpnew('-21;');
+ bool16bit :
+ result:=strpnew('-22;');
+ bool32bit :
+ result:=strpnew('-23;');
+ u64bit :
+ result:=strpnew('-32;');
+ s64bit :
+ result:=strpnew('-31;');
+ {u32bit : result:=def_stab_number(s32inttype.def)+';0;-1;'); }
+ else
+ result:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low)),tostr(longint(def.high))]);
+ end;
+ end;
+ end;
+
+ function floatdef_stabstr(def:tfloatdef):Pchar;
+ begin
+ case def.typ of
+ s32real,
+ s64real,
+ s80real:
+ result:=def_stabstr_evaluate(def,'r$1;${savesize};0;',[def_stab_number(s32inttype.def)]);
+ s64currency,
+ s64comp:
+ result:=def_stabstr_evaluate(def,'r$1;-${savesize};0;',[def_stab_number(s32inttype.def)]);
+ else
+ internalerror(200509261);
+ end;
+ end;
+
+ function filedef_stabstr(def:tfiledef):pchar;
+ begin
+{$ifdef cpu64bit}
+ result:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$2,64,64;'+
+ '_PRIVATE:ar$1;1;64;$3,128,256;USERDATA:ar$1;1;16;$3,384,128;'+
+ 'NAME:ar$1;0;255;$4,512,2048;;',[def_stab_number(s32inttype.def),
+ def_stab_number(s64inttype.def),
+ def_stab_number(u8inttype.def),
+ def_stab_number(cchartype.def)]);
+{$else cpu64bit}
+ result:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$1,64,32;'+
+ '_PRIVATE:ar$1;1;32;$3,96,256;USERDATA:ar$1;1;16;$2,352,128;'+
+ 'NAME:ar$1;0;255;$3,480,2048;;',[def_stab_number(s32inttype.def),
+ def_stab_number(u8inttype.def),
+ def_stab_number(cchartype.def)]);
+{$endif cpu64bit}
+ end;
+
+ function procdef_stabstr(def:tprocdef):pchar;
+ Var
+ RType : Char;
+ Obj,Info : String;
+ stabsstr : string;
+ p : pchar;
+ begin
+ obj := def.procsym.name;
+ info := '';
+ if (po_global in def.procoptions) then
+ RType := 'F'
+ else
+ RType := 'f';
+ if assigned(def.owner) then
+ begin
+ if (def.owner.symtabletype = objectsymtable) then
+ obj := def.owner.name^+'__'+def.procsym.name;
+ if not(cs_gdb_valgrind in aktglobalswitches) and
+ (def.owner.symtabletype=localsymtable) and
+ assigned(def.owner.defowner) and
+ assigned(tprocdef(def.owner.defowner).procsym) then
+ info := ','+def.procsym.name+','+tprocdef(def.owner.defowner).procsym.name;
+ end;
+ stabsstr:=def.mangledname;
+ getmem(p,length(stabsstr)+255);
+ strpcopy(p,'"'+obj+':'+RType
+ +def_stab_number(def.rettype.def)+info+'",'+tostr(n_function)
+ +',0,'+
+ tostr(def.fileinfo.line)
+ +',');
+ strpcopy(strend(p),stabsstr);
+ result:=strnew(p);
+ freemem(p,length(stabsstr)+255);
+ end;
+
+ function recorddef_stabstr(def:trecorddef):pchar;
+ var
+ state : Trecord_stabgen_state;
+ begin
+ getmem(state.stabstring,memsizeinc);
+ state.staballoc:=memsizeinc;
+ strpcopy(state.stabstring,'s'+tostr(def.size));
+ state.recoffset:=0;
+ state.stabsize:=strlen(state.stabstring);
+ def.symtable.foreach(@field_add_stabstr,@state);
+ state.stabstring[state.stabsize]:=';';
+ state.stabstring[state.stabsize+1]:=#0;
+ reallocmem(state.stabstring,state.stabsize+2);
+ result:=state.stabstring;
+ end;
+
+ function objectdef_stabstr(def:tobjectdef):pchar;
+ var
+ anc : tobjectdef;
+ state :Trecord_stabgen_state;
+ ts : string;
+ begin
+ { Write the invisible pointer for the class? }
+ if (def.objecttype=odt_class) and
+ (not def.writing_class_record_stab) then
+ begin
+ result:=strpnew('*'+def_stab_classnumber(def));
+ exit;
+ end;
+
+ state.staballoc:=memsizeinc;
+ getmem(state.stabstring,state.staballoc);
+ strpcopy(state.stabstring,'s'+tostr(tobjectsymtable(def.symtable).datasize));
+ if assigned(def.childof) then
+ begin
+ {only one ancestor not virtual, public, at base offset 0 }
+ { !1 , 0 2 0 , }
+ strpcopy(strend(state.stabstring),'!1,020,'+def_stab_classnumber(def.childof)+';');
+ end;
+ {virtual table to implement yet}
+ state.recoffset:=0;
+ state.stabsize:=strlen(state.stabstring);
+ def.symtable.foreach(@field_add_stabstr,@state);
+ if (oo_has_vmt in def.objectoptions) then
+ if not assigned(def.childof) or not(oo_has_vmt in def.childof.objectoptions) then
+ begin
+ ts:='$vf'+def_stab_classnumber(def)+':'+def_stab_number(vmtarraytype.def)+','+tostr(def.vmt_offset*8)+';';
+ strpcopy(state.stabstring+state.stabsize,ts);
+ inc(state.stabsize,length(ts));
+ end;
+ def.symtable.foreach(@method_add_stabstr,@state);
+ if (oo_has_vmt in def.objectoptions) then
+ begin
+ anc := def;
+ while assigned(anc.childof) and (oo_has_vmt in anc.childof.objectoptions) do
+ anc := anc.childof;
+ { just in case anc = self }
+ ts:=';~%'+def_stab_classnumber(anc)+';';
+ end
+ else
+ ts:=';';
+ strpcopy(state.stabstring+state.stabsize,ts);
+ inc(state.stabsize,length(ts));
+ reallocmem(state.stabstring,state.stabsize+1);
+ result:=state.stabstring;
+ end;
+
+ begin
+ result:=nil;
+ case def.deftype of
+ stringdef :
+ result:=stringdef_stabstr(tstringdef(def));
+ enumdef :
+ result:=enumdef_stabstr(tenumdef(def));
+ orddef :
+ result:=orddef_stabstr(torddef(def));
+ floatdef :
+ result:=floatdef_stabstr(tfloatdef(def));
+ filedef :
+ result:=filedef_stabstr(tfiledef(def));
+ recorddef :
+ result:=recorddef_stabstr(trecorddef(def));
+ variantdef :
+ result:=def_stabstr_evaluate(def,'formal${numberstring};',[]);
+ pointerdef :
+ result:=strpnew('*'+def_stab_number(tpointerdef(def).pointertype.def));
+ classrefdef :
+ result:=strpnew(def_stab_number(pvmttype.def));
+ setdef :
+ result:=def_stabstr_evaluate(def,'@s$1;S$2',[tostr(def.size*8),def_stab_number(tsetdef(def).elementtype.def)]);
+ formaldef :
+ result:=def_stabstr_evaluate(def,'formal${numberstring};',[]);
+ arraydef :
+ result:=def_stabstr_evaluate(def,'ar$1;$2;$3;$4',[def_stab_number(tarraydef(def).rangetype.def),
+ tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementtype.def)]);
+ procdef :
+ result:=procdef_stabstr(tprocdef(def));
+ procvardef :
+ result:=strpnew('*f'+def_stab_number(tprocvardef(def).rettype.def));
+ objectdef :
+ begin
+ if tobjectdef(def).writing_class_record_stab then
+ result:=objectdef_stabstr(tobjectdef(def))
+ else
+ result:=strpnew('*'+def_stab_classnumber(tobjectdef(def)));
+ end;
+ end;
+ end;
+
+
+ procedure TDebugInfoStabs.write_def_stabstr(list:taasmoutput;def:tdef);
+ var
+ stabchar : string[2];
+ ss,st,su : pchar;
+ begin
+ { procdefs require a different stabs style without type prefix }
+ if def.deftype=procdef then
+ begin
+ st:=def_stabstr(def);
+ { add to list }
+ list.concat(Tai_stab.create(stab_stabs,st));
+ end
+ else
+ begin
+ { type prefix }
+ if def.deftype in tagtypes then
+ stabchar := 'Tt'
+ else
+ stabchar := 't';
+ { Here we maybe generate a type, so we have to use numberstring }
+ if is_class(def) and
+ tobjectdef(def).writing_class_record_stab then
+ st:=def_stabstr_evaluate(def,'"${sym_name}:$1$2=',[stabchar,def_stab_classnumber(tobjectdef(def))])
+ else
+ st:=def_stabstr_evaluate(def,'"${sym_name}:$1$2=',[stabchar,def_stab_number(def)]);
+ ss:=def_stabstr(def);
+ reallocmem(st,strlen(ss)+512);
+ { line info is set to 0 for all defs, because the def can be in an other
+ unit and then the linenumber is invalid in the current sourcefile }
+ su:=def_stabstr_evaluate(def,'",${N_LSYM},0,0,0',[]);
+ strcopy(strecopy(strend(st),ss),su);
+ reallocmem(st,strlen(st)+1);
+ strdispose(ss);
+ strdispose(su);
+ { add to list }
+ list.concat(Tai_stab.create(stab_stabs,st));
+ end;
+ end;
+
+
+ procedure TDebugInfoStabs.field_write_defs(p:Tnamedindexitem;arg:pointer);
+ begin
+ if (Tsym(p).typ=fieldvarsym) and
+ not(sp_static in Tsym(p).symoptions) then
+ insertdef(taasmoutput(arg),tfieldvarsym(p).vartype.def);
+ end;
+
+
+ procedure TDebugInfoStabs.method_write_defs(p :tnamedindexitem;arg:pointer);
+ var
+ pd : tprocdef;
+ begin
+ if tsym(p).typ = procsym then
+ begin
+ pd:=tprocsym(p).first_procdef;
+ insertdef(taasmoutput(arg),pd.rettype.def);
+ end;
+ end;
+
+
+ procedure TDebugInfoStabs.insertdef(list:taasmoutput;def:tdef);
+ var
+ anc : tobjectdef;
+ oldtypesym : tsym;
+// nb : string[12];
+ begin
+ if (def.stab_state in [stab_state_writing,stab_state_written]) then
+ exit;
+ { to avoid infinite loops }
+ def.stab_state := stab_state_writing;
+ { write dependencies first }
+ case def.deftype of
+ stringdef :
+ begin
+ if tstringdef(def).string_typ=st_widestring then
+ insertdef(list,cwidechartype.def)
+ else
+ begin
+ insertdef(list,cchartype.def);
+ insertdef(list,u8inttype.def);
+ end;
+ end;
+ floatdef :
+ insertdef(list,s32inttype.def);
+ filedef :
+ begin
+ insertdef(list,s32inttype.def);
+{$ifdef cpu64bit}
+ insertdef(list,s64inttype.def);
+{$endif cpu64bit}
+ insertdef(list,u8inttype.def);
+ insertdef(list,cchartype.def);
+ end;
+ classrefdef :
+ insertdef(list,pvmttype.def);
+ pointerdef :
+ insertdef(list,tpointerdef(def).pointertype.def);
+ setdef :
+ insertdef(list,tsetdef(def).elementtype.def);
+ procvardef,
+ procdef :
+ insertdef(list,tprocdef(def).rettype.def);
+ arraydef :
+ begin
+ insertdef(list,tarraydef(def).rangetype.def);
+ insertdef(list,tarraydef(def).elementtype.def);
+ end;
+ recorddef :
+ trecorddef(def).symtable.foreach(@field_write_defs,list);
+ objectdef :
+ begin
+ insertdef(list,vmtarraytype.def);
+ { first the parents }
+ anc:=tobjectdef(def);
+ while assigned(anc.childof) do
+ begin
+ anc:=anc.childof;
+ insertdef(list,anc);
+ end;
+ tobjectdef(def).symtable.foreach(@field_write_defs,list);
+ tobjectdef(def).symtable.foreach(@method_write_defs,list);
+ end;
+ end;
+(*
+ { Handle pointerdefs to records and objects to avoid recursion }
+ if (def.deftype=pointerdef) and
+ (tpointerdef(def).pointertype.def.deftype in [recorddef,objectdef]) then
+ begin
+ def.stab_state:=stab_state_used;
+ write_def_stabstr(list,def);
+ {to avoid infinite recursion in record with next-like fields }
+ if tdef(tpointerdef(def).pointertype.def).stab_state=stab_state_writing then
+ begin
+ if assigned(tpointerdef(def).pointertype.def.typesym) then
+ begin
+ if is_class(tpointerdef(def).pointertype.def) then
+ nb:=def_stab_classnumber(tobjectdef(tpointerdef(def).pointertype.def))
+ else
+ nb:=def_stab_number(tpointerdef(def).pointertype.def);
+ list.concat(Tai_stab.create(stab_stabs,def_stabstr_evaluate(
+ def,'"${sym_name}:t${numberstring}=*$1=xs$2:",${N_LSYM},0,0,0',
+ [nb,tpointerdef(def).pointertype.def.typesym.name])));
+ end;
+ def.stab_state:=stab_state_written;
+ end
+ end
+ else
+*)
+ case def.deftype of
+ objectdef :
+ begin
+ { classes require special code to write the record and the invisible pointer }
+ if is_class(def) then
+ begin
+ { Write the record class itself }
+ tobjectdef(def).writing_class_record_stab:=true;
+ write_def_stabstr(list,def);
+ tobjectdef(def).writing_class_record_stab:=false;
+ { Write the invisible pointer class }
+ oldtypesym:=def.typesym;
+ def.typesym:=nil;
+ write_def_stabstr(list,def);
+ def.typesym:=oldtypesym;
+ end
+ else
+ write_def_stabstr(list,def);
+ { VMT symbol }
+ if (oo_has_vmt in tobjectdef(def).objectoptions) and
+ assigned(def.owner) and
+ assigned(def.owner.name) then
+ list.concat(Tai_stab.create(stab_stabs,strpnew('"vmt_'+def.owner.name^+tobjectdef(def).name+':S'+
+ def_stab_number(vmttype.def)+'",'+tostr(N_STSYM)+',0,0,'+tobjectdef(def).vmt_mangledname)));
+ end;
+ procdef :
+ begin
+ { procdefs are handled separatly }
+ end;
+ else
+ write_def_stabstr(list,def);
+ end;
+
+ def.stab_state := stab_state_written;
+ end;
+
+
+ procedure TDebugInfoStabs.write_symtable_defs(list:taasmoutput;st:tsymtable);
+
+ procedure dowritestabs(list:taasmoutput;st:tsymtable);
+ var
+ p : tdef;
+ begin
+ p:=tdef(st.defindex.first);
+ while assigned(p) do
+ begin
+ if (p.stab_state=stab_state_used) then
+ insertdef(list,p);
+ p:=tdef(p.indexnext);
+ end;
+ end;
+
+ var
+ old_writing_def_stabs : boolean;
+ begin
+ case st.symtabletype of
+ staticsymtable :
+ list.concat(tai_comment.Create(strpnew('Defs - Begin Staticsymtable')));
+ globalsymtable :
+ list.concat(tai_comment.Create(strpnew('Defs - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
+ end;
+ old_writing_def_stabs:=writing_def_stabs;
+ writing_def_stabs:=true;
+ dowritestabs(list,st);
+ writing_def_stabs:=old_writing_def_stabs;
+ case st.symtabletype of
+ staticsymtable :
+ list.concat(tai_comment.Create(strpnew('Defs - End Staticsymtable')));
+ globalsymtable :
+ list.concat(tai_comment.Create(strpnew('Defs - End unit '+st.name^+' has index '+tostr(st.moduleid))));
+ end;
+ end;
+
+
+ procedure TDebugInfoStabs.write_procdef(list:taasmoutput;pd:tprocdef);
+ var
+ templist : taasmoutput;
+ stabsendlabel : tasmlabel;
+ mangled_length : longint;
+ p : pchar;
+ hs : string;
+ begin
+ if assigned(pd.procstarttai) then
+ begin
+ templist:=taasmoutput.create;
+ { para types }
+ write_def_stabstr(templist,pd);
+ if assigned(pd.parast) then
+ write_symtable_syms(templist,pd.parast);
+ { local type defs and vars should not be written
+ inside the main proc stab }
+ if assigned(pd.localst) and
+ (pd.localst.symtabletype=localsymtable) then
+ write_symtable_syms(templist,pd.localst);
+ asmlist[al_procedures].insertlistbefore(pd.procstarttai,templist);
+ { end of procedure }
+ objectlibrary.getlabel(stabsendlabel,alt_dbgtype);
+ templist.concat(tai_label.create(stabsendlabel));
+ if assigned(pd.funcretsym) and
+ (tabstractnormalvarsym(pd.funcretsym).refs>0) then
+ begin
+ if tabstractnormalvarsym(pd.funcretsym).localloc.loc=LOC_REFERENCE then
+ begin
+ {$warning Need to add gdb support for ret in param register calling}
+ if paramanager.ret_in_param(pd.rettype.def,pd.proccalloption) then
+ hs:='X*'
+ else
+ hs:='X';
+ templist.concat(Tai_stab.create(stab_stabs,strpnew(
+ '"'+pd.procsym.name+':'+hs+def_stab_number(pd.rettype.def)+'",'+
+ tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(pd.funcretsym).localloc.reference.offset))));
+ if (m_result in aktmodeswitches) then
+ templist.concat(Tai_stab.create(stab_stabs,strpnew(
+ '"RESULT:'+hs+def_stab_number(pd.rettype.def)+'",'+
+ tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(pd.funcretsym).localloc.reference.offset))));
+ end;
+ end;
+ mangled_length:=length(pd.mangledname);
+ getmem(p,2*mangled_length+50);
+ strpcopy(p,'192,0,0,');
+ {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
+ strpcopy(strend(p),pd.mangledname);
+ if (target_info.use_function_relative_addresses) then
+ begin
+ strpcopy(strend(p),'-');
+ {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
+ strpcopy(strend(p),pd.mangledname);
+ end;
+ templist.concat(Tai_stab.Create(stab_stabn,strnew(p)));
+ strpcopy(p,'224,0,0,'+stabsendlabel.name);
+ if (target_info.use_function_relative_addresses) then
+ begin
+ strpcopy(strend(p),'-');
+ {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
+ strpcopy(strend(p),pd.mangledname);
+ end;
+ templist.concat(Tai_stab.Create(stab_stabn,strnew(p)));
+ freemem(p,2*mangled_length+50);
+ asmlist[al_procedures].insertlistbefore(pd.procendtai,templist);
+ templist.free;
+ end;
+ end;
+
+
+{****************************************************************************
+ TSym support
+****************************************************************************}
+
+ function TDebugInfoStabs.sym_var_value(const s:string;arg:pointer):string;
+ var
+ sym : tsym;
+ begin
+ sym:=tsym(arg);
+ result:='';
+ if s='name' then
+ result:=sym.name
+ else if s='mangledname' then
+ result:=sym.mangledname
+ else if s='ownername' then
+ result:=sym.owner.name^
+ else if s='line' then
+ result:=tostr(sym.fileinfo.line)
+ else if s='N_LSYM' then
+ result:=tostr(N_LSYM)
+ else if s='N_LCSYM' then
+ result:=tostr(N_LCSYM)
+ else if s='N_RSYM' then
+ result:=tostr(N_RSYM)
+ else if s='N_TSYM' then
+ result:=tostr(N_TSYM)
+ else if s='N_STSYM' then
+ result:=tostr(N_STSYM)
+ else if s='N_FUNCTION' then
+ result:=tostr(N_FUNCTION)
+ else
+ internalerror(200401152);
+ end;
+
+
+ function TDebugInfoStabs.sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):Pchar;
+ begin
+ result:=string_evaluate(s,@sym_var_value,sym,vars);
+ end;
+
+
+ procedure TDebugInfoStabs.insertsym(list:taasmoutput;sym:tsym);
+
+ function fieldvarsym_stabstr(sym:tfieldvarsym):Pchar;
+ begin
+ result:=nil;
+ if (sym.owner.symtabletype=objectsymtable) and
+ (sp_static in sym.symoptions) then
+ result:=sym_stabstr_evaluate(sym,'"${ownername}__${name}:S$1",${N_LCSYM},0,${line},${mangledname}',
+ [def_stab_number(sym.vartype.def)]);
+ end;
+
+ function globalvarsym_stabstr(sym:tglobalvarsym):Pchar;
+ var
+ st : string;
+ threadvaroffset : string;
+ regidx : Tregisterindex;
+ begin
+ result:=nil;
+ { external symbols can't be resolved at link time, so we
+ can't generate stabs for them }
+ if vo_is_external in sym.varoptions then
+ exit;
+ st:=def_stab_number(sym.vartype.def);
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ regidx:=findreg_by_number(sym.localloc.register);
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
+ { this is the register order for GDB}
+ if regidx<>0 then
+ result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
+ end;
+ else
+ begin
+ if (vo_is_thread_var in sym.varoptions) then
+ threadvaroffset:='+'+tostr(sizeof(aint))
+ else
+ threadvaroffset:='';
+ { Here we used S instead of
+ because with G GDB doesn't look at the address field
+ but searches the same name or with a leading underscore
+ but these names don't exist in pascal !}
+ st:='S'+st;
+ result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_LCSYM},0,${line},${mangledname}$2',[st,threadvaroffset]);
+ end;
+ end;
+ end;
+
+ function localvarsym_stabstr(sym:tlocalvarsym):Pchar;
+ var
+ st : string;
+ regidx : Tregisterindex;
+ begin
+ result:=nil;
+ { There is no space allocated for not referenced locals }
+ if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
+ exit;
+
+ st:=def_stab_number(sym.vartype.def);
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ regidx:=findreg_by_number(sym.localloc.register);
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
+ { this is the register order for GDB}
+ if regidx<>0 then
+ result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
+ end;
+ LOC_REFERENCE :
+ { offset to ebp => will not work if the framepointer is esp
+ so some optimizing will make things harder to debug }
+ result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[st,tostr(sym.localloc.reference.offset)])
+ else
+ internalerror(2003091814);
+ end;
+ end;
+
+ function paravarsym_stabstr(sym:tparavarsym):Pchar;
+ var
+ st : string;
+ regidx : Tregisterindex;
+ c : char;
+ begin
+ result:=nil;
+ { set loc to LOC_REFERENCE to get somewhat usable debugging info for -Or }
+ { while stabs aren't adapted for regvars yet }
+ if (vo_is_self in sym.varoptions) then
+ begin
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ regidx:=findreg_by_number(sym.localloc.register);
+ LOC_REFERENCE: ;
+ else
+ internalerror(2003091815);
+ end;
+ if (po_classmethod in tabstractprocdef(sym.owner.defowner).procoptions) or
+ (po_staticmethod in tabstractprocdef(sym.owner.defowner).procoptions) then
+ begin
+ if (sym.localloc.loc=LOC_REFERENCE) then
+ result:=sym_stabstr_evaluate(sym,'"pvmt:p$1",${N_TSYM},0,0,$2',
+ [def_stab_number(pvmttype.def),tostr(sym.localloc.reference.offset)]);
+ (* else
+ result:=sym_stabstr_evaluate(sym,'"pvmt:r$1",${N_RSYM},0,0,$2',
+ [def_stab_number(pvmttype.def),tostr(regstabs_table[regidx])]) *)
+ end
+ else
+ begin
+ if not(is_class(tprocdef(sym.owner.defowner)._class)) then
+ c:='v'
+ else
+ c:='p';
+ if (sym.localloc.loc=LOC_REFERENCE) then
+ result:=sym_stabstr_evaluate(sym,'"$$t:$1",${N_TSYM},0,0,$2',
+ [c+def_stab_number(tprocdef(sym.owner.defowner)._class),tostr(sym.localloc.reference.offset)]);
+ (* else
+ result:=sym_stabstr_evaluate(sym,'"$$t:r$1",${N_RSYM},0,0,$2',
+ [c+def_stab_number(tprocdef(sym.owner.defowner)._class),tostr(regstabs_table[regidx])]); *)
+ end;
+ end
+ else
+ begin
+ st:=def_stab_number(sym.vartype.def);
+
+ if paramanager.push_addr_param(sym.varspez,sym.vartype.def,tprocdef(sym.owner.defowner).proccalloption) and
+ not(vo_has_local_copy in sym.varoptions) and
+ not is_open_string(sym.vartype.def) then
+ st := 'v'+st { should be 'i' but 'i' doesn't work }
+ else
+ st := 'p'+st;
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ regidx:=findreg_by_number(sym.localloc.register);
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
+ { this is the register order for GDB}
+ if regidx<>0 then
+ result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(longint(regstabs_table[regidx]))]);
+ end;
+ LOC_REFERENCE :
+ { offset to ebp => will not work if the framepointer is esp
+ so some optimizing will make things harder to debug }
+ result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[st,tostr(sym.localloc.reference.offset)])
+ else
+ internalerror(2003091814);
+ end;
+ end;
+ end;
+
+ function constsym_stabstr(sym:tconstsym):Pchar;
+ var
+ st : string;
+ begin
+ case sym.consttyp of
+ conststring:
+ begin
+ if sym.value.len<200 then
+ st:='s'''+backspace_quote(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']),['"','\',#10,#13])+''''
+ else
+ st:='<constant string too long>';
+ end;
+ constord:
+ st:='i'+tostr(sym.value.valueord);
+ constpointer:
+ st:='i'+tostr(sym.value.valueordptr);
+ constreal:
+ begin
+ system.str(pbestreal(sym.value.valueptr)^,st);
+ st := 'r'+st;
+ end;
+ else
+ begin
+ { if we don't know just put zero !! }
+ st:='i0';
+ end;
+ end;
+ { valgrind does not support constants }
+ if cs_gdb_valgrind in aktglobalswitches then
+ result:=nil
+ else
+ result:=sym_stabstr_evaluate(sym,'"${name}:c=$1;",${N_FUNCTION},0,${line},0',[st]);
+ end;
+
+ function typesym_stabstr(sym:ttypesym) : pchar;
+ var
+ stabchar : string[2];
+ begin
+ result:=nil;
+ if not assigned(sym.restype.def) then
+ internalerror(200509262);
+ if sym.restype.def.deftype in tagtypes then
+ stabchar:='Tt'
+ else
+ stabchar:='t';
+ result:=sym_stabstr_evaluate(sym,'"${name}:$1$2",${N_LSYM},0,${line},0',[stabchar,def_stab_number(sym.restype.def)]);
+ end;
+
+ function procsym_stabstr(sym:tprocsym) : pchar;
+ var
+ i : longint;
+ begin
+ result:=nil;
+ for i:=1 to sym.procdef_count do
+ write_procdef(list,sym.procdef[i]);
+ end;
+
+ var
+ stabstr : Pchar;
+ begin
+ stabstr:=nil;
+ case sym.typ of
+ labelsym :
+ stabstr:=sym_stabstr_evaluate(sym,'"${name}",${N_LSYM},0,${line},0',[]);
+ fieldvarsym :
+ stabstr:=fieldvarsym_stabstr(tfieldvarsym(sym));
+ globalvarsym :
+ stabstr:=globalvarsym_stabstr(tglobalvarsym(sym));
+ localvarsym :
+ stabstr:=localvarsym_stabstr(tlocalvarsym(sym));
+ paravarsym :
+ stabstr:=paravarsym_stabstr(tparavarsym(sym));
+ typedconstsym :
+ stabstr:=sym_stabstr_evaluate(sym,'"${name}:S$1",${N_STSYM},0,${line},${mangledname}',
+ [def_stab_number(ttypedconstsym(sym).typedconsttype.def)]);
+ constsym :
+ stabstr:=constsym_stabstr(tconstsym(sym));
+ typesym :
+ stabstr:=typesym_stabstr(ttypesym(sym));
+ procsym :
+ stabstr:=procsym_stabstr(tprocsym(sym));
+ end;
+ if stabstr<>nil then
+ list.concat(Tai_stab.create(stab_stabs,stabstr));
+ { For object types write also the symtable entries }
+ if (sym.typ=typesym) and (ttypesym(sym).restype.def.deftype=objectdef) then
+ write_symtable_syms(list,tobjectdef(ttypesym(sym).restype.def).symtable);
+ sym.isstabwritten:=true;
+ end;
+
+
+ procedure TDebugInfoStabs.write_symtable_syms(list:taasmoutput;st:tsymtable);
+ var
+ p : tsym;
+ begin
+ case st.symtabletype of
+ staticsymtable :
+ list.concat(tai_comment.Create(strpnew('Syms - Begin Staticsymtable')));
+ globalsymtable :
+ list.concat(tai_comment.Create(strpnew('Syms - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
+ end;
+ p:=tsym(st.symindex.first);
+ while assigned(p) do
+ begin
+ if (not p.isstabwritten) then
+ insertsym(list,p);
+ p:=tsym(p.indexnext);
+ end;
+ case st.symtabletype of
+ staticsymtable :
+ list.concat(tai_comment.Create(strpnew('Syms - End Staticsymtable')));
+ globalsymtable :
+ list.concat(tai_comment.Create(strpnew('Syms - End unit '+st.name^+' has index '+tostr(st.moduleid))));
+ end;
+ end;
+
+{****************************************************************************
+ Proc/Module support
+****************************************************************************}
+
+ procedure tdebuginfostabs.inserttypeinfo;
+
+ procedure reset_unit_type_info;
+ var
+ hp : tmodule;
+ begin
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ hp.is_stab_written:=false;
+ hp:=tmodule(hp.next);
+ end;
+ end;
+
+ procedure write_used_unit_type_info(list:taasmoutput;hp:tmodule);
+ var
+ pu : tused_unit;
+ begin
+ pu:=tused_unit(hp.used_units.first);
+ while assigned(pu) do
+ begin
+ if not pu.u.is_stab_written then
+ begin
+ { prevent infinte loop for circular dependencies }
+ pu.u.is_stab_written:=true;
+ { write type info from used units, use a depth first
+ strategy to reduce the recursion in writing all
+ dependent stabs }
+ write_used_unit_type_info(list,pu.u);
+ if assigned(pu.u.globalsymtable) then
+ write_symtable_defs(list,pu.u.globalsymtable);
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ end;
+
+ var
+ stabsvarlist,
+ stabstypelist : taasmoutput;
+ storefilepos : tfileposinfo;
+ st : tsymtable;
+ i : longint;
+ begin
+ storefilepos:=aktfilepos;
+ aktfilepos:=current_module.mainfilepos;
+
+ global_stab_number:=0;
+ defnumberlist:=tlist.create;
+ stabsvarlist:=taasmoutput.create;
+ stabstypelist:=taasmoutput.create;
+
+ { include symbol that will be referenced from the main to be sure to
+ include this debuginfo .o file }
+ if current_module.is_unit then
+ begin
+ current_module.flags:=current_module.flags or uf_has_debuginfo;
+ st:=current_module.globalsymtable;
+ end
+ else
+ st:=current_module.localsymtable;
+ new_section(asmlist[al_stabs],sec_data,st.name^,0);
+ asmlist[al_stabs].concat(tai_symbol.Createname_global(make_mangledname('DEBUGINFO',st,''),AT_DATA,0));
+
+ { first write all global/local symbols. This will flag all required tdefs }
+ if assigned(current_module.globalsymtable) then
+ write_symtable_syms(stabsvarlist,current_module.globalsymtable);
+ if assigned(current_module.localsymtable) then
+ write_symtable_syms(stabsvarlist,current_module.localsymtable);
+
+ { reset unit type info flag }
+ reset_unit_type_info;
+
+ { write used types from the used units }
+ write_used_unit_type_info(stabstypelist,current_module);
+ { last write the types from this unit }
+ if assigned(current_module.globalsymtable) then
+ write_symtable_defs(stabstypelist,current_module.globalsymtable);
+ if assigned(current_module.localsymtable) then
+ write_symtable_defs(stabstypelist,current_module.localsymtable);
+
+ asmlist[al_stabs].concatlist(stabstypelist);
+ asmlist[al_stabs].concatlist(stabsvarlist);
+
+ { reset stab numbers }
+ for i:=0 to defnumberlist.count-1 do
+ begin
+ if assigned(defnumberlist[i]) then
+ begin
+ tdef(defnumberlist[i]).stab_number:=0;
+ tdef(defnumberlist[i]).stab_state:=stab_state_unused;
+ end;
+ end;
+
+ defnumberlist.free;
+ defnumberlist:=nil;
+
+ stabsvarlist.free;
+ stabstypelist.free;
+ aktfilepos:=storefilepos;
+ end;
+
+
+ procedure tdebuginfostabs.insertlineinfo(list:taasmoutput);
+ var
+ currfileinfo,
+ lastfileinfo : tfileposinfo;
+ currfuncname : pstring;
+ currsectype : tasmsectiontype;
+ hlabel : tasmlabel;
+ hp : tai;
+ infile : tinputfile;
+ begin
+ FillChar(lastfileinfo,sizeof(lastfileinfo),0);
+ currfuncname:=nil;
+ currsectype:=sec_code;
+ hp:=Tai(list.first);
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_section :
+ currsectype:=tai_section(hp).sectype;
+ ait_function_name :
+ currfuncname:=tai_function_name(hp).funcname;
+ ait_force_line :
+ lastfileinfo.line:=-1;
+ end;
+
+ if (currsectype=sec_code) and
+ (hp.typ=ait_instruction) then
+ begin
+ currfileinfo:=tailineinfo(hp).fileinfo;
+ { file changed ? (must be before line info) }
+ if (currfileinfo.fileindex<>0) and
+ (lastfileinfo.fileindex<>currfileinfo.fileindex) then
+ begin
+ infile:=current_module.sourcefiles.get_file(currfileinfo.fileindex);
+ if assigned(infile) then
+ begin
+ objectlibrary.getlabel(hlabel,alt_dbgfile);
+ { emit stabs }
+ if (infile.path^<>'') then
+ list.insertbefore(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(infile.path^,false))+'",'+tostr(n_includefile)+
+ ',0,0,'+hlabel.name),hp);
+ list.insertbefore(Tai_stab.Create_str(stab_stabs,'"'+FixFileName(infile.name^)+'",'+tostr(n_includefile)+
+ ',0,0,'+hlabel.name),hp);
+ list.insertbefore(tai_label.create(hlabel),hp);
+ { force new line info }
+ lastfileinfo.line:=-1;
+ end;
+ end;
+
+ { line changed ? }
+ if (lastfileinfo.line<>currfileinfo.line) and (currfileinfo.line<>0) then
+ begin
+ if assigned(currfuncname) and
+ (target_info.use_function_relative_addresses) then
+ begin
+ objectlibrary.getlabel(hlabel,alt_dbgline);
+ list.insertbefore(Tai_stab.Create_str(stab_stabn,tostr(n_textline)+',0,'+tostr(currfileinfo.line)+','+
+ hlabel.name+' - '+{$IFDEF POWERPC64}'.'+{$ENDIF POWERPC64}currfuncname^),hp);
+ list.insertbefore(tai_label.create(hlabel),hp);
+ end
+ else
+ list.insertbefore(Tai_stab.Create_str(stab_stabd,tostr(n_textline)+',0,'+tostr(currfileinfo.line)),hp);
+ end;
+ lastfileinfo:=currfileinfo;
+ end;
+
+ hp:=tai(hp.next);
+ end;
+ end;
+
+
+ procedure tdebuginfostabs.insertmoduleinfo;
+ var
+ hlabel : tasmlabel;
+ infile : tinputfile;
+ templist : taasmoutput;
+ begin
+ { emit main source n_sourcefile for start of module }
+ objectlibrary.getlabel(hlabel,alt_dbgfile);
+ infile:=current_module.sourcefiles.get_file(1);
+ templist:=taasmoutput.create;
+ new_section(templist,sec_code,'',0);
+ if (infile.path^<>'') then
+ templist.concat(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(infile.path^,false))+'",'+tostr(n_sourcefile)+
+ ',0,0,'+hlabel.name));
+ templist.concat(Tai_stab.Create_str(stab_stabs,'"'+FixFileName(infile.name^)+'",'+tostr(n_sourcefile)+
+ ',0,0,'+hlabel.name));
+ templist.concat(tai_label.create(hlabel));
+ asmlist[al_stabsstart].insertlist(templist);
+ templist.free;
+ { emit empty n_sourcefile for end of module }
+ objectlibrary.getlabel(hlabel,alt_dbgfile);
+ templist:=taasmoutput.create;
+ new_section(templist,sec_code,'',0);
+ templist.concat(Tai_stab.Create_str(stab_stabs,'"",'+tostr(n_sourcefile)+',0,0,'+hlabel.name));
+ templist.concat(tai_label.create(hlabel));
+ asmlist[al_stabsend].insertlist(templist);
+ templist.free;
+ end;
+
+
+ procedure tdebuginfostabs.referencesections(list:taasmoutput);
+ var
+ hp : tused_unit;
+ begin
+ { Reference all DEBUGINFO sections from the main .text section }
+ if (target_info.system <> system_powerpc_macos) then
+ begin
+ { include reference to all debuginfo sections of used units }
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ If (hp.u.flags and uf_has_debuginfo)=uf_has_debuginfo then
+ list.concat(Tai_const.Createname(make_mangledname('DEBUGINFO',hp.u.globalsymtable,''),AT_DATA,0));
+ hp:=tused_unit(hp.next);
+ end;
+ { include reference to debuginfo for this program }
+ list.concat(Tai_const.Createname(make_mangledname('DEBUGINFO',current_module.localsymtable,''),AT_DATA,0));
+ end;
+ end;
+
+
+ const
+ dbg_stabs_info : tdbginfo =
+ (
+ id : dbg_stabs;
+ idtxt : 'STABS';
+ );
+
+initialization
+ RegisterDebugInfo(dbg_stabs_info,TDebugInfoStabs);
+end.
diff --git a/compiler/defcmp.pas b/compiler/defcmp.pas
new file mode 100644
index 0000000000..8117ef0ea4
--- /dev/null
+++ b/compiler/defcmp.pas
@@ -0,0 +1,1489 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Compare definitions and parameter lists
+
+ 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 defcmp;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,
+ node,
+ symconst,symtype,symdef;
+
+ type
+ { if acp is cp_all the var const or nothing are considered equal }
+ tcompare_paras_type = ( cp_none, cp_value_equal_const, cp_all,cp_procvar);
+ tcompare_paras_option = (cpo_allowdefaults,cpo_ignorehidden,cpo_allowconvert,cpo_comparedefaultvalue);
+ tcompare_paras_options = set of tcompare_paras_option;
+
+ tcompare_defs_option = (cdo_internal,cdo_explicit,cdo_check_operator,cdo_allow_variant);
+ tcompare_defs_options = set of tcompare_defs_option;
+
+ tconverttype = (tc_none,
+ tc_equal,
+ tc_not_possible,
+ tc_string_2_string,
+ tc_char_2_string,
+ tc_char_2_chararray,
+ tc_pchar_2_string,
+ tc_cchar_2_pchar,
+ tc_cstring_2_pchar,
+ tc_cstring_2_int,
+ tc_ansistring_2_pchar,
+ tc_string_2_chararray,
+ tc_chararray_2_string,
+ tc_array_2_pointer,
+ tc_pointer_2_array,
+ tc_int_2_int,
+ tc_int_2_bool,
+ tc_bool_2_bool,
+ tc_bool_2_int,
+ tc_real_2_real,
+ tc_int_2_real,
+ tc_real_2_currency,
+ tc_proc_2_procvar,
+ tc_arrayconstructor_2_set,
+ tc_load_smallset,
+ tc_cord_2_pointer,
+ tc_intf_2_string,
+ tc_intf_2_guid,
+ tc_class_2_intf,
+ tc_char_2_char,
+ tc_normal_2_smallset,
+ tc_dynarray_2_openarray,
+ tc_pwchar_2_string,
+ tc_variant_2_dynarray,
+ tc_dynarray_2_variant,
+ tc_variant_2_enum,
+ tc_enum_2_variant,
+ tc_interface_2_variant,
+ tc_variant_2_interface,
+ tc_array_2_dynarray
+ );
+
+ function compare_defs_ext(def_from,def_to : tdef;
+ fromtreetype : tnodetype;
+ var doconv : tconverttype;
+ var operatorpd : tprocdef;
+ cdoptions:tcompare_defs_options):tequaltype;
+
+ { Returns if the type def_from can be converted to def_to or if both types are equal }
+ function compare_defs(def_from,def_to:tdef;fromtreetype:tnodetype):tequaltype;
+
+ { Returns true, if def1 and def2 are semantically the same }
+ function equal_defs(def_from,def_to:tdef):boolean;
+
+ { Checks for type compatibility (subgroups of type)
+ used for case statements... probably missing stuff
+ to use on other types }
+ function is_subequal(def1, def2: tdef): boolean;
+
+ {# true, if two parameter lists are equal
+ if acp is cp_none, all have to match exactly
+ if acp is cp_value_equal_const call by value
+ and call by const parameter are assumed as
+ equal
+ allowdefaults indicates if default value parameters
+ are allowed (in this case, the search order will first
+ search for a routine with default parameters, before
+ searching for the same definition with no parameters)
+ }
+ function compare_paras(para1,para2 : tlist; acp : tcompare_paras_type; cpoptions: tcompare_paras_options):tequaltype;
+
+ { True if a function can be assigned to a procvar }
+ { changed first argument type to pabstractprocdef so that it can also be }
+ { used to test compatibility between two pprocvardefs (JM) }
+ function proc_to_procvar_equal(def1:tabstractprocdef;def2:tprocvardef):tequaltype;
+
+
+implementation
+
+ uses
+ verbose,systems,
+ symtable,symsym,
+ defutil,symutil;
+
+
+ function compare_defs_ext(def_from,def_to : tdef;
+ fromtreetype : tnodetype;
+ var doconv : tconverttype;
+ var operatorpd : tprocdef;
+ cdoptions:tcompare_defs_options):tequaltype;
+
+ { Tbasetype:
+ uvoid,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit,
+ bool8bit,bool16bit,bool32bit,
+ uchar,uwidechar }
+
+ type
+ tbasedef=(bvoid,bchar,bint,bbool);
+ const
+ basedeftbl:array[tbasetype] of tbasedef =
+ (bvoid,
+ bint,bint,bint,bint,
+ bint,bint,bint,bint,
+ bbool,bbool,bbool,
+ bchar,bchar,bint);
+
+ basedefconvertsimplicit : array[tbasedef,tbasedef] of tconverttype =
+ { void, char, int, bool }
+ ((tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible),
+ (tc_not_possible,tc_char_2_char,tc_not_possible,tc_not_possible),
+ (tc_not_possible,tc_not_possible,tc_int_2_int,tc_not_possible),
+ (tc_not_possible,tc_not_possible,tc_not_possible,tc_bool_2_bool));
+ basedefconvertsexplicit : array[tbasedef,tbasedef] of tconverttype =
+ { void, char, int, bool }
+ ((tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible),
+ (tc_not_possible,tc_char_2_char,tc_int_2_int,tc_int_2_bool),
+ (tc_not_possible,tc_int_2_int,tc_int_2_int,tc_int_2_bool),
+ (tc_not_possible,tc_bool_2_int,tc_bool_2_int,tc_bool_2_bool));
+
+ var
+ subeq,eq : tequaltype;
+ hd1,hd2 : tdef;
+ hct : tconverttype;
+ hd3 : tobjectdef;
+ hpd : tprocdef;
+ begin
+ eq:=te_incompatible;
+ doconv:=tc_not_possible;
+
+ { safety check }
+ if not(assigned(def_from) and assigned(def_to)) then
+ begin
+ compare_defs_ext:=te_incompatible;
+ exit;
+ end;
+
+ { same def? then we've an exact match }
+ if def_from=def_to then
+ begin
+ doconv:=tc_equal;
+ compare_defs_ext:=te_exact;
+ exit;
+ end;
+
+ { we walk the wanted (def_to) types and check then the def_from
+ types if there is a conversion possible }
+ case def_to.deftype of
+ orddef :
+ begin
+ case def_from.deftype of
+ orddef :
+ begin
+ if (torddef(def_from).typ=torddef(def_to).typ) then
+ begin
+ case torddef(def_from).typ of
+ uchar,uwidechar,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit:
+ begin
+ if (torddef(def_from).low=torddef(def_to).low) and
+ (torddef(def_from).high=torddef(def_to).high) then
+ eq:=te_equal
+ else
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ uvoid,
+ bool8bit,bool16bit,bool32bit:
+ eq:=te_equal;
+ else
+ internalerror(200210061);
+ end;
+ end
+ else
+ begin
+ if cdo_explicit in cdoptions then
+ doconv:=basedefconvertsexplicit[basedeftbl[torddef(def_from).typ],basedeftbl[torddef(def_to).typ]]
+ else
+ doconv:=basedefconvertsimplicit[basedeftbl[torddef(def_from).typ],basedeftbl[torddef(def_to).typ]];
+ if (doconv=tc_not_possible) then
+ eq:=te_incompatible
+ else
+ { "punish" bad type conversions :) (JM) }
+ if (not is_in_limit(def_from,def_to)) and
+ (def_from.size > def_to.size) then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l1;
+ end;
+ end;
+ enumdef :
+ begin
+ { needed for char(enum) }
+ if cdo_explicit in cdoptions then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ floatdef :
+ begin
+ if is_currency(def_to) then
+ begin
+ doconv:=tc_real_2_currency;
+ eq:=te_convert_l2;
+ end;
+ end;
+ classrefdef,
+ procvardef,
+ pointerdef :
+ begin
+ if cdo_explicit in cdoptions then
+ begin
+ eq:=te_convert_l1;
+ if (fromtreetype=niln) then
+ begin
+ { will be handled by the constant folding }
+ doconv:=tc_equal;
+ end
+ else
+ doconv:=tc_int_2_int;
+ end;
+ end;
+ arraydef :
+ begin
+ if (m_mac in aktmodeswitches) and
+ (fromtreetype=stringconstn) then
+ begin
+ eq:=te_convert_l3;
+ doconv:=tc_cstring_2_int;
+ end;
+ end;
+ end;
+ end;
+
+ stringdef :
+ begin
+ case def_from.deftype of
+ stringdef :
+ begin
+ { Constant string }
+ if (fromtreetype=stringconstn) then
+ begin
+ { we can change the stringconst node }
+ if (tstringdef(def_from).string_typ=st_conststring) or
+ (tstringdef(def_from).string_typ=tstringdef(def_to).string_typ) then
+ eq:=te_equal
+ else
+ begin
+ doconv:=tc_string_2_string;
+ { Don't prefer conversions from widestring to a
+ normal string as we can loose information }
+ if tstringdef(def_from).string_typ=st_widestring then
+ eq:=te_convert_l3
+ else if tstringdef(def_to).string_typ=st_widestring then
+ eq:=te_convert_l2
+ else
+ eq:=te_equal;
+ end;
+ end
+ else
+ { Same string type, for shortstrings also the length must match }
+ if (tstringdef(def_from).string_typ=tstringdef(def_to).string_typ) and
+ ((tstringdef(def_from).string_typ<>st_shortstring) or
+ (tstringdef(def_from).len=tstringdef(def_to).len)) then
+ eq:=te_equal
+ else
+ begin
+ doconv:=tc_string_2_string;
+ case tstringdef(def_from).string_typ of
+ st_widestring :
+ begin
+ { Prefer conversions to ansistring }
+ if tstringdef(def_to).string_typ=st_ansistring then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l3;
+ end;
+ st_shortstring :
+ begin
+ { Prefer shortstrings of different length or conversions
+ from shortstring to ansistring }
+ if (tstringdef(def_to).string_typ=st_shortstring) then
+ eq:=te_convert_l1
+ else if tstringdef(def_to).string_typ=st_ansistring then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l3;
+ end;
+ st_ansistring :
+ begin
+ { Prefer conversion to widestrings }
+ if (tstringdef(def_to).string_typ=st_widestring) then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l3;
+ end;
+ end;
+ end;
+ end;
+ orddef :
+ begin
+ { char to string}
+ if is_char(def_from) or
+ is_widechar(def_from) then
+ begin
+ doconv:=tc_char_2_string;
+ eq:=te_convert_l1;
+ end;
+ end;
+ arraydef :
+ begin
+ { array of char to string, the length check is done by the firstpass of this node }
+ if is_chararray(def_from) or is_open_chararray(def_from) then
+ begin
+ { "Untyped" stringconstn is an array of char }
+ if fromtreetype=stringconstn then
+ begin
+ doconv:=tc_string_2_string;
+ { prefered string type depends on the $H switch }
+ if not(cs_ansistrings in aktlocalswitches) and
+ (tstringdef(def_to).string_typ=st_shortstring) then
+ eq:=te_equal
+ else if (cs_ansistrings in aktlocalswitches) and
+ (tstringdef(def_to).string_typ=st_ansistring) then
+ eq:=te_equal
+ else if tstringdef(def_to).string_typ=st_widestring then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l1;
+ end
+ else
+ begin
+ doconv:=tc_chararray_2_string;
+ if is_open_array(def_from) then
+ begin
+ if is_ansistring(def_to) then
+ eq:=te_convert_l1
+ else if is_widestring(def_to) then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l2;
+ end
+ else
+ begin
+ if is_shortstring(def_to) then
+ begin
+ { Only compatible with arrays that fit
+ smaller than 255 chars }
+ if (def_from.size <= 255) then
+ eq:=te_convert_l1;
+ end
+ else if is_ansistring(def_to) then
+ begin
+ if (def_from.size > 255) then
+ eq:=te_convert_l1
+ else
+ eq:=te_convert_l2;
+ end
+ else if is_widestring(def_to) then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l2;
+ end;
+ end;
+ end
+ else
+ { array of widechar to string, the length check is done by the firstpass of this node }
+ if is_widechararray(def_from) or is_open_widechararray(def_from) then
+ begin
+ doconv:=tc_chararray_2_string;
+ if is_widestring(def_to) then
+ eq:=te_convert_l1
+ else
+ { size of widechar array is double due the sizeof a widechar }
+ if not(is_shortstring(def_to) and (def_from.size>255*sizeof(widechar))) then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l2;
+ end;
+ end;
+ pointerdef :
+ begin
+ { pchar can be assigned to short/ansistrings,
+ but not in tp7 compatible mode }
+ if not(m_tp7 in aktmodeswitches) then
+ begin
+ if is_pchar(def_from) then
+ begin
+ doconv:=tc_pchar_2_string;
+ { prefer ansistrings because pchars can overflow shortstrings, }
+ { but only if ansistrings are the default (JM) }
+ if (is_shortstring(def_to) and
+ not(cs_ansistrings in aktlocalswitches)) or
+ (is_ansistring(def_to) and
+ (cs_ansistrings in aktlocalswitches)) then
+ eq:=te_convert_l1
+ else
+ eq:=te_convert_l2;
+ end
+ else if is_pwidechar(def_from) then
+ begin
+ doconv:=tc_pwchar_2_string;
+ if is_widestring(def_to) then
+ eq:=te_convert_l1
+ else
+ eq:=te_convert_l3;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ floatdef :
+ begin
+ case def_from.deftype of
+ orddef :
+ begin { ordinal to real }
+ if is_integer(def_from) or
+ (is_currency(def_from) and
+ (s64currencytype.def.deftype = floatdef)) then
+ begin
+ doconv:=tc_int_2_real;
+ eq:=te_convert_l1;
+ end
+ else if is_currency(def_from)
+ { and (s64currencytype.def.deftype = orddef)) } then
+ begin
+ { prefer conversion to orddef in this case, unless }
+ { the orddef < currency (then it will get convert l3, }
+ { and conversion to float is favoured) }
+ doconv:=tc_int_2_real;
+ eq:=te_convert_l2;
+ end;
+ end;
+ floatdef :
+ begin
+ if tfloatdef(def_from).typ=tfloatdef(def_to).typ then
+ eq:=te_equal
+ else
+ begin
+ if (fromtreetype=realconstn) or
+ not((cdo_explicit in cdoptions) and
+ (m_delphi in aktmodeswitches)) then
+ begin
+ doconv:=tc_real_2_real;
+ { do we loose precision? }
+ if def_to.size<def_from.size then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ enumdef :
+ begin
+ case def_from.deftype of
+ enumdef :
+ begin
+ if cdo_explicit in cdoptions then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_int_2_int;
+ end
+ else
+ begin
+ hd1:=def_from;
+ while assigned(tenumdef(hd1).basedef) do
+ hd1:=tenumdef(hd1).basedef;
+ hd2:=def_to;
+ while assigned(tenumdef(hd2).basedef) do
+ hd2:=tenumdef(hd2).basedef;
+ if (hd1=hd2) then
+ begin
+ eq:=te_convert_l1;
+ { because of packenum they can have different sizes! (JM) }
+ doconv:=tc_int_2_int;
+ end
+ else
+ begin
+ { assignment of an enum symbol to an unique type? }
+ if (fromtreetype=ordconstn) and
+ (tenumsym(tenumdef(hd1).firstenum)=tenumsym(tenumdef(hd2).firstenum)) then
+ begin
+ { because of packenum they can have different sizes! (JM) }
+ eq:=te_convert_l1;
+ doconv:=tc_int_2_int;
+ end;
+ end;
+ end;
+ end;
+ orddef :
+ begin
+ if cdo_explicit in cdoptions then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_int_2_int;
+ end;
+ end;
+ variantdef :
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_variant_2_enum;
+ end;
+ pointerdef :
+ begin
+ { ugly, but delphi allows it }
+ if (cdo_explicit in cdoptions) and
+ (m_delphi in aktmodeswitches) and
+ (eq=te_incompatible) then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+
+ arraydef :
+ begin
+ { open array is also compatible with a single element of its base type }
+ if is_open_array(def_to) and
+ equal_defs(def_from,tarraydef(def_to).elementtype.def) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ begin
+ case def_from.deftype of
+ arraydef :
+ begin
+ { to dynamic array }
+ if is_dynamic_array(def_to) then
+ begin
+ if equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
+ begin
+ { dynamic array -> dynamic array }
+ if is_dynamic_array(def_from) then
+ eq:=te_equal
+ { fpc modes only: array -> dyn. array }
+ else if (aktmodeswitches*[m_objfpc,m_fpc]<>[]) and
+ not(is_special_array(def_from)) and
+ is_zero_based_array(def_from) then
+ begin
+ eq:=te_convert_l2;
+ doconv:=tc_array_2_dynarray;
+ end;
+ end
+ end
+ else
+ { to open array }
+ if is_open_array(def_to) then
+ begin
+ { array constructor -> open array }
+ if is_array_constructor(def_from) then
+ begin
+ if is_void(tarraydef(def_from).elementtype.def) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ begin
+ subeq:=compare_defs_ext(tarraydef(def_from).elementtype.def,
+ tarraydef(def_to).elementtype.def,
+ arrayconstructorn,hct,hpd,[cdo_check_operator]);
+ if (subeq>=te_equal) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ if (subeq>te_incompatible) then
+ begin
+ doconv:=hct;
+ eq:=te_convert_l2;
+ end;
+ end;
+ end
+ else
+ { dynamic array -> open array }
+ if is_dynamic_array(def_from) and
+ equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
+ begin
+ doconv:=tc_dynarray_2_openarray;
+ eq:=te_convert_l2;
+ end
+ else
+ { array -> open array }
+ if equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
+ eq:=te_equal;
+ end
+ else
+ { to array of const }
+ if is_array_of_const(def_to) then
+ begin
+ if is_array_of_const(def_from) or
+ is_array_constructor(def_from) then
+ begin
+ eq:=te_equal;
+ end
+ else
+ { array of tvarrec -> array of const }
+ if equal_defs(tarraydef(def_to).elementtype.def,tarraydef(def_from).elementtype.def) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end
+ else
+ { to array of char, from "Untyped" stringconstn (array of char) }
+ if (fromtreetype=stringconstn) and
+ (is_chararray(def_to) or
+ is_widechararray(def_to)) then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_string_2_chararray;
+ end
+ else
+ { other arrays }
+ begin
+ { open array -> array }
+ if is_open_array(def_from) and
+ equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
+ begin
+ eq:=te_equal
+ end
+ else
+ { array -> array }
+ if not(m_tp7 in aktmodeswitches) and
+ not(m_delphi in aktmodeswitches) and
+ (tarraydef(def_from).lowrange=tarraydef(def_to).lowrange) and
+ (tarraydef(def_from).highrange=tarraydef(def_to).highrange) and
+ equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) and
+ equal_defs(tarraydef(def_from).rangetype.def,tarraydef(def_to).rangetype.def) then
+ begin
+ eq:=te_equal
+ end;
+ end;
+ end;
+ pointerdef :
+ begin
+ { nil and voidpointers are compatible with dyn. arrays }
+ if is_dynamic_array(def_to) and
+ ((fromtreetype=niln) or
+ is_voidpointer(def_from)) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ if is_zero_based_array(def_to) and
+ equal_defs(tpointerdef(def_from).pointertype.def,tarraydef(def_to).elementtype.def) then
+ begin
+ doconv:=tc_pointer_2_array;
+ eq:=te_convert_l1;
+ end;
+ end;
+ stringdef :
+ begin
+ { string to char array }
+ if (not is_special_array(def_to)) and
+ (is_char(tarraydef(def_to).elementtype.def)or
+ is_widechar(tarraydef(def_to).elementtype.def)) then
+ begin
+ doconv:=tc_string_2_chararray;
+ eq:=te_convert_l1;
+ end;
+ end;
+ orddef:
+ begin
+ if is_chararray(def_to) and
+ is_char(def_from) then
+ begin
+ doconv:=tc_char_2_chararray;
+ eq:=te_convert_l2;
+ end;
+ end;
+ recorddef :
+ begin
+ { tvarrec -> array of const }
+ if is_array_of_const(def_to) and
+ equal_defs(def_from,tarraydef(def_to).elementtype.def) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ variantdef :
+ begin
+ if is_dynamic_array(def_to) then
+ begin
+ doconv:=tc_variant_2_dynarray;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ variantdef :
+ begin
+ if (cdo_allow_variant in cdoptions) then
+ begin
+ case def_from.deftype of
+ enumdef :
+ begin
+ doconv:=tc_enum_2_variant;
+ eq:=te_convert_l1;
+ end;
+ arraydef :
+ begin
+ if is_dynamic_array(def_from) then
+ begin
+ doconv:=tc_dynarray_2_variant;
+ eq:=te_convert_l1;
+ end;
+ end;
+ objectdef :
+ begin
+ if is_interface(def_from) then
+ begin
+ doconv:=tc_interface_2_variant;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ pointerdef :
+ begin
+ case def_from.deftype of
+ stringdef :
+ begin
+ { string constant (which can be part of array constructor)
+ to zero terminated string constant }
+ if (fromtreetype in [arrayconstructorn,stringconstn]) and
+ (is_pchar(def_to) or is_pwidechar(def_to)) then
+ begin
+ doconv:=tc_cstring_2_pchar;
+ eq:=te_convert_l2;
+ end
+ else
+ if cdo_explicit in cdoptions then
+ begin
+ { pchar(ansistring) }
+ if is_pchar(def_to) and
+ is_ansistring(def_from) then
+ begin
+ doconv:=tc_ansistring_2_pchar;
+ eq:=te_convert_l1;
+ end
+ else
+ { pwidechar(widestring) }
+ if is_pwidechar(def_to) and
+ is_widestring(def_from) then
+ begin
+ doconv:=tc_ansistring_2_pchar;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ orddef :
+ begin
+ { char constant to zero terminated string constant }
+ if (fromtreetype=ordconstn) then
+ begin
+ if (is_char(def_from) or is_widechar(def_from)) and
+ (is_pchar(def_to) or is_pwidechar(def_to)) then
+ begin
+ doconv:=tc_cchar_2_pchar;
+ eq:=te_convert_l1;
+ end
+ else
+ if (m_delphi in aktmodeswitches) and is_integer(def_from) then
+ begin
+ doconv:=tc_cord_2_pointer;
+ eq:=te_convert_l2;
+ end;
+ end;
+ { delphi compatible, allow explicit typecasts from
+ ordinals to pointer.
+ It is also used by the compiler internally for inc(pointer,ordinal) }
+ if (eq=te_incompatible) and
+ not is_void(def_from) and
+ (
+ (
+ (m_delphi in aktmodeswitches) and
+ (cdo_explicit in cdoptions)
+ ) or
+ (cdo_internal in cdoptions)
+ ) then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ arraydef :
+ begin
+ { string constant (which can be part of array constructor)
+ to zero terminated string constant }
+ if (fromtreetype in [arrayconstructorn,stringconstn]) and
+ (is_pchar(def_to) or is_pwidechar(def_to)) then
+ begin
+ doconv:=tc_cstring_2_pchar;
+ eq:=te_convert_l2;
+ end
+ else
+ { chararray to pointer }
+ if (is_zero_based_array(def_from) or
+ is_open_array(def_from)) and
+ equal_defs(tarraydef(def_from).elementtype.def,tpointerdef(def_to).pointertype.def) then
+ begin
+ doconv:=tc_array_2_pointer;
+ { don't prefer the pchar overload when a constant
+ string was passed }
+ if fromtreetype=stringconstn then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end
+ else
+ { dynamic array to pointer, delphi only }
+ if (m_delphi in aktmodeswitches) and
+ is_dynamic_array(def_from) then
+ begin
+ eq:=te_equal;
+ end;
+ end;
+ pointerdef :
+ begin
+ { check for far pointers }
+ if (tpointerdef(def_from).is_far<>tpointerdef(def_to).is_far) then
+ begin
+ eq:=te_incompatible;
+ end
+ else
+ { the types can be forward type, handle before normal type check !! }
+ if assigned(def_to.typesym) and
+ (tpointerdef(def_to).pointertype.def.deftype=forwarddef) then
+ begin
+ if (def_from.typesym=def_to.typesym) then
+ eq:=te_equal
+ end
+ else
+ { same types }
+ if equal_defs(tpointerdef(def_from).pointertype.def,tpointerdef(def_to).pointertype.def) then
+ begin
+ eq:=te_equal
+ end
+ else
+ { child class pointer can be assigned to anchestor pointers }
+ if (
+ (tpointerdef(def_from).pointertype.def.deftype=objectdef) and
+ (tpointerdef(def_to).pointertype.def.deftype=objectdef) and
+ tobjectdef(tpointerdef(def_from).pointertype.def).is_related(
+ tobjectdef(tpointerdef(def_to).pointertype.def))
+ ) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ { all pointers can be assigned to void-pointer }
+ if is_void(tpointerdef(def_to).pointertype.def) then
+ begin
+ doconv:=tc_equal;
+ { give pwidechar,pchar a penalty so it prefers
+ conversion to ansistring }
+ if is_pchar(def_from) or
+ is_pwidechar(def_from) then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end
+ else
+ { all pointers can be assigned from void-pointer }
+ if is_void(tpointerdef(def_from).pointertype.def) or
+ { all pointers can be assigned from void-pointer or formaldef pointer, check
+ tw3777.pp if you change this }
+ (tpointerdef(def_from).pointertype.def.deftype=formaldef) then
+ begin
+ doconv:=tc_equal;
+ { give pwidechar a penalty so it prefers
+ conversion to pchar }
+ if is_pwidechar(def_to) then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end;
+ end;
+ procvardef :
+ begin
+ { procedure variable can be assigned to an void pointer,
+ this not allowed for methodpointers }
+ if (is_void(tpointerdef(def_to).pointertype.def) or
+ (m_mac_procvar in aktmodeswitches)) and
+ tprocvardef(def_from).is_addressonly then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ procdef :
+ begin
+ { procedure variable can be assigned to an void pointer,
+ this not allowed for methodpointers }
+ if (m_mac_procvar in aktmodeswitches) and
+ tprocdef(def_from).is_addressonly then
+ begin
+ doconv:=tc_proc_2_procvar;
+ eq:=te_convert_l2;
+ end;
+ end;
+ classrefdef,
+ objectdef :
+ begin
+ { class types and class reference type
+ can be assigned to void pointers, but it is less
+ preferred than assigning to a related objectdef }
+ if (
+ is_class_or_interface(def_from) or
+ (def_from.deftype=classrefdef)
+ ) and
+ (tpointerdef(def_to).pointertype.def.deftype=orddef) and
+ (torddef(tpointerdef(def_to).pointertype.def).typ=uvoid) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l2;
+ end;
+ end;
+ end;
+ end;
+
+ setdef :
+ begin
+ case def_from.deftype of
+ setdef :
+ begin
+ if assigned(tsetdef(def_from).elementtype.def) and
+ assigned(tsetdef(def_to).elementtype.def) then
+ begin
+ { sets with the same element base type are equal }
+ if is_subequal(tsetdef(def_from).elementtype.def,tsetdef(def_to).elementtype.def) then
+ eq:=te_equal;
+ end
+ else
+ { empty set is compatible with everything }
+ eq:=te_equal;
+ end;
+ arraydef :
+ begin
+ { automatic arrayconstructor -> set conversion }
+ if is_array_constructor(def_from) then
+ begin
+ doconv:=tc_arrayconstructor_2_set;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+
+ procvardef :
+ begin
+ case def_from.deftype of
+ procdef :
+ begin
+ { proc -> procvar }
+ if (m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches) then
+ begin
+ subeq:=proc_to_procvar_equal(tprocdef(def_from),tprocvardef(def_to));
+ if subeq>te_incompatible then
+ begin
+ doconv:=tc_proc_2_procvar;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ procvardef :
+ begin
+ { procvar -> procvar }
+ eq:=proc_to_procvar_equal(tprocvardef(def_from),tprocvardef(def_to));
+ end;
+ pointerdef :
+ begin
+ { nil is compatible with procvars }
+ if (fromtreetype=niln) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ { for example delphi allows the assignement from pointers }
+ { to procedure variables }
+ if (m_pointer_2_procedure in aktmodeswitches) and
+ is_void(tpointerdef(def_from).pointertype.def) and
+ tprocvardef(def_to).is_addressonly then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+
+ objectdef :
+ begin
+ { object pascal objects }
+ if (def_from.deftype=objectdef) and
+ (tobjectdef(def_from).is_related(tobjectdef(def_to))) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ { Class/interface specific }
+ if is_class_or_interface(def_to) then
+ begin
+ { void pointer also for delphi mode }
+ if (m_delphi in aktmodeswitches) and
+ is_voidpointer(def_from) then
+ begin
+ doconv:=tc_equal;
+ { prefer pointer-pointer assignments }
+ eq:=te_convert_l2;
+ end
+ else
+ { nil is compatible with class instances and interfaces }
+ if (fromtreetype=niln) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ { classes can be assigned to interfaces }
+ else if is_interface(def_to) and
+ is_class(def_from) and
+ assigned(tobjectdef(def_from).implementedinterfaces) then
+ begin
+ { we've to search in parent classes as well }
+ hd3:=tobjectdef(def_from);
+ while assigned(hd3) do
+ begin
+ if hd3.implementedinterfaces.searchintf(def_to)<>-1 then
+ begin
+ doconv:=tc_class_2_intf;
+ { don't prefer this over objectdef->objectdef }
+ eq:=te_convert_l2;
+ break;
+ end;
+ hd3:=hd3.childof;
+ end;
+ end
+ { Interface 2 GUID handling }
+ else if (def_to=tdef(rec_tguid)) and
+ (fromtreetype=typen) and
+ is_interface(def_from) and
+ assigned(tobjectdef(def_from).iidguid) then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_equal;
+ end
+ else if (def_from.deftype=variantdef) and is_interface(def_to) then
+ begin
+ doconv:=tc_variant_2_interface;
+ eq:=te_convert_l2;
+ end
+ { ugly, but delphi allows it }
+ else if (eq=te_incompatible) and
+ (def_from.deftype=orddef) and
+ (m_delphi in aktmodeswitches) and
+ (cdo_explicit in cdoptions) then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+
+ classrefdef :
+ begin
+ { similar to pointerdef wrt forwards }
+ if assigned(def_to.typesym) and
+ (tclassrefdef(def_to).pointertype.def.deftype=forwarddef) then
+ begin
+ if (def_from.typesym=def_to.typesym) then
+ eq:=te_equal;
+ end
+ else
+ { class reference types }
+ if (def_from.deftype=classrefdef) then
+ begin
+ if equal_defs(tclassrefdef(def_from).pointertype.def,tclassrefdef(def_to).pointertype.def) then
+ begin
+ eq:=te_equal;
+ end
+ else
+ begin
+ doconv:=tc_equal;
+ if (cdo_explicit in cdoptions) or
+ tobjectdef(tclassrefdef(def_from).pointertype.def).is_related(
+ tobjectdef(tclassrefdef(def_to).pointertype.def)) then
+ eq:=te_convert_l1;
+ end;
+ end
+ else
+ { nil is compatible with class references }
+ if (fromtreetype=niln) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+
+ filedef :
+ begin
+ { typed files are all equal to the abstract file type
+ name TYPEDFILE in system.pp in is_equal in types.pas
+ the problem is that it sholud be also compatible to FILE
+ but this would leed to a problem for ASSIGN RESET and REWRITE
+ when trying to find the good overloaded function !!
+ so all file function are doubled in system.pp
+ this is not very beautiful !!}
+ if (def_from.deftype=filedef) then
+ begin
+ if (tfiledef(def_from).filetyp=tfiledef(def_to).filetyp) then
+ begin
+ if
+ (
+ (tfiledef(def_from).typedfiletype.def=nil) and
+ (tfiledef(def_to).typedfiletype.def=nil)
+ ) or
+ (
+ (tfiledef(def_from).typedfiletype.def<>nil) and
+ (tfiledef(def_to).typedfiletype.def<>nil) and
+ equal_defs(tfiledef(def_from).typedfiletype.def,tfiledef(def_to).typedfiletype.def)
+ ) or
+ (
+ (tfiledef(def_from).filetyp = ft_typed) and
+ (tfiledef(def_to).filetyp = ft_typed) and
+ (
+ (tfiledef(def_from).typedfiletype.def = tdef(voidtype.def)) or
+ (tfiledef(def_to).typedfiletype.def = tdef(voidtype.def))
+ )
+ ) then
+ begin
+ eq:=te_equal;
+ end;
+ end
+ else
+ if ((tfiledef(def_from).filetyp = ft_untyped) and
+ (tfiledef(def_to).filetyp = ft_typed)) or
+ ((tfiledef(def_from).filetyp = ft_typed) and
+ (tfiledef(def_to).filetyp = ft_untyped)) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+
+ recorddef :
+ begin
+ { interface -> guid }
+ if is_interface(def_from) and
+ (def_to=rec_tguid) then
+ begin
+ doconv:=tc_intf_2_guid;
+ eq:=te_convert_l1;
+ end;
+ end;
+
+ formaldef :
+ begin
+ doconv:=tc_equal;
+ if (def_from.deftype=formaldef) then
+ eq:=te_equal
+ else
+ { Just about everything can be converted to a formaldef...}
+ if not (def_from.deftype in [abstractdef,errordef]) then
+ eq:=te_convert_l1;
+ end;
+ end;
+
+ { if we didn't find an appropriate type conversion yet
+ then we search also the := operator }
+ if (eq=te_incompatible) and
+ (
+ { Check for variants? }
+ (
+ (cdo_allow_variant in cdoptions) and
+ ((def_from.deftype=variantdef) or (def_to.deftype=variantdef))
+ ) or
+ { Check for operators? }
+ (
+ (cdo_check_operator in cdoptions) and
+ ((def_from.deftype in [objectdef,recorddef,arraydef,stringdef,variantdef]) or
+ (def_to.deftype in [objectdef,recorddef,arraydef,stringdef,variantdef]))
+ )
+ ) then
+ begin
+ operatorpd:=search_assignment_operator(def_from,def_to);
+ if assigned(operatorpd) then
+ eq:=te_convert_operator;
+ end;
+
+ { update convtype for te_equal when it is not yet set }
+ if (eq=te_equal) and
+ (doconv=tc_not_possible) then
+ doconv:=tc_equal;
+
+ compare_defs_ext:=eq;
+ end;
+
+
+ function equal_defs(def_from,def_to:tdef):boolean;
+ var
+ convtyp : tconverttype;
+ pd : tprocdef;
+ begin
+ { Compare defs with nothingn and no explicit typecasts and
+ searching for overloaded operators is not needed }
+ equal_defs:=(compare_defs_ext(def_from,def_to,nothingn,convtyp,pd,[])>=te_equal);
+ end;
+
+
+ function compare_defs(def_from,def_to:tdef;fromtreetype:tnodetype):tequaltype;
+ var
+ doconv : tconverttype;
+ pd : tprocdef;
+ begin
+ compare_defs:=compare_defs_ext(def_from,def_to,fromtreetype,doconv,pd,[cdo_check_operator,cdo_allow_variant]);
+ end;
+
+
+ function is_subequal(def1, def2: tdef): boolean;
+ var
+ basedef1,basedef2 : tenumdef;
+
+ Begin
+ is_subequal := false;
+ if assigned(def1) and assigned(def2) then
+ Begin
+ if (def1.deftype = orddef) and (def2.deftype = orddef) then
+ Begin
+ { see p.47 of Turbo Pascal 7.01 manual for the separation of types }
+ { range checking for case statements is done with testrange }
+ case torddef(def1).typ of
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit :
+ is_subequal:=(torddef(def2).typ in [s64bit,u64bit,s32bit,u32bit,u8bit,s8bit,s16bit,u16bit]);
+ bool8bit,bool16bit,bool32bit :
+ is_subequal:=(torddef(def2).typ in [bool8bit,bool16bit,bool32bit]);
+ uchar :
+ is_subequal:=(torddef(def2).typ=uchar);
+ uwidechar :
+ is_subequal:=(torddef(def2).typ=uwidechar);
+ end;
+ end
+ else
+ Begin
+ { Check if both basedefs are equal }
+ if (def1.deftype=enumdef) and (def2.deftype=enumdef) then
+ Begin
+ { get both basedefs }
+ basedef1:=tenumdef(def1);
+ while assigned(basedef1.basedef) do
+ basedef1:=basedef1.basedef;
+ basedef2:=tenumdef(def2);
+ while assigned(basedef2.basedef) do
+ basedef2:=basedef2.basedef;
+ is_subequal:=(basedef1=basedef2);
+ end;
+ end;
+ end;
+ end;
+
+
+ function compare_paras(para1,para2 : tlist; acp : tcompare_paras_type; cpoptions: tcompare_paras_options):tequaltype;
+ var
+ currpara1,
+ currpara2 : tparavarsym;
+ eq,lowesteq : tequaltype;
+ hpd : tprocdef;
+ convtype : tconverttype;
+ cdoptions : tcompare_defs_options;
+ i1,i2 : byte;
+ begin
+ compare_paras:=te_incompatible;
+ cdoptions:=[cdo_check_operator,cdo_allow_variant];
+ { we need to parse the list from left-right so the
+ not-default parameters are checked first }
+ lowesteq:=high(tequaltype);
+ i1:=0;
+ i2:=0;
+ if cpo_ignorehidden in cpoptions then
+ begin
+ while (i1<para1.count) and
+ (vo_is_hidden_para in tparavarsym(para1[i1]).varoptions) do
+ inc(i1);
+ while (i2<para2.count) and
+ (vo_is_hidden_para in tparavarsym(para2[i2]).varoptions) do
+ inc(i2);
+ end;
+ while (i1<para1.count) and (i2<para2.count) do
+ begin
+ eq:=te_incompatible;
+
+ currpara1:=tparavarsym(para1[i1]);
+ currpara2:=tparavarsym(para2[i2]);
+
+ { Unique types must match exact }
+ if ((df_unique in currpara1.vartype.def.defoptions) or (df_unique in currpara2.vartype.def.defoptions)) and
+ (currpara1.vartype.def<>currpara2.vartype.def) then
+ exit;
+
+ { Handle hidden parameters separately, because self is
+ defined as voidpointer for methodpointers }
+ if (vo_is_hidden_para in currpara1.varoptions) or
+ (vo_is_hidden_para in currpara2.varoptions) then
+ begin
+ { both must be hidden }
+ if (vo_is_hidden_para in currpara1.varoptions)<>(vo_is_hidden_para in currpara2.varoptions) then
+ exit;
+ eq:=te_equal;
+ if not(vo_is_self in currpara1.varoptions) and
+ not(vo_is_self in currpara2.varoptions) then
+ begin
+ if (currpara1.varspez<>currpara2.varspez) then
+ exit;
+ eq:=compare_defs_ext(currpara1.vartype.def,currpara2.vartype.def,nothingn,
+ convtype,hpd,cdoptions);
+ end;
+ end
+ else
+ begin
+ case acp of
+ cp_value_equal_const :
+ begin
+ if (
+ (currpara1.varspez<>currpara2.varspez) and
+ ((currpara1.varspez in [vs_var,vs_out]) or
+ (currpara2.varspez in [vs_var,vs_out]))
+ ) then
+ exit;
+ eq:=compare_defs_ext(currpara1.vartype.def,currpara2.vartype.def,nothingn,
+ convtype,hpd,cdoptions);
+ end;
+ cp_all :
+ begin
+ if (currpara1.varspez<>currpara2.varspez) then
+ exit;
+ eq:=compare_defs_ext(currpara1.vartype.def,currpara2.vartype.def,nothingn,
+ convtype,hpd,cdoptions);
+ end;
+ cp_procvar :
+ begin
+ if (currpara1.varspez<>currpara2.varspez) then
+ exit;
+ eq:=compare_defs_ext(currpara1.vartype.def,currpara2.vartype.def,nothingn,
+ convtype,hpd,cdoptions);
+ { Parameters must be at least equal otherwise the are incompatible }
+ if (eq<te_equal) then
+ eq:=te_incompatible;
+ end;
+ else
+ eq:=compare_defs_ext(currpara1.vartype.def,currpara2.vartype.def,nothingn,
+ convtype,hpd,cdoptions);
+ end;
+ end;
+ { check type }
+ if eq=te_incompatible then
+ exit;
+ if eq<lowesteq then
+ lowesteq:=eq;
+ { also check default value if both have it declared }
+ if (cpo_comparedefaultvalue in cpoptions) and
+ assigned(currpara1.defaultconstsym) and
+ assigned(currpara2.defaultconstsym) then
+ begin
+ if not equal_constsym(tconstsym(currpara1.defaultconstsym),tconstsym(currpara2.defaultconstsym)) then
+ exit;
+ end;
+ inc(i1);
+ inc(i2);
+ if cpo_ignorehidden in cpoptions then
+ begin
+ while (i1<para1.count) and
+ (vo_is_hidden_para in tparavarsym(para1[i1]).varoptions) do
+ inc(i1);
+ while (i2<para2.count) and
+ (vo_is_hidden_para in tparavarsym(para2[i2]).varoptions) do
+ inc(i2);
+ end;
+ end;
+ { when both lists are empty then the parameters are equal. Also
+ when one list is empty and the other has a parameter with default
+ value assigned then the parameters are also equal }
+ if ((i1>=para1.count) and (i2>=para2.count)) or
+ ((cpo_allowdefaults in cpoptions) and
+ (((i1<para1.count) and assigned(tparavarsym(para1[i1]).defaultconstsym)) or
+ ((i2<para2.count) and assigned(tparavarsym(para2[i2]).defaultconstsym)))) then
+ compare_paras:=lowesteq;
+ end;
+
+
+ function proc_to_procvar_equal(def1:tabstractprocdef;def2:tprocvardef):tequaltype;
+ var
+ eq : tequaltype;
+ po_comp : tprocoptions;
+ begin
+ proc_to_procvar_equal:=te_incompatible;
+ if not(assigned(def1)) or not(assigned(def2)) then
+ exit;
+ { check for method pointer }
+ if (def1.is_methodpointer xor def2.is_methodpointer) or
+ (def1.is_addressonly xor def2.is_addressonly) then
+ exit;
+ { check return value and options, methodpointer is already checked }
+ po_comp:=[po_staticmethod,po_interrupt,
+ po_iocheck,po_varargs];
+ if (m_delphi in aktmodeswitches) then
+ exclude(po_comp,po_varargs);
+ if (def1.proccalloption=def2.proccalloption) and
+ ((po_comp * def1.procoptions)= (po_comp * def2.procoptions)) and
+ equal_defs(def1.rettype.def,def2.rettype.def) then
+ begin
+ { return equal type based on the parameters, but a proc->procvar
+ is never exact, so map an exact match of the parameters to
+ te_equal }
+ eq:=compare_paras(def1.paras,def2.paras,cp_procvar,[]);
+ if eq=te_exact then
+ eq:=te_equal;
+ proc_to_procvar_equal:=eq;
+ end;
+ end;
+
+end.
diff --git a/compiler/defutil.pas b/compiler/defutil.pas
new file mode 100644
index 0000000000..a22c9f967b
--- /dev/null
+++ b/compiler/defutil.pas
@@ -0,0 +1,921 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit provides some help routines for type handling
+
+ 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 defutil;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,
+ symconst,symbase,symtype,symdef,
+ cgbase,cpubase;
+
+ type
+ tmmxtype = (mmxno,mmxu8bit,mmxs8bit,mmxu16bit,mmxs16bit,
+ mmxu32bit,mmxs32bit,mmxfixed16,mmxsingle);
+
+
+{*****************************************************************************
+ Basic type functions
+ *****************************************************************************}
+
+ {# Returns true, if definition defines an ordinal type }
+ function is_ordinal(def : tdef) : boolean;
+
+ {# Returns the minimal integer value of the type }
+ function get_min_value(def : tdef) : TConstExprInt;
+
+ {# Returns basetype of the specified integer range }
+ function range_to_basetype(l,h:TConstExprInt):tbasetype;
+
+ procedure range_to_type(l,h:TConstExprInt;var tt:ttype);
+
+ procedure int_to_type(v:TConstExprInt;var tt:ttype);
+
+ {# Returns true, if definition defines an integer type }
+ function is_integer(def : tdef) : boolean;
+
+ {# Returns true if definition is a boolean }
+ function is_boolean(def : tdef) : boolean;
+
+ {# Returns true if definition is a char
+
+ This excludes the unicode char.
+ }
+ function is_char(def : tdef) : boolean;
+
+ {# Returns true if definition is a widechar }
+ function is_widechar(def : tdef) : boolean;
+
+ {# Returns true if definition is a void}
+ function is_void(def : tdef) : boolean;
+
+ {# Returns true if definition is a smallset}
+ function is_smallset(p : tdef) : boolean;
+
+ {# Returns true, if def defines a signed data type
+ (only for ordinal types)
+ }
+ function is_signed(def : tdef) : boolean;
+
+ {# Returns true whether def_from's range is comprised in def_to's if both are
+ orddefs, false otherwise }
+ function is_in_limit(def_from,def_to : tdef) : boolean;
+
+ function is_in_limit_value(val_from:TConstExprInt;def_from,def_to : tdef) : boolean;
+
+{*****************************************************************************
+ Array helper functions
+ *****************************************************************************}
+
+ {# Returns true, if p points to a zero based (non special like open or
+ dynamic array def).
+
+ This is mainly used to see if the array
+ is convertable to a pointer
+ }
+ function is_zero_based_array(p : tdef) : boolean;
+
+ {# Returns true if p points to an open array definition }
+ function is_open_array(p : tdef) : boolean;
+
+ {# Returns true if p points to a dynamic array definition }
+ function is_dynamic_array(p : tdef) : boolean;
+
+ {# Returns true, if p points to an array of const definition }
+ function is_array_constructor(p : tdef) : boolean;
+
+ {# Returns true, if p points to a variant array }
+ function is_variant_array(p : tdef) : boolean;
+
+ {# Returns true, if p points to an array of const }
+ function is_array_of_const(p : tdef) : boolean;
+
+ {# Returns true, if p points any kind of special array
+
+ That is if the array is an open array, a variant
+ array, an array constants constructor, or an
+ array of const.
+ }
+ function is_special_array(p : tdef) : boolean;
+
+ {# Returns true if p is a char array def }
+ function is_chararray(p : tdef) : boolean;
+
+ {# Returns true if p is a wide char array def }
+ function is_widechararray(p : tdef) : boolean;
+
+ {# Returns true if p is a open char array def }
+ function is_open_chararray(p : tdef) : boolean;
+
+ {# Returns true if p is a open wide char array def }
+ function is_open_widechararray(p : tdef) : boolean;
+
+{*****************************************************************************
+ String helper functions
+ *****************************************************************************}
+
+ {# Returns true if p points to an open string type }
+ function is_open_string(p : tdef) : boolean;
+
+ {# Returns true if p is an ansi string type }
+ function is_ansistring(p : tdef) : boolean;
+
+ {# Returns true if p is a long string type }
+ function is_longstring(p : tdef) : boolean;
+
+ {# returns true if p is a wide string type }
+ function is_widestring(p : tdef) : boolean;
+
+ {# Returns true if p is a short string type }
+ function is_shortstring(p : tdef) : boolean;
+
+ {# Returns true if p is a pchar def }
+ function is_pchar(p : tdef) : boolean;
+
+ {# Returns true if p is a pwidechar def }
+ function is_pwidechar(p : tdef) : boolean;
+
+ {# Returns true if p is a voidpointer def }
+ function is_voidpointer(p : tdef) : boolean;
+
+ {# Returns true, if definition is a float }
+ function is_fpu(def : tdef) : boolean;
+
+ {# Returns true, if def is a currency type }
+ function is_currency(def : tdef) : boolean;
+
+ {# Returns true, if def is a single type }
+ function is_single(def : tdef) : boolean;
+
+ {# Returns true, if def is a double type }
+ function is_double(def : tdef) : boolean;
+
+ {# Returns true, if def is an extended type }
+ function is_extended(def : tdef) : boolean;
+
+ {# Returns true, if definition is a "real" real (i.e. single/double/extended) }
+ function is_real(def : tdef) : boolean;
+
+ {# Returns true, if def is a 32 bit integer type }
+ function is_32bitint(def : tdef) : boolean;
+
+ {# Returns true, if def is a 64 bit integer type }
+ function is_64bitint(def : tdef) : boolean;
+
+ {# Returns true, if def is a 64 bit type }
+ function is_64bit(def : tdef) : boolean;
+
+ {# If @var(l) isn't in the range of def a range check error (if not explicit) is generated and
+ the value is placed within the range
+ }
+ procedure testrange(def : tdef;var l : tconstexprint;explicit:boolean);
+
+ {# Returns the range of def, where @var(l) is the low-range and @var(h) is
+ the high-range.
+ }
+ procedure getrange(def : tdef;var l : TConstExprInt;var h : TConstExprInt);
+
+ { some type helper routines for MMX support }
+ function is_mmx_able_array(p : tdef) : boolean;
+
+ {# returns the mmx type }
+ function mmx_type(p : tdef) : tmmxtype;
+
+ {# From a definition return the abstract code generator size enum. It is
+ to note that the value returned can be @var(OS_NO) }
+ function def_cgsize(def: tdef): tcgsize;
+
+
+implementation
+
+ uses
+ systems,verbose;
+
+ { returns true, if def uses FPU }
+ function is_fpu(def : tdef) : boolean;
+ begin
+ is_fpu:=(def.deftype=floatdef);
+ end;
+
+
+ { returns true, if def is a currency type }
+ function is_currency(def : tdef) : boolean;
+ begin
+ case s64currencytype.def.deftype of
+ orddef :
+ result:=(def.deftype=orddef) and
+ (torddef(s64currencytype.def).typ=torddef(def).typ);
+ floatdef :
+ result:=(def.deftype=floatdef) and
+ (tfloatdef(s64currencytype.def).typ=tfloatdef(def).typ);
+ else
+ internalerror(200304222);
+ end;
+ end;
+
+
+ { returns true, if def is a single type }
+ function is_single(def : tdef) : boolean;
+ begin
+ result:=(def.deftype=floatdef) and
+ (tfloatdef(def).typ=s32real);
+ end;
+
+
+ { returns true, if def is a double type }
+ function is_double(def : tdef) : boolean;
+ begin
+ result:=(def.deftype=floatdef) and
+ (tfloatdef(def).typ=s64real);
+ end;
+
+
+ function is_extended(def : tdef) : boolean;
+ begin
+ result:=(def.deftype=floatdef) and
+ (tfloatdef(def).typ=s80real);
+ end;
+
+
+ { returns true, if definition is a "real" real (i.e. single/double/extended) }
+ function is_real(def : tdef) : boolean;
+ begin
+ result:=(def.deftype=floatdef) and
+ (tfloatdef(def).typ in [s32real,s64real,s80real]);
+ end;
+
+
+ function range_to_basetype(l,h:TConstExprInt):tbasetype;
+ begin
+ { prefer signed over unsigned }
+ if (l>=-128) and (h<=127) then
+ range_to_basetype:=s8bit
+ else if (l>=0) and (h<=255) then
+ range_to_basetype:=u8bit
+ else if (l>=-32768) and (h<=32767) then
+ range_to_basetype:=s16bit
+ else if (l>=0) and (h<=65535) then
+ range_to_basetype:=u16bit
+ else if (l>=low(longint)) and (h<=high(longint)) then
+ range_to_basetype:=s32bit
+ else if (l>=low(cardinal)) and (h<=high(cardinal)) then
+ range_to_basetype:=u32bit
+ else
+ range_to_basetype:=s64bit;
+ end;
+
+
+ procedure range_to_type(l,h:TConstExprInt;var tt:ttype);
+ begin
+ { prefer signed over unsigned }
+ if (l>=-128) and (h<=127) then
+ tt:=s8inttype
+ else if (l>=0) and (h<=255) then
+ tt:=u8inttype
+ else if (l>=-32768) and (h<=32767) then
+ tt:=s16inttype
+ else if (l>=0) and (h<=65535) then
+ tt:=u16inttype
+ else if (l>=low(longint)) and (h<=high(longint)) then
+ tt:=s32inttype
+ else if (l>=low(cardinal)) and (h<=high(cardinal)) then
+ tt:=u32inttype
+ else
+ tt:=s64inttype;
+ end;
+
+
+ procedure int_to_type(v:TConstExprInt;var tt:ttype);
+ begin
+ range_to_type(v,v,tt);
+ end;
+
+
+ { true if p is an ordinal }
+ function is_ordinal(def : tdef) : boolean;
+ var
+ dt : tbasetype;
+ begin
+ case def.deftype of
+ orddef :
+ begin
+ dt:=torddef(def).typ;
+ is_ordinal:=dt in [uchar,uwidechar,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit,
+ bool8bit,bool16bit,bool32bit];
+ end;
+ enumdef :
+ is_ordinal:=true;
+ else
+ is_ordinal:=false;
+ end;
+ end;
+
+
+ { returns the min. value of the type }
+ function get_min_value(def : tdef) : TConstExprInt;
+ begin
+ case def.deftype of
+ orddef:
+ get_min_value:=torddef(def).low;
+ enumdef:
+ get_min_value:=tenumdef(def).min;
+ else
+ get_min_value:=0;
+ end;
+ end;
+
+
+ { true if p is an integer }
+ function is_integer(def : tdef) : boolean;
+ begin
+ is_integer:=(def.deftype=orddef) and
+ (torddef(def).typ in [u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit]);
+ end;
+
+
+ { true if p is a boolean }
+ function is_boolean(def : tdef) : boolean;
+ begin
+ is_boolean:=(def.deftype=orddef) and
+ (torddef(def).typ in [bool8bit,bool16bit,bool32bit]);
+ end;
+
+
+ { true if p is a void }
+ function is_void(def : tdef) : boolean;
+ begin
+ is_void:=(def.deftype=orddef) and
+ (torddef(def).typ=uvoid);
+ end;
+
+
+ { true if p is a char }
+ function is_char(def : tdef) : boolean;
+ begin
+ is_char:=(def.deftype=orddef) and
+ (torddef(def).typ=uchar);
+ end;
+
+
+ { true if p is a wchar }
+ function is_widechar(def : tdef) : boolean;
+ begin
+ is_widechar:=(def.deftype=orddef) and
+ (torddef(def).typ=uwidechar);
+ end;
+
+
+ { true if p is signed (integer) }
+ function is_signed(def : tdef) : boolean;
+ var
+ dt : tbasetype;
+ begin
+ case def.deftype of
+ orddef :
+ begin
+ dt:=torddef(def).typ;
+ is_signed:=(dt in [s8bit,s16bit,s32bit,s64bit,scurrency]);
+ end;
+ enumdef :
+ is_signed:=tenumdef(def).min < 0;
+ arraydef :
+ is_signed:=is_signed(tarraydef(def).rangetype.def);
+ else
+ is_signed:=false;
+ end;
+ end;
+
+
+ function is_in_limit(def_from,def_to : tdef) : boolean;
+
+ var
+ fromqword, toqword: boolean;
+
+ begin
+ if (def_from.deftype <> orddef) or
+ (def_to.deftype <> orddef) then
+ begin
+ is_in_limit := false;
+ exit;
+ end;
+ fromqword := torddef(def_from).typ = u64bit;
+ toqword := torddef(def_to).typ = u64bit;
+ is_in_limit:=(toqword and is_signed(def_from)) or
+ ((not fromqword) and
+ (torddef(def_from).low>=torddef(def_to).low) and
+ (torddef(def_from).high<=torddef(def_to).high));
+ end;
+
+
+ function is_in_limit_value(val_from:TConstExprInt;def_from,def_to : tdef) : boolean;
+
+ begin
+ if (def_from.deftype <> orddef) and
+ (def_to.deftype <> orddef) then
+ internalerror(200210062);
+ if (torddef(def_to).typ = u64bit) then
+ begin
+ is_in_limit_value:=((TConstExprUInt(val_from)>=TConstExprUInt(torddef(def_to).low)) and
+ (TConstExprUInt(val_from)<=TConstExprUInt(torddef(def_to).high)));
+ end
+ else
+ begin;
+ is_in_limit_value:=((val_from>=torddef(def_to).low) and
+ (val_from<=torddef(def_to).high));
+ end;
+ end;
+
+
+ { true, if p points to an open array def }
+ function is_open_string(p : tdef) : boolean;
+ begin
+ is_open_string:=(p.deftype=stringdef) and
+ (tstringdef(p).string_typ=st_shortstring) and
+ (tstringdef(p).len=0);
+ end;
+
+
+ { true, if p points to a zero based array def }
+ function is_zero_based_array(p : tdef) : boolean;
+ begin
+ is_zero_based_array:=(p.deftype=arraydef) and
+ (tarraydef(p).lowrange=0) and
+ not(is_special_array(p));
+ end;
+
+ { true if p points to a dynamic array def }
+ function is_dynamic_array(p : tdef) : boolean;
+ begin
+ is_dynamic_array:=(p.deftype=arraydef) and
+ tarraydef(p).IsDynamicArray;
+ end;
+
+
+ { true, if p points to an open array def }
+ function is_open_array(p : tdef) : boolean;
+ begin
+ { check for s32inttype is needed, because for u32bit the high
+ range is also -1 ! (PFV) }
+ is_open_array:=(p.deftype=arraydef) and
+ (tarraydef(p).rangetype.def=s32inttype.def) and
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=-1) and
+ not(tarraydef(p).IsConstructor) and
+ not(tarraydef(p).IsVariant) and
+ not(tarraydef(p).IsArrayOfConst) and
+ not(tarraydef(p).IsDynamicArray);
+
+ end;
+
+ { true, if p points to an array of const def }
+ function is_array_constructor(p : tdef) : boolean;
+ begin
+ is_array_constructor:=(p.deftype=arraydef) and
+ (tarraydef(p).IsConstructor);
+ end;
+
+ { true, if p points to a variant array }
+ function is_variant_array(p : tdef) : boolean;
+ begin
+ is_variant_array:=(p.deftype=arraydef) and
+ (tarraydef(p).IsVariant);
+ end;
+
+ { true, if p points to an array of const }
+ function is_array_of_const(p : tdef) : boolean;
+ begin
+ is_array_of_const:=(p.deftype=arraydef) and
+ (tarraydef(p).IsArrayOfConst);
+ end;
+
+ { true, if p points to a special array }
+ function is_special_array(p : tdef) : boolean;
+ begin
+ is_special_array:=(p.deftype=arraydef) and
+ ((tarraydef(p).IsVariant) or
+ (tarraydef(p).IsArrayOfConst) or
+ (tarraydef(p).IsConstructor) or
+ (tarraydef(p).IsDynamicArray) or
+ is_open_array(p)
+ );
+ end;
+
+{$ifdef ansistring_bits}
+ { true if p is an ansi string def }
+ function is_ansistring(p : tdef) : boolean;
+ begin
+ is_ansistring:=(p.deftype=stringdef) and
+ (tstringdef(p).string_typ in [st_ansistring16,st_ansistring32,st_ansistring64]);
+ end;
+{$else}
+ { true if p is an ansi string def }
+ function is_ansistring(p : tdef) : boolean;
+ begin
+ is_ansistring:=(p.deftype=stringdef) and
+ (tstringdef(p).string_typ=st_ansistring);
+ end;
+{$endif}
+
+ { true if p is an long string def }
+ function is_longstring(p : tdef) : boolean;
+ begin
+ is_longstring:=(p.deftype=stringdef) and
+ (tstringdef(p).string_typ=st_longstring);
+ end;
+
+
+ { true if p is an wide string def }
+ function is_widestring(p : tdef) : boolean;
+ begin
+ is_widestring:=(p.deftype=stringdef) and
+ (tstringdef(p).string_typ=st_widestring);
+ end;
+
+
+ { true if p is an short string def }
+ function is_shortstring(p : tdef) : boolean;
+ begin
+ is_shortstring:=(p.deftype=stringdef) and
+ (tstringdef(p).string_typ=st_shortstring);
+ end;
+
+ { true if p is a char array def }
+ function is_chararray(p : tdef) : boolean;
+ begin
+ is_chararray:=(p.deftype=arraydef) and
+ is_char(tarraydef(p).elementtype.def) and
+ not(is_special_array(p));
+ end;
+
+ { true if p is a widechar array def }
+ function is_widechararray(p : tdef) : boolean;
+ begin
+ is_widechararray:=(p.deftype=arraydef) and
+ is_widechar(tarraydef(p).elementtype.def) and
+ not(is_special_array(p));
+ end;
+
+
+ { true if p is a open char array def }
+ function is_open_chararray(p : tdef) : boolean;
+ begin
+ is_open_chararray:= is_open_array(p) and
+ is_char(tarraydef(p).elementtype.def);
+ end;
+
+ { true if p is a open wide char array def }
+ function is_open_widechararray(p : tdef) : boolean;
+ begin
+ is_open_widechararray:= is_open_array(p) and
+ is_widechar(tarraydef(p).elementtype.def);
+ end;
+
+ { true if p is a pchar def }
+ function is_pchar(p : tdef) : boolean;
+ begin
+ is_pchar:=(p.deftype=pointerdef) and
+ (is_char(tpointerdef(p).pointertype.def) or
+ (is_zero_based_array(tpointerdef(p).pointertype.def) and
+ is_chararray(tpointerdef(p).pointertype.def)));
+ end;
+
+ { true if p is a pchar def }
+ function is_pwidechar(p : tdef) : boolean;
+ begin
+ is_pwidechar:=(p.deftype=pointerdef) and
+ (is_widechar(tpointerdef(p).pointertype.def) or
+ (is_zero_based_array(tpointerdef(p).pointertype.def) and
+ is_widechararray(tpointerdef(p).pointertype.def)));
+ end;
+
+
+ { true if p is a voidpointer def }
+ function is_voidpointer(p : tdef) : boolean;
+ begin
+ is_voidpointer:=(p.deftype=pointerdef) and
+ (tpointerdef(p).pointertype.def.deftype=orddef) and
+ (torddef(tpointerdef(p).pointertype.def).typ=uvoid);
+ end;
+
+
+ { true if p is a smallset def }
+ function is_smallset(p : tdef) : boolean;
+ begin
+ is_smallset:=(p.deftype=setdef) and
+ (tsetdef(p).settype=smallset);
+ end;
+
+
+ { true, if def is a 32 bit int type }
+ function is_32bitint(def : tdef) : boolean;
+ begin
+ result:=(def.deftype=orddef) and (torddef(def).typ in [u32bit,s32bit])
+ end;
+
+
+ { true, if def is a 64 bit int type }
+ function is_64bitint(def : tdef) : boolean;
+ begin
+ is_64bitint:=(def.deftype=orddef) and (torddef(def).typ in [u64bit,s64bit])
+ end;
+
+
+ { true, if def is a 64 bit type }
+ function is_64bit(def : tdef) : boolean;
+ begin
+ is_64bit:=(def.deftype=orddef) and (torddef(def).typ in [u64bit,s64bit,scurrency])
+ end;
+
+
+ { if l isn't in the range of def a range check error (if not explicit) is generated and
+ the value is placed within the range }
+ procedure testrange(def : tdef;var l : tconstexprint;explicit:boolean);
+ var
+ lv,hv: TConstExprInt;
+ error: boolean;
+ begin
+ error := false;
+ { for 64 bit types we need only to check if it is less than }
+ { zero, if def is a qword node }
+ if is_64bitint(def) then
+ begin
+ if (l<0) and (torddef(def).typ=u64bit) then
+ begin
+ { don't zero the result, because it may come from hex notation
+ like $ffffffffffffffff! (JM)
+ l:=0; }
+ if not explicit then
+ begin
+ if (cs_check_range in aktlocalswitches) then
+ Message(parser_e_range_check_error)
+ else
+ Message(parser_w_range_check_error);
+ end;
+ error := true;
+ end;
+ end
+ else
+ begin
+ getrange(def,lv,hv);
+ if (l<lv) or (l>hv) then
+ begin
+ if not explicit then
+ begin
+ if ((def.deftype=enumdef) and
+ { delphi allows range check errors in
+ enumeration type casts FK }
+ not(m_delphi in aktmodeswitches)) or
+ (cs_check_range in aktlocalswitches) then
+ Message(parser_e_range_check_error)
+ else
+ Message(parser_w_range_check_error);
+ end;
+ error := true;
+ end;
+ end;
+ if error then
+ begin
+ { Fix the value to fit in the allocated space for this type of variable }
+ case longint(def.size) of
+ 1: l := l and $ff;
+ 2: l := l and $ffff;
+ { work around sign extension bug (to be fixed) (JM) }
+ 4: l := l and (int64($fffffff) shl 4 + $f);
+ end;
+ { do sign extension if necessary (JM) }
+ if is_signed(def) then
+ begin
+ case longint(def.size) of
+ 1: l := shortint(l);
+ 2: l := smallint(l);
+ 4: l := longint(l);
+ end;
+ end;
+ end;
+ end;
+
+
+ { return the range from def in l and h }
+ procedure getrange(def : tdef;var l : TConstExprInt;var h : TConstExprInt);
+ begin
+ case def.deftype of
+ orddef :
+ begin
+ l:=torddef(def).low;
+ h:=torddef(def).high;
+ end;
+ enumdef :
+ begin
+ l:=tenumdef(def).min;
+ h:=tenumdef(def).max;
+ end;
+ arraydef :
+ begin
+ l:=tarraydef(def).lowrange;
+ h:=tarraydef(def).highrange;
+ end;
+ else
+ internalerror(987);
+ end;
+ end;
+
+
+ function mmx_type(p : tdef) : tmmxtype;
+ begin
+ mmx_type:=mmxno;
+ if is_mmx_able_array(p) then
+ begin
+ if tarraydef(p).elementtype.def.deftype=floatdef then
+ case tfloatdef(tarraydef(p).elementtype.def).typ of
+ s32real:
+ mmx_type:=mmxsingle;
+ end
+ else
+ case torddef(tarraydef(p).elementtype.def).typ of
+ u8bit:
+ mmx_type:=mmxu8bit;
+ s8bit:
+ mmx_type:=mmxs8bit;
+ u16bit:
+ mmx_type:=mmxu16bit;
+ s16bit:
+ mmx_type:=mmxs16bit;
+ u32bit:
+ mmx_type:=mmxu32bit;
+ s32bit:
+ mmx_type:=mmxs32bit;
+ end;
+ end;
+ end;
+
+
+ function is_mmx_able_array(p : tdef) : boolean;
+ begin
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx_saturation in aktlocalswitches) then
+ begin
+ is_mmx_able_array:=(p.deftype=arraydef) and
+ not(is_special_array(p)) and
+ (
+ (
+ (tarraydef(p).elementtype.def.deftype=orddef) and
+ (
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (torddef(tarraydef(p).elementtype.def).typ in [u32bit,s32bit])
+ )
+ or
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=3) and
+ (torddef(tarraydef(p).elementtype.def).typ in [u16bit,s16bit])
+ )
+ )
+ )
+ or
+ (
+ (
+ (tarraydef(p).elementtype.def.deftype=floatdef) and
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (tfloatdef(tarraydef(p).elementtype.def).typ=s32real)
+ )
+ )
+ )
+ );
+ end
+ else
+ begin
+ is_mmx_able_array:=(p.deftype=arraydef) and
+ (
+ (
+ (tarraydef(p).elementtype.def.deftype=orddef) and
+ (
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (torddef(tarraydef(p).elementtype.def).typ in [u32bit,s32bit])
+ )
+ or
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=3) and
+ (torddef(tarraydef(p).elementtype.def).typ in [u16bit,s16bit])
+ )
+ or
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=7) and
+ (torddef(tarraydef(p).elementtype.def).typ in [u8bit,s8bit])
+ )
+ )
+ )
+ or
+ (
+ (tarraydef(p).elementtype.def.deftype=floatdef) and
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (tfloatdef(tarraydef(p).elementtype.def).typ=s32real)
+ )
+ )
+ );
+ end;
+{$else SUPPORT_MMX}
+ is_mmx_able_array:=false;
+{$endif SUPPORT_MMX}
+ end;
+
+
+ function def_cgsize(def: tdef): tcgsize;
+ begin
+ case def.deftype of
+ orddef,
+ enumdef,
+ setdef:
+ begin
+ result:=int_cgsize(def.size);
+ if is_signed(def) then
+ result:=tcgsize(ord(result)+(ord(OS_S8)-ord(OS_8)));
+ end;
+ classrefdef,
+ pointerdef:
+ result := OS_ADDR;
+ procvardef:
+ begin
+ if tprocvardef(def).is_methodpointer and
+ (not tprocvardef(def).is_addressonly) then
+ result := OS_64
+ else
+ result := OS_ADDR;
+ end;
+ stringdef :
+ begin
+ if is_ansistring(def) or is_widestring(def) then
+ result := OS_ADDR
+ else
+ result:=int_cgsize(def.size);
+ end;
+ objectdef :
+ begin
+ if is_class_or_interface(def) then
+ result := OS_ADDR
+ else
+ result:=int_cgsize(def.size);
+ end;
+ floatdef:
+ if cs_fp_emulation in aktmoduleswitches then
+ result:=int_cgsize(def.size)
+ else
+ result:=tfloat2tcgsize[tfloatdef(def).typ];
+ recorddef :
+ result:=int_cgsize(def.size);
+ arraydef :
+ begin
+ if not is_special_array(def) then
+ result := int_cgsize(def.size)
+ else
+ begin
+ if is_dynamic_array(def) then
+ result := OS_ADDR
+ else
+ result := OS_NO;
+ end;
+ end;
+ else
+ begin
+ { undefined size }
+ result:=OS_NO;
+ end;
+ end;
+ end;
+
+
+end.
diff --git a/compiler/dwarf.pas b/compiler/dwarf.pas
new file mode 100644
index 0000000000..0e0c2188c6
--- /dev/null
+++ b/compiler/dwarf.pas
@@ -0,0 +1,419 @@
+{
+ Copyright (c) 2003-2004 by Peter Vreman and Florian Klaempfl
+
+ This units contains special support for DWARF debug info
+
+ 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 dwarf;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,
+ cgbase,cpubase,
+ aasmbase,aasmtai;
+
+ const
+ maxdwarfops = 2;
+
+ type
+ tdwarfoperenc=(doe_uleb,doe_sleb,doe_ptr,doe_32bit,doe_16bit,doe_8bit);
+ tdwarfopertype=(dop_reg,dop_const,dop_sym,dop_reloffset);
+
+ tdwarfoper=record
+ enc : tdwarfoperenc;
+ case typ:tdwarfopertype of
+ dop_reg : (register:tregister);
+ dop_const : (value:int64);
+ dop_sym : (sym:tasmsymbol);
+ dop_reloffset : (beginsym,endsym:tasmsymbol);
+ end;
+
+ tdwarfitem=class(TLinkedListItem)
+ op : byte;
+ ops : byte;
+ oper : array[0..maxdwarfops-1] of tdwarfoper;
+ constructor create(aop:longint);
+ constructor create_reg(aop:longint;enc1:tdwarfoperenc;reg:tregister);
+ constructor create_const(aop:longint;enc1:tdwarfoperenc;val:int64);
+ constructor create_reloffset(aop:longint;enc1:tdwarfoperenc;beginlab,endlab:tasmsymbol);
+ constructor create_reg_const(aop:longint;enc1:tdwarfoperenc;reg:tregister;enc2:tdwarfoperenc;val:longint);
+ procedure generate_code(list:taasmoutput);
+ end;
+
+ tdwarf=class
+ private
+ Fal_dwarf : TLinkedList;
+ public
+ constructor create;
+ destructor destroy;override;
+ property al_dwarf:TlinkedList read Fal_dwarf;
+ end;
+
+ tdwarfcfi=class(tdwarf)
+ private
+ FFrameStartLabel,
+ FFrameEndLabel,
+ FLastloclabel : tasmlabel;
+ procedure cfa_advance_loc(list:taasmoutput);
+ protected
+ code_alignment_factor,
+ data_alignment_factor : shortint;
+ public
+ constructor create;
+ procedure generate_code(list:taasmoutput);
+ { operations }
+ procedure start_frame(list:taasmoutput);
+ procedure end_frame(list:taasmoutput);
+ procedure cfa_offset(list:taasmoutput;reg:tregister;ofs:longint);
+ procedure cfa_restore(list:taasmoutput;reg:tregister);
+ procedure cfa_def_cfa_register(list:taasmoutput;reg:tregister);
+ procedure cfa_def_cfa_offset(list:taasmoutput;ofs:longint);
+ end;
+
+
+ var
+ dwarfcfi : tdwarfcfi;
+
+ function dwarf_reg(r:tregister):longint;
+
+
+implementation
+
+ uses
+ verbose;
+
+ const
+ { Call frame information }
+ DW_CFA_set_loc = $01;
+ DW_CFA_advance_loc1 = $02;
+ DW_CFA_advance_loc2 = $03;
+ DW_CFA_advance_loc4 = $04;
+ DW_CFA_offset_extended = $05;
+ DW_CFA_restore_extended = $06;
+ DW_CFA_def_cfa = $0c;
+ DW_CFA_def_cfa_register = $0d;
+ DW_CFA_def_cfa_offset = $0e;
+ { Own additions }
+ DW_CFA_start_frame = $f0;
+ DW_CFA_end_frame = $f1;
+
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ function dwarf_reg(r:tregister):longint;
+ begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ end;
+
+
+{****************************************************************************
+ TDWARF
+****************************************************************************}
+
+ constructor tdwarf.create;
+ begin
+ Fal_dwarf:=TLinkedList.Create;
+ end;
+
+
+ destructor tdwarf.destroy;
+ begin
+ Fal_dwarf.Free;
+ end;
+
+
+{****************************************************************************
+ TDWARFITEM
+****************************************************************************}
+
+ constructor tdwarfitem.create(aop:longint);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=0;
+ end;
+
+
+ constructor tdwarfitem.create_reg(aop:longint;enc1:tdwarfoperenc;reg:tregister);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=1;
+ oper[0].typ:=dop_reg;
+ oper[0].enc:=enc1;
+ oper[0].register:=reg;
+ end;
+
+
+ constructor tdwarfitem.create_const(aop:longint;enc1:tdwarfoperenc;val:int64);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=1;
+ oper[0].typ:=dop_const;
+ oper[0].enc:=enc1;
+ oper[0].value:=val;
+ end;
+
+
+ constructor tdwarfitem.create_reloffset(aop:longint;enc1:tdwarfoperenc;beginlab,endlab:tasmsymbol);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=1;
+ { relative offsets are passed }
+ oper[0].typ:=dop_reloffset;
+ oper[0].enc:=enc1;
+ oper[0].beginsym:=beginlab;
+ oper[0].endsym:=endlab;
+ end;
+
+
+ constructor tdwarfitem.create_reg_const(aop:longint;enc1:tdwarfoperenc;reg:tregister;enc2:tdwarfoperenc;val:longint);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=2;
+ oper[0].typ:=dop_reg;
+ oper[0].enc:=enc1;
+ oper[0].register:=reg;
+ oper[1].typ:=dop_const;
+ oper[1].enc:=enc2;
+ oper[1].value:=val;
+ end;
+
+
+ procedure tdwarfitem.generate_code(list:taasmoutput);
+ const
+ enc2ait_const : array[tdwarfoperenc] of taitype = (
+ ait_const_uleb128bit,ait_const_sleb128bit,ait_const_ptr,
+ ait_const_32bit,ait_const_16bit,ait_const_8bit
+ );
+ var
+ i : integer;
+ begin
+ list.concat(tai_const.create_8bit(op));
+ for i:=0 to ops-1 do
+ begin
+ case oper[i].typ of
+ dop_const :
+ list.concat(tai_const.create(enc2ait_const[oper[i].enc],oper[i].value));
+ dop_sym :
+ begin
+ if oper[i].enc<>doe_ptr then
+ internalerror(200404127);
+ list.concat(tai_const.create_sym(oper[i].sym));
+ end;
+ dop_reloffset :
+ list.concat(tai_const.create_rel_sym(enc2ait_const[oper[i].enc],oper[i].beginsym,oper[i].endsym));
+ dop_reg :
+ list.concat(tai_const.create(enc2ait_const[oper[i].enc],regdwarf_table[findreg_by_number(oper[i].register)]));
+ else
+ internalerror(200404128);
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TDWARFCFI
+****************************************************************************}
+
+ constructor tdwarfcfi.create;
+ begin
+ inherited create;
+ FFrameStartLabel:=nil;
+ FFrameEndLabel:=nil;
+ FLastLocLabel:=nil;
+ code_alignment_factor:=1;
+ data_alignment_factor:=-1;
+ end;
+
+
+ procedure tdwarfcfi.generate_code(list:taasmoutput);
+ var
+ hp : tdwarfitem;
+ cielabel,
+ lenstartlabel,
+ lenendlabel : tasmlabel;
+ tc : tai_const;
+ begin
+ new_section(list,sec_debug_frame,'',0);
+ { CIE
+ DWORD length
+ DWORD CIE_Id = 0xffffffff
+ BYTE version = 1
+ STRING augmentation = "" = BYTE 0
+ ULEB128 code alignment factor = 1
+ ULEB128 data alignment factor = -1
+ BYTE return address register
+ <...> start sequence
+ }
+ objectlibrary.getjumplabel(cielabel);
+ list.concat(tai_label.create(cielabel));
+ objectlibrary.getjumplabel(lenstartlabel);
+ objectlibrary.getjumplabel(lenendlabel);
+ list.concat(tai_const.create_rel_sym(ait_const_32bit,lenstartlabel,lenendlabel));
+ list.concat(tai_label.create(lenstartlabel));
+ list.concat(tai_const.create_32bit(longint($ffffffff)));
+ list.concat(tai_const.create_8bit(1));
+ list.concat(tai_const.create_8bit(0)); { empty string }
+ list.concat(tai_const.create_uleb128bit(code_alignment_factor));
+ list.concat(tai_const.create_sleb128bit(data_alignment_factor));
+ list.concat(tai_const.create_8bit(dwarf_reg(NR_RETURN_ADDRESS_REG)));
+ { Generate standard code
+ def_cfa(stackpointer,sizeof(aint))
+ cfa_offset_extended(returnaddres,-sizeof(aint))
+ }
+{$warning TODO This needs to be target dependent}
+ list.concat(tai_const.create_8bit(DW_CFA_def_cfa));
+ list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_STACK_POINTER_REG)));
+ list.concat(tai_const.create_uleb128bit(sizeof(aint)));
+ list.concat(tai_const.create_8bit(DW_CFA_offset_extended));
+ list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_RETURN_ADDRESS_REG)));
+ list.concat(tai_const.create_uleb128bit((-sizeof(aint)) div data_alignment_factor));
+ list.concat(cai_align.create_zeros(4));
+ list.concat(tai_label.create(lenendlabel));
+ lenstartlabel:=nil;
+ lenendlabel:=nil;
+
+ hp:=TDwarfItem(al_dwarf.first);
+ while assigned(hp) do
+ begin
+ case hp.op of
+ DW_CFA_Start_Frame :
+ begin
+ if assigned(lenstartlabel) then
+ internalerror(200404125);
+ if (hp.ops<>1) or
+ (hp.oper[0].typ<>dop_reloffset) then
+ internalerror(200404126);
+ objectlibrary.getjumplabel(lenstartlabel);
+ objectlibrary.getjumplabel(lenendlabel);
+ { FDE
+ DWORD length
+ DWORD CIE-pointer = cielabel
+ PTRSIZE initial location = oper[0]
+ PTRSIZE function size = oper[1]
+ }
+ list.concat(tai_const.create_rel_sym(ait_const_32bit,lenstartlabel,lenendlabel));
+ list.concat(tai_label.create(lenstartlabel));
+ { force label offset to 32bit }
+ tc:=tai_const.create_sym(cielabel);
+ tc.typ:=ait_const_32bit;
+ list.concat(tc);
+ list.concat(tai_const.create_sym(hp.oper[0].beginsym));
+ list.concat(tai_const.create_rel_sym(ait_const_ptr,hp.oper[0].beginsym,hp.oper[0].endsym));
+ end;
+ DW_CFA_End_Frame :
+ begin
+ list.concat(cai_align.create_zeros(4));
+ list.concat(tai_label.create(lenendlabel));
+ lenstartlabel:=nil;
+ lenendlabel:=nil;
+ end;
+ else
+ hp.generate_code(list);
+ end;
+ hp:=TDwarfItem(hp.next);
+ end;
+ { Check for open frames }
+ if assigned(lenstartlabel) then
+ internalerror(2004041210);
+ { al_dwarf is processed, remove items }
+ al_dwarf.Clear;
+ end;
+
+
+ procedure tdwarfcfi.start_frame(list:taasmoutput);
+ begin
+ if assigned(FFrameStartLabel) then
+ internalerror(200404129);
+ objectlibrary.getjumplabel(FFrameStartLabel);
+ objectlibrary.getjumplabel(FFrameEndLabel);
+ FLastloclabel:=FFrameStartLabel;
+ list.concat(tai_label.create(FFrameStartLabel));
+ al_dwarf.concat(tdwarfitem.create_reloffset(DW_CFA_start_frame,doe_32bit,FFrameStartLabel,FFrameEndLabel));
+ end;
+
+
+ procedure tdwarfcfi.end_frame(list:taasmoutput);
+ begin
+ if not assigned(FFrameStartLabel) then
+ internalerror(2004041213);
+ al_dwarf.concat(tdwarfitem.create(DW_CFA_end_frame));
+ list.concat(tai_label.create(FFrameEndLabel));
+ FFrameStartLabel:=nil;
+ FFrameEndLabel:=nil;
+ FLastLocLabel:=nil;
+ end;
+
+
+ procedure tdwarfcfi.cfa_advance_loc(list:taasmoutput);
+ var
+ currloclabel : tasmlabel;
+ begin
+ if FLastloclabel=nil then
+ internalerror(200404082);
+ objectlibrary.getjumplabel(currloclabel);
+ list.concat(tai_label.create(currloclabel));
+ al_dwarf.concat(tdwarfitem.create_reloffset(DW_CFA_advance_loc4,doe_32bit,FLastloclabel,currloclabel));
+ FLastloclabel:=currloclabel;
+ end;
+
+
+ procedure tdwarfcfi.cfa_offset(list:taasmoutput;reg:tregister;ofs:longint);
+ begin
+ cfa_advance_loc(list);
+{$warning TODO check if ref is a temp}
+ { offset must be positive }
+ al_dwarf.concat(tdwarfitem.create_reg_const(DW_CFA_offset_extended,doe_uleb,reg,doe_uleb,ofs div data_alignment_factor));
+ end;
+
+
+ procedure tdwarfcfi.cfa_restore(list:taasmoutput;reg:tregister);
+ begin
+ cfa_advance_loc(list);
+ al_dwarf.concat(tdwarfitem.create_reg(DW_CFA_restore_extended,doe_uleb,reg));
+ end;
+
+
+ procedure tdwarfcfi.cfa_def_cfa_register(list:taasmoutput;reg:tregister);
+ begin
+ cfa_advance_loc(list);
+ al_dwarf.concat(tdwarfitem.create_reg(DW_CFA_def_cfa_register,doe_uleb,reg));
+ end;
+
+
+ procedure tdwarfcfi.cfa_def_cfa_offset(list:taasmoutput;ofs:longint);
+ begin
+ cfa_advance_loc(list);
+ al_dwarf.concat(tdwarfitem.create_const(DW_CFA_def_cfa_offset,doe_uleb,ofs));
+ end;
+
+
+begin
+{$warning TODO Maybe initialize per module}
+ dwarfcfi:=tdwarfcfi.create;
+end.
diff --git a/compiler/export.pas b/compiler/export.pas
new file mode 100644
index 0000000000..60bacf4545
--- /dev/null
+++ b/compiler/export.pas
@@ -0,0 +1,179 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an uniform export object
+
+ 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 export;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cutils,cclasses,
+ systems,
+ symtype,
+ aasmbase;
+
+const
+ { export options }
+ eo_resident = $1;
+ eo_index = $2;
+ eo_name = $4;
+
+type
+ texported_item = class(TLinkedListItem)
+ sym : tsym;
+ index : longint;
+ name : pstring;
+ options : word;
+ is_var : boolean;
+ constructor create;
+ destructor destroy;override;
+ end;
+
+ texportlib=class
+ private
+ notsupmsg : boolean;
+ procedure NotSupported;
+ public
+ edatalabel : tasmlabel;
+ constructor Create;virtual;
+ destructor Destroy;override;
+ procedure preparelib(const s : string);virtual;
+ procedure exportprocedure(hp : texported_item);virtual;
+ procedure exportvar(hp : texported_item);virtual;
+ procedure generatelib;virtual;
+ end;
+
+ TExportLibClass=class of TExportLib;
+
+var
+ CExportLib : array[tsystem] of TExportLibClass;
+ ExportLib : TExportLib;
+
+procedure RegisterExport(t:tsystem;c:TExportLibClass);
+procedure InitExport;
+procedure DoneExport;
+
+implementation
+
+uses
+ verbose,globals;
+
+{****************************************************************************
+ TExported_procedure
+****************************************************************************}
+
+constructor texported_item.Create;
+begin
+ inherited Create;
+ sym:=nil;
+ index:=-1;
+ name:=nil;
+ options:=0;
+ is_var:=false;
+end;
+
+
+destructor texported_item.destroy;
+begin
+ stringdispose(name);
+ inherited destroy;
+end;
+
+
+{****************************************************************************
+ TExportLib
+****************************************************************************}
+
+constructor texportlib.Create;
+begin
+ notsupmsg:=false;
+ edatalabel:=nil;
+end;
+
+
+destructor texportlib.Destroy;
+begin
+end;
+
+
+procedure texportlib.NotSupported;
+begin
+ { show the message only once }
+ if not notsupmsg then
+ begin
+ Message(exec_e_dll_not_supported);
+ notsupmsg:=true;
+ end;
+end;
+
+
+procedure texportlib.preparelib(const s:string);
+begin
+ NotSupported;
+end;
+
+
+procedure texportlib.exportprocedure(hp : texported_item);
+begin
+ NotSupported;
+end;
+
+
+procedure texportlib.exportvar(hp : texported_item);
+begin
+ NotSupported;
+end;
+
+
+procedure texportlib.generatelib;
+begin
+ NotSupported;
+end;
+
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+procedure RegisterExport(t:tsystem;c:TExportLibClass);
+begin
+ CExportLib[t]:=c;
+end;
+
+
+procedure InitExport;
+begin
+ if assigned(CExportLib[target_info.system]) then
+ exportlib:=CExportLib[target_info.system].Create
+ else
+ exportlib:=TExportLib.Create;
+end;
+
+
+procedure DoneExport;
+begin
+ if assigned(Exportlib) then
+ Exportlib.free;
+end;
+
+
+end.
diff --git a/compiler/finput.pas b/compiler/finput.pas
new file mode 100644
index 0000000000..c52925abb0
--- /dev/null
+++ b/compiler/finput.pas
@@ -0,0 +1,740 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an extended file management
+
+ 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 finput;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses;
+
+ const
+ InputFileBufSize=32*1024;
+ linebufincrease=512;
+
+ type
+ tlongintarr = array[0..1000000] of longint;
+ plongintarr = ^tlongintarr;
+
+ tinputfile = class
+ path,name : pstring; { path and filename }
+ next : tinputfile; { next file for reading }
+
+ is_macro,
+ endoffile, { still bytes left to read }
+ closed : boolean; { is the file closed }
+
+ buf : pchar; { buffer }
+ bufstart, { buffer start position in the file }
+ bufsize, { amount of bytes in the buffer }
+ maxbufsize : longint; { size in memory for the buffer }
+
+ saveinputpointer : pchar; { save fields for scanner variables }
+ savelastlinepos,
+ saveline_no : longint;
+
+ linebuf : plongintarr; { line buffer to retrieve lines }
+ maxlinebuf : longint;
+
+ ref_index : longint; { to handle the browser refs }
+ ref_next : tinputfile;
+
+ constructor create(const fn:string);
+ destructor destroy;override;
+ procedure setpos(l:longint);
+ procedure seekbuf(fpos:longint);
+ procedure readbuf;
+ function open:boolean;
+ procedure close;
+ procedure tempclose;
+ function tempopen:boolean;
+ procedure setmacro(p:pchar;len:longint);
+ procedure setline(line,linepos:longint);
+ function getlinestr(l:longint):string;
+ function getfiletime:longint;
+ protected
+ filetime : longint;
+ function fileopen(const filename: string): boolean; virtual; abstract;
+ function fileseek(pos: longint): boolean; virtual; abstract;
+ function fileread(var databuf; maxsize: longint): longint; virtual; abstract;
+ function fileeof: boolean; virtual; abstract;
+ function fileclose: boolean; virtual; abstract;
+ procedure filegettime; virtual; abstract;
+ end;
+
+ tdosinputfile = class(tinputfile)
+ protected
+ function fileopen(const filename: string): boolean; override;
+ function fileseek(pos: longint): boolean; override;
+ function fileread(var databuf; maxsize: longint): longint; override;
+ function fileeof: boolean; override;
+ function fileclose: boolean; override;
+ procedure filegettime; override;
+ private
+ f : file; { current file handle }
+ end;
+
+ tinputfilemanager = class
+ files : tinputfile;
+ last_ref_index : longint;
+ cacheindex : longint;
+ cacheinputfile : tinputfile;
+ constructor create;
+ destructor destroy;override;
+ procedure register_file(f : tinputfile);
+ procedure inverse_register_indexes;
+ function get_file(l:longint) : tinputfile;
+ function get_file_name(l :longint):string;
+ function get_file_path(l :longint):string;
+ end;
+
+{****************************************************************************
+ TModuleBase
+ ****************************************************************************}
+
+ type
+ tmodulestate = (ms_unknown,
+ ms_registered,
+ ms_load,ms_compile,
+ ms_second_load,ms_second_compile,
+ ms_compiled
+ );
+ const
+ ModuleStateStr : array[TModuleState] of string[20] = (
+ 'Unknown',
+ 'Registered',
+ 'Load','Compile',
+ 'Second_Load','Second_Compile',
+ 'Compiled'
+ );
+
+ type
+ tmodulebase = class(TLinkedListItem)
+ { index }
+ unit_index : longint; { global counter for browser }
+ { status }
+ state : tmodulestate;
+ { sources }
+ sourcefiles : tinputfilemanager;
+ { paths and filenames }
+ paramallowoutput : boolean; { original allowoutput parameter }
+ paramfn, { original filename }
+ path, { path where the module is find/created }
+ outputpath, { path where the .s / .o / exe are created }
+ modulename, { name of the module in uppercase }
+ realmodulename, { name of the module in the orignal case }
+ objfilename, { fullname of the objectfile }
+ newfilename, { fullname of the assemblerfile }
+ ppufilename, { fullname of the ppufile }
+ staticlibfilename, { fullname of the static libraryfile }
+ sharedlibfilename, { fullname of the shared libraryfile }
+ mapfilename, { fullname of the mapfile }
+ exefilename, { fullname of the exefile }
+ mainsource : pstring; { name of the main sourcefile }
+ constructor create(const s:string);
+ destructor destroy;override;
+ procedure setfilename(const fn:string;allowoutput:boolean);
+ function get_asmfilename : string;
+ end;
+
+
+implementation
+
+uses
+{$IFDEF USE_SYSUTILS}
+ SysUtils,
+ GlobType,
+{$ELSE USE_SYSUTILS}
+ dos,
+{$ENDIF USE_SYSUTILS}
+{$ifdef heaptrc}
+ fmodule,
+ ppheap,
+{$endif heaptrc}
+ globals,systems
+ ;
+
+{****************************************************************************
+ TINPUTFILE
+ ****************************************************************************}
+
+ constructor tinputfile.create(const fn:string);
+{$IFDEF USE_SYSUTILS}
+{$ELSE USE_SYSUTILS}
+ var
+ p:dirstr;
+ n:namestr;
+ e:extstr;
+{$ENDIF USE_SYSUTILS}
+ begin
+{$IFDEF USE_SYSUTILS}
+ name:=stringdup(SplitFileName(fn));
+ path:=stringdup(SplitPath(fn));
+{$ELSE USE_SYSUTILS}
+ FSplit(fn,p,n,e);
+ name:=stringdup(n+e);
+ path:=stringdup(p);
+{$ENDIF USE_SYSUTILS}
+ next:=nil;
+ filetime:=-1;
+ { file info }
+ is_macro:=false;
+ endoffile:=false;
+ closed:=true;
+ buf:=nil;
+ bufstart:=0;
+ bufsize:=0;
+ maxbufsize:=InputFileBufSize;
+ { save fields }
+ saveinputpointer:=nil;
+ saveline_no:=0;
+ savelastlinepos:=0;
+ { indexing refs }
+ ref_next:=nil;
+ ref_index:=0;
+ { line buffer }
+ linebuf:=nil;
+ maxlinebuf:=0;
+ end;
+
+
+ destructor tinputfile.destroy;
+ begin
+ if not closed then
+ close;
+ stringdispose(path);
+ stringdispose(name);
+ { free memory }
+ if assigned(linebuf) then
+ freemem(linebuf,maxlinebuf shl 2);
+ end;
+
+
+ procedure tinputfile.setpos(l:longint);
+ begin
+ bufstart:=l;
+ end;
+
+
+ procedure tinputfile.seekbuf(fpos:longint);
+ begin
+ if closed then
+ exit;
+ fileseek(fpos);
+ bufstart:=fpos;
+ bufsize:=0;
+ end;
+
+
+ procedure tinputfile.readbuf;
+ begin
+ if is_macro then
+ endoffile:=true;
+ if closed then
+ exit;
+ inc(bufstart,bufsize);
+ bufsize:=fileread(buf^,maxbufsize-1);
+ buf[bufsize]:=#0;
+ endoffile:=fileeof;
+ end;
+
+
+ function tinputfile.open:boolean;
+ begin
+ open:=false;
+ if not closed then
+ Close;
+ if not fileopen(path^+name^) then
+ exit;
+ { file }
+ endoffile:=false;
+ closed:=false;
+ Getmem(buf,MaxBufsize);
+ bufstart:=0;
+ bufsize:=0;
+ open:=true;
+ end;
+
+
+ procedure tinputfile.close;
+ begin
+ if is_macro then
+ begin
+ if assigned(buf) then
+ begin
+ Freemem(buf,maxbufsize);
+ buf:=nil;
+ end;
+ closed:=true;
+ exit;
+ end;
+ if not closed then
+ begin
+ fileclose;
+ closed:=true;
+ end;
+ if assigned(buf) then
+ begin
+ Freemem(buf,maxbufsize);
+ buf:=nil;
+ end;
+ bufstart:=0;
+ end;
+
+
+ procedure tinputfile.tempclose;
+ begin
+ if is_macro then
+ exit;
+ if not closed then
+ begin
+ fileclose;
+ if assigned(buf) then
+ begin
+ Freemem(buf,maxbufsize);
+ buf:=nil;
+ end;
+ closed:=true;
+ end;
+ end;
+
+
+ function tinputfile.tempopen:boolean;
+ begin
+ tempopen:=false;
+ if is_macro then
+ begin
+ { seek buffer postion to bufstart }
+ if bufstart>0 then
+ begin
+ move(buf[bufstart],buf[0],bufsize-bufstart+1);
+ bufstart:=0;
+ end;
+ tempopen:=true;
+ exit;
+ end;
+ if not closed then
+ exit;
+ if not fileopen(path^+name^) then
+ exit;
+ closed:=false;
+ { get new mem }
+ Getmem(buf,maxbufsize);
+ { restore state }
+ fileseek(BufStart);
+ bufsize:=0;
+ readbuf;
+ tempopen:=true;
+ end;
+
+
+ procedure tinputfile.setmacro(p:pchar;len:longint);
+ begin
+ { create new buffer }
+ getmem(buf,len+1);
+ move(p^,buf^,len);
+ buf[len]:=#0;
+ { reset }
+ bufstart:=0;
+ bufsize:=len;
+ maxbufsize:=len+1;
+ is_macro:=true;
+ endoffile:=true;
+ closed:=true;
+ end;
+
+
+ procedure tinputfile.setline(line,linepos:longint);
+ var
+ oldlinebuf : plongintarr;
+ begin
+ if line<1 then
+ exit;
+ while (line>=maxlinebuf) do
+ begin
+ oldlinebuf:=linebuf;
+ { create new linebuf and move old info }
+ getmem(linebuf,(maxlinebuf+linebufincrease) shl 2);
+ if assigned(oldlinebuf) then
+ begin
+ move(oldlinebuf^,linebuf^,maxlinebuf shl 2);
+ freemem(oldlinebuf,maxlinebuf shl 2);
+ end;
+ fillchar(linebuf^[maxlinebuf],linebufincrease shl 2,0);
+ inc(maxlinebuf,linebufincrease);
+ end;
+ linebuf^[line]:=linepos;
+ end;
+
+
+ function tinputfile.getlinestr(l:longint):string;
+ var
+ c : char;
+ i,
+ fpos : longint;
+ p : pchar;
+ begin
+ getlinestr:='';
+ if l<maxlinebuf then
+ begin
+ fpos:=linebuf^[l];
+ { fpos is set negativ if the line was already written }
+ { but we still know the correct value }
+ if fpos<0 then
+ fpos:=-fpos+1;
+ if closed then
+ open;
+ { in current buf ? }
+ if (fpos<bufstart) or (fpos>bufstart+bufsize) then
+ begin
+ seekbuf(fpos);
+ readbuf;
+ end;
+ { the begin is in the buf now simply read until #13,#10 }
+ i:=0;
+ p:=@buf[fpos-bufstart];
+ repeat
+ c:=p^;
+ if c=#0 then
+ begin
+ if endoffile then
+ break;
+ readbuf;
+ p:=buf;
+ c:=p^;
+ end;
+ if c in [#10,#13] then
+ break;
+ inc(i);
+ getlinestr[i]:=c;
+ inc(p);
+ until (i=255);
+ getlinestr[0]:=chr(i);
+ end;
+ end;
+
+
+ function tinputfile.getfiletime:longint;
+ begin
+ if filetime=-1 then
+ filegettime;
+ getfiletime:=filetime;
+ end;
+
+
+{****************************************************************************
+ TDOSINPUTFILE
+ ****************************************************************************}
+
+ function tdosinputfile.fileopen(const filename: string): boolean;
+ var
+ ofm : byte;
+ begin
+ { Check if file exists, this will also check if it is
+ a real file and not a directory }
+ if not fileexists(filename) then
+ begin
+ result:=false;
+ exit;
+ end;
+ { Open file }
+ ofm:=filemode;
+ filemode:=0;
+ Assign(f,filename);
+ {$I-}
+ reset(f,1);
+ {$I+}
+ filemode:=ofm;
+ fileopen:=(ioresult=0);
+ end;
+
+
+ function tdosinputfile.fileseek(pos: longint): boolean;
+ begin
+ {$I-}
+ seek(f,Pos);
+ {$I+}
+ fileseek:=(ioresult=0);
+ end;
+
+
+ function tdosinputfile.fileread(var databuf; maxsize: longint): longint;
+ var
+ w : longint;
+ begin
+ blockread(f,databuf,maxsize,w);
+ fileread:=w;
+ end;
+
+
+ function tdosinputfile.fileeof: boolean;
+ begin
+ fileeof:=eof(f);
+ end;
+
+
+ function tdosinputfile.fileclose: boolean;
+ begin
+ {$I-}
+ system.close(f);
+ {$I+}
+ fileclose:=(ioresult=0);
+ end;
+
+
+ procedure tdosinputfile.filegettime;
+ begin
+ filetime:=getnamedfiletime(path^+name^);
+ end;
+
+
+{****************************************************************************
+ Tinputfilemanager
+ ****************************************************************************}
+
+ constructor tinputfilemanager.create;
+ begin
+ files:=nil;
+ last_ref_index:=0;
+ cacheindex:=0;
+ cacheinputfile:=nil;
+ end;
+
+
+ destructor tinputfilemanager.destroy;
+ var
+ hp : tinputfile;
+ begin
+ hp:=files;
+ while assigned(hp) do
+ begin
+ files:=files.ref_next;
+ hp.free;
+ hp:=files;
+ end;
+ last_ref_index:=0;
+ end;
+
+
+ procedure tinputfilemanager.register_file(f : tinputfile);
+ begin
+ { don't register macro's }
+ if f.is_macro then
+ exit;
+ inc(last_ref_index);
+ f.ref_next:=files;
+ f.ref_index:=last_ref_index;
+ files:=f;
+ { update cache }
+ cacheindex:=last_ref_index;
+ cacheinputfile:=f;
+{$ifdef heaptrc}
+ ppheap_register_file(f.name^,current_module.unit_index*100000+f.ref_index);
+{$endif heaptrc}
+ end;
+
+
+ { this procedure is necessary after loading the
+ sources files from a PPU file PM }
+ procedure tinputfilemanager.inverse_register_indexes;
+ var
+ f : tinputfile;
+ begin
+ f:=files;
+ while assigned(f) do
+ begin
+ f.ref_index:=last_ref_index-f.ref_index+1;
+ f:=f.ref_next;
+ end;
+ { reset cache }
+ cacheindex:=0;
+ cacheinputfile:=nil;
+ end;
+
+
+
+ function tinputfilemanager.get_file(l :longint) : tinputfile;
+ var
+ ff : tinputfile;
+ begin
+ { check cache }
+ if (l=cacheindex) and assigned(cacheinputfile) then
+ begin
+ get_file:=cacheinputfile;
+ exit;
+ end;
+ ff:=files;
+ while assigned(ff) and (ff.ref_index<>l) do
+ ff:=ff.ref_next;
+ get_file:=ff;
+ end;
+
+
+ function tinputfilemanager.get_file_name(l :longint):string;
+ var
+ hp : tinputfile;
+ begin
+ hp:=get_file(l);
+ if assigned(hp) then
+ get_file_name:=hp.name^
+ else
+ get_file_name:='';
+ end;
+
+
+ function tinputfilemanager.get_file_path(l :longint):string;
+ var
+ hp : tinputfile;
+ begin
+ hp:=get_file(l);
+ if assigned(hp) then
+ get_file_path:=hp.path^
+ else
+ get_file_path:='';
+ end;
+
+
+{****************************************************************************
+ TModuleBase
+ ****************************************************************************}
+
+ procedure tmodulebase.setfilename(const fn:string;allowoutput:boolean);
+ var
+ p : dirstr;
+ n : NameStr;
+ e : ExtStr;
+ prefix,
+ suffix,
+ extension : NameStr;
+ begin
+ stringdispose(objfilename);
+ stringdispose(newfilename);
+ stringdispose(ppufilename);
+ stringdispose(staticlibfilename);
+ stringdispose(sharedlibfilename);
+ stringdispose(mapfilename);
+ stringdispose(exefilename);
+ stringdispose(outputpath);
+ stringdispose(path);
+ { Create names }
+ paramfn := stringdup(fn);
+ paramallowoutput := allowoutput;
+{$IFDEF USE_SYSUTILS}
+ p := SplitPath(fn);
+ n := SplitName(fn);
+ e := SplitExtension(fn);
+{$ELSE USE_SYSUTILS}
+ fsplit(fn,p,n,e);
+{$ENDIF USE_SYSUTILS}
+ n:=FixFileName(n);
+ { set path }
+ path:=stringdup(FixPath(p,false));
+ { obj,asm,ppu names }
+ p:=path^;
+ if AllowOutput then
+ begin
+ if (OutputUnitDir<>'') then
+ p:=OutputUnitDir
+ else
+ if (OutputExeDir<>'') then
+ p:=OutputExeDir;
+ end;
+ outputpath:=stringdup(p);
+ newfilename := stringdup(n);
+ objfilename:=stringdup(p+n+target_info.objext);
+ ppufilename:=stringdup(p+n+target_info.unitext);
+ { lib and exe could be loaded with a file specified with -o }
+ prefix := target_info.sharedlibprefix;
+ suffix := '';
+ extension := target_info.sharedlibext;
+
+ if AllowOutput and (compile_level=1) then
+ begin
+ if OutputFile <> '' then n:=OutputFile;
+ if Assigned(OutputPrefix) then prefix := OutputPrefix^;
+ if Assigned(OutputSuffix) then suffix := OutputSuffix^;
+ if OutputExtension <> '' then extension := OutputExtension;
+ end;
+
+ staticlibfilename:=stringdup(p+target_info.staticlibprefix+n+target_info.staticlibext);
+ { output dir of exe can be specified separatly }
+ if AllowOutput and (OutputExeDir<>'') then
+ p:=OutputExeDir
+ else
+ p:=path^;
+ sharedlibfilename:=stringdup(p+prefix+n+suffix+extension);
+ exefilename:=stringdup(p+n+target_info.exeext);
+ mapfilename:=stringdup(p+n+'.map');
+ end;
+
+
+ constructor tmodulebase.create(const s:string);
+ begin
+ modulename:=stringdup(Upper(s));
+ realmodulename:=stringdup(s);
+ mainsource:=nil;
+ ppufilename:=nil;
+ objfilename:=nil;
+ newfilename:=nil;
+ staticlibfilename:=nil;
+ sharedlibfilename:=nil;
+ exefilename:=nil;
+ mapfilename:=nil;
+ outputpath:=nil;
+ path:=nil;
+ { status }
+ state:=ms_registered;
+ { unit index }
+ inc(global_unit_count);
+ unit_index:=global_unit_count;
+ { sources }
+ sourcefiles:=TInputFileManager.Create;
+ end;
+
+
+ function tmodulebase.get_asmfilename : string;
+ begin
+ get_asmfilename:=outputpath^+newfilename^+target_info.asmext;
+ end;
+
+ destructor tmodulebase.destroy;
+ begin
+ if assigned(sourcefiles) then
+ sourcefiles.free;
+ sourcefiles:=nil;
+ stringdispose(objfilename);
+ stringdispose(newfilename);
+ stringdispose(ppufilename);
+ stringdispose(staticlibfilename);
+ stringdispose(sharedlibfilename);
+ stringdispose(exefilename);
+ stringdispose(mapfilename);
+ stringdispose(outputpath);
+ stringdispose(path);
+ stringdispose(modulename);
+ stringdispose(realmodulename);
+ stringdispose(mainsource);
+ inherited destroy;
+ end;
+
+end.
diff --git a/compiler/fmodule.pas b/compiler/fmodule.pas
new file mode 100644
index 0000000000..efe27ddaa8
--- /dev/null
+++ b/compiler/fmodule.pas
@@ -0,0 +1,831 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the first loading and searching of the modules
+
+ 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 fmodule;
+
+{$i fpcdefs.inc}
+
+{$ifdef go32v2}
+ {$define shortasmprefix}
+{$endif}
+{$ifdef watcom}
+ {$define shortasmprefix}
+{$endif}
+{$ifdef tos}
+ {$define shortasmprefix}
+{$endif}
+{$ifdef OS2}
+ { Allthough OS/2 supports long filenames I play it safe and
+ use 8.3 filenames, because this allows the compiler to run
+ on a FAT partition. (DM) }
+ {$define shortasmprefix}
+{$endif}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globals,finput,
+ symbase,symsym,aasmbase;
+
+
+ type
+ trecompile_reason = (rr_unknown,
+ rr_noppu,rr_sourcenewer,rr_build,rr_crcchanged
+ );
+
+ TExternalsItem=class(TLinkedListItem)
+ public
+ found : longbool;
+ data : pstring;
+ constructor Create(const s:string);
+ Destructor Destroy;override;
+ end;
+
+ tlinkcontaineritem=class(tlinkedlistitem)
+ public
+ data : pstring;
+ needlink : cardinal;
+ constructor Create(const s:string;m:cardinal);
+ destructor Destroy;override;
+ end;
+
+ tlinkcontainer=class(tlinkedlist)
+ procedure add(const s : string;m:cardinal);
+ function get(var m:cardinal) : string;
+ function getusemask(mask:cardinal) : string;
+ function find(const s:string):boolean;
+ end;
+
+ tmodule = class;
+ tused_unit = class;
+
+ tunitmaprec = record
+ u : tmodule;
+ { number of references }
+ refs : longint;
+ { index in the derefmap }
+ derefidx : longint;
+ end;
+ punitmap = ^tunitmaprec;
+
+ tderefmaprec = record
+ u : tmodule;
+ { modulename, used during ppu load }
+ modulename : pstring;
+ end;
+ pderefmap = ^tderefmaprec;
+
+ tmodule = class(tmodulebase)
+ do_reload, { force reloading of the unit }
+ do_compile, { need to compile the sources }
+ sources_avail, { if all sources are reachable }
+ interface_compiled, { if the interface section has been parsed/compiled/loaded }
+ is_stab_written,
+ is_reset,
+ is_unit,
+ in_interface, { processing the implementation part? }
+ in_global : boolean; { allow global settings }
+ mode_switch_allowed : boolean; { Whether a mode switch is still allowed at this point in the parsing.}
+ mainfilepos : tfileposinfo;
+ recompile_reason : trecompile_reason; { the reason why the unit should be recompiled }
+ crc,
+ interface_crc : cardinal;
+ flags : cardinal; { the PPU flags }
+ islibrary : boolean; { if it is a library (win32 dll) }
+ moduleid : longint;
+ unitmap : punitmap; { mapping of all used units }
+ unitmapsize : longint; { number of units in the map }
+ derefmap : pderefmap; { mapping of all units needed for deref }
+ derefmapcnt : longint; { number of units in the map }
+ derefmapsize : longint; { number of units in the map }
+ derefdataintflen : longint;
+ derefdata : tdynamicarray;
+ globalsymtable, { pointer to the global symtable of this unit }
+ localsymtable : tsymtable;{ pointer to the local symtable of this unit }
+ globalmacrosymtable, { pointer to the global macro symtable of this unit }
+ localmacrosymtable : tsymtable;{ pointer to the local macro symtable of this unit }
+ scanner : pointer; { scanner object used }
+ procinfo : pointer; { current procedure being compiled }
+ loaded_from : tmodule;
+ uses_imports : boolean; { Set if the module imports from DLL's.}
+ imports : tlinkedlist;
+ _exports : tlinkedlist;
+ externals : tlinkedlist; {Only for DLL scanners by using Unix-style $LINKLIB }
+ resourcefiles : tstringlist;
+ linkunitofiles,
+ linkunitstaticlibs,
+ linkunitsharedlibs,
+ linkotherofiles, { objects,libs loaded from the source }
+ linkothersharedlibs, { using $L or $LINKLIB or import lib (for linux) }
+ linkotherstaticlibs : tlinkcontainer;
+
+ used_units : tlinkedlist;
+ dependent_units : tlinkedlist;
+
+ localunitsearchpath, { local searchpaths }
+ localobjectsearchpath,
+ localincludesearchpath,
+ locallibrarysearchpath : TSearchPathList;
+
+ asmprefix : pstring; { prefix for the smartlink asmfiles }
+ librarydata : tasmlibrarydata; { librarydata for this module }
+ {create creates a new module which name is stored in 's'. LoadedFrom
+ points to the module calling it. It is nil for the first compiled
+ module. This allow inheritence of all path lists. MUST pay attention
+ to that when creating link.res!!!!(mazen)}
+ constructor create(LoadedFrom:TModule;const s:string;_is_unit:boolean);
+ destructor destroy;override;
+ procedure reset;virtual;
+ procedure adddependency(callermodule:tmodule);
+ procedure flagdependent(callermodule:tmodule);
+ function addusedunit(hp:tmodule;inuses:boolean;usym:tunitsym):tused_unit;
+ procedure updatemaps;
+ function derefidx_unit(id:longint):longint;
+ function resolve_unit(id:longint):tmodule;
+ procedure allunitsused;
+ procedure setmodulename(const s:string);
+ end;
+
+ tused_unit = class(tlinkedlistitem)
+ checksum,
+ interface_checksum : cardinal;
+ in_uses,
+ in_interface : boolean;
+ u : tmodule;
+ unitsym : tunitsym;
+ constructor create(_u : tmodule;intface,inuses:boolean;usym:tunitsym);
+ end;
+
+ tdependent_unit = class(tlinkedlistitem)
+ u : tmodule;
+ constructor create(_u : tmodule);
+ end;
+
+ var
+ main_module : tmodule; { Main module of the program }
+ current_module : tmodule; { Current module which is compiled or loaded }
+ compiled_module : tmodule; { Current module which is compiled }
+ usedunits : tlinkedlist; { Used units for this program }
+ loaded_units : tlinkedlist; { All loaded units }
+ SmartLinkOFiles : TStringList; { List of .o files which are generated,
+ used to delete them after linking }
+
+ function get_source_file(moduleindex,fileindex : longint) : tinputfile;
+ procedure addloadedunit(hp:tmodule);
+
+
+implementation
+
+ uses
+ {$IFDEF USE_SYSUTILS}
+ SysUtils,
+ GlobType,
+ {$ELSE USE_SYSUTILS}
+ dos,
+ {$ENDIF USE_SYSUTILS}
+ verbose,systems,
+ scanner,ppu,
+ procinfo;
+
+
+{*****************************************************************************
+ Global Functions
+*****************************************************************************}
+
+ function get_source_file(moduleindex,fileindex : longint) : tinputfile;
+ var
+ hp : tmodule;
+ begin
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) and (hp.unit_index<>moduleindex) do
+ hp:=tmodule(hp.next);
+ if assigned(hp) then
+ get_source_file:=hp.sourcefiles.get_file(fileindex)
+ else
+ get_source_file:=nil;
+ end;
+
+
+ procedure addloadedunit(hp:tmodule);
+ begin
+ hp.moduleid:=loaded_units.count;
+ loaded_units.concat(hp);
+ end;
+
+
+{****************************************************************************
+ TLinkContainerItem
+ ****************************************************************************}
+
+ constructor TLinkContainerItem.Create(const s:string;m:cardinal);
+ begin
+ inherited Create;
+ data:=stringdup(s);
+ needlink:=m;
+ end;
+
+
+ destructor TLinkContainerItem.Destroy;
+ begin
+ stringdispose(data);
+ end;
+
+
+{****************************************************************************
+ TLinkContainer
+ ****************************************************************************}
+
+ procedure TLinkContainer.add(const s : string;m:cardinal);
+ begin
+ inherited concat(TLinkContainerItem.Create(s,m));
+ end;
+
+
+ function TLinkContainer.get(var m:cardinal) : string;
+ var
+ p : tlinkcontaineritem;
+ begin
+ p:=tlinkcontaineritem(inherited getfirst);
+ if p=nil then
+ begin
+ get:='';
+ m:=0;
+ end
+ else
+ begin
+ get:=p.data^;
+ m:=p.needlink;
+ p.free;
+ end;
+ end;
+
+
+ function TLinkContainer.getusemask(mask:cardinal) : string;
+ var
+ p : tlinkcontaineritem;
+ found : boolean;
+ begin
+ found:=false;
+ repeat
+ p:=tlinkcontaineritem(inherited getfirst);
+ if p=nil then
+ begin
+ getusemask:='';
+ exit;
+ end;
+ getusemask:=p.data^;
+ found:=(p.needlink and mask)<>0;
+ p.free;
+ until found;
+ end;
+
+
+ function TLinkContainer.find(const s:string):boolean;
+ var
+ newnode : tlinkcontaineritem;
+ begin
+ find:=false;
+ newnode:=tlinkcontaineritem(First);
+ while assigned(newnode) do
+ begin
+ if newnode.data^=s then
+ begin
+ find:=true;
+ exit;
+ end;
+ newnode:=tlinkcontaineritem(newnode.next);
+ end;
+ end;
+
+
+{****************************************************************************
+ TExternalsItem
+ ****************************************************************************}
+
+ constructor tExternalsItem.Create(const s:string);
+ begin
+ inherited Create;
+ found:=false;
+ data:=stringdup(s);
+ end;
+
+
+ destructor tExternalsItem.Destroy;
+ begin
+ stringdispose(data);
+ inherited;
+ end;
+
+
+{****************************************************************************
+ TUSED_UNIT
+ ****************************************************************************}
+
+ constructor tused_unit.create(_u : tmodule;intface,inuses:boolean;usym:tunitsym);
+ begin
+ u:=_u;
+ in_interface:=intface;
+ in_uses:=inuses;
+ unitsym:=usym;
+ if _u.state=ms_compiled then
+ begin
+ checksum:=u.crc;
+ interface_checksum:=u.interface_crc;
+ end
+ else
+ begin
+ checksum:=0;
+ interface_checksum:=0;
+ end;
+ end;
+
+
+{****************************************************************************
+ TDENPENDENT_UNIT
+ ****************************************************************************}
+
+ constructor tdependent_unit.create(_u : tmodule);
+ begin
+ u:=_u;
+ end;
+
+
+{****************************************************************************
+ TMODULE
+ ****************************************************************************}
+
+ constructor tmodule.create(LoadedFrom:TModule;const s:string;_is_unit:boolean);
+ var
+ p : dirstr;
+ n : namestr;
+ e : extstr;
+ begin
+ {$IFDEF USE_SYSUTILS}
+ p := SplitPath(s);
+ n := SplitName(s);
+ e := SplitExtension(s);
+ {$ELSE USE_SYSUTILS}
+ FSplit(s,p,n,e);
+ {$ENDIF USE_SYSUTILS}
+ { Programs have the name 'Program' to don't conflict with dup id's }
+ if _is_unit then
+ inherited create(n)
+ else
+ inherited create('Program');
+ mainsource:=stringdup(s);
+ { Dos has the famous 8.3 limit :( }
+{$ifdef shortasmprefix}
+ asmprefix:=stringdup(FixFileName('as'));
+{$else}
+ asmprefix:=stringdup(FixFileName(n));
+{$endif}
+ setfilename(p+n,true);
+ localunitsearchpath:=TSearchPathList.Create;
+ localobjectsearchpath:=TSearchPathList.Create;
+ localincludesearchpath:=TSearchPathList.Create;
+ locallibrarysearchpath:=TSearchPathList.Create;
+ used_units:=TLinkedList.Create;
+ dependent_units:=TLinkedList.Create;
+ resourcefiles:=TStringList.Create;
+ linkunitofiles:=TLinkContainer.Create;
+ linkunitstaticlibs:=TLinkContainer.Create;
+ linkunitsharedlibs:=TLinkContainer.Create;
+ linkotherofiles:=TLinkContainer.Create;
+ linkotherstaticlibs:=TLinkContainer.Create;
+ linkothersharedlibs:=TLinkContainer.Create;
+ crc:=0;
+ interface_crc:=0;
+ flags:=0;
+ scanner:=nil;
+ unitmap:=nil;
+ unitmapsize:=0;
+ derefmap:=nil;
+ derefmapsize:=0;
+ derefmapcnt:=0;
+ derefdata:=TDynamicArray.Create(1024);
+ derefdataintflen:=0;
+ globalsymtable:=nil;
+ localsymtable:=nil;
+ globalmacrosymtable:=nil;
+ localmacrosymtable:=nil;
+ loaded_from:=LoadedFrom;
+ do_reload:=false;
+ do_compile:=false;
+ sources_avail:=true;
+ mainfilepos.line:=0;
+ mainfilepos.column:=0;
+ mainfilepos.fileindex:=0;
+ recompile_reason:=rr_unknown;
+ in_interface:=true;
+ in_global:=true;
+ is_unit:=_is_unit;
+ islibrary:=false;
+ is_stab_written:=false;
+ is_reset:=false;
+ mode_switch_allowed:= true;
+ uses_imports:=false;
+ imports:=TLinkedList.Create;
+ _exports:=TLinkedList.Create;
+ externals:=TLinkedList.Create;
+ librarydata:=tasmlibrarydata.create(realmodulename^);
+ end;
+
+
+ destructor tmodule.Destroy;
+ var
+{$ifdef MEMDEBUG}
+ d : tmemdebug;
+{$endif}
+ i : longint;
+ hpi : tprocinfo;
+ begin
+ if assigned(unitmap) then
+ freemem(unitmap);
+ if assigned(derefmap) then
+ begin
+ for i:=0 to derefmapcnt-1 do
+ stringdispose(derefmap[i].modulename);
+ freemem(derefmap);
+ end;
+ if assigned(imports) then
+ imports.free;
+ if assigned(_exports) then
+ _exports.free;
+ if assigned(externals) then
+ externals.free;
+ if assigned(scanner) then
+ begin
+ { also update current_scanner if it was pointing
+ to this module }
+ if current_scanner=tscannerfile(scanner) then
+ current_scanner:=nil;
+ tscannerfile(scanner).free;
+ end;
+ if assigned(procinfo) then
+ begin
+ if current_procinfo=tprocinfo(procinfo) then
+ current_procinfo:=nil;
+ { release procinfo tree }
+ while assigned(procinfo) do
+ begin
+ hpi:=tprocinfo(procinfo).parent;
+ tprocinfo(procinfo).free;
+ procinfo:=hpi;
+ end;
+ end;
+ used_units.free;
+ dependent_units.free;
+ resourcefiles.Free;
+ linkunitofiles.Free;
+ linkunitstaticlibs.Free;
+ linkunitsharedlibs.Free;
+ linkotherofiles.Free;
+ linkotherstaticlibs.Free;
+ linkothersharedlibs.Free;
+ stringdispose(objfilename);
+ stringdispose(newfilename);
+ stringdispose(ppufilename);
+ stringdispose(staticlibfilename);
+ stringdispose(sharedlibfilename);
+ stringdispose(exefilename);
+ stringdispose(outputpath);
+ stringdispose(path);
+ stringdispose(realmodulename);
+ stringdispose(mainsource);
+ stringdispose(asmprefix);
+ localunitsearchpath.Free;
+ localobjectsearchpath.free;
+ localincludesearchpath.free;
+ locallibrarysearchpath.free;
+{$ifdef MEMDEBUG}
+ d:=tmemdebug.create(modulename^+' - symtable');
+{$endif}
+ derefdata.free;
+ if assigned(globalsymtable) then
+ globalsymtable.free;
+ if assigned(localsymtable) then
+ localsymtable.free;
+ if assigned(globalmacrosymtable) then
+ globalmacrosymtable.free;
+ if assigned(localmacrosymtable) then
+ localmacrosymtable.free;
+{$ifdef MEMDEBUG}
+ d.free;
+{$endif}
+{$ifdef MEMDEBUG}
+ d:=tmemdebug.create(modulename^+' - librarydata');
+{$endif}
+ librarydata.free;
+{$ifdef MEMDEBUG}
+ d.free;
+{$endif}
+ stringdispose(modulename);
+ inherited Destroy;
+ end;
+
+
+ procedure tmodule.reset;
+ var
+ hpi : tprocinfo;
+ i : longint;
+ begin
+ if assigned(scanner) then
+ begin
+ { also update current_scanner if it was pointing
+ to this module }
+ if current_scanner=tscannerfile(scanner) then
+ current_scanner:=nil;
+ tscannerfile(scanner).free;
+ scanner:=nil;
+ end;
+ if assigned(procinfo) then
+ begin
+ if current_procinfo=tprocinfo(procinfo) then
+ current_procinfo:=nil;
+ { release procinfo tree }
+ while assigned(procinfo) do
+ begin
+ hpi:=tprocinfo(procinfo).parent;
+ tprocinfo(procinfo).free;
+ procinfo:=hpi;
+ end;
+ end;
+ if assigned(globalsymtable) then
+ begin
+ globalsymtable.free;
+ globalsymtable:=nil;
+ end;
+ if assigned(localsymtable) then
+ begin
+ localsymtable.free;
+ localsymtable:=nil;
+ end;
+ if assigned(globalmacrosymtable) then
+ begin
+ globalmacrosymtable.free;
+ globalmacrosymtable:=nil;
+ end;
+ if assigned(localmacrosymtable) then
+ begin
+ localmacrosymtable.free;
+ localmacrosymtable:=nil;
+ end;
+ derefdata.free;
+ derefdata:=TDynamicArray.Create(1024);
+ if assigned(unitmap) then
+ begin
+ freemem(unitmap);
+ unitmap:=nil;
+ end;
+ if assigned(derefmap) then
+ begin
+ for i:=0 to derefmapcnt-1 do
+ stringdispose(derefmap[i].modulename);
+ freemem(derefmap);
+ derefmap:=nil;
+ end;
+ unitmapsize:=0;
+ derefmapsize:=0;
+ derefmapcnt:=0;
+ derefdataintflen:=0;
+ sourcefiles.free;
+ sourcefiles:=tinputfilemanager.create;
+ librarydata.free;
+ librarydata:=tasmlibrarydata.create(realmodulename^);
+ imports.free;
+ imports:=tlinkedlist.create;
+ _exports.free;
+ _exports:=tlinkedlist.create;
+ externals.free;
+ externals:=tlinkedlist.create;
+ used_units.free;
+ used_units:=TLinkedList.Create;
+ dependent_units.free;
+ dependent_units:=TLinkedList.Create;
+ resourcefiles.Free;
+ resourcefiles:=TStringList.Create;
+ linkunitofiles.Free;
+ linkunitofiles:=TLinkContainer.Create;
+ linkunitstaticlibs.Free;
+ linkunitstaticlibs:=TLinkContainer.Create;
+ linkunitsharedlibs.Free;
+ linkunitsharedlibs:=TLinkContainer.Create;
+ linkotherofiles.Free;
+ linkotherofiles:=TLinkContainer.Create;
+ linkotherstaticlibs.Free;
+ linkotherstaticlibs:=TLinkContainer.Create;
+ linkothersharedlibs.Free;
+ linkothersharedlibs:=TLinkContainer.Create;
+ uses_imports:=false;
+ do_compile:=false;
+ do_reload:=false;
+ interface_compiled:=false;
+ in_interface:=true;
+ in_global:=true;
+ mode_switch_allowed:=true;
+ is_stab_written:=false;
+ is_reset:=false;
+ crc:=0;
+ interface_crc:=0;
+ flags:=0;
+ mainfilepos.line:=0;
+ mainfilepos.column:=0;
+ mainfilepos.fileindex:=0;
+ recompile_reason:=rr_unknown;
+ {
+ The following fields should not
+ be reset:
+ mainsource
+ state
+ loaded_from
+ sources_avail
+ }
+ end;
+
+
+ procedure tmodule.adddependency(callermodule:tmodule);
+ begin
+ { This is not needed for programs }
+ if not callermodule.is_unit then
+ exit;
+ Message2(unit_u_add_depend_to,callermodule.modulename^,modulename^);
+ dependent_units.concat(tdependent_unit.create(callermodule));
+ end;
+
+
+ procedure tmodule.flagdependent(callermodule:tmodule);
+ var
+ pm : tdependent_unit;
+ begin
+ { flag all units that depend on this unit for reloading }
+ pm:=tdependent_unit(current_module.dependent_units.first);
+ while assigned(pm) do
+ begin
+ { We do not have to reload the unit that wants to load
+ this unit, unless this unit is already compiled during
+ the loading }
+ if (pm.u=callermodule) and
+ (pm.u.state<>ms_compiled) then
+ Message1(unit_u_no_reload_is_caller,pm.u.modulename^)
+ else
+ if pm.u.state=ms_second_compile then
+ Message1(unit_u_no_reload_in_second_compile,pm.u.modulename^)
+ else
+ begin
+ pm.u.do_reload:=true;
+ Message1(unit_u_flag_for_reload,pm.u.modulename^);
+ end;
+ pm:=tdependent_unit(pm.next);
+ end;
+ end;
+
+
+ function tmodule.addusedunit(hp:tmodule;inuses:boolean;usym:tunitsym):tused_unit;
+ var
+ pu : tused_unit;
+ begin
+ pu:=tused_unit.create(hp,in_interface,inuses,usym);
+ used_units.concat(pu);
+ addusedunit:=pu;
+ end;
+
+
+ procedure tmodule.updatemaps;
+ var
+ oldmapsize : longint;
+ hp : tmodule;
+ i : longint;
+ begin
+ { Extend unitmap }
+ oldmapsize:=unitmapsize;
+ unitmapsize:=loaded_units.count;
+ reallocmem(unitmap,unitmapsize*sizeof(tunitmaprec));
+ fillchar(unitmap[oldmapsize],(unitmapsize-oldmapsize)*sizeof(tunitmaprec),0);
+
+ { Extend Derefmap }
+ oldmapsize:=derefmapsize;
+ derefmapsize:=loaded_units.count;
+ reallocmem(derefmap,derefmapsize*sizeof(tderefmaprec));
+ fillchar(derefmap[oldmapsize],(derefmapsize-oldmapsize)*sizeof(tderefmaprec),0);
+
+ { Add all units to unitmap }
+ hp:=tmodule(loaded_units.first);
+ i:=0;
+ while assigned(hp) do
+ begin
+ if hp.moduleid>=unitmapsize then
+ internalerror(200501151);
+ { Verify old entries }
+ if (i<oldmapsize) then
+ begin
+ if (hp.moduleid<>i) or
+ (unitmap[hp.moduleid].u<>hp) then
+ internalerror(200501156);
+ end
+ else
+ begin
+ unitmap[hp.moduleid].u:=hp;
+ unitmap[hp.moduleid].derefidx:=-1;
+ end;
+ inc(i);
+ hp:=tmodule(hp.next);
+ end;
+ end;
+
+
+ function tmodule.derefidx_unit(id:longint):longint;
+ begin
+ if id>=unitmapsize then
+ internalerror(2005011511);
+ if unitmap[id].derefidx=-1 then
+ begin
+ unitmap[id].derefidx:=derefmapcnt;
+ inc(derefmapcnt);
+ derefmap[unitmap[id].derefidx].u:=unitmap[id].u;
+ end;
+ if unitmap[id].derefidx>=derefmapsize then
+ internalerror(2005011514);
+ result:=unitmap[id].derefidx;
+ end;
+
+
+ function tmodule.resolve_unit(id:longint):tmodule;
+ var
+ hp : tmodule;
+ begin
+ if id>=derefmapsize then
+ internalerror(200306231);
+ result:=derefmap[id].u;
+ if not assigned(result) then
+ begin
+ if not assigned(derefmap[id].modulename) or
+ (derefmap[id].modulename^='') then
+ internalerror(200501159);
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.modulename^=derefmap[id].modulename^ then
+ break;
+ hp:=tmodule(hp.next);
+ end;
+ if not assigned(hp) then
+ internalerror(2005011510);
+ derefmap[id].u:=hp;
+ result:=hp;
+ end;
+ end;
+
+
+ procedure tmodule.allunitsused;
+ var
+ pu : tused_unit;
+ begin
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ if assigned(pu.u.globalsymtable) then
+ begin
+ if unitmap[pu.u.moduleid].u<>pu.u then
+ internalerror(200501157);
+ { Give a note when the unit is not referenced, skip
+ this is for units with an initialization/finalization }
+ if (unitmap[pu.u.moduleid].refs=0) and
+ ((pu.u.flags and (uf_init or uf_finalize))=0) then
+ CGMessagePos2(pu.unitsym.fileinfo,sym_n_unit_not_used,pu.u.realmodulename^,realmodulename^);
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ end;
+
+
+ procedure tmodule.setmodulename(const s:string);
+ begin
+ stringdispose(modulename);
+ stringdispose(realmodulename);
+ modulename:=stringdup(upper(s));
+ realmodulename:=stringdup(s);
+ { also update asmlibrary names }
+ librarydata.name:=modulename^;
+ librarydata.realname:=realmodulename^;
+ end;
+
+end.
diff --git a/compiler/fpcdefs.inc b/compiler/fpcdefs.inc
new file mode 100644
index 0000000000..8b3b54fe68
--- /dev/null
+++ b/compiler/fpcdefs.inc
@@ -0,0 +1,93 @@
+{$ifdef FPC}
+ {$mode objfpc}
+ {$asmmode default}
+ {$H-}
+ {$goto on}
+ {$inline on}
+
+{$ifdef win32}
+ { 256MB stack }
+ { under windows the stack can't grow }
+ {$MEMORY 256000000}
+{$else win32}
+ { 1MB stack }
+ {$MEMORY 1000000}
+{$endif win32}
+ { This reduces the memory requirements a lot }
+ {$PACKENUM 1}
+
+ { We don't use exceptions, so turn off the implicit
+ exceptions in the constructors }
+ {$IMPLICITEXCEPTIONS OFF}
+ { Inline small functions, but not when EXTDEBUG is used }
+ {$ifndef EXTDEBUG}
+ {$define USEINLINE}
+ {$endif EXTDEBUG}
+
+ {$define USEEXCEPT}
+
+ {$ifdef cpuarm}
+ {$packrecords c}
+ {$endif cpuarm}
+{$endif}
+
+{$ifdef i386}
+ {$define x86}
+ {$define cpuflags}
+ {$define cpuextended}
+ {$define USECMOV}
+ {$define SUPPORT_MMX}
+ {$define cpumm}
+{$endif i386}
+
+{$ifdef x86_64}
+ {$define x86}
+ {$define cpuflags}
+ {$define cpu64bit}
+ {$define cpuextended}
+ {$define cpufloat128}
+ {$define cputargethasfixedstack}
+ {$define USECMOV}
+ {$define cpumm}
+{$endif x86_64}
+
+{$ifdef alpha}
+ {$define cpu64bit}
+{$endif alpha}
+
+{$ifdef sparc}
+ {$define cpuflags}
+ {$define cputargethasfixedstack}
+ {$define cpurequiresproperalignment}
+{$endif sparc}
+
+{$ifdef powerpc}
+ {$define cpuflags}
+ {$define cputargethasfixedstack}
+ {$define cpumm}
+{$endif powerpc}
+
+{$ifdef powerpc64}
+ {$define cpu64bit}
+ {$define cpuflags}
+ {$define cputargethasfixedstack}
+ {$define cpumm}
+ {$define cpurequiresproperalignment}
+{$endif powerpc64}
+
+{$ifdef arm}
+ {$define cpuflags}
+ {$define cpufpemu}
+ {$define cpuneedsdiv32helper}
+ {$define cputargethasfixedstack}
+ {$define cpurequiresproperalignment}
+{$endif arm}
+
+{$ifdef m68k}
+ {$define cpuflags}
+ {$define cpufpemu}
+{$endif m68k}
+
+{$IFDEF MACOS}
+{$DEFINE MACOS_USE_FAKE_SYSUTILS}
+{$ENDIF MACOS}
diff --git a/compiler/fppu.pas b/compiler/fppu.pas
new file mode 100644
index 0000000000..2dad576c66
--- /dev/null
+++ b/compiler/fppu.pas
@@ -0,0 +1,1605 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the first loading and searching of the modules
+
+ 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 fppu;
+
+{$i fpcdefs.inc}
+
+{ close ppufiles on system that are
+ short on file handles like DOS system PM }
+{$ifdef GO32V2}
+ {$define SHORT_ON_FILE_HANDLES}
+{$endif GO32V2}
+{$ifdef WATCOM}
+ {$define SHORT_ON_FILE_HANDLES}
+{$endif WATCOM}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,finput,fmodule,
+ symbase,ppu,symtype;
+
+ type
+ tppumodule = class(tmodule)
+ ppufile : tcompilerppufile; { the PPU file }
+ sourcefn : pstring; { Source specified with "uses .. in '..'" }
+{$ifdef Test_Double_checksum}
+ crc_array : pointer;
+ crc_size : longint;
+ crc_array2 : pointer;
+ crc_size2 : longint;
+{$endif def Test_Double_checksum}
+ constructor create(LoadedFrom:TModule;const s:string;const fn:string;_is_unit:boolean);
+ destructor destroy;override;
+ procedure reset;override;
+ function openppu:boolean;
+ procedure getppucrc;
+ procedure writeppu;
+ procedure loadppu;
+ function needrecompile:boolean;
+ private
+ function search_unit(onlysource,shortname:boolean):boolean;
+ procedure load_interface;
+ procedure load_implementation;
+ procedure load_symtable_refs;
+ procedure load_usedunits;
+ procedure writesourcefiles;
+ procedure writeusedunit(intf:boolean);
+ procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
+ procedure writederefmap;
+ procedure writederefdata;
+ procedure putasmsymbol_in_idx(s:tnamedindexitem;arg:pointer);
+ procedure writeasmsymbols;
+ procedure readsourcefiles;
+ procedure readloadunit;
+ procedure readlinkcontainer(var p:tlinkcontainer);
+ procedure readderefmap;
+ procedure readderefdata;
+ procedure readasmsymbols;
+{$IFDEF MACRO_DIFF_HINT}
+ procedure writeusedmacro(p:TNamedIndexItem;arg:pointer);
+ procedure writeusedmacros;
+ procedure readusedmacros;
+{$ENDIF}
+ end;
+
+ procedure reload_flagged_units;
+ function registerunit(callermodule:tmodule;const s : stringid;const fn:string) : tppumodule;
+
+
+implementation
+
+uses
+ verbose,systems,version,
+ symtable, symsym,
+ scanner,
+ aasmbase,
+ parser;
+
+{****************************************************************************
+ Helpers
+ ****************************************************************************}
+
+ procedure reload_flagged_units;
+ var
+ hp : tmodule;
+ begin
+ { now reload all dependent units }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.do_reload then
+ tppumodule(hp).loadppu;
+ hp:=tmodule(hp.next);
+ end;
+ end;
+
+
+{****************************************************************************
+ TPPUMODULE
+ ****************************************************************************}
+
+ constructor tppumodule.create(LoadedFrom:TModule;const s:string;const fn:string;_is_unit:boolean);
+ begin
+ inherited create(LoadedFrom,s,_is_unit);
+ ppufile:=nil;
+ sourcefn:=stringdup(fn);
+ end;
+
+
+ destructor tppumodule.Destroy;
+ begin
+ if assigned(ppufile) then
+ ppufile.free;
+ ppufile:=nil;
+ stringdispose(sourcefn);
+ inherited Destroy;
+ end;
+
+
+ procedure tppumodule.reset;
+ begin
+ if assigned(ppufile) then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ end;
+ inherited reset;
+ end;
+
+
+ function tppumodule.openppu:boolean;
+ var
+ ppufiletime : longint;
+ begin
+ openppu:=false;
+ Message1(unit_t_ppu_loading,ppufilename^);
+ { Get ppufile time (also check if the file exists) }
+ ppufiletime:=getnamedfiletime(ppufilename^);
+ if ppufiletime=-1 then
+ exit;
+ { Open the ppufile }
+ Message1(unit_u_ppu_name,ppufilename^);
+ ppufile:=tcompilerppufile.create(ppufilename^);
+ if not ppufile.openfile then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_file_too_short);
+ exit;
+ end;
+ { check for a valid PPU file }
+ if not ppufile.CheckPPUId then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_invalid_header);
+ exit;
+ end;
+ { check for allowed PPU versions }
+ if not (ppufile.GetPPUVersion = CurrentPPUVersion) then
+ begin
+ Message1(unit_u_ppu_invalid_version,tostr(ppufile.GetPPUVersion));
+ ppufile.free;
+ ppufile:=nil;
+ exit;
+ end;
+ { check the target processor }
+ if tsystemcpu(ppufile.header.cpu)<>target_cpu then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_invalid_processor);
+ exit;
+ end;
+ { check target }
+ if tsystem(ppufile.header.target)<>target_info.system then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_invalid_target);
+ exit;
+ end;
+{$ifdef cpufpemu}
+ { check if floating point emulation is on?}
+ { fpu emulation isn't unit levelwise
+ if ((ppufile.header.flags and uf_fpu_emulation)<>0) and
+ (cs_fp_emulation in aktmoduleswitches) then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_invalid_fpumode);
+ exit;
+ end;
+ }
+{$endif cpufpemu}
+
+ { Load values to be access easier }
+ flags:=ppufile.header.flags;
+ crc:=ppufile.header.checksum;
+ interface_crc:=ppufile.header.interface_checksum;
+ { Show Debug info }
+ Message1(unit_u_ppu_time,filetimestring(ppufiletime));
+ Message1(unit_u_ppu_flags,tostr(flags));
+ Message1(unit_u_ppu_crc,hexstr(ppufile.header.checksum,8));
+ Message1(unit_u_ppu_crc,hexstr(ppufile.header.interface_checksum,8)+' (intfc)');
+ do_compile:=false;
+ openppu:=true;
+ end;
+
+
+ function tppumodule.search_unit(onlysource,shortname:boolean):boolean;
+ var
+ singlepathstring,
+ filename : string;
+
+ Function UnitExists(const ext:string;var foundfile:string):boolean;
+ begin
+ Message1(unit_t_unitsearch,Singlepathstring+filename+ext);
+ UnitExists:=FindFile(FileName+ext,Singlepathstring,foundfile);
+ end;
+
+ Function PPUSearchPath(const s:string):boolean;
+ var
+ found : boolean;
+ hs : string;
+ begin
+ Found:=false;
+ singlepathstring:=FixPath(s,false);
+ { Check for PPU file }
+ Found:=UnitExists(target_info.unitext,hs);
+ if Found then
+ Begin
+ SetFileName(hs,false);
+ Found:=OpenPPU;
+ End;
+ PPUSearchPath:=Found;
+ end;
+
+ Function SourceSearchPath(const s:string):boolean;
+ var
+ found : boolean;
+ hs : string;
+ begin
+ Found:=false;
+ singlepathstring:=FixPath(s,false);
+ { Check for Sources }
+ ppufile:=nil;
+ do_compile:=true;
+ recompile_reason:=rr_noppu;
+ {Check for .pp file}
+ Found:=UnitExists(sourceext,hs);
+ if not Found then
+ begin
+ { Check for .pas }
+ Found:=UnitExists(pasext,hs);
+ end;
+ if not Found and (m_mac in aktmodeswitches) then
+ begin
+ { Check for .p, if mode is macpas}
+ Found:=UnitExists(pext,hs);
+ end;
+ stringdispose(mainsource);
+ if Found then
+ begin
+ sources_avail:=true;
+ { Load Filenames when found }
+ mainsource:=StringDup(hs);
+ SetFileName(hs,false);
+ end
+ else
+ sources_avail:=false;
+ SourceSearchPath:=Found;
+ end;
+
+ Function SearchPath(const s:string):boolean;
+ var
+ found : boolean;
+ begin
+ { First check for a ppu, then for the source }
+ found:=false;
+ if not onlysource then
+ found:=PPUSearchPath(s);
+ if not found then
+ found:=SourceSearchPath(s);
+ SearchPath:=found;
+ end;
+
+ Function SearchPathList(list:TSearchPathList):boolean;
+ var
+ hp : TStringListItem;
+ found : boolean;
+ begin
+ found:=false;
+ hp:=TStringListItem(list.First);
+ while assigned(hp) do
+ begin
+ found:=SearchPath(hp.Str);
+ if found then
+ break;
+ hp:=TStringListItem(hp.next);
+ end;
+ SearchPathList:=found;
+ end;
+
+ var
+ fnd : boolean;
+ hs : string;
+ begin
+ if shortname then
+ filename:=FixFileName(Copy(realmodulename^,1,8))
+ else
+ filename:=FixFileName(realmodulename^);
+ { try to find unit
+ 1. look for ppu in cwd
+ 2. look for ppu in outputpath if set, this is tp7 compatible (PFV)
+ 3. look for the specified source file (from the uses line)
+ 4. look for source in cwd
+ 5. look in same path as local unit
+ 6. local unit pathlist
+ 7. global unit pathlist }
+ fnd:=false;
+ if not onlysource then
+ begin
+ fnd:=PPUSearchPath('.');
+ if (not fnd) and (outputpath^<>'') then
+ fnd:=PPUSearchPath(outputpath^);
+ end;
+ if (not fnd) and (sourcefn^<>'') then
+ begin
+ { the full filename is specified so we can't use here the
+ searchpath (PFV) }
+ Message1(unit_t_unitsearch,AddExtension(sourcefn^,sourceext));
+ fnd:=FindFile(AddExtension(sourcefn^,sourceext),'',hs);
+ if not fnd then
+ begin
+ Message1(unit_t_unitsearch,AddExtension(sourcefn^,pasext));
+ fnd:=FindFile(AddExtension(sourcefn^,pasext),'',hs);
+ end;
+ if not fnd and ((m_mac in aktmodeswitches) or target_info.p_ext_support) then
+ begin
+ Message1(unit_t_unitsearch,AddExtension(sourcefn^,pext));
+ fnd:=FindFile(AddExtension(sourcefn^,pext),'',hs);
+ end;
+ if fnd then
+ begin
+ sources_avail:=true;
+ do_compile:=true;
+ recompile_reason:=rr_noppu;
+ stringdispose(mainsource);
+ mainsource:=StringDup(hs);
+ SetFileName(hs,false);
+ end;
+ end;
+ if not fnd then
+ fnd:=SourceSearchPath('.');
+ if (not fnd) and Assigned(Loaded_From) then
+ begin
+ fnd:=PPUSearchPath(Loaded_From.Path^);
+ if not fnd then
+ fnd:=SourceSearchPath(Loaded_From.Path^);
+ if not fnd then
+ fnd:=SearchPathList(Loaded_From.LocalUnitSearchPath);
+ end;
+ if not fnd then
+ fnd:=SearchPathList(UnitSearchPath);
+
+ { try to find a file with the first 8 chars of the modulename, like
+ dos }
+ if (not fnd) and (length(filename)>8) then
+ begin
+ filename:=copy(filename,1,8);
+ fnd:=SearchPath('.');
+ if (not fnd) then
+ fnd:=SearchPathList(LocalUnitSearchPath);
+ if not fnd then
+ fnd:=SearchPathList(UnitSearchPath);
+ end;
+ search_unit:=fnd;
+ end;
+
+
+{**********************************
+ PPU Reading/Writing Helpers
+***********************************}
+
+{$IFDEF MACRO_DIFF_HINT}
+ var
+ is_initial: Boolean;
+
+ procedure tppumodule.writeusedmacro(p:TNamedIndexItem;arg:pointer);
+ begin
+ if tmacro(p).is_used or is_initial then
+ begin
+ ppufile.putstring(p.name);
+ ppufile.putbyte(byte(is_initial));
+ ppufile.putbyte(byte(tmacro(p).is_used));
+ end;
+ end;
+
+ procedure tppumodule.writeusedmacros;
+ begin
+ ppufile.do_crc:=false;
+ is_initial:= true;
+ initialmacrosymtable.foreach(@writeusedmacro,nil);
+ is_initial:= false;
+ if assigned(globalmacrosymtable) then
+ globalmacrosymtable.foreach(@writeusedmacro,nil);
+ localmacrosymtable.foreach(@writeusedmacro,nil);
+ ppufile.writeentry(ibusedmacros);
+ ppufile.do_crc:=true;
+ end;
+{$ENDIF}
+
+ procedure tppumodule.writesourcefiles;
+ var
+ hp : tinputfile;
+ i,j : longint;
+ begin
+ { second write the used source files }
+ ppufile.do_crc:=false;
+ hp:=sourcefiles.files;
+ { write source files directly in good order }
+ j:=0;
+ while assigned(hp) do
+ begin
+ inc(j);
+ hp:=hp.ref_next;
+ end;
+ while j>0 do
+ begin
+ hp:=sourcefiles.files;
+ for i:=1 to j-1 do
+ hp:=hp.ref_next;
+ ppufile.putstring(hp.name^);
+ ppufile.putlongint(hp.getfiletime);
+ dec(j);
+ end;
+ ppufile.writeentry(ibsourcefiles);
+ ppufile.do_crc:=true;
+ end;
+
+
+ procedure tppumodule.writeusedunit(intf:boolean);
+ var
+ hp : tused_unit;
+ oldcrc : boolean;
+ begin
+ { write a reference for each used unit }
+ hp:=tused_unit(used_units.first);
+ while assigned(hp) do
+ begin
+ if hp.in_interface=intf then
+ begin
+ ppufile.putstring(hp.u.realmodulename^);
+ { the checksum should not affect the crc of this unit ! (PFV) }
+ oldcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ ppufile.putlongint(longint(hp.checksum));
+ ppufile.putlongint(longint(hp.interface_checksum));
+ ppufile.do_crc:=oldcrc;
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+ ppufile.do_interface_crc:=true;
+ ppufile.writeentry(ibloadunit);
+ end;
+
+
+ procedure tppumodule.writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
+ var
+ hcontainer : tlinkcontainer;
+ s : string;
+ mask : cardinal;
+ begin
+ hcontainer:=TLinkContainer.Create;
+ while not p.empty do
+ begin
+ s:=p.get(mask);
+ if strippath then
+ ppufile.putstring(SplitFileName(s))
+ else
+ ppufile.putstring(s);
+ ppufile.putlongint(mask);
+ hcontainer.add(s,mask);
+ end;
+ ppufile.writeentry(id);
+ p.Free;
+ p:=hcontainer;
+ end;
+
+
+ procedure tppumodule.writederefmap;
+ var
+ i : longint;
+ oldcrc : boolean;
+ begin
+ { This does not influence crc }
+ oldcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ { The unit map used for resolving }
+ ppufile.putlongint(derefmapcnt);
+ for i:=0 to derefmapcnt-1 do
+ begin
+ if not assigned(derefmap[i].u) then
+ internalerror(2005011512);
+ ppufile.putstring(derefmap[i].u.modulename^)
+ end;
+ ppufile.writeentry(ibderefmap);
+ ppufile.do_crc:=oldcrc;
+ end;
+
+
+ procedure tppumodule.writederefdata;
+ var
+ oldcrc : boolean;
+ len,hlen : longint;
+ buf : array[0..1023] of byte;
+ begin
+ if derefdataintflen>derefdata.size then
+ internalerror(200310223);
+ derefdata.seek(0);
+ { Write interface data }
+ len:=derefdataintflen;
+ while (len>0) do
+ begin
+ if len>1024 then
+ hlen:=1024
+ else
+ hlen:=len;
+ derefdata.read(buf,hlen);
+ ppufile.putdata(buf,hlen);
+ dec(len,hlen);
+ end;
+ { Write implementation data, this does not influence crc }
+ oldcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ len:=derefdata.size-derefdataintflen;
+ while (len>0) do
+ begin
+ if len>1024 then
+ hlen:=1024
+ else
+ hlen:=len;
+ derefdata.read(buf,hlen);
+ ppufile.putdata(buf,hlen);
+ dec(len,hlen);
+ end;
+ if derefdata.pos<>derefdata.size then
+ internalerror(200310224);
+ ppufile.do_crc:=oldcrc;
+ ppufile.writeentry(ibderefdata);
+ end;
+
+
+ procedure tppumodule.putasmsymbol_in_idx(s:tnamedindexitem;arg:pointer);
+ begin
+ if tasmsymbol(s).ppuidx<>-1 then
+ librarydata.asmsymbolidx^[tasmsymbol(s).ppuidx-1]:=tasmsymbol(s);
+ end;
+
+
+ procedure tppumodule.writeasmsymbols;
+ var
+ s : tasmsymbol;
+ i : longint;
+ asmsymtype : byte;
+ begin
+ { get an ordered list of all symbols to put in the ppu }
+ getmem(librarydata.asmsymbolidx,librarydata.asmsymbolppuidx*sizeof(pointer));
+ fillchar(librarydata.asmsymbolidx^,librarydata.asmsymbolppuidx*sizeof(pointer),0);
+ librarydata.symbolsearch.foreach(@putasmsymbol_in_idx,nil);
+ { write the number of symbols }
+ ppufile.putlongint(librarydata.asmsymbolppuidx);
+ { write the symbols from the indexed list to the ppu }
+ for i:=1 to librarydata.asmsymbolppuidx do
+ begin
+ s:=librarydata.asmsymbolidx^[i-1];
+ if not assigned(s) then
+ internalerror(200208071);
+ if s.Classtype=tasmlabel then
+ asmsymtype:=2
+ else
+ asmsymtype:=1;
+ ppufile.putbyte(asmsymtype);
+ case asmsymtype of
+ 1 :
+ ppufile.putstring(s.name);
+ 2 :
+ begin
+ ppufile.putbyte(byte(tasmlabel(s).labeltype));
+ ppufile.putlongint(tasmlabel(s).labelnr);
+ end;
+ end;
+ ppufile.putbyte(byte(s.defbind));
+ ppufile.putbyte(byte(s.typ));
+ end;
+ ppufile.writeentry(ibasmsymbols);
+ end;
+
+{$IFDEF MACRO_DIFF_HINT}
+
+{
+ Define MACRO_DIFF_HINT for the whole compiler (and ppudump)
+ to turn this facility on. Also the hint messages defined
+ below must be commented in in the msg/errore.msg file.
+
+ There is some problems with this, thats why it is shut off:
+
+ At the first compilation, consider a macro which is not initially
+ defined, but it is used (e g the check that it is undefined is true).
+ Since it do not exist, there is no macro object where the is_used
+ flag can be set. Later on when the macro is defined, and the ppu
+ is opened, the check cannot detect this.
+
+ Also, in which macro object should this flag be set ? It cant be set
+ for macros in the initialmacrosymboltable since this table is shared
+ between different files.
+}
+
+ procedure tppumodule.readusedmacros;
+ var
+ hs : string;
+ mac : tmacro;
+ was_initial,
+ was_used : boolean;
+ {Reads macros which was defined or used when the module was compiled.
+ This is done when a ppu file is open, before it possibly is parsed.}
+ begin
+ while not ppufile.endofentry do
+ begin
+ hs:=ppufile.getstring;
+ was_initial:=boolean(ppufile.getbyte);
+ was_used:=boolean(ppufile.getbyte);
+ mac:=tmacro(initialmacrosymtable.search(hs));
+ if assigned(mac) then
+ begin
+{$ifndef EXTDEBUG}
+ { if we don't have the sources why tell }
+ if sources_avail then
+{$endif ndef EXTDEBUG}
+ if (not was_initial) and was_used then
+ Message2(unit_h_cond_not_set_in_last_compile,hs,mainsource^);
+ end
+ else { not assigned }
+ if was_initial and
+ was_used then
+ Message2(unit_h_cond_set_in_last_compile,hs,mainsource^);
+ end;
+ end;
+{$ENDIF}
+
+ procedure tppumodule.readsourcefiles;
+ var
+ temp,hs : string;
+ temp_dir : string;
+ main_dir : string;
+ found,
+ is_main : boolean;
+ orgfiletime,
+ source_time : longint;
+ hp : tinputfile;
+ begin
+ sources_avail:=true;
+ is_main:=true;
+ main_dir:='';
+ while not ppufile.endofentry do
+ begin
+ hs:=ppufile.getstring;
+ orgfiletime:=ppufile.getlongint;
+ temp_dir:='';
+ if (flags and uf_in_library)<>0 then
+ begin
+ sources_avail:=false;
+ temp:=' library';
+ end
+ else if pos('Macro ',hs)=1 then
+ begin
+ { we don't want to find this file }
+ { but there is a problem with file indexing !! }
+ temp:='';
+ end
+ else
+ begin
+ { check the date of the source files:
+ 1 path of ppu
+ 2 path of main source
+ 3 current dir
+ 4 include/unit path }
+ Source_Time:=GetNamedFileTime(path^+hs);
+ found:=false;
+ if Source_Time<>-1 then
+ hs:=path^+hs
+ else
+ if not(is_main) then
+ begin
+ Source_Time:=GetNamedFileTime(main_dir+hs);
+ if Source_Time<>-1 then
+ hs:=main_dir+hs;
+ end;
+ if Source_Time=-1 then
+ Source_Time:=GetNamedFileTime(hs);
+ if (Source_Time=-1) then
+ begin
+ if is_main then
+ found:=unitsearchpath.FindFile(hs,temp_dir)
+ else
+ found:=includesearchpath.FindFile(hs,temp_dir);
+ if found then
+ begin
+ Source_Time:=GetNamedFileTime(temp_dir);
+ if Source_Time<>-1 then
+ hs:=temp_dir;
+ end;
+ end;
+ if Source_Time<>-1 then
+ begin
+ if is_main then
+ main_dir:=splitpath(hs);
+ temp:=' time '+filetimestring(source_time);
+ if (orgfiletime<>-1) and
+ (source_time<>orgfiletime) then
+ begin
+ if ((flags and uf_release)=0) then
+ begin
+ do_compile:=true;
+ recompile_reason:=rr_sourcenewer;
+ end
+ else
+ Message2(unit_h_source_modified,hs,ppufilename^);
+ temp:=temp+' *';
+ end;
+ end
+ else
+ begin
+ sources_avail:=false;
+ temp:=' not found';
+ end;
+ hp:=tinputfile.create(hs);
+ { the indexing is wrong here PM }
+ sourcefiles.register_file(hp);
+ end;
+ if is_main then
+ begin
+ stringdispose(mainsource);
+ mainsource:=stringdup(hs);
+ end;
+ Message1(unit_u_ppu_source,hs+temp);
+ is_main:=false;
+ end;
+ { check if we want to rebuild every unit, only if the sources are
+ available }
+ if do_build and sources_avail and
+ ((flags and uf_release)=0) then
+ begin
+ do_compile:=true;
+ recompile_reason:=rr_build;
+ end;
+ end;
+
+
+ procedure tppumodule.readloadunit;
+ var
+ hs : string;
+ pu : tused_unit;
+ hp : tppumodule;
+ intfchecksum,
+ checksum : cardinal;
+ begin
+ while not ppufile.endofentry do
+ begin
+ hs:=ppufile.getstring;
+ checksum:=cardinal(ppufile.getlongint);
+ intfchecksum:=cardinal(ppufile.getlongint);
+ { set the state of this unit before registering, this is
+ needed for a correct circular dependency check }
+ hp:=registerunit(self,hs,'');
+ pu:=addusedunit(hp,false,nil);
+ pu.checksum:=checksum;
+ pu.interface_checksum:=intfchecksum;
+ end;
+ in_interface:=false;
+ end;
+
+
+ procedure tppumodule.readlinkcontainer(var p:tlinkcontainer);
+ var
+ s : string;
+ m : longint;
+ begin
+ while not ppufile.endofentry do
+ begin
+ s:=ppufile.getstring;
+ m:=ppufile.getlongint;
+ p.add(s,m);
+ end;
+ end;
+
+
+ procedure tppumodule.readderefmap;
+ var
+ i : longint;
+ begin
+ { Load unit map used for resolving }
+ derefmapsize:=ppufile.getlongint;
+ getmem(derefmap,derefmapsize*sizeof(tderefmaprec));
+ fillchar(derefmap^,derefmapsize*sizeof(tderefmaprec),0);
+ for i:=0 to derefmapsize-1 do
+ derefmap[i].modulename:=stringdup(ppufile.getstring);
+ end;
+
+
+ procedure tppumodule.readderefdata;
+ var
+ len,hlen : longint;
+ buf : array[0..1023] of byte;
+ begin
+ len:=ppufile.entrysize;
+ while (len>0) do
+ begin
+ if len>1024 then
+ hlen:=1024
+ else
+ hlen:=len;
+ ppufile.getdata(buf,hlen);
+ derefdata.write(buf,hlen);
+ dec(len,hlen);
+ end;
+ end;
+
+
+ procedure tppumodule.readasmsymbols;
+ var
+ labelnr,
+ i : longint;
+ name : string;
+ labeltype : tasmlabeltype;
+ bind : TAsmSymBind;
+ typ : TAsmSymType;
+ asmsymtype : byte;
+ begin
+ librarydata.asmsymbolppuidx:=ppufile.getlongint;
+ if librarydata.asmsymbolppuidx>0 then
+ begin
+ getmem(librarydata.asmsymbolidx,librarydata.asmsymbolppuidx*sizeof(pointer));
+ fillchar(librarydata.asmsymbolidx^,librarydata.asmsymbolppuidx*sizeof(pointer),0);
+ for i:=1 to librarydata.asmsymbolppuidx do
+ begin
+ asmsymtype:=ppufile.getbyte;
+ case asmsymtype of
+ 1 :
+ name:=ppufile.getstring;
+ 2 :
+ begin
+ labeltype:=tasmlabeltype(ppufile.getbyte);
+ labelnr:=ppufile.getlongint;
+ end;
+ else
+ internalerror(200208192);
+ end;
+ bind:=tasmsymbind(ppufile.getbyte);
+ typ:=tasmsymtype(ppufile.getbyte);
+ case asmsymtype of
+ 1 :
+ librarydata.asmsymbolidx^[i-1]:=librarydata.newasmsymbol(name,bind,typ);
+ 2 :
+ librarydata.asmsymbolidx^[i-1]:=librarydata.newasmlabel(labelnr,labeltype,(typ=AT_DATA));
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tppumodule.load_interface;
+ var
+ b : byte;
+ newmodulename : string;
+ begin
+ { read interface part }
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibmodulename :
+ begin
+ newmodulename:=ppufile.getstring;
+ if (cs_check_unit_name in aktglobalswitches) and
+ (upper(newmodulename)<>modulename^) then
+ Message2(unit_f_unit_name_error,realmodulename^,newmodulename);
+ stringdispose(modulename);
+ stringdispose(realmodulename);
+ modulename:=stringdup(upper(newmodulename));
+ realmodulename:=stringdup(newmodulename);
+ end;
+ ibsourcefiles :
+ readsourcefiles;
+{$IFDEF MACRO_DIFF_HINT}
+ ibusedmacros :
+ readusedmacros;
+{$ENDIF}
+ ibloadunit :
+ readloadunit;
+ iblinkunitofiles :
+ readlinkcontainer(LinkUnitOFiles);
+ iblinkunitstaticlibs :
+ readlinkcontainer(LinkUnitStaticLibs);
+ iblinkunitsharedlibs :
+ readlinkcontainer(LinkUnitSharedLibs);
+ iblinkotherofiles :
+ readlinkcontainer(LinkotherOFiles);
+ iblinkotherstaticlibs :
+ readlinkcontainer(LinkotherStaticLibs);
+ iblinkothersharedlibs :
+ readlinkcontainer(LinkotherSharedLibs);
+ ibderefmap :
+ readderefmap;
+ ibderefdata :
+ readderefdata;
+ ibendinterface :
+ break;
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ { we can already stop when we know that we must recompile }
+ if do_compile then
+ exit;
+ until false;
+ end;
+
+
+ procedure tppumodule.load_implementation;
+ var
+ b : byte;
+ begin
+ { read implementation part }
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibloadunit :
+ readloadunit;
+ ibasmsymbols :
+ readasmsymbols;
+ ibendimplementation :
+ break;
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ until false;
+ end;
+
+
+ procedure tppumodule.load_symtable_refs;
+ var
+ b : byte;
+ i : longint;
+ begin
+ if (flags and uf_has_browser)<>0 then
+ begin
+ tstoredsymtable(globalsymtable).load_references(ppufile,true);
+ for i:=0 to unitmapsize-1 do
+ tstoredsymtable(globalsymtable).load_references(ppufile,false);
+ b:=ppufile.readentry;
+ if b<>ibendbrowser then
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ if ((flags and uf_local_browser)<>0) then
+ tstaticsymtable(localsymtable).load_references(ppufile,true);
+ end;
+
+
+ procedure tppumodule.writeppu;
+ var
+ pu : tused_unit;
+ begin
+ Message1(unit_u_ppu_write,realmodulename^);
+
+ { create unit flags }
+ if cs_browser in aktmoduleswitches then
+ flags:=flags or uf_has_browser;
+ if cs_local_browser in aktmoduleswitches then
+ flags:=flags or uf_local_browser;
+ if do_release then
+ flags:=flags or uf_release;
+ if assigned(localsymtable) then
+ flags:=flags or uf_local_symtable;
+{$ifdef cpufpemu}
+ if (cs_fp_emulation in aktmoduleswitches) then
+ flags:=flags or uf_fpu_emulation;
+{$endif cpufpemu}
+{$ifdef Test_Double_checksum_write}
+ Assign(CRCFile,s+'.IMP');
+ Rewrite(CRCFile);
+{$endif def Test_Double_checksum_write}
+
+ { create new ppufile }
+ ppufile:=tcompilerppufile.create(ppufilename^);
+ if not ppufile.createfile then
+ Message(unit_f_ppu_cannot_write);
+
+ { first the unitname }
+ ppufile.putstring(realmodulename^);
+ ppufile.writeentry(ibmodulename);
+
+ writesourcefiles;
+{$IFDEF MACRO_DIFF_HINT}
+ writeusedmacros;
+{$ENDIF}
+
+ { write interface uses }
+ writeusedunit(true);
+
+ { write the objectfiles and libraries that come for this unit,
+ preserve the containers becuase they are still needed to load
+ the link.res. All doesn't depend on the crc! It doesn't matter
+ if a unit is in a .o or .a file }
+ ppufile.do_crc:=false;
+ writelinkcontainer(linkunitofiles,iblinkunitofiles,true);
+ writelinkcontainer(linkunitstaticlibs,iblinkunitstaticlibs,true);
+ writelinkcontainer(linkunitsharedlibs,iblinkunitsharedlibs,true);
+ writelinkcontainer(linkotherofiles,iblinkotherofiles,false);
+ writelinkcontainer(linkotherstaticlibs,iblinkotherstaticlibs,true);
+ writelinkcontainer(linkothersharedlibs,iblinkothersharedlibs,true);
+ ppufile.do_crc:=true;
+
+ { generate implementation deref data, the interface deref data is
+ already generated when calculating the interface crc }
+ if (cs_compilesystem in aktmoduleswitches) then
+ begin
+ tstoredsymtable(globalsymtable).buildderef;
+ derefdataintflen:=derefdata.size;
+ end;
+ tstoredsymtable(globalsymtable).buildderefimpl;
+ if (flags and uf_local_symtable)<>0 then
+ begin
+ tstoredsymtable(localsymtable).buildderef;
+ tstoredsymtable(localsymtable).buildderefimpl;
+ end;
+ writederefmap;
+ writederefdata;
+
+ ppufile.writeentry(ibendinterface);
+
+ { write the symtable entries }
+ tstoredsymtable(globalsymtable).ppuwrite(ppufile);
+
+ if assigned(globalmacrosymtable) and (globalmacrosymtable.symindex.count > 0) then
+ begin
+ ppufile.putbyte(byte(true));
+ ppufile.writeentry(ibexportedmacros);
+ tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
+ end
+ else
+ begin
+ ppufile.putbyte(byte(false));
+ ppufile.writeentry(ibexportedmacros);
+ end;
+
+ { everything after this doesn't affect the crc }
+ ppufile.do_crc:=false;
+
+ { write implementation uses }
+ writeusedunit(false);
+
+ { write asmsymbols }
+ writeasmsymbols;
+
+ { end of implementation }
+ ppufile.writeentry(ibendimplementation);
+
+ { write static symtable
+ needed for local debugging of unit functions }
+ if (flags and uf_local_symtable)<>0 then
+ tstoredsymtable(localsymtable).ppuwrite(ppufile);
+
+ { write all browser section }
+ if (flags and uf_has_browser)<>0 then
+ begin
+ tstoredsymtable(globalsymtable).write_references(ppufile,true);
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ tstoredsymtable(pu.u.globalsymtable).write_references(ppufile,false);
+ pu:=tused_unit(pu.next);
+ end;
+ ppufile.writeentry(ibendbrowser);
+ end;
+ if ((flags and uf_local_browser)<>0) then
+ begin
+ if not assigned(localsymtable) then
+ internalerror(200408271);
+ tstaticsymtable(localsymtable).write_references(ppufile,true);
+ end;
+
+ { the last entry ibend is written automaticly }
+
+ { flush to be sure }
+ ppufile.flush;
+ { create and write header }
+ ppufile.header.size:=ppufile.size;
+ ppufile.header.checksum:=ppufile.crc;
+ ppufile.header.interface_checksum:=ppufile.interface_crc;
+ ppufile.header.compiler:=wordversion;
+ ppufile.header.cpu:=word(target_cpu);
+ ppufile.header.target:=word(target_info.system);
+ ppufile.header.flags:=flags;
+ ppufile.writeheader;
+
+ { save crc in current module also }
+ crc:=ppufile.crc;
+ interface_crc:=ppufile.interface_crc;
+
+{$ifdef Test_Double_checksum_write}
+ close(CRCFile);
+{$endif Test_Double_checksum_write}
+
+ ppufile.closefile;
+ ppufile.free;
+ ppufile:=nil;
+ end;
+
+
+ procedure tppumodule.getppucrc;
+ begin
+{$ifdef Test_Double_checksum_write}
+ Assign(CRCFile,s+'.INT')
+ Rewrite(CRCFile);
+{$endif def Test_Double_checksum_write}
+
+ { create new ppufile }
+ ppufile:=tcompilerppufile.create(ppufilename^);
+ ppufile.crc_only:=true;
+ if not ppufile.createfile then
+ Message(unit_f_ppu_cannot_write);
+
+ { first the unitname }
+ ppufile.putstring(realmodulename^);
+ ppufile.writeentry(ibmodulename);
+
+ { the interface units affect the crc }
+ writeusedunit(true);
+
+ { deref data of interface that affect the crc }
+ derefdata.reset;
+ tstoredsymtable(globalsymtable).buildderef;
+ derefdataintflen:=derefdata.size;
+ writederefmap;
+ writederefdata;
+
+ ppufile.writeentry(ibendinterface);
+
+ { write the symtable entries }
+ tstoredsymtable(globalsymtable).ppuwrite(ppufile);
+
+ if assigned(globalmacrosymtable) and (globalmacrosymtable.symindex.count > 0) then
+ begin
+ ppufile.putbyte(byte(true));
+ ppufile.writeentry(ibexportedmacros);
+ tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
+ end
+ else
+ begin
+ ppufile.putbyte(byte(false));
+ ppufile.writeentry(ibexportedmacros);
+ end;
+
+ { save crc }
+ crc:=ppufile.crc;
+ interface_crc:=ppufile.interface_crc;
+
+ { end of implementation, to generate a correct ppufile
+ for ppudump when using INTFPPU define }
+ ppufile.writeentry(ibendimplementation);
+
+{$ifdef Test_Double_checksum}
+ crc_array:=ppufile.crc_test;
+ ppufile.crc_test:=nil;
+ crc_size:=ppufile.crc_index2;
+ crc_array2:=ppufile.crc_test2;
+ ppufile.crc_test2:=nil;
+ crc_size2:=ppufile.crc_index2;
+{$endif Test_Double_checksum}
+
+{$ifdef Test_Double_checksum_write}
+ close(CRCFile);
+{$endif Test_Double_checksum_write}
+
+ { create and write header, this will only be used
+ for debugging purposes }
+ ppufile.header.size:=ppufile.size;
+ ppufile.header.checksum:=ppufile.crc;
+ ppufile.header.interface_checksum:=ppufile.interface_crc;
+ ppufile.header.compiler:=wordversion;
+ ppufile.header.cpu:=word(target_cpu);
+ ppufile.header.target:=word(target_info.system);
+ ppufile.header.flags:=flags;
+ ppufile.writeheader;
+
+ ppufile.closefile;
+ ppufile.free;
+ ppufile:=nil;
+ end;
+
+
+ procedure tppumodule.load_usedunits;
+ var
+ pu : tused_unit;
+ load_refs : boolean;
+ oldobjectlibrary : tasmlibrarydata;
+ begin
+ if current_module<>self then
+ internalerror(200212284);
+ load_refs:=true;
+
+ { load the used units from interface }
+ in_interface:=true;
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ if pu.in_interface then
+ begin
+ tppumodule(pu.u).loadppu;
+ { if this unit is compiled we can stop }
+ if state=ms_compiled then
+ exit;
+ { add this unit to the dependencies }
+ pu.u.adddependency(self);
+ { need to recompile the current unit, check the interface
+ crc. And when not compiled with -Ur then check the complete
+ crc }
+ if (pu.u.interface_crc<>pu.interface_checksum) or
+ (
+ ((ppufile.header.flags and uf_release)=0) and
+ (pu.u.crc<>pu.checksum)
+ ) then
+ begin
+ Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.realmodulename^);
+ recompile_reason:=rr_crcchanged;
+ do_compile:=true;
+ exit;
+ end;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+
+ { ok, now load the interface of this unit }
+ if current_module<>self then
+ internalerror(200208187);
+ globalsymtable:=tglobalsymtable.create(modulename^,moduleid);
+ tstoredsymtable(globalsymtable).ppuload(ppufile);
+
+ if ppufile.readentry<>ibexportedmacros then
+ Message(unit_f_ppu_read_error);
+ if boolean(ppufile.getbyte) then
+ begin
+ globalmacrosymtable:=tmacrosymtable.Create(true);
+ tstoredsymtable(globalmacrosymtable).ppuload(ppufile)
+ end;
+
+ interface_compiled:=true;
+
+ { read the implementation part, containing
+ the implementation uses and objectdata }
+ in_interface:=false;
+ load_implementation;
+
+ { now only read the implementation uses }
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ if (not pu.in_interface) then
+ begin
+ tppumodule(pu.u).loadppu;
+ { if this unit is compiled we can stop }
+ if state=ms_compiled then
+ exit;
+ { add this unit to the dependencies }
+ pu.u.adddependency(self);
+ { need to recompile the current unit ? }
+ if (pu.u.interface_crc<>pu.interface_checksum) then
+ begin
+ Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.realmodulename^+' {impl}');
+ recompile_reason:=rr_crcchanged;
+ do_compile:=true;
+ exit;
+ end;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+
+ { load implementation symtable }
+ if (flags and uf_local_symtable)<>0 then
+ begin
+ localsymtable:=tstaticsymtable.create(modulename^,moduleid);
+ tstaticsymtable(localsymtable).ppuload(ppufile);
+ end;
+
+ { we can now derefence all pointers to the implementation parts }
+ oldobjectlibrary:=objectlibrary;
+ objectlibrary:=librarydata;
+ tstoredsymtable(globalsymtable).derefimpl;
+ if assigned(localsymtable) then
+ tstoredsymtable(localsymtable).derefimpl;
+ objectlibrary:=oldobjectlibrary;
+
+ { load browser info if stored }
+ if ((flags and uf_has_browser)<>0) and load_refs then
+ begin
+ if current_module<>self then
+ internalerror(200208188);
+ load_symtable_refs;
+ end;
+ end;
+
+
+ function tppumodule.needrecompile:boolean;
+ var
+ pu : tused_unit;
+ begin
+ result:=false;
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ { need to recompile the current unit, check the interface
+ crc. And when not compiled with -Ur then check the complete
+ crc }
+ if (pu.u.interface_crc<>pu.interface_checksum) or
+ (
+ (pu.in_interface) and
+ (pu.u.crc<>pu.checksum)
+ ) then
+ begin
+ result:=true;
+ exit;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ end;
+
+
+ procedure tppumodule.loadppu;
+ const
+ ImplIntf : array[boolean] of string[15]=('implementation','interface');
+ var
+ do_load,
+ second_time : boolean;
+ old_current_module : tmodule;
+ begin
+ old_current_module:=current_module;
+ Message3(unit_u_load_unit,old_current_module.modulename^,
+ ImplIntf[old_current_module.in_interface],
+ modulename^);
+
+ { Update loaded_from to detect cycles }
+ loaded_from:=old_current_module;
+
+ { check if the globalsymtable is already available, but
+ we must reload when the do_reload flag is set }
+ if (not do_reload) and
+ assigned(globalsymtable) then
+ exit;
+
+ { reset }
+ do_load:=true;
+ second_time:=false;
+ current_module:=self;
+ SetCompileModule(current_module);
+ Fillchar(aktfilepos,0,sizeof(aktfilepos));
+
+ { A force reload }
+ if do_reload then
+ begin
+ Message(unit_u_forced_reload);
+ do_reload:=false;
+ { When the unit is already loaded or being loaded
+ we can maybe skip a complete reload/recompile }
+ if assigned(globalsymtable) and
+ (not needrecompile) then
+ begin
+ { When we don't have any data stored yet there
+ is nothing to resolve }
+ if interface_compiled then
+ begin
+ Message1(unit_u_reresolving_unit,modulename^);
+ tstoredsymtable(globalsymtable).deref;
+ tstoredsymtable(globalsymtable).derefimpl;
+ if assigned(localsymtable) then
+ begin
+ tstoredsymtable(localsymtable).deref;
+ tstoredsymtable(localsymtable).derefimpl;
+ end;
+ end
+ else
+ Message1(unit_u_skipping_reresolving_unit,modulename^);
+ do_load:=false;
+ end;
+ end;
+
+ if do_load then
+ begin
+ { we are loading a new module, save the state of the scanner
+ and reset scanner+module }
+ if assigned(current_scanner) then
+ current_scanner.tempcloseinputfile;
+ current_scanner:=nil;
+
+ { loading the unit for a second time? }
+ if state=ms_registered then
+ state:=ms_load
+ else
+ begin
+ { try to load the unit a second time first }
+ Message1(unit_u_second_load_unit,modulename^);
+ Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
+ { Flag modules to reload }
+ flagdependent(old_current_module);
+ { Reset the module }
+ reset;
+ if state in [ms_compile,ms_second_compile] then
+ begin
+ Message1(unit_u_second_compile_unit,modulename^);
+ state:=ms_second_compile;
+ do_compile:=true;
+ end
+ else
+ state:=ms_second_load;
+ second_time:=true;
+ end;
+
+ { close old_current_ppu on system that are
+ short on file handles like DOS PM }
+{$ifdef SHORT_ON_FILE_HANDLES}
+ if old_current_module.is_unit and
+ assigned(tppumodule(old_current_module).ppufile) then
+ tppumodule(old_current_module).ppufile.tempclose;
+{$endif SHORT_ON_FILE_HANDLES}
+
+ { try to opening ppu, skip this when we already
+ know that we need to compile the unit }
+ if not do_compile then
+ begin
+ Message1(unit_u_loading_unit,modulename^);
+ search_unit(false,false);
+ if not do_compile then
+ begin
+ load_interface;
+ if not do_compile then
+ begin
+ load_usedunits;
+ if not do_compile then
+ Message1(unit_u_finished_loading_unit,modulename^);
+ end;
+ end;
+ { PPU is not needed anymore }
+ if assigned(ppufile) then
+ begin
+ ppufile.closefile;
+ ppufile.free;
+ ppufile:=nil;
+ end;
+ end;
+
+ { Do we need to recompile the unit }
+ if do_compile then
+ begin
+ { recompile the unit or give a fatal error if sources not available }
+ if not(sources_avail) then
+ begin
+ if (not search_unit(true,false)) and
+ (length(modulename^)>8) then
+ search_unit(true,true);
+ if not(sources_avail) then
+ begin
+ if recompile_reason=rr_noppu then
+ Message1(unit_f_cant_find_ppu,realmodulename^)
+ else
+ Message1(unit_f_cant_compile_unit,realmodulename^);
+ end;
+ end;
+ { Flag modules to reload }
+ flagdependent(old_current_module);
+ { Reset the module }
+ reset;
+ { compile this module }
+ if not(state in [ms_compile,ms_second_compile]) then
+ state:=ms_compile;
+ compile(mainsource^);
+ end
+ else
+ state:=ms_compiled;
+
+ if current_module<>self then
+ internalerror(200212282);
+
+ if in_interface then
+ internalerror(200212283);
+
+ { for a second_time recompile reload all dependent units,
+ for a first time compile register the unit _once_ }
+ if second_time then
+ reload_flagged_units
+ else
+ usedunits.concat(tused_unit.create(self,true,false,nil));
+
+ { reopen the old module }
+{$ifdef SHORT_ON_FILE_HANDLES}
+ if old_current_module.is_unit and
+ assigned(tppumodule(old_current_module).ppufile) then
+ tppumodule(old_current_module).ppufile.tempopen;
+{$endif SHORT_ON_FILE_HANDLES}
+
+ { reload old scanner }
+ current_scanner:=tscannerfile(old_current_module.scanner);
+ if assigned(current_scanner) then
+ begin
+ current_scanner.tempopeninputfile;
+ current_scanner.gettokenpos
+ end
+ else
+ fillchar(aktfilepos,sizeof(aktfilepos),0);
+ end;
+
+ { we are back, restore current_module }
+ current_module:=old_current_module;
+ SetCompileModule(current_module);
+ end;
+
+
+{*****************************************************************************
+ RegisterUnit
+*****************************************************************************}
+
+
+ function registerunit(callermodule:tmodule;const s : stringid;const fn:string) : tppumodule;
+ var
+ ups : stringid;
+ hp : tppumodule;
+ hp2 : tmodule;
+ begin
+ { Info }
+ ups:=upper(s);
+ { search all loaded units }
+ hp:=tppumodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.modulename^=ups then
+ begin
+ { only check for units. The main program is also
+ as a unit in the loaded_units list. We simply need
+ to ignore this entry (PFV) }
+ if hp.is_unit then
+ begin
+ { both units in interface ? }
+ if callermodule.in_interface and
+ hp.in_interface then
+ begin
+ { check for a cycle }
+ hp2:=callermodule.loaded_from;
+ while assigned(hp2) and (hp2<>hp) do
+ begin
+ if hp2.in_interface then
+ hp2:=hp2.loaded_from
+ else
+ hp2:=nil;
+ end;
+ if assigned(hp2) then
+ Message2(unit_f_circular_unit_reference,callermodule.realmodulename^,hp.realmodulename^);
+ end;
+ break;
+ end;
+ end;
+ { the next unit }
+ hp:=tppumodule(hp.next);
+ end;
+ { the unit is not in the loaded units,
+ we create an entry and register the unit }
+ if not assigned(hp) then
+ begin
+ Message1(unit_u_registering_new_unit,Upper(s));
+ hp:=tppumodule.create(callermodule,s,fn,true);
+ hp.loaded_from:=callermodule;
+ addloadedunit(hp);
+ end;
+ { return }
+ registerunit:=hp;
+ end;
+
+end.
diff --git a/compiler/gendef.pas b/compiler/gendef.pas
new file mode 100644
index 0000000000..5826c8ad7d
--- /dev/null
+++ b/compiler/gendef.pas
@@ -0,0 +1,159 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generation of a .def file for needed for Os2/Win32
+
+ 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 gendef;
+
+{$i fpcdefs.inc}
+
+interface
+uses
+ cclasses;
+
+type
+ tdeffile=class
+ fname : string;
+ constructor create(const fn:string);
+ destructor destroy;override;
+ procedure addexport(const s:string);
+ procedure addimport(const s:string);
+ procedure writefile;
+ function empty : boolean;
+ private
+ is_empty : boolean;
+ WrittenOnDisk : boolean;
+ exportlist,
+ importlist : tstringlist;
+ end;
+
+var
+ deffile : tdeffile;
+
+
+implementation
+
+uses
+ systems,cutils,globtype,globals;
+
+{******************************************************************************
+ TDefFile
+******************************************************************************}
+
+constructor tdeffile.create(const fn:string);
+begin
+ fname:=fn;
+ WrittenOnDisk:=false;
+ is_empty:=true;
+ importlist:=TStringList.Create;
+ exportlist:=TStringList.Create;
+end;
+
+
+destructor tdeffile.destroy;
+begin
+ if WrittenOnDisk and
+ not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(FName);
+ importlist.Free;
+ exportlist.Free;
+end;
+
+
+
+procedure tdeffile.addexport(const s:string);
+begin
+ exportlist.insert(s);
+ is_empty:=false;
+end;
+
+
+procedure tdeffile.addimport(const s:string);
+begin
+ importlist.insert(s);
+ is_empty:=false;
+end;
+
+
+function tdeffile.empty : boolean;
+begin
+ empty:=is_empty or DescriptionSetExplicity;
+end;
+
+
+procedure tdeffile.writefile;
+var
+ t : text;
+begin
+ If WrittenOnDisk then
+ Exit;
+{ open file }
+ assign(t,fname);
+ {$I+}
+ rewrite(t);
+ {$I-}
+ if ioresult<>0 then
+ exit;
+{$ifdef i386}
+ case target_info.system of
+ system_i386_Os2, system_i386_emx:
+ begin
+ write(t,'NAME '+inputfile);
+ if usewindowapi then
+ write(t,' WINDOWAPI');
+ writeln(t,'');
+ writeln(t,'PROTMODE');
+ writeln(t,'DESCRIPTION '+''''+description+'''');
+ writeln(t,'DATA'#9'MULTIPLE');
+ writeln(t,'STACKSIZE'#9+tostr(stacksize));
+ writeln(t,'HEAPSIZE'#9+tostr(heapsize));
+ end;
+ system_i386_win32, system_i386_wdosx :
+ begin
+ if description<>'' then
+ writeln(t,'DESCRIPTION '+''''+description+'''');
+ if dllversion<>'' then
+ writeln(t,'VERSION '+dllversion);
+ end;
+ end;
+{$endif}
+
+{write imports}
+ if not importlist.empty then
+ begin
+ writeln(t,'');
+ writeln(t,'IMPORTS');
+ while not importlist.empty do
+ writeln(t,#9+importlist.getfirst);
+ end;
+
+{write exports}
+ if not exportlist.empty then
+ begin
+ writeln(t,'');
+ writeln(t,'EXPORTS');
+ while not exportlist.empty do
+ writeln(t,#9+exportlist.getfirst);
+ end;
+
+ close(t);
+ WrittenOnDisk:=true;
+end;
+
+end.
diff --git a/compiler/globals.pas b/compiler/globals.pas
new file mode 100644
index 0000000000..21721ac164
--- /dev/null
+++ b/compiler/globals.pas
@@ -0,0 +1,2245 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements some support functions and global variables
+
+ 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 globals;
+
+{$i fpcdefs.inc}
+
+{ Use the internal linker by default }
+{ define INTERNALLINKER}
+
+interface
+
+ uses
+{$ifdef win32}
+ windows,
+{$endif}
+{$ifdef hasunix}
+ {$ifdef havelinuxrtl10}
+ linux,
+ {$else}
+ Baseunix,unix,
+ {$endif}
+{$endif}
+{$IFDEF USE_SYSUTILS}
+ SysUtils,
+{$ELSE USE_SYSUTILS}
+ strings,
+ dos,
+{$ENDIF USE_SYSUTILS}
+ cutils,cclasses,
+ cpuinfo,
+ globtype,version,systems;
+
+ const
+ delphimodeswitches : tmodeswitches=
+ [m_delphi,m_all,m_class,m_objpas,m_result,m_string_pchar,
+ m_pointer_2_procedure,m_autoderef,m_tp_procvar,m_initfinal,m_default_ansistring,
+ m_out,m_default_para,m_duplicate_names,m_hintdirective,m_add_pointer];
+ fpcmodeswitches : tmodeswitches=
+ [m_fpc,m_all,m_string_pchar,m_nested_comment,m_repeat_forward,
+ m_cvar_support,m_initfinal,m_add_pointer,m_hintdirective];
+ objfpcmodeswitches : tmodeswitches=
+ [m_objfpc,m_fpc,m_all,m_class,m_objpas,m_result,m_string_pchar,m_nested_comment,
+ m_repeat_forward,m_cvar_support,m_initfinal,m_add_pointer,m_out,m_default_para,m_hintdirective];
+ tpmodeswitches : tmodeswitches=
+ [m_tp7,m_all,m_tp_procvar,m_duplicate_names];
+ gpcmodeswitches : tmodeswitches=
+ [m_gpc,m_all,m_tp_procvar];
+ macmodeswitches : tmodeswitches=
+ [m_mac,m_all,m_result,m_cvar_support,m_mac_procvar];
+
+
+ { maximum nesting of routines }
+ maxnesting = 32;
+
+ { Filenames and extensions }
+ sourceext = '.pp';
+ pasext = '.pas';
+ pext = '.p';
+
+ treelogfilename = 'tree.log';
+
+{$if defined(CPUARM) and defined(FPUFPA)}
+ MathQNaN : tdoublearray = (0,0,252,255,0,0,0,0);
+ MathInf : tdoublearray = (0,0,240,127,0,0,0,0);
+ MathNegInf : tdoublearray = (0,0,240,255,0,0,0,0);
+ MathPi : tdoublearray = (251,33,9,64,24,45,68,84);
+{$else}
+{$ifdef FPC_LITTLE_ENDIAN}
+ MathQNaN : tdoublearray = (0,0,0,0,0,0,252,255);
+ MathInf : tdoublearray = (0,0,0,0,0,0,240,127);
+ MathNegInf : tdoublearray = (0,0,0,0,0,0,240,255);
+ MathPi : tdoublearray = (24,45,68,84,251,33,9,64);
+ MathPiExtended : textendedarray = (53,194,104,33,162,218,15,201,0,64);
+{$else FPC_LITTLE_ENDIAN}
+ MathQNaN : tdoublearray = (255,252,0,0,0,0,0,0);
+ MathInf : tdoublearray = (127,240,0,0,0,0,0,0);
+ MathNegInf : tdoublearray = (255,240,0,0,0,0,0,0);
+ MathPi : tdoublearray = (64,9,33,251,84,68,45,24);
+ MathPiExtended : textendedarray = (64,0,201,15,218,162,33,104,194,53);
+{$endif FPC_LITTLE_ENDIAN}
+{$endif}
+
+ type
+ TFPUException = (exInvalidOp, exDenormalized, exZeroDivide,
+ exOverflow, exUnderflow, exPrecision);
+ TFPUExceptionMask = set of TFPUException;
+
+ pfileposinfo = ^tfileposinfo;
+ tfileposinfo = record
+ line : longint;
+ column : word;
+ fileindex : word;
+ { moduleindex : word; }
+ end;
+
+ TSearchPathList = class(TStringList)
+ procedure AddPath(s:string;addfirst:boolean);overload;
+ procedure AddPath(SrcPath,s:string;addfirst:boolean);overload;
+ procedure AddList(list:TSearchPathList;addfirst:boolean);
+ function FindFile(const f : string;var foundfile:string):boolean;
+ end;
+
+ tcodepagestring = string[20];
+
+ var
+ { specified inputfile }
+ inputdir : dirstr;
+ inputfile : namestr;
+ inputextension : extstr;
+ { specified outputfile with -o parameter }
+ outputfile : namestr;
+ outputprefix : pstring;
+ outputsuffix : pstring;
+ outputextension : namestr;
+ { specified with -FE or -FU }
+ outputexedir : dirstr;
+ outputunitdir : dirstr;
+
+ { things specified with parameters }
+ paratarget : tsystem;
+ paratargetdbg : tdbg;
+ paratargetasm : tasm;
+ paralinkoptions,
+ paradynamiclinker : string;
+ paraprintnodetree : byte;
+ parapreprocess : boolean;
+ printnodefile : text;
+
+ { typical cross compiling params}
+
+ { directory where the utils can be found (options -FD) }
+ utilsdirectory : dirstr;
+ { targetname specific prefix used by these utils (options -XP<path>) }
+ utilsprefix : dirstr;
+ cshared : boolean; { pass --shared to ld to link C libs shared}
+ Dontlinkstdlibpath: Boolean; { Don't add std paths to linkpath}
+ rlinkpath : dirstr; { rpath-link linkdir override}
+
+ { some flags for global compiler switches }
+ do_build,
+ do_release,
+ do_make : boolean;
+ { path for searching units, different paths can be seperated by ; }
+ exepath : dirstr; { Path to ppc }
+ librarysearchpath,
+ unitsearchpath,
+ objectsearchpath,
+ includesearchpath : TSearchPathList;
+ autoloadunits : string;
+
+ { linking }
+ usewindowapi : boolean;
+ description : string;
+ DescriptionSetExplicity : boolean;
+ dllversion : string;
+ dllmajor,
+ dllminor,
+ dllrevision : word; { revision only for netware }
+ UseDeffileForExports : boolean;
+ UseDeffileForExportsSetExplicitly : boolean;
+ RelocSection : boolean;
+ RelocSectionSetExplicitly : boolean;
+ LinkTypeSetExplicitly : boolean;
+
+ akttokenpos, { position of the last token }
+ aktfilepos : tfileposinfo; { current position }
+
+ nwscreenname : string;
+ nwthreadname : string;
+ nwcopyright : string;
+
+ codegenerror : boolean; { true if there is an error reported }
+
+ block_type : tblock_type; { type of currently parsed block }
+
+ parsing_para_level : integer; { parameter level, used to convert
+ proc calls to proc loads in firstcalln }
+ compile_level : word;
+ make_ref : boolean;
+ resolving_forward : boolean; { used to add forward reference as second ref }
+ inlining_procedure : boolean; { are we inlining a procedure }
+ exceptblockcounter : integer; { each except block gets a unique number check gotos }
+ aktexceptblock : integer; { the exceptblock number of the current block (0 if none) }
+
+ { commandline values }
+ initglobalswitches : tglobalswitches;
+ initmoduleswitches : tmoduleswitches;
+ initlocalswitches : tlocalswitches;
+ initmodeswitches : tmodeswitches;
+ {$IFDEF testvarsets}
+ Initsetalloc, {0=fixed, 1 =var}
+ {$ENDIF}
+ initpackenum : shortint;
+ {$ifdef ansistring_bits}
+ initansistring_bits: Tstringbits;
+ {$endif}
+ initalignment : talignmentinfo;
+ initoptprocessor,
+ initspecificoptprocessor : tprocessors;
+ initfputype : tfputype;
+ initasmmode : tasmmode;
+ initinterfacetype : tinterfacetypes;
+ initdefproccall : tproccalloption;
+ initsourcecodepage : tcodepagestring;
+
+ { current state values }
+ aktglobalswitches : tglobalswitches;
+ aktmoduleswitches : tmoduleswitches;
+ aktlocalswitches : tlocalswitches;
+ nextaktlocalswitches : tlocalswitches;
+ localswitcheschanged : boolean;
+ aktmodeswitches : tmodeswitches;
+ {$IFDEF testvarsets}
+ aktsetalloc,
+ {$ENDIF}
+ aktpackrecords,
+ aktpackenum : shortint;
+ {$ifdef ansistring_bits}
+ aktansistring_bits : Tstringbits;
+ {$endif}
+ aktmaxfpuregisters : longint;
+ aktalignment : talignmentinfo;
+ aktoptprocessor,
+ aktspecificoptprocessor : tprocessors;
+ aktfputype : tfputype;
+ aktasmmode : tasmmode;
+ aktinterfacetype : tinterfacetypes;
+ aktdefproccall : tproccalloption;
+ aktsourcecodepage : tcodepagestring;
+
+ { Memory sizes }
+ heapsize,
+ stacksize,
+ jmp_buf_size : longint;
+
+{$Ifdef EXTDEBUG}
+ { parameter switches }
+ debugstop : boolean;
+{$EndIf EXTDEBUG}
+ { windows / OS/2 application type }
+ apptype : tapptype;
+
+ const
+ DLLsource : boolean = false;
+ DLLImageBase : pstring = nil;
+
+ { used to set all registers used for each global function
+ this should dramatically decrease the number of
+ recompilations needed PM }
+ simplify_ppu : boolean = true;
+
+ { should we allow non static members ? }
+ allow_only_static : boolean = false;
+
+ Inside_asm_statement : boolean = false;
+
+ global_unit_count : word = 0;
+
+ { for error info in pp.pas }
+ parser_current_file : string = '';
+
+{$ifdef m68k}
+ { PalmOS resources }
+ palmos_applicationname : string = 'FPC Application';
+ palmos_applicationid : string[4] = 'FPCA';
+{$endif m68k}
+
+{$ifdef powerpc}
+ { default calling convention used on MorphOS }
+ syscall_convention : string = 'LEGACY';
+{$endif powerpc}
+
+ { default name of the C-style "main" procedure of the library/program }
+ { (this will be prefixed with the target_info.cprefix) }
+ mainaliasname : string = 'main';
+
+ procedure abstract;
+
+ function bstoslash(const s : string) : string;
+
+ function getdatestr:string;
+ function gettimestr:string;
+ function filetimestring( t : longint) : string;
+
+ procedure DefaultReplacements(var s:string);
+ {Gives the absolute path to the current directory}
+ function GetCurrentDir:string;
+ {Gives the relative path to the current directory,
+ with a trailing dir separator. E. g. on unix ./ }
+ function CurDirRelPath(systeminfo: tsysteminfo): string;
+ function path_absolute(const s : string) : boolean;
+ Function PathExists ( F : String) : Boolean;
+ Function FileExists ( Const F : String) : Boolean;
+ function FileExistsNonCase(const path,fn:string;var foundfile:string):boolean;
+ Function RemoveFile(const f:string):boolean;
+ Function RemoveDir(d:string):boolean;
+ Function GetFileTime ( Var F : File) : Longint;
+ Function GetNamedFileTime ( Const F : String) : Longint;
+ {Extracts the path without its filename, from a path.}
+ Function SplitPath(const s:string):string;
+ Function SplitFileName(const s:string):string;
+ Function SplitName(const s:string):string;
+ Function SplitExtension(Const HStr:String):String;
+ Function AddExtension(Const HStr,ext:String):String;
+ Function ForceExtension(Const HStr,ext:String):String;
+ Function FixPath(s:string;allowdot:boolean):string;
+ function FixFileName(const s:string):string;
+ function TargetFixPath(s:string;allowdot:boolean):string;
+ function TargetFixFileName(const s:string):string;
+ procedure SplitBinCmd(const s:string;var bstr: String;var cstr:TCmdStr);
+ function FindFile(const f : string;path : string;var foundfile:string):boolean;
+ function FindFilePchar(const f : string;path : pchar;var foundfile:string):boolean;
+ function FindExe(const bin:string;var foundfile:string):boolean;
+ function GetShortName(const n:string):string;
+ function cleanpath(const s:string):String;
+
+ function Shell(const command:string): longint;
+ function GetEnvPChar(const envname:string):pchar;
+ procedure FreeEnvPChar(p:pchar);
+
+ procedure SetFPUExceptionMask(const Mask: TFPUExceptionMask);
+ function is_number_float(d : double) : boolean;
+
+ function SetAktProcCall(const s:string; changeInit: boolean):boolean;
+ function SetProcessor(const s:string; changeInit: boolean):boolean;
+ function SetFpuType(const s:string; changeInit: boolean):boolean;
+
+ procedure InitGlobals;
+ procedure DoneGlobals;
+
+ function string2guid(const s: string; var GUID: TGUID): boolean;
+ function guid2string(const GUID: TGUID): string;
+
+ function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
+
+ {# Routine to get the required alignment for size of data, which will
+ be placed in bss segment, according to the current alignment requirements }
+ function var_align(siz: longint): longint;
+ {# Routine to get the required alignment for size of data, which will
+ be placed in data/const segment, according to the current alignment requirements }
+ function const_align(siz: longint): longint;
+
+{$IFDEF MACOS_USE_FAKE_SYSUTILS}
+
+{Since SysUtils is not yet available for MacOS, fake
+ Exceptions classes are included here.}
+
+type
+ { exceptions }
+ Exception = class(TObject);
+
+ EExternal = class(Exception);
+
+ { integer math exceptions }
+ EInterror = Class(EExternal);
+ EDivByZero = Class(EIntError);
+ ERangeError = Class(EIntError);
+ EIntOverflow = Class(EIntError);
+
+ { General math errors }
+ EMathError = Class(EExternal);
+ EInvalidOp = Class(EMathError);
+ EZeroDivide = Class(EMathError);
+ EOverflow = Class(EMathError);
+ EUnderflow = Class(EMathError);
+
+{$ENDIF MACOS_USE_FAKE_SYSUTILS}
+
+implementation
+
+ uses
+{$ifdef macos}
+ macutils,
+{$endif}
+ comphook;
+
+ procedure abstract;
+ begin
+ do_internalerror(255);
+ end;
+
+
+ procedure WarnNonExistingPath(const path : string);
+ begin
+ if assigned(do_comment) then
+ do_comment(V_Tried,'Path "'+path+'" not found');
+ end;
+
+
+ function bstoslash(const s : string) : string;
+ {
+ return string s with all \ changed into /
+ }
+ var
+ i : longint;
+ begin
+ for i:=1to length(s) do
+ if s[i]='\' then
+ bstoslash[i]:='/'
+ else
+ bstoslash[i]:=s[i];
+ bstoslash[0]:=s[0];
+ end;
+
+
+{****************************************************************************
+ Time Handling
+****************************************************************************}
+
+ Function L0(l:longint):string;
+ {
+ return the string of value l, if l<10 then insert a zero, so
+ the string is always at least 2 chars '01','02',etc
+ }
+ var
+ s : string;
+ begin
+ Str(l,s);
+ if l<10 then
+ s:='0'+s;
+ L0:=s;
+ end;
+
+
+ function gettimestr:string;
+ {
+ get the current time in a string HH:MM:SS
+ }
+ var
+ hour,min,sec,hsec : word;
+ begin
+{$IFDEF USE_SYSUTILS}
+ DecodeTime(Time,hour,min,sec,hsec);
+{$ELSE USE_SYSUTILS}
+ dos.gettime(hour,min,sec,hsec);
+{$ENDIF USE_SYSUTILS}
+ gettimestr:=L0(Hour)+':'+L0(min)+':'+L0(sec);
+ end;
+
+
+ function getdatestr:string;
+ {
+ get the current date in a string YY/MM/DD
+ }
+ var
+{$IFDEF USE_SYSUTILS}
+ Year,Month,Day: Word;
+{$ELSE USE_SYSUTILS}
+ Year,Month,Day,Wday : Word;
+{$ENDIF USE_SYSUTILS}
+ begin
+{$IFDEF USE_SYSUTILS}
+ DecodeDate(Date,year,month,day);
+{$ELSE USE_SYSUTILS}
+ dos.getdate(year,month,day,wday);
+{$ENDIF USE_SYSUTILS}
+ getdatestr:=L0(Year)+'/'+L0(Month)+'/'+L0(Day);
+ end;
+
+
+ function filetimestring( t : longint) : string;
+ {
+ convert dos datetime t to a string YY/MM/DD HH:MM:SS
+ }
+ var
+{$IFDEF USE_SYSUTILS}
+ DT : TDateTime;
+ hsec : word;
+{$ELSE USE_SYSUTILS}
+ DT : DateTime;
+{$ENDIF USE_SYSUTILS}
+ Year,Month,Day: Word;
+ hour,min,sec : word;
+ begin
+ if t=-1 then
+ begin
+ Result := 'Not Found';
+ exit;
+ end;
+{$IFDEF USE_SYSUTILS}
+ DT := FileDateToDateTime(t);
+ DecodeTime(DT,hour,min,sec,hsec);
+ DecodeDate(DT,year,month,day);
+{$ELSE USE_SYSUTILS}
+ unpacktime(t,DT);
+ year := DT.year;
+ month := DT.month;
+ day := DT.day;
+ hour := DT.hour;
+ min := DT.min;
+ sec := DT.sec;
+{$ENDIF USE_SYSUTILS}
+ Result := L0(Year)+'/'+L0(Month)+'/'+L0(Day)+' '+L0(Hour)+':'+L0(min)+':'+L0(sec);
+ end;
+
+
+{****************************************************************************
+ Default Macro Handling
+****************************************************************************}
+
+ procedure DefaultReplacements(var s:string);
+ begin
+ { Replace some macros }
+ Replace(s,'$FPCVERSION',version_string);
+ Replace(s,'$FPCFULLVERSION',full_version_string);
+ Replace(s,'$FPCDATE',date_string);
+ Replace(s,'$FPCCPU',target_cpu_string);
+ Replace(s,'$FPCOS',target_os_string);
+ if tf_use_8_3 in Source_Info.Flags then
+ Replace(s,'$FPCTARGET',target_os_string)
+ else
+ Replace(s,'$FPCTARGET',target_full_string);
+ end;
+
+
+{****************************************************************************
+ File Handling
+****************************************************************************}
+
+ var
+ CachedCurrentDir : string;
+
+ {Gives the absolute path to the current directory}
+ function GetCurrentDir:string;
+ begin
+ if CachedCurrentDir='' then
+ begin
+ GetDir(0,CachedCurrentDir);
+ CachedCurrentDir:=FixPath(CachedCurrentDir,false);
+ end;
+ result:=CachedCurrentDir;
+ end;
+
+ {Gives the relative path to the current directory,
+ with a trailing dir separator. E. g. on unix ./ }
+ function CurDirRelPath(systeminfo: tsysteminfo): string;
+
+ begin
+ if systeminfo.system <> system_powerpc_macos then
+ CurDirRelPath:= '.'+systeminfo.DirSep
+ else
+ CurDirRelPath:= ':'
+ end;
+
+
+ function path_absolute(const s : string) : boolean;
+ {
+ is path s an absolute path?
+ }
+ begin
+ path_absolute:=false;
+{$ifdef unix}
+ if (length(s)>0) and (s[1]='/') then
+ path_absolute:=true;
+{$else unix}
+{$ifdef amiga}
+ if ((length(s)>0) and ((s[1]='\') or (s[1]='/'))) or (Pos(':',s) = length(s)) then
+ path_absolute:=true;
+{$else}
+{$ifdef macos}
+ if IsMacFullPath(s) then
+ path_absolute:=true;
+{$else}
+ if ((length(s)>0) and ((s[1]='\') or (s[1]='/'))) or
+ ((length(s)>2) and (s[2]=':') and ((s[3]='\') or (s[3]='/'))) then
+ path_absolute:=true;
+{$endif macos}
+{$endif amiga}
+{$endif unix}
+ end;
+
+{$ifndef FPC}
+ Procedure FindClose(var Info : SearchRec);
+ Begin
+ End;
+{$endif not FPC}
+
+
+ Function FileExists ( Const F : String) : Boolean;
+{$IFDEF USE_SYSUTILS}
+{$ELSE USE_SYSUTILS}
+ var
+ Info : SearchRec;
+{$ENDIF USE_SYSUTILS}
+ begin
+{$IFDEF USE_SYSUTILS}
+ Result:=SysUtils.FileExists(f);
+{$ELSE USE_SYSUTILS}
+ findfirst(F,readonly+archive+hidden,info);
+ result:=(doserror=0);
+ findclose(Info);
+{$ENDIF USE_SYSUTILS}
+ if assigned(do_comment) then
+ begin
+ if Result then
+ do_comment(V_Tried,'Searching file '+F+'... found')
+ else
+ do_comment(V_Tried,'Searching file '+F+'... not found');
+ end;
+ end;
+
+
+ function FileExistsNonCase(const path,fn:string;var foundfile:string):boolean;
+ var
+ fn2 : string;
+ begin
+ result:=false;
+ if source_info.files_case_relevent then
+ begin
+ {
+ Search order for case sensitive systems:
+ 1. NormalCase
+ 2. lowercase
+ 3. UPPERCASE
+ }
+ FoundFile:=path+fn;
+ If FileExists(FoundFile) then
+ begin
+ result:=true;
+ exit;
+ end;
+ fn2:=Lower(fn);
+ if fn2<>fn then
+ begin
+ FoundFile:=path+fn2;
+ If FileExists(FoundFile) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ fn2:=Upper(fn);
+ if fn2<>fn then
+ begin
+ FoundFile:=path+fn2;
+ If FileExists(FoundFile) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end
+ else
+ begin
+ { None case sensitive only lowercase }
+ FoundFile:=path+Lower(fn);
+ If FileExists(FoundFile) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ { Set foundfile to something usefull }
+ FoundFile:=fn;
+ end;
+
+
+ Function PathExists ( F : String) : Boolean;
+ Var
+{$IFDEF USE_SYSUTILS}
+{$ELSE USE_SYSUTILS}
+ FF : file;
+{$ENDIF USE_SYSUTILS}
+ A: word;
+ I: longint;
+ begin
+ if F = '' then
+ begin
+ PathExists := true;
+ exit;
+ end;
+{$ifdef USE_SYSUTILS}
+ F := ExpandFileName(F);
+{$else USE_SYSUTILS}
+ F := FExpand (F);
+{$endif USE_SYSUTILS}
+ I := Pos (DriveSeparator, F);
+ if (F [Length (F)] = DirectorySeparator)
+ and (((I = 0) and (Length (F) > 1)) or (I <> Length (F) - 1))
+ then
+ Delete (F, Length (F), 1);
+{$IFDEF USE_SYSUTILS}
+ PathExists := FileGetAttr(F) and faDirectory = faDirectory;
+{$ELSE USE_SYSUTILS}
+ Assign (FF, FExpand (F));
+ GetFAttr (FF, A);
+ PathExists := (DosError = 0) and (A and Directory = Directory);
+{$ENDIF USE_SYSUTILS}
+ end;
+
+
+ Function RemoveFile(const f:string):boolean;
+ var
+ g : file;
+ begin
+ assign(g,f);
+ {$I-}
+ erase(g);
+ {$I+}
+ RemoveFile:=(ioresult=0);
+ end;
+
+
+ Function RemoveDir(d:string):boolean;
+ begin
+ if d[length(d)]=source_info.DirSep then
+ Delete(d,length(d),1);
+ {$I-}
+ rmdir(d);
+ {$I+}
+ RemoveDir:=(ioresult=0);
+ end;
+
+
+ Function SplitPath(const s:string):string;
+ var
+ i : longint;
+ begin
+ i:=Length(s);
+{$ifdef macos}
+ while (i>0) and not(s[i] in [':']) do
+ dec(i);
+{$else macos}
+ while (i>0) and not(s[i] in ['/','\']) do
+ dec(i);
+{$endif macos}
+ SplitPath:=Copy(s,1,i);
+ end;
+
+
+ Function SplitFileName(const s:string):string;
+{$IFDEF USE_SYSUTILS}
+{$ELSE USE_SYSUTILS}
+ var
+ p : dirstr;
+ n : namestr;
+ e : extstr;
+{$ENDIF USE_SYSUTILS}
+ begin
+{$IFDEF USE_SYSUTILS}
+ SplitFileName:=ExtractFileName(s);
+{$ELSE USE_SYSUTILS}
+ FSplit(s,p,n,e);
+ SplitFileName:=n+e;
+{$ENDIF USE_SYSUTILS}
+ end;
+
+
+ Function SplitName(const s:string):string;
+ var
+ i,j : longint;
+ begin
+ i:=Length(s);
+ j:=Length(s);
+ while (i>0) and not(s[i] in ['/','\']) do
+ dec(i);
+ while (j>0) and (s[j]<>'.') do
+ dec(j);
+ if j<=i then
+ j:=255;
+ SplitName:=Copy(s,i+1,j-(i+1));
+ end;
+
+
+ Function SplitExtension(Const HStr:String):String;
+ var
+ j : longint;
+ begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ begin
+ if hstr[j]=source_info.DirSep then
+ j:=0
+ else
+ dec(j);
+ end;
+ if j=0 then
+ j:=254;
+ SplitExtension:=Copy(Hstr,j,255);
+ end;
+
+
+ Function AddExtension(Const HStr,ext:String):String;
+ begin
+ if (Ext<>'') and (SplitExtension(HStr)='') then
+ AddExtension:=Hstr+Ext
+ else
+ AddExtension:=Hstr;
+ end;
+
+
+ Function ForceExtension(Const HStr,ext:String):String;
+ var
+ j : longint;
+ begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ j:=255;
+ ForceExtension:=Copy(Hstr,1,j-1)+Ext;
+ end;
+
+
+ Function FixPath(s:string;allowdot:boolean):string;
+ var
+ i : longint;
+ begin
+ { Fix separator }
+ for i:=1 to length(s) do
+ if s[i] in ['/','\'] then
+ s[i]:=source_info.DirSep;
+ { Fix ending / }
+ if (length(s)>0) and (s[length(s)]<>source_info.DirSep) and
+ (s[length(s)]<>':') then
+ s:=s+source_info.DirSep;
+ { Remove ./ }
+ if (not allowdot) and (s='.'+source_info.DirSep) then
+ s:='';
+ { return }
+ if source_info.files_case_relevent then
+ FixPath:=s
+ else
+ FixPath:=Lower(s);
+ end;
+
+ {Actually the version in macutils.pp could be used,
+ but that would not work for crosscompiling, so this is a slightly modified
+ version of it.}
+ function TranslatePathToMac (const path: string; mpw: Boolean): string;
+
+ function GetVolumeIdentifier: string;
+
+ begin
+ GetVolumeIdentifier := '{Boot}'
+ (*
+ if mpw then
+ GetVolumeIdentifier := '{Boot}'
+ else
+ GetVolumeIdentifier := macosBootVolumeName;
+ *)
+ end;
+
+ var
+ slashPos, oldpos, newpos, oldlen, maxpos: Longint;
+
+ begin
+ oldpos := 1;
+ slashPos := Pos('/', path);
+ if (slashPos <> 0) then {its a unix path}
+ begin
+ if slashPos = 1 then
+ begin {its a full path}
+ oldpos := 2;
+ TranslatePathToMac := GetVolumeIdentifier;
+ end
+ else {its a partial path}
+ TranslatePathToMac := ':';
+ end
+ else
+ begin
+ slashPos := Pos('\', path);
+ if (slashPos <> 0) then {its a dos path}
+ begin
+ if slashPos = 1 then
+ begin {its a full path, without drive letter}
+ oldpos := 2;
+ TranslatePathToMac := GetVolumeIdentifier;
+ end
+ else if (Length(path) >= 2) and (path[2] = ':') then {its a full path, with drive letter}
+ begin
+ oldpos := 4;
+ TranslatePathToMac := GetVolumeIdentifier;
+ end
+ else {its a partial path}
+ TranslatePathToMac := ':';
+ end;
+ end;
+
+ if (slashPos <> 0) then {its a unix or dos path}
+ begin
+ {Translate "/../" to "::" , "/./" to ":" and "/" to ":" }
+ newpos := Length(TranslatePathToMac);
+ oldlen := Length(path);
+ SetLength(TranslatePathToMac, newpos + oldlen); {It will be no longer than what is already}
+ {prepended plus length of path.}
+ maxpos := Length(TranslatePathToMac); {Get real maxpos, can be short if String is ShortString}
+
+ {There is never a slash in the beginning, because either it was an absolute path, and then the}
+ {drive and slash was removed, or it was a relative path without a preceding slash.}
+ while oldpos <= oldlen do
+ begin
+ {Check if special dirs, ./ or ../ }
+ if path[oldPos] = '.' then
+ if (oldpos + 1 <= oldlen) and (path[oldPos + 1] = '.') then
+ begin
+ if (oldpos + 2 > oldlen) or (path[oldPos + 2] in ['/', '\']) then
+ begin
+ {It is "../" or ".." translates to ":" }
+ if newPos = maxPos then
+ begin {Shouldn't actually happen, but..}
+ Exit('');
+ end;
+ newPos := newPos + 1;
+ TranslatePathToMac[newPos] := ':';
+ oldPos := oldPos + 3;
+ continue; {Start over again}
+ end;
+ end
+ else if (oldpos + 1 > oldlen) or (path[oldPos + 1] in ['/', '\']) then
+ begin
+ {It is "./" or "." ignor it }
+ oldPos := oldPos + 2;
+ continue; {Start over again}
+ end;
+
+ {Collect file or dir name}
+ while (oldpos <= oldlen) and not (path[oldPos] in ['/', '\']) do
+ begin
+ if newPos = maxPos then
+ begin {Shouldn't actually happen, but..}
+ Exit('');
+ end;
+ newPos := newPos + 1;
+ TranslatePathToMac[newPos] := path[oldPos];
+ oldPos := oldPos + 1;
+ end;
+
+ {When we come here there is either a slash or we are at the end.}
+ if (oldpos <= oldlen) then
+ begin
+ if newPos = maxPos then
+ begin {Shouldn't actually happen, but..}
+ Exit('');
+ end;
+ newPos := newPos + 1;
+ TranslatePathToMac[newPos] := ':';
+ oldPos := oldPos + 1;
+ end;
+ end;
+
+ SetLength(TranslatePathToMac, newpos);
+ end
+ else if (path = '.') then
+ TranslatePathToMac := ':'
+ else if (path = '..') then
+ TranslatePathToMac := '::'
+ else
+ TranslatePathToMac := path; {its a mac path}
+ end;
+
+
+ function FixFileName(const s:string):string;
+ var
+ i : longint;
+ begin
+ if source_info.system = system_powerpc_MACOS then
+ FixFileName:= TranslatePathToMac(s, true)
+ else if source_info.files_case_relevent then
+ begin
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '/','\' :
+ FixFileName[i]:=source_info.dirsep;
+ else
+ FixFileName[i]:=s[i];
+ end;
+ end;
+ FixFileName[0]:=s[0];
+ end
+ else
+ begin
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '/','\' :
+ FixFileName[i]:=source_info.dirsep;
+ 'A'..'Z' :
+ FixFileName[i]:=char(byte(s[i])+32);
+ else
+ FixFileName[i]:=s[i];
+ end;
+ end;
+ FixFileName[0]:=s[0];
+ end;
+ end;
+
+
+ Function TargetFixPath(s:string;allowdot:boolean):string;
+ var
+ i : longint;
+ begin
+ { Fix separator }
+ for i:=1 to length(s) do
+ if s[i] in ['/','\'] then
+ s[i]:=target_info.DirSep;
+ { Fix ending / }
+ if (length(s)>0) and (s[length(s)]<>target_info.DirSep) and
+ (s[length(s)]<>':') then
+ s:=s+target_info.DirSep;
+ { Remove ./ }
+ if (not allowdot) and (s='.'+target_info.DirSep) then
+ s:='';
+ { return }
+ if target_info.files_case_relevent then
+ TargetFixPath:=s
+ else
+ TargetFixPath:=Lower(s);
+ end;
+
+
+ function TargetFixFileName(const s:string):string;
+ var
+ i : longint;
+ begin
+ if target_info.system = system_powerpc_MACOS then
+ TargetFixFileName:= TranslatePathToMac(s, true)
+ else if target_info.files_case_relevent then
+ begin
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '/','\' :
+ TargetFixFileName[i]:=target_info.dirsep;
+ else
+ TargetFixFileName[i]:=s[i];
+ end;
+ end;
+ TargetFixFileName[0]:=s[0];
+ end
+ else
+ begin
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '/','\' :
+ TargetFixFileName[i]:=target_info.dirsep;
+ 'A'..'Z' :
+ TargetFixFileName[i]:=char(byte(s[i])+32);
+ else
+ TargetFixFileName[i]:=s[i];
+ end;
+ end;
+ TargetFixFileName[0]:=s[0];
+ end;
+ end;
+
+
+ procedure SplitBinCmd(const s:string;var bstr:String;var cstr:TCmdStr);
+ var
+ i : longint;
+ begin
+ i:=pos(' ',s);
+ if i>0 then
+ begin
+ bstr:=Copy(s,1,i-1);
+ cstr:=Copy(s,i+1,length(s)-i);
+ end
+ else
+ begin
+ bstr:=s;
+ cstr:='';
+ end;
+ end;
+
+ procedure TSearchPathList.AddPath(s:string;addfirst:boolean);
+ begin
+ AddPath('',s,AddFirst);
+ end;
+
+ procedure TSearchPathList.AddPath(SrcPath,s:string;addfirst:boolean);
+ var
+ staridx,
+ j : longint;
+ prefix,
+ suffix,
+ CurrentDir,
+ currPath : string;
+ subdirfound : boolean;
+{$IFDEF USE_SYSUTILS}
+ dir : TSearchRec;
+{$ELSE USE_SYSUTILS}
+ dir : searchrec;
+{$ENDIF USE_SYSUTILS}
+ hp : TStringListItem;
+
+ procedure AddCurrPath;
+ begin
+ if addfirst then
+ begin
+ Remove(currPath);
+ Insert(currPath);
+ end
+ else
+ begin
+ { Check if already in path, then we don't add it }
+ hp:=Find(currPath);
+ if not assigned(hp) then
+ Concat(currPath);
+ end;
+ end;
+
+ begin
+ if s='' then
+ exit;
+ { Support default macro's }
+ DefaultReplacements(s);
+ { get current dir }
+ CurrentDir:=GetCurrentDir;
+ repeat
+ { get currpath }
+ if addfirst then
+ begin
+ j:=length(s);
+ while (j>0) and (s[j]<>';') do
+ dec(j);
+ currPath:= TrimSpace(Copy(s,j+1,length(s)-j));
+ DePascalQuote(currPath);
+ currPath:=FixPath(currPath,false);
+ if j=0 then
+ s:=''
+ else
+ System.Delete(s,j,length(s)-j+1);
+ end
+ else
+ begin
+ j:=Pos(';',s);
+ if j=0 then
+ j:=255;
+ currPath:= TrimSpace(Copy(s,1,j-1));
+ DePascalQuote(currPath);
+ currPath:=SrcPath+FixPath(currPath,false);
+ System.Delete(s,1,j);
+ end;
+
+ { fix pathname }
+ if currPath='' then
+ currPath:= CurDirRelPath(source_info)
+ else
+ begin
+{$ifdef USE_SYSUTILS}
+ currPath:=FixPath(ExpandFileName(currpath),false);
+{$else USE_SYSUTILS}
+ currPath:=FixPath(FExpand(currPath),false);
+{$endif USE_SYSUTILS}
+ if (CurrentDir<>'') and (Copy(currPath,1,length(CurrentDir))=CurrentDir) then
+ begin
+{$ifdef AMIGA}
+ currPath:= CurrentDir+Copy(currPath,length(CurrentDir)+1,255);
+{$else}
+ currPath:= CurDirRelPath(source_info)+Copy(currPath,length(CurrentDir)+1,255);
+{$endif}
+ end;
+ end;
+ { wildcard adding ? }
+ staridx:=pos('*',currpath);
+ if staridx>0 then
+ begin
+ prefix:=SplitPath(Copy(currpath,1,staridx));
+ suffix:=Copy(currpath,staridx+1,length(currpath));
+ subdirfound:=false;
+{$IFDEF USE_SYSUTILS}
+ if findfirst(prefix+'*',faDirectory,dir) = 0 then
+ begin
+ repeat
+ if (dir.name<>'.') and
+ (dir.name<>'..') and
+ ((dir.attr and faDirectory)<>0) then
+ begin
+ subdirfound:=true;
+ currpath:=prefix+dir.name+suffix;
+ if (suffix='') or PathExists(currpath) then
+ begin
+ hp:=Find(currPath);
+ if not assigned(hp) then
+ AddCurrPath;
+ end;
+ end;
+ until findnext(dir) <> 0;
+ end;
+{$ELSE USE_SYSUTILS}
+ findfirst(prefix+'*',directory,dir);
+ while doserror=0 do
+ begin
+ if (dir.name<>'.') and
+ (dir.name<>'..') and
+ ((dir.attr and directory)<>0) then
+ begin
+ subdirfound:=true;
+ currpath:=prefix+dir.name+suffix;
+ if (suffix='') or PathExists(currpath) then
+ begin
+ hp:=Find(currPath);
+ if not assigned(hp) then
+ AddCurrPath;
+ end;
+ end;
+ findnext(dir);
+ end;
+{$ENDIF USE_SYSUTILS}
+ FindClose(dir);
+ if not subdirfound then
+ WarnNonExistingPath(currpath);
+ end
+ else
+ begin
+ if PathExists(currpath) then
+ AddCurrPath
+ else
+ WarnNonExistingPath(currpath);
+ end;
+ until (s='');
+ end;
+
+
+ procedure TSearchPathList.AddList(list:TSearchPathList;addfirst:boolean);
+ var
+ s : string;
+ hl : TSearchPathList;
+ hp,hp2 : TStringListItem;
+ begin
+ if list.empty then
+ exit;
+ { create temp and reverse the list }
+ if addfirst then
+ begin
+ hl:=TSearchPathList.Create;
+ hp:=TStringListItem(list.first);
+ while assigned(hp) do
+ begin
+ hl.insert(hp.Str);
+ hp:=TStringListItem(hp.next);
+ end;
+ while not hl.empty do
+ begin
+ s:=hl.GetFirst;
+ Remove(s);
+ Insert(s);
+ end;
+ hl.Free;
+ end
+ else
+ begin
+ hp:=TStringListItem(list.first);
+ while assigned(hp) do
+ begin
+ hp2:=Find(hp.Str);
+ { Check if already in path, then we don't add it }
+ if not assigned(hp2) then
+ Concat(hp.Str);
+ hp:=TStringListItem(hp.next);
+ end;
+ end;
+ end;
+
+
+ function TSearchPathList.FindFile(const f : string;var foundfile:string):boolean;
+ Var
+ p : TStringListItem;
+ begin
+ FindFile:=false;
+ p:=TStringListItem(first);
+ while assigned(p) do
+ begin
+ result:=FileExistsNonCase(p.Str,f,FoundFile);
+ if result then
+ exit;
+ p:=TStringListItem(p.next);
+ end;
+ { Return original filename if not found }
+ FoundFile:=f;
+ end;
+
+
+ Function GetFileTime ( Var F : File) : Longint;
+ Var
+ {$ifdef hasunix}
+ info: Stat;
+ {$endif}
+ L : longint;
+ begin
+ {$ifdef hasunix}
+ {$IFDEF havelinuxrtl10}
+ FStat (F,Info);
+ L:=Info.Mtime;
+ {$ELSE}
+ FPFStat (F,Info);
+ L:=Info.st_Mtime;
+ {$ENDIF}
+ {$else}
+ GetFTime(f,l);
+ {$endif}
+ GetFileTime:=L;
+ end;
+
+
+ Function GetNamedFileTime (Const F : String) : Longint;
+ begin
+ GetNamedFileTime:=do_getnamedfiletime(F);
+ end;
+
+
+ function FindFile(const f : string;path : string;var foundfile:string):boolean;
+ Var
+ singlepathstring : string;
+ i : longint;
+ begin
+{$ifdef Unix}
+ for i:=1 to length(path) do
+ if path[i]=':' then
+ path[i]:=';';
+{$endif Unix}
+ FindFile:=false;
+ repeat
+ i:=pos(';',path);
+ if i=0 then
+ i:=256;
+ singlepathstring:=FixPath(copy(path,1,i-1),false);
+ delete(path,1,i);
+ result:=FileExistsNonCase(singlepathstring,f,FoundFile);
+ if result then
+ exit;
+ until path='';
+ FoundFile:=f;
+ end;
+
+
+ function FindFilePchar(const f : string;path : pchar;var foundfile:string):boolean;
+ Var
+ singlepathstring : string;
+ startpc,pc : pchar;
+ sepch : char;
+ begin
+ FindFilePchar:=false;
+ if Assigned (Path) then
+ begin
+{$ifdef Unix}
+ sepch:=':';
+{$else}
+{$ifdef macos}
+ sepch:=',';
+{$else}
+ sepch:=';';
+{$endif macos}
+{$endif Unix}
+ pc:=path;
+ repeat
+ startpc:=pc;
+ while (pc^<>sepch) and (pc^<>';') and (pc^<>#0) do
+ inc(pc);
+ move(startpc^,singlepathstring[1],pc-startpc);
+ singlepathstring[0]:=char(longint(pc-startpc));
+ singlepathstring:=FixPath(singlepathstring,false);
+ result:=FileExistsNonCase(singlepathstring,f,FoundFile);
+ if result then
+ exit;
+ if (pc^=#0) then
+ break;
+ inc(pc);
+ until false;
+ end;
+ foundfile:=f;
+ end;
+
+
+ function FindExe(const bin:string;var foundfile:string):boolean;
+ var
+ p : pchar;
+ found : boolean;
+ begin
+ found:=FindFile(FixFileName(AddExtension(bin,source_info.exeext)),'.;'+exepath,foundfile);
+ if not found then
+ begin
+{$ifdef macos}
+ p:=GetEnvPchar('Commands');
+{$else}
+ p:=GetEnvPchar('PATH');
+{$endif}
+ found:=FindFilePChar(FixFileName(AddExtension(bin,source_info.exeext)),p,foundfile);
+ FreeEnvPChar(p);
+ end;
+ FindExe:=found;
+ end;
+
+
+ function GetShortName(const n:string):string;
+{$ifdef win32}
+ var
+ hs,hs2 : string;
+ i : longint;
+{$endif}
+{$ifdef go32v2}
+ var
+ hs : string;
+{$endif}
+{$ifdef watcom}
+ var
+ hs : string;
+{$endif}
+ begin
+ GetShortName:=n;
+{$ifdef win32}
+ hs:=n+#0;
+ i:=Windows.GetShortPathName(@hs[1],@hs2[1],high(hs2));
+ if (i>0) and (i<=high(hs2)) then
+ begin
+ hs2[0]:=chr(strlen(@hs2[1]));
+ GetShortName:=hs2;
+ end;
+{$endif}
+{$ifdef go32v2}
+ hs:=n;
+ if Dos.GetShortName(hs) then
+ GetShortName:=hs;
+{$endif}
+{$ifdef watcom}
+ hs:=n;
+ if Dos.GetShortName(hs) then
+ GetShortName:=hs;
+{$endif}
+ end;
+
+
+function CleanPath(const s:string):String;
+{ Wrapper that encapsulate fexpand/expandfilename}
+begin
+{$IFDEF USE_SYSUTILS}
+ cleanpath:=ExpandFileName(s);
+{$else}
+ cleanpath:=fexpand(s);
+{$endif}
+end;
+ {****************************************************************************
+ OS Dependent things
+ ****************************************************************************}
+
+ function GetEnvPChar(const envname:string):pchar;
+ {$ifdef win32}
+ var
+ s : string;
+ i,len : longint;
+ hp,p,p2 : pchar;
+ {$endif}
+ begin
+ {$ifdef hasunix}
+ GetEnvPchar:={$ifdef havelinuxrtl10}Linux.getenv{$else}BaseUnix.fpGetEnv{$endif}(envname);
+ {$define GETENVOK}
+ {$endif}
+ {$ifdef win32}
+ GetEnvPchar:=nil;
+ p:=GetEnvironmentStrings;
+ hp:=p;
+ while hp^<>#0 do
+ begin
+ s:=strpas(hp);
+ i:=pos('=',s);
+ len:=strlen(hp);
+ if upper(copy(s,1,i-1))=upper(envname) then
+ begin
+ GetMem(p2,len-length(envname));
+ Move(hp[i],p2^,len-length(envname));
+ GetEnvPchar:=p2;
+ break;
+ end;
+ { next string entry}
+ hp:=hp+len+1;
+ end;
+ FreeEnvironmentStrings(p);
+ {$define GETENVOK}
+ {$endif}
+ {$ifdef os2}
+ GetEnvPChar := Dos.GetEnvPChar (EnvName);
+ {$define GETENVOK}
+ {$endif}
+ {$ifdef GETENVOK}
+ {$undef GETENVOK}
+ {$else}
+ GetEnvPchar:=StrPNew(Dos.Getenv(envname));
+ {$endif}
+ end;
+
+
+ procedure FreeEnvPChar(p:pchar);
+ begin
+ {$ifndef hasunix}
+ {$ifndef os2}
+ StrDispose(p);
+ {$endif}
+ {$endif}
+ end;
+
+{$IFDEF MORPHOS}
+{$DEFINE AMIGASHELL}
+{$ENDIF}
+{$IFDEF AMIGA}
+{$DEFINE AMIGASHELL}
+{$ENDIF}
+
+ function Shell(const command:string): longint;
+ { This is already defined in the linux.ppu for linux, need for the *
+ expansion under linux }
+ {$ifdef hasunix}
+ begin
+ result := {$ifdef havelinuxrtl10}Linux{$else}Unix{$endif}.Shell(command);
+ end;
+ {$else}
+ {$ifdef amigashell}
+ begin
+{$IFDEF USE_SYSUTILS}
+ result := ExecuteProcess('',command);
+{$ELSE USE_SYSUTILS}
+ exec('',command);
+ if (doserror <> 0) then
+ result := doserror
+ else
+ result := dosexitcode;
+ end;
+{$ENDIF USE_SYSUTILS}
+ {$else}
+ var
+ comspec : string;
+ begin
+ comspec:=getenv('COMSPEC');
+{$IFDEF USE_SYSUTILS}
+ result := ExecuteProcess(comspec,' /C '+command);
+{$ELSE USE_SYSUTILS}
+ Exec(comspec,' /C '+command);
+ if (doserror <> 0) then
+ result := doserror
+ else
+ result := dosexitcode;
+ end;
+{$ENDIF USE_SYSUTILS}
+ {$endif}
+ {$endif}
+
+{$UNDEF AMIGASHELL}
+
+{$ifdef CPUI386}
+ {$define HASSETFPUEXCEPTIONMASK}
+ { later, this should be replaced by the math unit }
+ const
+ Default8087CW : word = $1332;
+
+ procedure Set8087CW(cw:word);assembler;
+ asm
+ movw cw,%ax
+ movw %ax,default8087cw
+ fnclex
+ fldcw default8087cw
+ end;
+
+
+ function Get8087CW:word;assembler;
+ asm
+ pushl $0
+ fnstcw (%esp)
+ popl %eax
+ end;
+
+
+ procedure SetFPUExceptionMask(const Mask: TFPUExceptionMask);
+ var
+ CtlWord: Word;
+ begin
+ CtlWord:=Get8087CW;
+ Set8087CW( (CtlWord and $FFC0) or Byte(Longint(Mask)) );
+ end;
+{$endif CPUI386}
+
+{$ifdef CPUX86_64}
+ {$define HASSETFPUEXCEPTIONMASK}
+ { later, this should be replaced by the math unit }
+ const
+ Default8087CW : word = $1332;
+
+ procedure Set8087CW(cw:word);assembler;
+ asm
+ movw cw,%ax
+ movw %ax,default8087cw
+ fnclex
+ fldcw default8087cw
+ end;
+
+
+ function Get8087CW:word;assembler;
+ asm
+ pushq $0
+ fnstcw (%rsp)
+ popq %rax
+ end;
+
+
+ procedure SetSSECSR(w : dword);
+ var
+ _w : dword;
+ begin
+ _w:=w;
+ asm
+ ldmxcsr _w
+ end;
+ end;
+
+
+ function GetSSECSR : dword;
+ var
+ _w : dword;
+ begin
+ asm
+ stmxcsr _w
+ end;
+ result:=_w;
+ end;
+
+
+ procedure SetFPUExceptionMask(const Mask: TFPUExceptionMask);
+ var
+ CtlWord: Word;
+ newmask : dword;
+ const
+ MM_MaskInvalidOp = %0000000010000000;
+ MM_MaskDenorm = %0000000100000000;
+ MM_MaskDivZero = %0000001000000000;
+ MM_MaskOverflow = %0000010000000000;
+ MM_MaskUnderflow = %0000100000000000;
+ MM_MaskPrecision = %0001000000000000;
+ begin
+ { classic FPU }
+ CtlWord:=Get8087CW;
+ Set8087CW( (CtlWord and $FFC0) or Byte(Longint(Mask)) );
+
+ { SSE }
+
+ newmask:=GetSSECSR;
+
+ { invalid operation }
+ if (exInvalidOp in mask) then
+ newmask:=newmask or MM_MaskInvalidOp
+ else
+ newmask:=newmask and not(MM_MaskInvalidOp);
+
+ { denormals }
+ if (exDenormalized in mask) then
+ newmask:=newmask or MM_MaskDenorm
+ else
+ newmask:=newmask and not(MM_MaskDenorm);
+
+ { zero divide }
+ if (exZeroDivide in mask) then
+ newmask:=newmask or MM_MaskDivZero
+ else
+ newmask:=newmask and not(MM_MaskDivZero);
+
+ { overflow }
+ if (exOverflow in mask) then
+ newmask:=newmask or MM_MaskOverflow
+ else
+ newmask:=newmask and not(MM_MaskOverflow);
+
+ { underflow }
+ if (exUnderflow in mask) then
+ newmask:=newmask or MM_MaskUnderflow
+ else
+ newmask:=newmask and not(MM_MaskUnderflow);
+
+ { Precision (inexact result) }
+ if (exPrecision in mask) then
+ newmask:=newmask or MM_MaskPrecision
+ else
+ newmask:=newmask and not(MM_MaskPrecision);
+ SetSSECSR(newmask);
+ end;
+{$endif CPUX86_64}
+
+{$ifdef CPUPOWERPC}
+ {$define HASSETFPUEXCEPTIONMASK}
+ procedure SetFPUExceptionMask(const Mask: TFPUExceptionMask);
+ var
+ newmask: record
+ case byte of
+ 1: (d: double);
+ 2: (a,b: cardinal);
+ end;
+ begin
+ { load current control register contents }
+ asm
+ mffs f0
+ stfd f0,newmask.d
+ end;
+ { invalid operation: bit 24 (big endian, bit 0 = left-most bit) }
+ if (exInvalidOp in mask) then
+ newmask.b := newmask.b and not(1 shl (31-24))
+ else
+ newmask.b := newmask.b or (1 shl (31-24));
+
+ { denormals can not cause exceptions on the PPC }
+
+ { zero divide: bit 27 }
+ if (exZeroDivide in mask) then
+ newmask.b := newmask.b and not(1 shl (31-27))
+ else
+ newmask.b := newmask.b or (1 shl (31-27));
+
+ { overflow: bit 25 }
+ if (exOverflow in mask) then
+ newmask.b := newmask.b and not(1 shl (31-25))
+ else
+ newmask.b := newmask.b or (1 shl (31-25));
+
+ { underflow: bit 26 }
+ if (exUnderflow in mask) then
+ newmask.b := newmask.b and not(1 shl (31-26))
+ else
+ newmask.b := newmask.b or (1 shl (31-26));
+
+ { Precision (inexact result): bit 28 }
+ if (exPrecision in mask) then
+ newmask.b := newmask.b and not(1 shl (31-28))
+ else
+ newmask.b := newmask.b or (1 shl (31-28));
+ { update control register contents }
+ asm
+ lfd f0, newmask.d
+ mtfsf 255,f0
+ end;
+ end;
+{$endif CPUPOWERPC}
+
+{$ifdef CPUSPARC}
+ {$define HASSETFPUEXCEPTIONMASK}
+ procedure SetFPUExceptionMask(const Mask: TFPUExceptionMask);
+ var
+ fsr : cardinal;
+ begin
+ { load current control register contents }
+ asm
+ st %fsr,fsr
+ end;
+ { invalid operation: bit 27 }
+ if (exInvalidOp in mask) then
+ fsr:=fsr and not(1 shl 27)
+ else
+ fsr:=fsr or (1 shl 27);
+
+ { zero divide: bit 24 }
+ if (exZeroDivide in mask) then
+ fsr:=fsr and not(1 shl 24)
+ else
+ fsr:=fsr or (1 shl 24);
+
+ { overflow: bit 26 }
+ if (exOverflow in mask) then
+ fsr:=fsr and not(1 shl 26)
+ else
+ fsr:=fsr or (1 shl 26);
+
+ { underflow: bit 25 }
+ if (exUnderflow in mask) then
+ fsr:=fsr and not(1 shl 25)
+ else
+ fsr:=fsr or (1 shl 25);
+
+ { Precision (inexact result): bit 23 }
+ if (exPrecision in mask) then
+ fsr:=fsr and not(1 shl 23)
+ else
+ fsr:=fsr or (1 shl 23);
+ { update control register contents }
+ asm
+ ld fsr,%fsr
+ end;
+ end;
+{$endif CPUSPARC}
+
+{$ifndef HASSETFPUEXCEPTIONMASK}
+ procedure SetFPUExceptionMask(const Mask: TFPUExceptionMask);
+ begin
+ end;
+{$endif HASSETFPUEXCEPTIONMASK}
+
+ function is_number_float(d : double) : boolean;
+ var
+ bytearray : array[0..7] of byte;
+ begin
+ move(d,bytearray,8);
+ { only 1.1 save, 1.0.x will use always little endian }
+{$ifdef FPC_BIG_ENDIAN}
+ result:=((bytearray[0] and $7f)<>$7f) or ((bytearray[1] and $f0)<>$f0);
+{$else FPC_BIG_ENDIAN}
+ result:=((bytearray[7] and $7f)<>$7f) or ((bytearray[6] and $f0)<>$f0);
+{$endif FPC_BIG_ENDIAN}
+ end;
+
+
+ function convertdoublearray(d : tdoublearray) : tdoublearray;{$ifdef USEINLINE}inline;{$endif}
+{$ifdef CPUARM}
+ var
+ i : longint;
+ begin
+ for i:=0 to 3 do
+ begin
+ result[i+4]:=d[i];
+ result[i]:=d[i+4];
+ end;
+{$else CPUARM}
+ begin
+ result:=d;
+{$endif CPUARM}
+ end;
+
+
+ function SetAktProcCall(const s:string; changeInit:boolean):boolean;
+ const
+ DefProcCallName : array[tproccalloption] of string[12] = ('',
+ 'CDECL',
+ 'CPPDECL',
+ 'FAR16',
+ 'OLDFPCCALL',
+ '', { internproc }
+ '', { syscall }
+ 'PASCAL',
+ 'REGISTER',
+ 'SAFECALL',
+ 'STDCALL',
+ 'SOFTFLOAT',
+ 'MWPASCAL'
+ );
+ var
+ t : tproccalloption;
+ begin
+ result:=false;
+ for t:=low(tproccalloption) to high(tproccalloption) do
+ if DefProcCallName[t]=s then
+ begin
+ AktDefProcCall:=t;
+ result:=true;
+ break;
+ end;
+ if changeinit then
+ InitDefProcCall:=AktDefProcCall;
+ end;
+
+
+ function SetProcessor(const s:string; changeInit: boolean):boolean;
+ var
+ t : tprocessors;
+ begin
+ SetProcessor:=false;
+ for t:=low(tprocessors) to high(tprocessors) do
+ if processorsstr[t]=s then
+ begin
+ aktspecificoptprocessor:=t;
+ SetProcessor:=true;
+ break;
+ end;
+ if changeinit then
+ initspecificoptprocessor:=aktspecificoptprocessor;
+ end;
+
+
+ function SetFpuType(const s:string; changeInit: boolean):boolean;
+ var
+ t : tfputype;
+ begin
+ SetFpuType:=false;
+ for t:=low(tfputype) to high(tfputype) do
+ if fputypestr[t]=s then
+ begin
+ aktfputype:=t;
+ SetFpuType:=true;
+ break;
+ end;
+ if changeinit then
+ initfputype:=aktfputype;
+ end;
+
+
+ { '('D1:'00000000-'D2:'0000-'D3:'0000-'D4:'0000-000000000000)' }
+ function string2guid(const s: string; var GUID: TGUID): boolean;
+ function ishexstr(const hs: string): boolean;
+ var
+ i: integer;
+ begin
+ ishexstr:=false;
+ for i:=1 to Length(hs) do begin
+ if not (hs[i] in ['0'..'9','A'..'F','a'..'f']) then
+ exit;
+ end;
+ ishexstr:=true;
+ end;
+ function hexstr2longint(const hexs: string): longint;
+ var
+ i: integer;
+ rl: longint;
+ begin
+ rl:=0;
+ for i:=1 to length(hexs) do begin
+ rl:=rl shl 4;
+ case hexs[i] of
+ '0'..'9' : inc(rl,ord(hexs[i])-ord('0'));
+ 'A'..'F' : inc(rl,ord(hexs[i])-ord('A')+10);
+ 'a'..'f' : inc(rl,ord(hexs[i])-ord('a')+10);
+ end
+ end;
+ hexstr2longint:=rl;
+ end;
+ var
+ i: integer;
+ begin
+ if (Length(s)=38) and (s[1]='{') and (s[38]='}') and
+ (s[10]='-') and (s[15]='-') and (s[20]='-') and (s[25]='-') and
+ ishexstr(copy(s,2,8)) and ishexstr(copy(s,11,4)) and
+ ishexstr(copy(s,16,4)) and ishexstr(copy(s,21,4)) and
+ ishexstr(copy(s,26,12)) then begin
+ GUID.D1:=dword(hexstr2longint(copy(s,2,8)));
+ { these values are arealdy in the correct range (4 chars = word) }
+ GUID.D2:=word(hexstr2longint(copy(s,11,4)));
+ GUID.D3:=word(hexstr2longint(copy(s,16,4)));
+ for i:=0 to 1 do
+ GUID.D4[i]:=byte(hexstr2longint(copy(s,21+i*2,2)));
+ for i:=2 to 7 do
+ GUID.D4[i]:=byte(hexstr2longint(copy(s,22+i*2,2)));
+ string2guid:=true;
+ end
+ else
+ string2guid:=false;
+ end;
+
+ function guid2string(const GUID: TGUID): string;
+ function long2hex(l, len: longint): string;
+ const
+ hextbl: array[0..15] of char = '0123456789ABCDEF';
+ var
+ rs: string;
+ i: integer;
+ begin
+ rs[0]:=chr(len);
+ for i:=len downto 1 do begin
+ rs[i]:=hextbl[l and $F];
+ l:=l shr 4;
+ end;
+ long2hex:=rs;
+ end;
+ begin
+ guid2string:=
+ '{'+long2hex(GUID.D1,8)+
+ '-'+long2hex(GUID.D2,4)+
+ '-'+long2hex(GUID.D3,4)+
+ '-'+long2hex(GUID.D4[0],2)+long2hex(GUID.D4[1],2)+
+ '-'+long2hex(GUID.D4[2],2)+long2hex(GUID.D4[3],2)+
+ long2hex(GUID.D4[4],2)+long2hex(GUID.D4[5],2)+
+ long2hex(GUID.D4[6],2)+long2hex(GUID.D4[7],2)+
+ '}';
+ end;
+
+
+ function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
+ var
+ tok : string;
+ vstr : string;
+ l : longint;
+ code : integer;
+ b : talignmentinfo;
+ begin
+ UpdateAlignmentStr:=true;
+ uppervar(s);
+ fillchar(b,sizeof(b),0);
+ repeat
+ tok:=GetToken(s,'=');
+ if tok='' then
+ break;
+ vstr:=GetToken(s,',');
+ val(vstr,l,code);
+ if tok='PROC' then
+ b.procalign:=l
+ else if tok='JUMP' then
+ b.jumpalign:=l
+ else if tok='LOOP' then
+ b.loopalign:=l
+ else if tok='CONSTMIN' then
+ b.constalignmin:=l
+ else if tok='CONSTMAX' then
+ b.constalignmax:=l
+ else if tok='VARMIN' then
+ b.varalignmin:=l
+ else if tok='VARMAX' then
+ b.varalignmax:=l
+ else if tok='LOCALMIN' then
+ b.localalignmin:=l
+ else if tok='LOCALMAX' then
+ b.localalignmax:=l
+ else if tok='RECORDMIN' then
+ b.recordalignmin:=l
+ else if tok='RECORDMAX' then
+ b.recordalignmax:=l
+ else { Error }
+ UpdateAlignmentStr:=false;
+ until false;
+ UpdateAlignment(a,b);
+ end;
+
+
+ function var_align(siz: longint): longint;
+ begin
+ siz := size_2_align(siz);
+ var_align := used_align(siz,aktalignment.varalignmin,aktalignment.varalignmax);
+ end;
+
+
+ function const_align(siz: longint): longint;
+ begin
+ siz := size_2_align(siz);
+ const_align := used_align(siz,aktalignment.constalignmin,aktalignment.constalignmax);
+ end;
+
+
+{****************************************************************************
+ Init
+****************************************************************************}
+
+{$ifdef unix}
+ {$define need_path_search}
+{$endif unix}
+{$ifdef os2}
+ {$define need_path_search}
+{$endif os2}
+{$ifdef macos}
+ {$define need_path_search}
+{$endif macos}
+
+ procedure get_exepath;
+ var
+ hs1 : namestr;
+ hs2 : extstr;
+{$IFDEF USE_SYSUTILS}
+ exeName:String;
+{$ENDIF USE_SYSUTILS}
+{$ifdef need_path_search}
+ p : pchar;
+{$endif need_path_search}
+ begin
+{$IFDEF USE_SYSUTILS}
+ exepath:=GetEnvironmentVariable('PPC_EXEC_PATH');
+{$ELSE USE_SYSUTILS}
+ exepath:=dos.getenv('PPC_EXEC_PATH');
+{$ENDIF USE_SYSUTILS}
+ if exepath='' then
+{$IFDEF USE_SYSUTILS}
+ exeName := FixFileName(system.paramstr(0));
+ exepath := ExtractFilePath(exeName);
+ hs1 := ExtractFileName(exeName);
+ hs2 := ExtractFileExt(exeName);
+{$ELSE USE_SYSUTILS}
+ fsplit(FixFileName(system.paramstr(0)),exepath,hs1,hs2);
+{$ENDIF USE_SYSUTILS}
+{$ifdef need_path_search}
+ if exepath='' then
+ begin
+ if pos(source_info.exeext,hs1) <>
+ (length(hs1) - length(source_info.exeext)+1) then
+ hs1 := hs1 + source_info.exeext;
+{$ifdef macos}
+ p:=GetEnvPchar('Commands');
+{$else macos}
+ p:=GetEnvPchar('PATH');
+{$endif macos}
+ FindFilePChar(hs1,p,exepath);
+ FreeEnvPChar(p);
+ exepath:=SplitPath(exepath);
+ end;
+{$endif need_path_search}
+ exepath:=FixPath(exepath,false);
+ end;
+
+
+
+ procedure DoneGlobals;
+ begin
+ if assigned(DLLImageBase) then
+ StringDispose(DLLImageBase);
+ librarysearchpath.Free;
+ unitsearchpath.Free;
+ objectsearchpath.Free;
+ includesearchpath.Free;
+ end;
+
+ procedure InitGlobals;
+ begin
+ get_exepath;
+
+ { reset globals }
+ do_build:=false;
+ do_release:=false;
+ do_make:=true;
+ compile_level:=0;
+ DLLsource:=false;
+ inlining_procedure:=false;
+ resolving_forward:=false;
+ make_ref:=false;
+ LinkTypeSetExplicitly:=false;
+ paratarget:=system_none;
+ paratargetasm:=as_none;
+ paratargetdbg:=dbg_none;
+
+ { Output }
+ OutputFile:='';
+ OutputPrefix:=Nil;
+ OutputSuffix:=Nil;
+ OutputExtension:='';
+
+ OutputExeDir:='';
+ OutputUnitDir:='';
+
+ { Utils directory }
+ utilsdirectory:='';
+ utilsprefix:='';
+ cshared:=false;
+ rlinkpath:='';
+
+ { Search Paths }
+ librarysearchpath:=TSearchPathList.Create;
+ unitsearchpath:=TSearchPathList.Create;
+ includesearchpath:=TSearchPathList.Create;
+ objectsearchpath:=TSearchPathList.Create;
+
+ { Def file }
+ usewindowapi:=false;
+ description:='Compiled by FPC '+version_string+' - '+target_cpu_string;
+ DescriptionSetExplicity:=false;
+ dllversion:='';
+ dllmajor:=1;
+ dllminor:=0;
+ dllrevision:=0;
+ nwscreenname := '';
+ nwthreadname := '';
+ nwcopyright := '';
+ UseDeffileForExports:=false;
+ UseDeffileForExportsSetExplicitly:=false;
+ RelocSection:=false;
+ RelocSectionSetExplicitly:=false;
+ LinkTypeSetExplicitly:=false;
+
+ { Init values }
+ initmodeswitches:=fpcmodeswitches;
+ initlocalswitches:=[cs_check_io,cs_typed_const_writable];
+ initmoduleswitches:=[cs_extsyntax,cs_implicit_exceptions];
+ initsourcecodepage:='8859-1';
+ initglobalswitches:=[cs_check_unit_name,cs_link_static{$ifdef INTERNALLINKER},cs_link_internal,cs_link_map{$endif}];
+ fillchar(initalignment,sizeof(talignmentinfo),0);
+ { might be overridden later }
+ initasmmode:=asmmode_standard;
+{$ifdef i386}
+ initoptprocessor:=ClassPentium3;
+ initspecificoptprocessor:=Class386;
+
+ initfputype:=fpu_x87;
+
+ initpackenum:=4;
+ {$IFDEF testvarsets}
+ initsetalloc:=0;
+ {$ENDIF}
+ initasmmode:=asmmode_i386_att;
+{$endif i386}
+{$ifdef m68k}
+ initoptprocessor:=MC68020;
+ initpackenum:=4;
+ {$IFDEF testvarsets}
+ initsetalloc:=0;
+ {$ENDIF}
+{$endif m68k}
+{$ifdef powerpc}
+ initoptprocessor:=PPC604;
+ initpackenum:=4;
+ {$IFDEF testvarsets}
+ initsetalloc:=0;
+ {$ENDIF}
+ initfputype:=fpu_standard;
+{$endif powerpc}
+{$ifdef POWERPC64}
+ initoptprocessor:=PPC970;
+ initpackenum:=4;
+ {$IFDEF testvarsets}
+ initsetalloc:=0;
+ {$ENDIF}
+ initfputype:=fpu_standard;
+{$endif POWERPC64}
+{$ifdef sparc}
+ initoptprocessor:=SPARC_V8;
+ initpackenum:=4;
+ {$IFDEF testvarsets}
+ initsetalloc:=0;
+ {$ENDIF}
+{$endif sparc}
+{$ifdef arm}
+ initpackenum:=4;
+ {$IFDEF testvarsets}
+ initsetalloc:=0;
+ {$ENDIF}
+ initfputype:=fpu_fpa;
+{$endif arm}
+{$ifdef x86_64}
+ initoptprocessor:=ClassAthlon64;
+ initspecificoptprocessor:=ClassAthlon64;
+
+ initfputype:=fpu_sse64;
+
+ initpackenum:=4;
+ {$IFDEF testvarsets}
+ initsetalloc:=0;
+ {$ENDIF}
+ initasmmode:=asmmode_x86_64_gas;
+{$endif x86_64}
+ initinterfacetype:=it_interfacecom;
+ initdefproccall:=pocall_default;
+
+ { memory sizes, will be overriden by parameter or default for target
+ in options or init_parser }
+ stacksize:=0;
+ { not initialized yet }
+ jmp_buf_size:=-1;
+
+ apptype:=app_cui;
+ end;
+
+end.
diff --git a/compiler/globtype.pas b/compiler/globtype.pas
new file mode 100644
index 0000000000..4eae2cbedf
--- /dev/null
+++ b/compiler/globtype.pas
@@ -0,0 +1,316 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Global types
+
+ 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 globtype;
+
+{$i fpcdefs.inc}
+
+interface
+
+ const
+ maxidlen = 127;
+
+ type
+{TCmdStr is used to pass command line parameters to an external program to be
+executed from the FPC application. In some circomstances, this can be more
+than 255 characters. That's why using Ansi Strings}
+{$IFDEF USE_SYSUTILS}
+ TCmdStr = AnsiString;
+ PathStr = String;
+ DirStr = String;
+ NameStr = String;
+ ExtStr = String;
+{$ELSE USE_SYSUTILS}
+ TCmdStr = String;
+{$ENDIF USE_SYSUTILS}
+
+{$ifndef fpc}
+ qword = int64;
+{$endif fpc}
+
+ { Natural integer register type and size for the target machine }
+{$ifdef cpu64bit}
+ AWord = qword;
+ AInt = Int64;
+{$else cpu64bit}
+ AWord = longword;
+ AInt = longint;
+{$endif cpu64bit}
+ PAWord = ^AWord;
+ PAInt = ^AInt;
+
+ { the ordinal type used when evaluating constant integer expressions }
+ TConstExprInt = int64;
+ { ... the same unsigned }
+ TConstExprUInt = qword;
+ { This must be an ordinal type with the same size as a pointer
+ Note: Must be unsigned! Otherwise, ugly code like
+ pointer(-1) will result in a pointer with the value
+ $fffffffffffffff on a 32bit machine if the compiler uses
+ int64 constants internally (JM) }
+ TConstPtrUInt = AWord;
+
+ tdoublearray = array[0..7] of byte;
+ textendedarray = array[0..9] of byte;
+
+ pconstset = ^tconstset;
+ tconstset = set of 0..255;
+
+ { Switches which can be changed locally }
+ tlocalswitch = (cs_localnone,
+ { codegen }
+ cs_check_overflow,cs_check_range,cs_check_object,
+ cs_check_io,cs_check_stack,
+ cs_checkpointer,
+ cs_generate_stackframes,cs_do_assertion,cs_generate_rtti,
+ cs_full_boolean_eval,cs_typed_const_writable,cs_allow_enum_calc,
+ { mmx }
+ cs_mmx,cs_mmx_saturation,
+ { parser }
+ cs_typed_addresses,cs_strict_var_strings,cs_ansistrings,
+ { macpas specific}
+ cs_external_var, cs_externally_visible
+ );
+ tlocalswitches = set of tlocalswitch;
+
+ { Switches which can be changed only at the beginning of a new module }
+ tmoduleswitch = (cs_modulenone,
+ { parser }
+ cs_fp_emulation,cs_extsyntax,cs_openstring,
+ { support }
+ cs_support_inline,cs_support_goto,cs_support_macro,
+ cs_support_c_operators,cs_static_keyword,
+ { generation }
+ cs_profile,cs_debuginfo,cs_browser,cs_local_browser,cs_compilesystem,
+ cs_lineinfo,cs_implicit_exceptions,
+ { linking }
+ cs_create_smart,cs_create_dynamic,cs_create_pic
+ );
+ tmoduleswitches = set of tmoduleswitch;
+
+ { Switches which can be changed only for a whole program/compilation,
+ mostly set with commandline }
+ tglobalswitch = (cs_globalnone,
+ { parameter switches }
+ cs_check_unit_name,cs_constructor_name,
+ { units }
+ cs_load_objpas_unit,
+ cs_load_gpc_unit,
+ cs_load_fpcylix_unit,
+ { optimizer }
+ cs_regvars,cs_no_regalloc,cs_uncertainopts,cs_littlesize,
+ cs_optimize,cs_fastoptimize,cs_slowoptimize,cs_align,cs_loopunroll,
+ { browser }
+ cs_browser_log,
+ { debuginfo }
+ cs_use_heaptrc,cs_use_lineinfo,
+ cs_gdb_valgrind,
+ { assembling }
+ cs_asm_leave,cs_asm_extern,cs_asm_pipe,cs_asm_source,
+ cs_asm_regalloc,cs_asm_tempalloc,cs_asm_nodes,
+ { linking }
+ cs_link_extern,cs_link_static,cs_link_smart,cs_link_shared,cs_link_deffile,
+ cs_link_strip,cs_link_staticflag,cs_link_on_target,cs_link_internal,
+ cs_link_map,cs_link_pthread
+ );
+ tglobalswitches = set of tglobalswitch;
+
+ { Switches which can be changed by a mode (fpc,tp7,delphi) }
+ tmodeswitch = (m_none,m_all, { needed for keyword }
+ { generic }
+ m_fpc,m_objfpc,m_delphi,m_tp7,m_gpc,m_mac,
+ { more specific }
+ m_class, { delphi class model }
+ m_objpas, { load objpas unit }
+ m_result, { result in functions }
+ m_string_pchar, { pchar 2 string conversion }
+ m_cvar_support, { cvar variable directive }
+ m_nested_comment, { nested comments }
+ m_tp_procvar, { tp style procvars (no @ needed) }
+ m_mac_procvar, { macpas style procvars }
+ m_repeat_forward, { repeating forward declarations is needed }
+ m_pointer_2_procedure, { allows the assignement of pointers to
+ procedure variables }
+ m_autoderef, { does auto dereferencing of struct. vars }
+ m_initfinal, { initialization/finalization for units }
+ m_add_pointer, { allow pointer add/sub operations }
+ m_default_ansistring, { ansistring turned on by default }
+ m_out, { support the calling convention OUT }
+ m_default_para, { support default parameters }
+ m_hintdirective, { support hint directives }
+ m_duplicate_names { allow locals/paras to have duplicate names of globals }
+ );
+ tmodeswitches = set of tmodeswitch;
+
+ { Win32, OS/2 & MacOS application types }
+ tapptype = (
+ app_none,
+ app_native,
+ app_gui, { graphic user-interface application}
+ app_cui, { console application}
+ app_fs, { full-screen type application (OS/2 and EMX only) }
+ app_tool { tool application, (MPW tool for MacOS, MacOS only)}
+ );
+
+ { interface types }
+ tinterfacetypes = (
+ it_interfacecom,
+ it_interfacecorba
+ );
+
+ { currently parsed block type }
+ tblock_type = (bt_none,
+ bt_general,bt_type,bt_const,bt_except,bt_body
+ );
+
+ { Temp types }
+ ttemptype = (tt_none,
+ tt_free,tt_normal,tt_persistent,
+ tt_noreuse,tt_freenoreuse);
+ ttemptypeset = set of ttemptype;
+
+ { calling convention for tprocdef and tprocvardef }
+ tproccalloption=(pocall_none,
+ { procedure uses C styled calling }
+ pocall_cdecl,
+ { C++ calling conventions }
+ pocall_cppdecl,
+ { Far16 for OS/2 }
+ pocall_far16,
+ { Old style FPC default calling }
+ pocall_oldfpccall,
+ { Procedure has compiler magic}
+ pocall_internproc,
+ { procedure is a system call, applies e.g. to MorphOS and PalmOS }
+ pocall_syscall,
+ { pascal standard left to right }
+ pocall_pascal,
+ { procedure uses register (fastcall) calling }
+ pocall_register,
+ { safe call calling conventions }
+ pocall_safecall,
+ { procedure uses stdcall call }
+ pocall_stdcall,
+ { Special calling convention for cpus without a floating point
+ unit. Floating point numbers are passed in integer registers
+ instead of floating point registers. Depending on the other
+ available calling conventions available for the cpu
+ this replaces either pocall_fastcall or pocall_stdcall.
+ }
+ pocall_softfloat,
+ { Metrowerks Pascal. Special case on Mac OS (X): passes all }
+ { constant records by reference. }
+ pocall_mwpascal
+ );
+ tproccalloptions = set of tproccalloption;
+
+ tprocinfoflag=(
+ { procedure has at least one assembler block }
+ pi_has_assembler_block,
+ { procedure does a call }
+ pi_do_call,
+ { procedure has a try statement = no register optimization }
+ pi_uses_exceptions,
+ { procedure is declared as @var(assembler), don't optimize}
+ pi_is_assembler,
+ { procedure contains data which needs to be finalized }
+ pi_needs_implicit_finally,
+ { procedure has the implicit try..finally generated }
+ pi_has_implicit_finally,
+ { procedure uses fpu}
+ pi_uses_fpu,
+ { procedure uses GOT for PIC code }
+ pi_needs_got,
+ { references var/proc/type/const in static symtable,
+ i.e. not allowed for inlining from other units }
+ pi_uses_static_symtable
+ );
+ tprocinfoflags=set of tprocinfoflag;
+
+{$ifdef ansistring_bits}
+ Tstringbits=(sb_16,sb_32,sb_64);
+{$endif}
+
+ const
+ proccalloptionStr : array[tproccalloption] of string[14]=('',
+ 'CDecl',
+ 'CPPDecl',
+ 'Far16',
+ 'OldFPCCall',
+ 'InternProc',
+ 'SysCall',
+ 'Pascal',
+ 'Register',
+ 'SafeCall',
+ 'StdCall',
+ 'SoftFloat',
+ 'MWPascal'
+ );
+
+ { Default calling convention }
+{$ifdef x86}
+ pocall_default = pocall_register;
+{$else}
+ pocall_default = pocall_stdcall;
+{$endif}
+
+ type
+ stringid = string[maxidlen];
+
+ tnormalset = set of byte; { 256 elements set }
+ pnormalset = ^tnormalset;
+
+ pboolean = ^boolean;
+ pdouble = ^double;
+ pbyte = ^byte;
+ pword = ^word;
+ plongint = ^longint;
+ plongintarray = plongint;
+
+ Tconstant=record
+ case signed:boolean of
+ false:
+ (valueu:cardinal);
+ true:
+ (values:longint);
+ end;
+
+ {$ifndef xFPC}
+ type
+ pguid = ^tguid;
+ tguid = packed record
+ D1: LongWord;
+ D2: Word;
+ D3: Word;
+ D4: array[0..7] of Byte;
+ end;
+ {$endif}
+
+ const
+ { link options }
+ link_none = $0;
+ link_allways = $1;
+ link_static = $2;
+ link_smart = $4;
+ link_shared = $8;
+
+implementation
+
+end.
diff --git a/compiler/html/i386/readme.txt b/compiler/html/i386/readme.txt
new file mode 100644
index 0000000000..b1f0f0ba45
--- /dev/null
+++ b/compiler/html/i386/readme.txt
@@ -0,0 +1,5 @@
+This directory contains the documentation of the compiler with i386 as target.
+To get the documentation you've to run the pasdoc utility. You can get it from
+http://pasdoc.sourceforge.net. Do a make htmldocs in the compiler directory
+to create the documentation. The generated all*.html file provide access
+to the different documentation.
diff --git a/compiler/html/powerpc/readme.txt b/compiler/html/powerpc/readme.txt
new file mode 100644
index 0000000000..7a534cd114
--- /dev/null
+++ b/compiler/html/powerpc/readme.txt
@@ -0,0 +1,5 @@
+This directory contains the documentation of the compiler with powerpc as target.
+To get the documentation you've to run the pasdoc utility. You can get it from
+http://pasdoc.sourceforge.net. Do a make htmldocs in the compiler directory
+to create the documentation. The generated all*.html file provide access
+to the different documentation.
diff --git a/compiler/htypechk.pas b/compiler/htypechk.pas
new file mode 100644
index 0000000000..7db14c51e9
--- /dev/null
+++ b/compiler/htypechk.pas
@@ -0,0 +1,2150 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit exports some help routines for the type checking
+
+ 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 htypechk;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ tokens,cpuinfo,
+ node,
+ symconst,symtype,symdef,symsym,symbase;
+
+ type
+ Ttok2nodeRec=record
+ tok : ttoken;
+ nod : tnodetype;
+ op_overloading_supported : boolean;
+ end;
+
+ pcandidate = ^tcandidate;
+ tcandidate = record
+ next : pcandidate;
+ data : tprocdef;
+ wrongparaidx,
+ firstparaidx : integer;
+ exact_count,
+ equal_count,
+ cl1_count,
+ cl2_count,
+ cl3_count,
+ coper_count : integer; { should be signed }
+ ordinal_distance : bestreal;
+ invalid : boolean;
+ wrongparanr : byte;
+ end;
+
+ tcallcandidates = class
+ private
+ FProcSym : tprocsym;
+ FProcs : pcandidate;
+ FProcVisibleCnt,
+ FProcCnt : integer;
+ FParaNode : tnode;
+ FParaLength : smallint;
+ FAllowVariant : boolean;
+ function proc_add(pd:tprocdef):pcandidate;
+ public
+ constructor create(sym:tprocsym;st:tsymtable;ppn:tnode;isprop,ignorevis : boolean);
+ constructor create_operator(op:ttoken;ppn:tnode);
+ destructor destroy;override;
+ procedure list(all:boolean);
+{$ifdef EXTDEBUG}
+ procedure dump_info(lvl:longint);
+{$endif EXTDEBUG}
+ procedure get_information;
+ function choose_best(var bestpd:tabstractprocdef):integer;
+ procedure find_wrong_para;
+ property Count:integer read FProcCnt;
+ property VisibleCount:integer read FProcVisibleCnt;
+ end;
+
+ const
+ tok2nodes=25;
+ tok2node:array[1..tok2nodes] of ttok2noderec=(
+ (tok:_PLUS ;nod:addn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_MINUS ;nod:subn;op_overloading_supported:true), { binary and unary overloading supported }
+ (tok:_STAR ;nod:muln;op_overloading_supported:true), { binary overloading supported }
+ (tok:_SLASH ;nod:slashn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_EQUAL ;nod:equaln;op_overloading_supported:true), { binary overloading supported }
+ (tok:_GT ;nod:gtn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_LT ;nod:ltn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_GTE ;nod:gten;op_overloading_supported:true), { binary overloading supported }
+ (tok:_LTE ;nod:lten;op_overloading_supported:true), { binary overloading supported }
+ (tok:_SYMDIF ;nod:symdifn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_STARSTAR;nod:starstarn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_AS ;nod:asn;op_overloading_supported:false), { binary overloading NOT supported }
+ (tok:_OP_IN ;nod:inn;op_overloading_supported:false), { binary overloading NOT supported }
+ (tok:_OP_IS ;nod:isn;op_overloading_supported:false), { binary overloading NOT supported }
+ (tok:_OP_OR ;nod:orn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_AND ;nod:andn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_DIV ;nod:divn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_NOT ;nod:notn;op_overloading_supported:true), { unary overloading supported }
+ (tok:_OP_MOD ;nod:modn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_SHL ;nod:shln;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_SHR ;nod:shrn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_XOR ;nod:xorn;op_overloading_supported:true), { binary overloading supported }
+ (tok:_ASSIGNMENT;nod:assignn;op_overloading_supported:true), { unary overloading supported }
+ (tok:_CARET ;nod:caretn;op_overloading_supported:false), { binary overloading NOT supported }
+ (tok:_UNEQUAL ;nod:unequaln;op_overloading_supported:false) { binary overloading NOT supported overload = instead }
+ );
+ const
+ { firstcallparan without varspez we don't count the ref }
+{$ifdef extdebug}
+ count_ref : boolean = true;
+{$endif def extdebug}
+ allow_array_constructor : boolean = false;
+
+ function node2opstr(nt:tnodetype):string;
+
+ { check operator args and result type }
+ function isbinaryoperatoroverloadable(treetyp:tnodetype;ld:tdef;lt:tnodetype;rd:tdef;rt:tnodetype) : boolean;
+ function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
+ function isunaryoverloaded(var t : tnode) : boolean;
+ function isbinaryoverloaded(var t : tnode) : boolean;
+
+ { Register Allocation }
+ procedure make_not_regable(p : tnode);
+ procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
+
+ { procvar handling }
+ function is_procvar_load(p:tnode):boolean;
+ procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
+
+ { sets varsym varstate field correctly }
+ type
+ tvarstateflag = (vsf_must_be_valid,vsf_use_hints);
+ tvarstateflags = set of tvarstateflag;
+ procedure set_varstate(p:tnode;newstate:tvarstate;varstateflags:tvarstateflags);
+
+ { sets the callunique flag, if the node is a vecn, }
+ { takes care of type casts etc. }
+ procedure set_unique(p : tnode);
+
+ function valid_for_formal_var(p : tnode) : boolean;
+ function valid_for_formal_const(p : tnode) : boolean;
+ function valid_for_var(p:tnode):boolean;
+ function valid_for_assignment(p:tnode):boolean;
+ function valid_for_addr(p : tnode) : boolean;
+
+ function allowenumop(nt:tnodetype):boolean;
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symtable,
+ defutil,defcmp,
+ nbas,ncnv,nld,nmem,ncal,nmat,ninl,nutils,
+ cgbase,procinfo
+ ;
+
+ type
+ TValidAssign=(Valid_Property,Valid_Void,Valid_Const,Valid_Addr);
+ TValidAssigns=set of TValidAssign;
+
+
+ function node2opstr(nt:tnodetype):string;
+ var
+ i : integer;
+ begin
+ result:='<unknown>';
+ for i:=1 to tok2nodes do
+ if tok2node[i].nod=nt then
+ begin
+ result:=tokeninfo^[tok2node[i].tok].str;
+ break;
+ end;
+ end;
+
+
+ function isbinaryoperatoroverloadable(treetyp:tnodetype;ld:tdef;lt:tnodetype;rd:tdef;rt:tnodetype) : boolean;
+
+ function internal_check(treetyp:tnodetype;ld:tdef;lt:tnodetype;rd:tdef;rt:tnodetype;var allowed:boolean):boolean;
+ begin
+ internal_check:=true;
+ case ld.deftype of
+ formaldef,
+ recorddef,
+ variantdef :
+ begin
+ allowed:=true;
+ end;
+ procvardef :
+ begin
+ if (rd.deftype in [pointerdef,procdef,procvardef]) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ pointerdef :
+ begin
+ if ((rd.deftype in [orddef,enumdef,pointerdef,classrefdef,procvardef]) or
+ is_class_or_interface(rd)) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+
+ { don't allow pchar+string }
+ if (is_pchar(ld) or is_pwidechar(ld)) and
+ ((rd.deftype=stringdef) or
+ is_pchar(rd) or
+ is_pwidechar(rd) or
+ is_chararray(rd) or
+ is_widechararray(rd)) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ arraydef :
+ begin
+ { not mmx }
+ if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(ld) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ { not chararray+[(wide)char,(wide)string,(wide)chararray] }
+ if (is_chararray(ld) or is_widechararray(ld) or
+ is_open_chararray(ld) or is_open_widechararray(ld))
+ and
+ ((rd.deftype in [stringdef,orddef,enumdef]) or
+ is_pchar(rd) or
+ is_pwidechar(rd) or
+ is_chararray(rd) or
+ is_widechararray(rd) or
+ is_open_chararray(rd) or
+ is_open_widechararray(rd) or
+ (rt=niln)) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ { dynamic array compare with niln }
+ if ((is_dynamic_array(ld) and
+ (rt=niln)) or
+ (is_dynamic_array(ld) and is_dynamic_array(rd)))
+ and
+ (treetyp in [equaln,unequaln]) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ objectdef :
+ begin
+ { <> and = are defined for classes }
+ if (treetyp in [equaln,unequaln]) and
+ is_class_or_interface(ld) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ stringdef :
+ begin
+ if (rd.deftype in [orddef,enumdef,stringdef]) or
+ is_pchar(rd) or
+ is_pwidechar(rd) or
+ is_chararray(rd) or
+ is_widechararray(rd) or
+ is_open_chararray(rd) or
+ is_open_widechararray(rd) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ else
+ internal_check:=false;
+ end;
+ end;
+
+ var
+ allowed : boolean;
+ begin
+ { power ** is always possible }
+ if (treetyp=starstarn) then
+ begin
+ isbinaryoperatoroverloadable:=true;
+ exit;
+ end;
+ { order of arguments does not matter so we have to check also
+ the reversed order }
+ allowed:=false;
+ if not internal_check(treetyp,ld,lt,rd,rt,allowed) then
+ internal_check(treetyp,rd,rt,ld,lt,allowed);
+ isbinaryoperatoroverloadable:=allowed;
+ end;
+
+
+ function isunaryoperatoroverloadable(treetyp : tnodetype;ld : tdef) : boolean;
+ begin
+ result:=false;
+ case treetyp of
+ subn,
+ unaryminusn :
+ begin
+ if (ld.deftype in [orddef,enumdef,floatdef]) then
+ exit;
+
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(ld) then
+ exit;
+{$endif SUPPORT_MMX}
+
+ result:=true;
+ end;
+
+ notn :
+ begin
+ if (ld.deftype in [orddef,enumdef,floatdef]) then
+ exit;
+
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(ld) then
+ exit;
+{$endif SUPPORT_MMX}
+
+ result:=true;
+ end;
+ end;
+ end;
+
+
+ function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
+ var
+ ld,rd : tdef;
+ i : longint;
+ eq : tequaltype;
+ conv : tconverttype;
+ pd : tprocdef;
+ begin
+ result:=false;
+ case pf.parast.symindex.count of
+ 1 : begin
+ ld:=tparavarsym(pf.parast.symindex.first).vartype.def;
+ { assignment is a special case }
+ if optoken=_ASSIGNMENT then
+ begin
+ eq:=compare_defs_ext(ld,pf.rettype.def,nothingn,conv,pd,[cdo_explicit]);
+ result:=(eq=te_incompatible);
+ end
+ else
+ begin
+ for i:=1 to tok2nodes do
+ if tok2node[i].tok=optoken then
+ begin
+ result:=
+ tok2node[i].op_overloading_supported and
+ isunaryoperatoroverloadable(tok2node[i].nod,ld);
+ break;
+ end;
+ end;
+ end;
+ 2 : begin
+ for i:=1 to tok2nodes do
+ if tok2node[i].tok=optoken then
+ begin
+ ld:=tparavarsym(pf.parast.symindex.first).vartype.def;
+ rd:=tparavarsym(pf.parast.symindex.first.indexnext).vartype.def;
+ result:=
+ tok2node[i].op_overloading_supported and
+ isbinaryoperatoroverloadable(tok2node[i].nod,ld,nothingn,rd,nothingn);
+ break;
+ end;
+ end;
+ end;
+ end;
+
+
+ function isunaryoverloaded(var t : tnode) : boolean;
+ var
+ ld : tdef;
+ optoken : ttoken;
+ operpd : tprocdef;
+ ppn : tcallparanode;
+ candidates : tcallcandidates;
+ cand_cnt : integer;
+ begin
+ result:=false;
+ operpd:=nil;
+
+ { load easier access variables }
+ ld:=tunarynode(t).left.resulttype.def;
+ if not isunaryoperatoroverloadable(t.nodetype,ld) then
+ exit;
+
+ { operator overload is possible }
+ result:=true;
+
+ case t.nodetype of
+ notn:
+ optoken:=_OP_NOT;
+ unaryminusn:
+ optoken:=_MINUS;
+ else
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ t:=cnothingnode.create;
+ exit;
+ end;
+ end;
+
+ { generate parameter nodes }
+ ppn:=ccallparanode.create(tunarynode(t).left.getcopy,nil);
+ ppn.get_paratype;
+ candidates:=tcallcandidates.create_operator(optoken,ppn);
+
+ { stop when there are no operators found }
+ if candidates.count=0 then
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ candidates.free;
+ ppn.free;
+ t:=cnothingnode.create;
+ exit;
+ end;
+
+ { Retrieve information about the candidates }
+ candidates.get_information;
+{$ifdef EXTDEBUG}
+ { Display info when multiple candidates are found }
+ candidates.dump_info(V_Debug);
+{$endif EXTDEBUG}
+ cand_cnt:=candidates.choose_best(operpd);
+
+ { exit when no overloads are found }
+ if cand_cnt=0 then
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ candidates.free;
+ ppn.free;
+ t:=cnothingnode.create;
+ exit;
+ end;
+
+ { Multiple candidates left? }
+ if cand_cnt>1 then
+ begin
+ CGMessage(type_e_cant_choose_overload_function);
+{$ifdef EXTDEBUG}
+ candidates.dump_info(V_Hint);
+{$else EXTDEBUG}
+ candidates.list(false);
+{$endif EXTDEBUG}
+ { we'll just use the first candidate to make the
+ call }
+ end;
+ candidates.free;
+
+ inc(operpd.procsym.refs);
+
+ { the nil as symtable signs firstcalln that this is
+ an overloaded operator }
+ t:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil,[]);
+
+ { we already know the procdef to use, so it can
+ skip the overload choosing in callnode.det_resulttype }
+ tcallnode(t).procdefinition:=operpd;
+ end;
+
+
+ function isbinaryoverloaded(var t : tnode) : boolean;
+ var
+ rd,ld : tdef;
+ optoken : ttoken;
+ operpd : tprocdef;
+ ht : tnode;
+ ppn : tcallparanode;
+ candidates : tcallcandidates;
+ cand_cnt : integer;
+ begin
+ isbinaryoverloaded:=false;
+ operpd:=nil;
+ { load easier access variables }
+ ld:=tbinarynode(t).left.resulttype.def;
+ rd:=tbinarynode(t).right.resulttype.def;
+ if not isbinaryoperatoroverloadable(t.nodetype,ld,tbinarynode(t).left.nodetype,rd,tbinarynode(t).right.nodetype) then
+ exit;
+
+ { operator overload is possible }
+ result:=true;
+
+ case t.nodetype of
+ equaln,
+ unequaln :
+ optoken:=_EQUAL;
+ addn:
+ optoken:=_PLUS;
+ subn:
+ optoken:=_MINUS;
+ muln:
+ optoken:=_STAR;
+ starstarn:
+ optoken:=_STARSTAR;
+ slashn:
+ optoken:=_SLASH;
+ ltn:
+ optoken:=_LT;
+ gtn:
+ optoken:=_GT;
+ lten:
+ optoken:=_LTE;
+ gten:
+ optoken:=_GTE;
+ symdifn :
+ optoken:=_SYMDIF;
+ modn :
+ optoken:=_OP_MOD;
+ orn :
+ optoken:=_OP_OR;
+ xorn :
+ optoken:=_OP_XOR;
+ andn :
+ optoken:=_OP_AND;
+ divn :
+ optoken:=_OP_DIV;
+ shln :
+ optoken:=_OP_SHL;
+ shrn :
+ optoken:=_OP_SHR;
+ else
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ t:=cnothingnode.create;
+ exit;
+ end;
+ end;
+
+ { generate parameter nodes }
+ ppn:=ccallparanode.create(tbinarynode(t).right.getcopy,ccallparanode.create(tbinarynode(t).left.getcopy,nil));
+ ppn.get_paratype;
+ candidates:=tcallcandidates.create_operator(optoken,ppn);
+
+ { for commutative operators we can swap arguments and try again }
+ if (candidates.count=0) and
+ not(optoken in [_OP_SHL,_OP_SHR,_OP_DIV,_OP_MOD,_STARSTAR,_SLASH,_MINUS]) then
+ begin
+ candidates.free;
+ reverseparameters(ppn);
+ { reverse compare operators }
+ case optoken of
+ _LT:
+ optoken:=_GTE;
+ _GT:
+ optoken:=_LTE;
+ _LTE:
+ optoken:=_GT;
+ _GTE:
+ optoken:=_LT;
+ end;
+ candidates:=tcallcandidates.create_operator(optoken,ppn);
+ end;
+
+ { stop when there are no operators found }
+ if candidates.count=0 then
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ candidates.free;
+ ppn.free;
+ t:=cnothingnode.create;
+ exit;
+ end;
+
+ { Retrieve information about the candidates }
+ candidates.get_information;
+{$ifdef EXTDEBUG}
+ { Display info when multiple candidates are found }
+ candidates.dump_info(V_Debug);
+{$endif EXTDEBUG}
+ cand_cnt:=candidates.choose_best(operpd);
+
+ { exit when no overloads are found }
+ if cand_cnt=0 then
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ candidates.free;
+ ppn.free;
+ t:=cnothingnode.create;
+ exit;
+ end;
+
+ { Multiple candidates left? }
+ if cand_cnt>1 then
+ begin
+ CGMessage(type_e_cant_choose_overload_function);
+{$ifdef EXTDEBUG}
+ candidates.dump_info(V_Hint);
+{$else EXTDEBUG}
+ candidates.list(false);
+{$endif EXTDEBUG}
+ { we'll just use the first candidate to make the
+ call }
+ end;
+ candidates.free;
+
+ inc(operpd.procsym.refs);
+
+ { the nil as symtable signs firstcalln that this is
+ an overloaded operator }
+ ht:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil,[]);
+
+ { we already know the procdef to use, so it can
+ skip the overload choosing in callnode.det_resulttype }
+ tcallnode(ht).procdefinition:=operpd;
+
+ if t.nodetype=unequaln then
+ ht:=cnotnode.create(ht);
+ t:=ht;
+ end;
+
+
+{****************************************************************************
+ Register Calculation
+****************************************************************************}
+
+ { marks an lvalue as "unregable" }
+ procedure make_not_regable(p : tnode);
+ begin
+ case p.nodetype of
+ typeconvn :
+ make_not_regable(ttypeconvnode(p).left);
+ loadn :
+ if tloadnode(p).symtableentry.typ in [globalvarsym,localvarsym,paravarsym] then
+ tabstractvarsym(tloadnode(p).symtableentry).varregable:=vr_none;
+ end;
+ end;
+
+
+ { calculates the needed registers for a binary operator }
+ procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
+
+ begin
+ p.left_right_max;
+
+ { Only when the difference between the left and right registers < the
+ wanted registers allocate the amount of registers }
+
+ if assigned(p.left) then
+ begin
+ if assigned(p.right) then
+ begin
+ { the location must be already filled in because we need it to }
+ { calculate the necessary number of registers (JM) }
+ if p.expectloc = LOC_INVALID then
+ internalerror(200110101);
+
+ if (abs(p.left.registersint-p.right.registersint)<r32) or
+ ((p.expectloc = LOC_FPUREGISTER) and
+ (p.right.registersfpu <= p.left.registersfpu) and
+ ((p.right.registersfpu <> 0) or (p.left.registersfpu <> 0)) and
+ (p.left.registersint < p.right.registersint)) then
+ inc(p.registersint,r32);
+ if (abs(p.left.registersfpu-p.right.registersfpu)<fpu) then
+ inc(p.registersfpu,fpu);
+{$ifdef SUPPORT_MMX}
+ if (abs(p.left.registersmmx-p.right.registersmmx)<mmx) then
+ inc(p.registersmmx,mmx);
+{$endif SUPPORT_MMX}
+ { the following is a little bit guessing but I think }
+ { it's the only way to solve same internalerrors: }
+ { if the left and right node both uses registers }
+ { and return a mem location, but the current node }
+ { doesn't use an integer register we get probably }
+ { trouble when restoring a node }
+ if (p.left.registersint=p.right.registersint) and
+ (p.registersint=p.left.registersint) and
+ (p.registersint>0) and
+ (p.left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE]) and
+ (p.right.expectloc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ inc(p.registersint);
+ end
+ else
+ begin
+ if (p.left.registersint<r32) then
+ inc(p.registersint,r32);
+ if (p.left.registersfpu<fpu) then
+ inc(p.registersfpu,fpu);
+{$ifdef SUPPORT_MMX}
+ if (p.left.registersmmx<mmx) then
+ inc(p.registersmmx,mmx);
+{$endif SUPPORT_MMX}
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ Subroutine Handling
+****************************************************************************}
+
+ function is_procvar_load(p:tnode):boolean;
+ begin
+ result:=false;
+ { remove voidpointer typecast for tp procvars }
+ if ((m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches)) and
+ (p.nodetype=typeconvn) and
+ is_voidpointer(p.resulttype.def) then
+ p:=tunarynode(p).left;
+ result:=(p.nodetype=typeconvn) and
+ (ttypeconvnode(p).convtype=tc_proc_2_procvar);
+ end;
+
+
+ { local routines can't be assigned to procvars }
+ procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
+ begin
+ if (from_def.parast.symtablelevel>normal_function_level) and
+ (to_def.deftype=procvardef) then
+ CGMessage(type_e_cannot_local_proc_to_procvar);
+ end;
+
+
+ procedure set_varstate(p:tnode;newstate:tvarstate;varstateflags:tvarstateflags);
+ var
+ hsym : tabstractvarsym;
+ begin
+ while assigned(p) do
+ begin
+ case p.nodetype of
+ typeconvn :
+ begin
+ case ttypeconvnode(p).convtype of
+ tc_cchar_2_pchar,
+ tc_cstring_2_pchar,
+ tc_array_2_pointer :
+ exclude(varstateflags,vsf_must_be_valid);
+ tc_pchar_2_string,
+ tc_pointer_2_array :
+ include(varstateflags,vsf_must_be_valid);
+ end;
+ p:=tunarynode(p).left;
+ end;
+ subscriptn :
+ p:=tunarynode(p).left;
+ vecn:
+ begin
+ set_varstate(tbinarynode(p).right,vs_used,[vsf_must_be_valid]);
+ if not(tunarynode(p).left.resulttype.def.deftype in [stringdef,arraydef]) then
+ include(varstateflags,vsf_must_be_valid);
+ p:=tunarynode(p).left;
+ end;
+ { do not parse calln }
+ calln :
+ break;
+ loadn :
+ begin
+ if (tloadnode(p).symtableentry.typ in [localvarsym,paravarsym,globalvarsym]) then
+ begin
+ hsym:=tabstractvarsym(tloadnode(p).symtableentry);
+ if (vsf_must_be_valid in varstateflags) and (hsym.varstate=vs_declared) then
+ begin
+ { Give warning/note for uninitialized locals }
+ if assigned(hsym.owner) and
+ not(vo_is_external in hsym.varoptions) and
+ (hsym.owner.symtabletype in [localsymtable,staticsymtable]) and
+ (hsym.owner=current_procinfo.procdef.localst) then
+ begin
+ if (vo_is_funcret in hsym.varoptions) then
+ CGMessage(sym_w_function_result_not_set)
+ else
+ begin
+ if tloadnode(p).symtable.symtabletype=localsymtable then
+ begin
+ if (vsf_use_hints in varstateflags) then
+ CGMessage1(sym_h_uninitialized_local_variable,hsym.realname)
+ else
+ CGMessage1(sym_w_uninitialized_local_variable,hsym.realname);
+ end
+ else
+ begin
+ if (vsf_use_hints in varstateflags) then
+ CGMessage1(sym_h_uninitialized_variable,hsym.realname)
+ else
+ CGMessage1(sym_w_uninitialized_variable,hsym.realname);
+ end;
+ end;
+ end;
+ end;
+ { don't override vs_used with vs_assigned }
+ if hsym.varstate<>vs_used then
+ hsym.varstate:=newstate;
+ end;
+ break;
+ end;
+ callparan :
+ internalerror(200310081);
+ else
+ break;
+ end;{case }
+ end;
+ end;
+
+
+ procedure set_unique(p : tnode);
+ begin
+ while assigned(p) do
+ begin
+ case p.nodetype of
+ vecn:
+ begin
+ include(p.flags,nf_callunique);
+ break;
+ end;
+ typeconvn,
+ subscriptn,
+ derefn:
+ p:=tunarynode(p).left;
+ else
+ break;
+ end;
+ end;
+ end;
+
+
+ function valid_for_assign(p:tnode;opts:TValidAssigns):boolean;
+ var
+ hp : tnode;
+ gotstring,
+ gotwith,
+ gotsubscript,
+ gotrecord,
+ gotpointer,
+ gotvec,
+ gotclass,
+ gotdynarray,
+ gotderef : boolean;
+ fromdef,
+ todef : tdef;
+ errmsg : longint;
+ begin
+ if valid_const in opts then
+ errmsg:=type_e_variable_id_expected
+ else
+ errmsg:=type_e_argument_cant_be_assigned;
+ result:=false;
+ gotsubscript:=false;
+ gotvec:=false;
+ gotderef:=false;
+ gotrecord:=false;
+ gotclass:=false;
+ gotpointer:=false;
+ gotwith:=false;
+ gotdynarray:=false;
+ gotstring:=false;
+ hp:=p;
+ if not(valid_void in opts) and
+ is_void(hp.resulttype.def) then
+ begin
+ CGMessagePos(hp.fileinfo,errmsg);
+ exit;
+ end;
+ while assigned(hp) do
+ begin
+ { property allowed? calln has a property check itself }
+ if (nf_isproperty in hp.flags) then
+ begin
+ if (hp.nodetype=calln) then
+ begin
+ { check return type }
+ case hp.resulttype.def.deftype of
+ pointerdef :
+ gotpointer:=true;
+ objectdef :
+ gotclass:=is_class_or_interface(hp.resulttype.def);
+ recorddef :
+ gotrecord:=true;
+ classrefdef :
+ gotclass:=true;
+ stringdef :
+ gotstring:=true;
+ end;
+ if (valid_property in opts) then
+ begin
+ { don't allow writing to calls that will create
+ temps like calls that return a structure and we
+ are assigning to a member }
+ if (valid_const in opts) or
+ not(
+ (gotsubscript and gotrecord) or
+ (gotstring and gotvec)
+ ) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,errmsg);
+ end
+ else
+ begin
+ { 1. if it returns a pointer and we've found a deref,
+ 2. if it returns a class or record and a subscription or with is found
+ 3. if the address is needed of a field (subscriptn) }
+ if (gotpointer and gotderef) or
+ (gotstring and gotvec) or
+ (
+ (gotclass or gotrecord) and
+ (gotsubscript or gotwith)
+ ) or
+ (
+ (gotvec and gotdynarray)
+ ) or
+ (
+ (Valid_Addr in opts) and
+ (hp.nodetype=subscriptn)
+ ) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,errmsg);
+ end;
+ end
+ else
+ result:=true;
+ exit;
+ end;
+ if (Valid_Const in opts) and is_constnode(hp) then
+ begin
+ result:=true;
+ exit;
+ end;
+ case hp.nodetype of
+ temprefn :
+ begin
+ valid_for_assign := true;
+ exit;
+ end;
+ derefn :
+ begin
+ gotderef:=true;
+ hp:=tderefnode(hp).left;
+ end;
+ typeconvn :
+ begin
+ { typecast sizes must match, exceptions:
+ - implicit typecast made by absolute
+ - from formaldef
+ - from void
+ - from/to open array
+ - typecast from pointer to array }
+ fromdef:=ttypeconvnode(hp).left.resulttype.def;
+ todef:=hp.resulttype.def;
+ if not((nf_absolute in ttypeconvnode(hp).flags) or
+ (fromdef.deftype=formaldef) or
+ is_void(fromdef) or
+ is_open_array(fromdef) or
+ is_open_array(todef) or
+ ((fromdef.deftype=pointerdef) and (todef.deftype=arraydef)) or
+ ((fromdef.deftype = objectdef) and (todef.deftype = objectdef) and
+ (tobjectdef(fromdef).is_related(tobjectdef(todef))))) and
+ (fromdef.size<>todef.size) then
+ begin
+ { in TP it is allowed to typecast to smaller types. But the variable can't
+ be in a register }
+ if (m_tp7 in aktmodeswitches) or
+ (todef.size<fromdef.size) then
+ make_not_regable(hp)
+ else
+ CGMessagePos2(hp.fileinfo,type_e_typecast_wrong_size_for_assignment,tostr(fromdef.size),tostr(todef.size));
+ end;
+ { don't allow assignments to typeconvs that need special code }
+ if not(gotsubscript or gotvec or gotderef) and
+ not(ttypeconvnode(hp).assign_allowed) then
+ begin
+ CGMessagePos(hp.fileinfo,errmsg);
+ exit;
+ end;
+ case hp.resulttype.def.deftype of
+ pointerdef :
+ gotpointer:=true;
+ objectdef :
+ gotclass:=is_class_or_interface(hp.resulttype.def);
+ classrefdef :
+ gotclass:=true;
+ arraydef :
+ begin
+ { pointer -> array conversion is done then we need to see it
+ as a deref, because a ^ is then not required anymore }
+ if (ttypeconvnode(hp).left.resulttype.def.deftype=pointerdef) then
+ gotderef:=true;
+ end;
+ end;
+ hp:=ttypeconvnode(hp).left;
+ end;
+ vecn :
+ begin
+ gotvec:=true;
+ { accesses to dyn. arrays override read only access in delphi }
+ if (m_delphi in aktmodeswitches) and is_dynamic_array(tunarynode(hp).left.resulttype.def) then
+ gotdynarray:=true;
+ hp:=tunarynode(hp).left;
+ end;
+ asn :
+ begin
+ { asn can't be assigned directly, it returns the value in a register instead
+ of reference. }
+ if not(gotsubscript or gotderef or gotvec) then
+ begin
+ CGMessagePos(hp.fileinfo,errmsg);
+ exit;
+ end;
+ hp:=tunarynode(hp).left;
+ end;
+ subscriptn :
+ begin
+ gotsubscript:=true;
+ { loop counter? }
+ if not(Valid_Const in opts) and
+ (vo_is_loop_counter in tsubscriptnode(hp).vs.varoptions) then
+ CGMessage1(parser_e_illegal_assignment_to_count_var,tsubscriptnode(hp).vs.realname);
+ { a class/interface access is an implicit }
+ { dereferencing }
+ hp:=tsubscriptnode(hp).left;
+ if is_class_or_interface(hp.resulttype.def) then
+ gotderef:=true;
+ end;
+ muln,
+ divn,
+ andn,
+ xorn,
+ orn,
+ notn,
+ subn,
+ addn :
+ begin
+ { Allow operators on a pointer, or an integer
+ and a pointer typecast and deref has been found }
+ if ((hp.resulttype.def.deftype=pointerdef) or
+ (is_integer(hp.resulttype.def) and gotpointer)) and
+ gotderef then
+ result:=true
+ else
+ { Temp strings are stored in memory, for compatibility with
+ delphi only }
+ if (m_delphi in aktmodeswitches) and
+ ((valid_addr in opts) or
+ (valid_const in opts)) and
+ (hp.resulttype.def.deftype=stringdef) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ niln,
+ pointerconstn :
+ begin
+ { to support e.g. @tmypointer(0)^.data; see tests/tbs/tb0481 }
+ if gotderef then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
+ exit;
+ end;
+ addrn :
+ begin
+ if gotderef then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
+ exit;
+ end;
+ calln :
+ begin
+ { check return type }
+ case hp.resulttype.def.deftype of
+ arraydef :
+ begin
+ { dynamic arrays are allowed when there is also a
+ vec node }
+ if is_dynamic_array(hp.resulttype.def) and
+ gotvec then
+ begin
+ gotderef:=true;
+ gotpointer:=true;
+ end;
+ end;
+ pointerdef :
+ gotpointer:=true;
+ objectdef :
+ gotclass:=is_class_or_interface(hp.resulttype.def);
+ recorddef, { handle record like class it needs a subscription }
+ classrefdef :
+ gotclass:=true;
+ stringdef :
+ gotstring:=true;
+ end;
+ { 1. if it returns a pointer and we've found a deref,
+ 2. if it returns a class or record and a subscription or with is found
+ 3. string is returned }
+ if (gotstring and gotvec) or
+ (gotpointer and gotderef) or
+ (gotclass and (gotsubscript or gotwith)) then
+ result:=true
+ else
+ { Temp strings are stored in memory, for compatibility with
+ delphi only }
+ if (m_delphi in aktmodeswitches) and
+ (valid_addr in opts) and
+ (hp.resulttype.def.deftype=stringdef) then
+ result:=true
+ else
+ if ([valid_const,valid_addr] * opts = [valid_const]) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,errmsg);
+ exit;
+ end;
+ inlinen :
+ begin
+ if (valid_const in opts) and
+ (tinlinenode(hp).inlinenumber in [in_typeof_x]) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ loadn :
+ begin
+ case tloadnode(hp).symtableentry.typ of
+ absolutevarsym,
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ { loop counter? }
+ if not(Valid_Const in opts) and
+ not gotderef and
+ (vo_is_loop_counter in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
+ CGMessage1(parser_e_illegal_assignment_to_count_var,tloadnode(hp).symtableentry.realname);
+ { derefed pointer }
+ if (tabstractvarsym(tloadnode(hp).symtableentry).varspez=vs_const) then
+ begin
+ { allow p^:= constructions with p is const parameter }
+ if gotderef or gotdynarray or (Valid_Const in opts) then
+ result:=true
+ else
+ CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
+ exit;
+ end;
+ { Are we at a with symtable, then we need to process the
+ withrefnode also to check for maybe a const load }
+ if (tloadnode(hp).symtable.symtabletype=withsymtable) then
+ begin
+ { continue with processing the withref node }
+ hp:=tnode(twithsymtable(tloadnode(hp).symtable).withrefnode);
+ gotwith:=true;
+ end
+ else
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ typedconstsym :
+ begin
+ if ttypedconstsym(tloadnode(hp).symtableentry).is_writable or
+ (valid_addr in opts) or
+ (valid_const in opts) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,type_e_no_assign_to_const);
+ exit;
+ end;
+ procsym :
+ begin
+ if (Valid_Const in opts) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ labelsym :
+ begin
+ if (Valid_Addr in opts) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ constsym:
+ begin
+ if (tconstsym(tloadnode(hp).symtableentry).consttyp=constresourcestring) and
+ (valid_addr in opts) then
+ result:=true
+ else
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ else
+ begin
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ end;
+ end;
+ else
+ begin
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ function valid_for_var(p:tnode):boolean;
+ begin
+ valid_for_var:=valid_for_assign(p,[]);
+ end;
+
+
+ function valid_for_formal_var(p : tnode) : boolean;
+ begin
+ valid_for_formal_var:=valid_for_assign(p,[valid_void]);
+ end;
+
+
+ function valid_for_formal_const(p : tnode) : boolean;
+ begin
+ valid_for_formal_const:=(p.resulttype.def.deftype=formaldef) or
+ valid_for_assign(p,[valid_void,valid_const]);
+ end;
+
+
+ function valid_for_assignment(p:tnode):boolean;
+ begin
+ valid_for_assignment:=valid_for_assign(p,[valid_property]);
+ end;
+
+
+ function valid_for_addr(p : tnode) : boolean;
+ begin
+ result:=valid_for_assign(p,[valid_const,valid_addr,valid_void]);
+ end;
+
+
+ procedure var_para_allowed(var eq:tequaltype;def_from,def_to:Tdef);
+ begin
+ { Note: eq must be already valid, it will only be updated! }
+ case def_to.deftype of
+ formaldef :
+ begin
+ { all types can be passed to a formaldef }
+ eq:=te_equal;
+ end;
+ orddef :
+ begin
+ { allows conversion from word to integer and
+ byte to shortint, but only for TP7 compatibility }
+ if (m_tp7 in aktmodeswitches) and
+ (def_from.deftype=orddef) and
+ (def_from.size=def_to.size) then
+ eq:=te_convert_l1;
+ end;
+ arraydef :
+ begin
+ if is_open_array(def_to) and
+ is_dynamic_array(def_from) and
+ equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
+ eq:=te_convert_l2;
+ end;
+ pointerdef :
+ begin
+ { an implicit pointer conversion is allowed }
+ if (def_from.deftype=pointerdef) then
+ eq:=te_convert_l1;
+ end;
+ stringdef :
+ begin
+ { all shortstrings are allowed, size is not important }
+ if is_shortstring(def_from) and
+ is_shortstring(def_to) then
+ eq:=te_equal;
+ end;
+ objectdef :
+ begin
+ { child objects can be also passed }
+ { in non-delphi mode, otherwise }
+ { they must match exactly, except }
+ { if they are objects }
+ if (def_from.deftype=objectdef) and
+ (
+ not(m_delphi in aktmodeswitches) or
+ (
+ (tobjectdef(def_from).objecttype=odt_object) and
+ (tobjectdef(def_to).objecttype=odt_object)
+ )
+ ) and
+ (tobjectdef(def_from).is_related(tobjectdef(def_to))) then
+ eq:=te_convert_l1;
+ end;
+ filedef :
+ begin
+ { an implicit file conversion is also allowed }
+ { from a typed file to an untyped one }
+ if (def_from.deftype=filedef) and
+ (tfiledef(def_from).filetyp = ft_typed) and
+ (tfiledef(def_to).filetyp = ft_untyped) then
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+
+
+ procedure para_allowed(var eq:tequaltype;p:tcallparanode;def_to:tdef);
+ begin
+ { Note: eq must be already valid, it will only be updated! }
+ case def_to.deftype of
+ formaldef :
+ begin
+ { all types can be passed to a formaldef }
+ eq:=te_equal;
+ end;
+ stringdef :
+ begin
+ { to support ansi/long/wide strings in a proper way }
+ { string and string[10] are assumed as equal }
+ { when searching the correct overloaded procedure }
+ if (p.resulttype.def.deftype=stringdef) and
+ (tstringdef(def_to).string_typ=tstringdef(p.resulttype.def).string_typ) then
+ eq:=te_equal
+ else
+ { Passing a constant char to ansistring or shortstring or
+ a widechar to widestring then handle it as equal. }
+ if (p.left.nodetype=ordconstn) and
+ (
+ is_char(p.resulttype.def) and
+ (is_shortstring(def_to) or is_ansistring(def_to))
+ ) or
+ (
+ is_widechar(p.resulttype.def) and
+ is_widestring(def_to)
+ ) then
+ eq:=te_equal
+ end;
+ setdef :
+ begin
+ { set can also be a not yet converted array constructor }
+ if (p.resulttype.def.deftype=arraydef) and
+ (tarraydef(p.resulttype.def).IsConstructor) and
+ not(tarraydef(p.resulttype.def).IsVariant) then
+ eq:=te_equal;
+ end;
+ procvardef :
+ begin
+ { in tp7 mode proc -> procvar is allowed }
+ if ((m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches)) and
+ (p.left.nodetype=calln) and
+ (proc_to_procvar_equal(tprocdef(tcallnode(p.left).procdefinition),tprocvardef(def_to))>=te_equal) then
+ eq:=te_equal
+ else
+ if (m_mac_procvar in aktmodeswitches) and
+ is_procvar_load(p.left) then
+ eq:=te_convert_l2;
+ end;
+ end;
+ end;
+
+
+ function allowenumop(nt:tnodetype):boolean;
+ begin
+ result:=(nt in [equaln,unequaln,ltn,lten,gtn,gten]) or
+ ((cs_allow_enum_calc in aktlocalswitches) and
+ (nt in [addn,subn]));
+ end;
+
+
+{****************************************************************************
+ TCallCandidates
+****************************************************************************}
+
+ constructor tcallcandidates.create(sym:tprocsym;st:tsymtable;ppn:tnode;isprop,ignorevis : boolean);
+ var
+ j : integer;
+ pd : tprocdef;
+ hp : pcandidate;
+ found,
+ has_overload_directive : boolean;
+ topclassh : tobjectdef;
+ srsymtable : tsymtable;
+ srprocsym : tprocsym;
+ pt : tcallparanode;
+
+ begin
+ if not assigned(sym) then
+ internalerror(200411015);
+
+ FProcSym:=sym;
+ FProcs:=nil;
+ FProccnt:=0;
+ FProcvisiblecnt:=0;
+ FParanode:=ppn;
+ FAllowVariant:=true;
+
+ { determine length of parameter list }
+ pt:=tcallparanode(ppn);
+ FParalength:=0;
+ while assigned(pt) do
+ begin
+ inc(FParalength);
+ pt:=tcallparanode(pt.right);
+ end;
+
+ { when the definition has overload directive set, we search for
+ overloaded definitions in the class, this only needs to be done once
+ for class entries as the tree keeps always the same }
+ if (not sym.overloadchecked) and
+ (sym.owner.symtabletype=objectsymtable) and
+ (po_overload in sym.first_procdef.procoptions) then
+ search_class_overloads(sym);
+
+ { when the class passed is defined in this unit we
+ need to use the scope of that class. This is a trick
+ that can be used to access protected members in other
+ units. At least kylix supports it this way (PFV) }
+ if assigned(st) and
+ (
+ (st.symtabletype=objectsymtable) or
+ ((st.symtabletype=withsymtable) and
+ (st.defowner.deftype=objectdef))
+ ) and
+ (st.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ st.defowner.owner.iscurrentunit then
+ topclassh:=tobjectdef(st.defowner)
+ else
+ begin
+ if assigned(current_procinfo) then
+ topclassh:=current_procinfo.procdef._class
+ else
+ topclassh:=nil;
+ end;
+
+ { link all procedures which have the same # of parameters }
+ for j:=1 to sym.procdef_count do
+ begin
+ pd:=sym.procdef[j];
+ { Is the procdef visible? This needs to be checked on
+ procdef level since a symbol can contain both private and
+ public declarations. But the check should not be done
+ when the callnode is generated by a property
+
+ inherited overrides invisible anonymous inherited (FK) }
+
+ if isprop or ignorevis or
+ (pd.owner.symtabletype<>objectsymtable) or
+ pd.is_visible_for_object(topclassh) then
+ begin
+ { we have at least one procedure that is visible }
+ inc(FProcvisiblecnt);
+ { only when the # of parameter are supported by the
+ procedure }
+ if (FParalength>=pd.minparacount) and
+ ((po_varargs in pd.procoptions) or { varargs }
+ (FParalength<=pd.maxparacount)) then
+ proc_add(pd);
+ end;
+ end;
+
+ { remember if the procedure is declared with the overload directive,
+ it's information is still needed also after all procs are removed }
+ has_overload_directive:=(po_overload in sym.first_procdef.procoptions);
+
+ { when the definition has overload directive set, we search for
+ overloaded definitions in the symtablestack. The found
+ entries are only added to the procs list and not the procsym, because
+ the list can change in every situation }
+ if has_overload_directive and
+ (sym.owner.symtabletype<>objectsymtable) then
+ begin
+ srsymtable:=sym.owner.next;
+ while assigned(srsymtable) do
+ begin
+ if srsymtable.symtabletype in [localsymtable,staticsymtable,globalsymtable] then
+ begin
+ srprocsym:=tprocsym(srsymtable.speedsearch(sym.name,sym.speedvalue));
+ if assigned(srprocsym) and
+ (srprocsym.typ=procsym) then
+ begin
+ { if this visible procedure doesn't have overload we can stop
+ searching }
+ if not(po_overload in srprocsym.first_procdef.procoptions) and
+ srprocsym.first_procdef.is_visible_for_object(topclassh) then
+ break;
+ { process all overloaded definitions }
+ for j:=1 to srprocsym.procdef_count do
+ begin
+ pd:=srprocsym.procdef[j];
+ { only visible procedures need to be added }
+ if pd.is_visible_for_object(topclassh) then
+ begin
+ { only when the # of parameter are supported by the
+ procedure }
+ if (FParalength>=pd.minparacount) and
+ ((po_varargs in pd.procoptions) or { varargs }
+ (FParalength<=pd.maxparacount)) then
+ begin
+ found:=false;
+ hp:=FProcs;
+ while assigned(hp) do
+ begin
+ { Only compare visible parameters for the user }
+ if compare_paras(hp^.data.paras,pd.paras,cp_value_equal_const,[cpo_ignorehidden])>=te_equal then
+ begin
+ found:=true;
+ break;
+ end;
+ hp:=hp^.next;
+ end;
+ if not found then
+ proc_add(pd);
+ end;
+ end;
+ end;
+ end;
+ end;
+ srsymtable:=srsymtable.next;
+ end;
+ end;
+ end;
+
+
+ constructor tcallcandidates.create_operator(op:ttoken;ppn:tnode);
+ var
+ j : integer;
+ pd : tprocdef;
+ hp : pcandidate;
+ found : boolean;
+ srsymtable : tsymtable;
+ srprocsym : tprocsym;
+ pt : tcallparanode;
+ sv : cardinal;
+ begin
+ FProcSym:=nil;
+ FProcs:=nil;
+ FProccnt:=0;
+ FProcvisiblecnt:=0;
+ FParanode:=ppn;
+ FAllowVariant:=false;
+
+ { determine length of parameter list }
+ pt:=tcallparanode(ppn);
+ FParalength:=0;
+ while assigned(pt) do
+ begin
+ if pt.resulttype.def.deftype=variantdef then
+ FAllowVariant:=true;
+ inc(FParalength);
+ pt:=tcallparanode(pt.right);
+ end;
+
+ { we search all overloaded operator definitions in the symtablestack. The found
+ entries are only added to the procs list and not the procsym, because
+ the list can change in every situation }
+ sv:=getspeedvalue(overloaded_names[op]);
+ srsymtable:=symtablestack;
+ while assigned(srsymtable) do
+ begin
+ if srsymtable.symtabletype in [localsymtable,staticsymtable,globalsymtable] then
+ begin
+ srprocsym:=tprocsym(srsymtable.speedsearch(overloaded_names[op],sv));
+ if assigned(srprocsym) and
+ (srprocsym.typ=procsym) then
+ begin
+ { Store first procsym found }
+ if not assigned(FProcsym) then
+ FProcsym:=srprocsym;
+
+ { process all overloaded definitions }
+ for j:=1 to srprocsym.procdef_count do
+ begin
+ pd:=srprocsym.procdef[j];
+ { only when the # of parameter are supported by the
+ procedure }
+ if (FParalength>=pd.minparacount) and
+ (FParalength<=pd.maxparacount) then
+ begin
+ found:=false;
+ hp:=FProcs;
+ while assigned(hp) do
+ begin
+ { Only compare visible parameters for the user }
+ if compare_paras(hp^.data.paras,pd.paras,cp_value_equal_const,[cpo_ignorehidden])>=te_equal then
+ begin
+ found:=true;
+ break;
+ end;
+ hp:=hp^.next;
+ end;
+ if not found then
+ proc_add(pd);
+ end;
+ end;
+ end;
+ end;
+ srsymtable:=srsymtable.next;
+ end;
+ end;
+
+
+ destructor tcallcandidates.destroy;
+ var
+ hpnext,
+ hp : pcandidate;
+ begin
+ hp:=FProcs;
+ while assigned(hp) do
+ begin
+ hpnext:=hp^.next;
+ dispose(hp);
+ hp:=hpnext;
+ end;
+ end;
+
+
+ function tcallcandidates.proc_add(pd:tprocdef):pcandidate;
+ var
+ defaultparacnt : integer;
+ begin
+ { generate new candidate entry }
+ new(result);
+ fillchar(result^,sizeof(tcandidate),0);
+ result^.data:=pd;
+ result^.next:=FProcs;
+ FProcs:=result;
+ inc(FProccnt);
+ { Find last parameter, skip all default parameters
+ that are not passed. Ignore this skipping for varargs }
+ result^.firstparaidx:=pd.paras.count-1;
+ if not(po_varargs in pd.procoptions) then
+ begin
+ { ignore hidden parameters }
+ while (result^.firstparaidx>=0) and (vo_is_hidden_para in tparavarsym(pd.paras[result^.firstparaidx]).varoptions) do
+ dec(result^.firstparaidx);
+ defaultparacnt:=pd.maxparacount-FParalength;
+ if defaultparacnt>0 then
+ begin
+ if defaultparacnt>result^.firstparaidx+1 then
+ internalerror(200401141);
+ dec(result^.firstparaidx,defaultparacnt);
+ end;
+ end;
+ end;
+
+
+ procedure tcallcandidates.list(all:boolean);
+ var
+ hp : pcandidate;
+ begin
+ hp:=FProcs;
+ while assigned(hp) do
+ begin
+ if all or
+ (not hp^.invalid) then
+ MessagePos1(hp^.data.fileinfo,sym_h_param_list,hp^.data.fullprocname(false));
+ hp:=hp^.next;
+ end;
+ end;
+
+
+{$ifdef EXTDEBUG}
+ procedure tcallcandidates.dump_info(lvl:longint);
+
+ function ParaTreeStr(p:tcallparanode):string;
+ begin
+ result:='';
+ while assigned(p) do
+ begin
+ if result<>'' then
+ result:=','+result;
+ result:=p.resulttype.def.typename+result;
+ p:=tcallparanode(p.right);
+ end;
+ end;
+
+ var
+ hp : pcandidate;
+ i : integer;
+ currpara : tparavarsym;
+ begin
+ if not CheckVerbosity(lvl) then
+ exit;
+ Comment(lvl+V_LineInfo,'Overloaded callnode: '+FProcSym.name+'('+ParaTreeStr(tcallparanode(FParaNode))+')');
+ hp:=FProcs;
+ while assigned(hp) do
+ begin
+ Comment(lvl,' '+hp^.data.fullprocname(false));
+ if (hp^.invalid) then
+ Comment(lvl,' invalid')
+ else
+ begin
+ Comment(lvl,' ex: '+tostr(hp^.exact_count)+
+ ' eq: '+tostr(hp^.equal_count)+
+ ' l1: '+tostr(hp^.cl1_count)+
+ ' l2: '+tostr(hp^.cl2_count)+
+ ' l3: '+tostr(hp^.cl3_count)+
+ ' oper: '+tostr(hp^.coper_count)+
+ ' ord: '+realtostr(hp^.ordinal_distance));
+ { Print parameters in left-right order }
+ for i:=0 to hp^.data.paras.count-1 do
+ begin
+ currpara:=tparavarsym(hp^.data.paras[i]);
+ if (vo_is_hidden_para in currpara.varoptions) then
+ Comment(lvl,' - '+currpara.vartype.def.typename+' : '+EqualTypeName[currpara.eqval]);
+ end;
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+{$endif EXTDEBUG}
+
+
+ procedure tcallcandidates.get_information;
+ var
+ hp : pcandidate;
+ currpara : tparavarsym;
+ paraidx : integer;
+ currparanr : byte;
+ rfh,rth : bestreal;
+ objdef : tobjectdef;
+ def_from,
+ def_to : tdef;
+ currpt,
+ pt : tcallparanode;
+ eq : tequaltype;
+ convtype : tconverttype;
+ pdoper : tprocdef;
+ releasecurrpt : boolean;
+ cdoptions : tcompare_defs_options;
+ begin
+ cdoptions:=[cdo_check_operator];
+ if FAllowVariant then
+ include(cdoptions,cdo_allow_variant);
+ { process all procs }
+ hp:=FProcs;
+ while assigned(hp) do
+ begin
+ { We compare parameters in reverse order (right to left),
+ the firstpara is already pointing to the last parameter
+ were we need to start comparing }
+ currparanr:=FParalength;
+ paraidx:=hp^.firstparaidx;
+ while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(hp^.data.paras[paraidx]).varoptions) do
+ dec(paraidx);
+ pt:=tcallparanode(FParaNode);
+ while assigned(pt) and (paraidx>=0) do
+ begin
+ currpara:=tparavarsym(hp^.data.paras[paraidx]);
+ { currpt can be changed from loadn to calln when a procvar
+ is passed. This is to prevent that the change is permanent }
+ currpt:=pt;
+ releasecurrpt:=false;
+ { retrieve current parameter definitions to compares }
+ eq:=te_incompatible;
+ def_from:=currpt.resulttype.def;
+ def_to:=currpara.vartype.def;
+ if not(assigned(def_from)) then
+ internalerror(200212091);
+ if not(
+ assigned(def_to) or
+ ((po_varargs in hp^.data.procoptions) and
+ (currparanr>hp^.data.minparacount))
+ ) then
+ internalerror(200212092);
+
+ { Convert tp procvars when not expecting a procvar }
+ if (def_to.deftype<>procvardef) and
+ (currpt.left.resulttype.def.deftype=procvardef) then
+ begin
+ releasecurrpt:=true;
+ currpt:=tcallparanode(pt.getcopy);
+ if maybe_call_procvar(currpt.left,true) then
+ begin
+ currpt.resulttype:=currpt.left.resulttype;
+ def_from:=currpt.left.resulttype.def;
+ end;
+ end;
+
+ { varargs are always equal, but not exact }
+ if (po_varargs in hp^.data.procoptions) and
+ (currparanr>hp^.data.minparacount) then
+ begin
+ eq:=te_equal;
+ end
+ else
+ { same definition -> exact }
+ if (def_from=def_to) then
+ begin
+ eq:=te_exact;
+ end
+ else
+ { for value and const parameters check if a integer is constant or
+ included in other integer -> equal and calc ordinal_distance }
+ if not(currpara.varspez in [vs_var,vs_out]) and
+ is_integer(def_from) and
+ is_integer(def_to) and
+ is_in_limit(def_from,def_to) then
+ begin
+ eq:=te_equal;
+ hp^.ordinal_distance:=hp^.ordinal_distance+
+ abs(bestreal(torddef(def_from).low)-bestreal(torddef(def_to).low));
+ if (torddef(def_to).typ=u64bit) then
+ rth:=bestreal(qword(torddef(def_to).high))
+ else
+ rth:=bestreal(torddef(def_to).high);
+ if (torddef(def_from).typ=u64bit) then
+ rfh:=bestreal(qword(torddef(def_from).high))
+ else
+ rfh:=bestreal(torddef(def_from).high);
+ hp^.ordinal_distance:=hp^.ordinal_distance+abs(rth-rfh);
+ { Give wrong sign a small penalty, this is need to get a diffrence
+ from word->[longword,longint] }
+ if is_signed(def_from)<>is_signed(def_to) then
+ hp^.ordinal_distance:=hp^.ordinal_distance+1.0;
+ end
+ else
+ { for value and const parameters check precision of real, give
+ penalty for loosing of precision. var and out parameters must match exactly }
+ if not(currpara.varspez in [vs_var,vs_out]) and
+ is_real(def_from) and
+ is_real(def_to) then
+ begin
+ eq:=te_equal;
+ if is_extended(def_to) then
+ rth:=bestreal(4)
+ else
+ if is_double (def_to) then
+ rth:=bestreal(2)
+ else
+ rth:=bestreal(1);
+ if is_extended(def_from) then
+ rfh:=bestreal(4)
+ else
+ if is_double (def_from) then
+ rfh:=bestreal(2)
+ else
+ rfh:=bestreal(1);
+ { penalty for shrinking of precision }
+ if rth<rfh then
+ rfh:=(rfh-rth)*16
+ else
+ rfh:=rth-rfh;
+ hp^.ordinal_distance:=hp^.ordinal_distance+rfh;
+ end
+ else
+ { related object parameters also need to determine the distance between the current
+ object and the object we are comparing with. var and out parameters must match exactly }
+ if not(currpara.varspez in [vs_var,vs_out]) and
+ (def_from.deftype=objectdef) and
+ (def_to.deftype=objectdef) and
+ (tobjectdef(def_from).objecttype=tobjectdef(def_to).objecttype) and
+ tobjectdef(def_from).is_related(tobjectdef(def_to)) then
+ begin
+ eq:=te_convert_l1;
+ objdef:=tobjectdef(def_from);
+ while assigned(objdef) do
+ begin
+ if objdef=def_to then
+ break;
+ hp^.ordinal_distance:=hp^.ordinal_distance+1;
+ objdef:=objdef.childof;
+ end;
+ end
+ else
+ { generic type comparision }
+ begin
+ eq:=compare_defs_ext(def_from,def_to,currpt.left.nodetype,convtype,pdoper,cdoptions);
+
+ { when the types are not equal we need to check
+ some special case for parameter passing }
+ if (eq<te_equal) then
+ begin
+ if currpara.varspez in [vs_var,vs_out] then
+ begin
+ { para requires an equal type so the previous found
+ match was not good enough, reset to incompatible }
+ eq:=te_incompatible;
+ { var_para_allowed will return te_equal and te_convert_l1 to
+ make a difference for best matching }
+ var_para_allowed(eq,currpt.resulttype.def,currpara.vartype.def)
+ end
+ else
+ para_allowed(eq,currpt,def_to);
+ end;
+ end;
+
+ { when a procvar was changed to a call an exact much is
+ downgraded to equal. This way an overload call with the
+ procvar is choosen. See tb0471 (PFV) }
+ if (pt<>currpt) and (eq=te_exact) then
+ eq:=te_equal;
+
+ { increase correct counter }
+ case eq of
+ te_exact :
+ inc(hp^.exact_count);
+ te_equal :
+ inc(hp^.equal_count);
+ te_convert_l1 :
+ inc(hp^.cl1_count);
+ te_convert_l2 :
+ inc(hp^.cl2_count);
+ te_convert_l3 :
+ inc(hp^.cl3_count);
+ te_convert_operator :
+ inc(hp^.coper_count);
+ te_incompatible :
+ hp^.invalid:=true;
+ else
+ internalerror(200212072);
+ end;
+
+ { stop checking when an incompatible parameter is found }
+ if hp^.invalid then
+ begin
+ { store the current parameter info for
+ a nice error message when no procedure is found }
+ hp^.wrongparaidx:=paraidx;
+ hp^.wrongparanr:=currparanr;
+ break;
+ end;
+
+{$ifdef EXTDEBUG}
+ { store equal in node tree for dump }
+ currpara.eqval:=eq;
+{$endif EXTDEBUG}
+
+ { maybe release temp currpt }
+ if releasecurrpt then
+ currpt.free;
+
+ { next parameter in the call tree }
+ pt:=tcallparanode(pt.right);
+
+ { next parameter for definition, only goto next para
+ if we're out of the varargs }
+ if not(po_varargs in hp^.data.procoptions) or
+ (currparanr<=hp^.data.maxparacount) then
+ begin
+ { Ignore vs_hidden parameters }
+ repeat
+ dec(paraidx);
+ until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(hp^.data.paras[paraidx]).varoptions);
+ end;
+ dec(currparanr);
+ end;
+ if not(hp^.invalid) and
+ (assigned(pt) or (paraidx>=0) or (currparanr<>0)) then
+ internalerror(200212141);
+ { next candidate }
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ function is_better_candidate(currpd,bestpd:pcandidate):integer;
+ var
+ res : integer;
+ begin
+ {
+ Return values:
+ > 0 when currpd is better than bestpd
+ < 0 when bestpd is better than currpd
+ = 0 when both are equal
+
+ To choose the best candidate we use the following order:
+ - Incompatible flag
+ - (Smaller) Number of convert operator parameters.
+ - (Smaller) Number of convertlevel 2 parameters.
+ - (Smaller) Number of convertlevel 1 parameters.
+ - (Bigger) Number of exact parameters.
+ - (Smaller) Number of equal parameters.
+ - (Smaller) Total of ordinal distance. For example, the distance of a word
+ to a byte is 65535-255=65280.
+ }
+ if bestpd^.invalid then
+ begin
+ if currpd^.invalid then
+ res:=0
+ else
+ res:=1;
+ end
+ else
+ if currpd^.invalid then
+ res:=-1
+ else
+ begin
+ { less operator parameters? }
+ res:=(bestpd^.coper_count-currpd^.coper_count);
+ if (res=0) then
+ begin
+ { less cl3 parameters? }
+ res:=(bestpd^.cl3_count-currpd^.cl3_count);
+ if (res=0) then
+ begin
+ { less cl2 parameters? }
+ res:=(bestpd^.cl2_count-currpd^.cl2_count);
+ if (res=0) then
+ begin
+ { less cl1 parameters? }
+ res:=(bestpd^.cl1_count-currpd^.cl1_count);
+ if (res=0) then
+ begin
+ { more exact parameters? }
+ res:=(currpd^.exact_count-bestpd^.exact_count);
+ if (res=0) then
+ begin
+ { less equal parameters? }
+ res:=(bestpd^.equal_count-currpd^.equal_count);
+ if (res=0) then
+ begin
+ { smaller ordinal distance? }
+ if (currpd^.ordinal_distance<bestpd^.ordinal_distance) then
+ res:=1
+ else
+ if (currpd^.ordinal_distance>bestpd^.ordinal_distance) then
+ res:=-1
+ else
+ res:=0;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ is_better_candidate:=res;
+ end;
+
+
+ function tcallcandidates.choose_best(var bestpd:tabstractprocdef):integer;
+ var
+ besthpstart,
+ hp : pcandidate;
+ cntpd,
+ res : integer;
+ begin
+ {
+ Returns the number of candidates left and the
+ first candidate is returned in pdbest
+ }
+ { Setup the first procdef as best, only count it as a result
+ when it is valid }
+ bestpd:=FProcs^.data;
+ if FProcs^.invalid then
+ cntpd:=0
+ else
+ cntpd:=1;
+ if assigned(FProcs^.next) then
+ begin
+ besthpstart:=FProcs;
+ hp:=FProcs^.next;
+ while assigned(hp) do
+ begin
+ res:=is_better_candidate(hp,besthpstart);
+ if (res>0) then
+ begin
+ { hp is better, flag all procs to be incompatible }
+ while (besthpstart<>hp) do
+ begin
+ besthpstart^.invalid:=true;
+ besthpstart:=besthpstart^.next;
+ end;
+ { besthpstart is already set to hp }
+ bestpd:=besthpstart^.data;
+ cntpd:=1;
+ end
+ else
+ if (res<0) then
+ begin
+ { besthpstart is better, flag current hp to be incompatible }
+ hp^.invalid:=true;
+ end
+ else
+ begin
+ { res=0, both are valid }
+ if not hp^.invalid then
+ inc(cntpd);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+ result:=cntpd;
+ end;
+
+
+ procedure tcallcandidates.find_wrong_para;
+ var
+ currparanr : smallint;
+ hp : pcandidate;
+ pt : tcallparanode;
+ wrongpara : tparavarsym;
+ begin
+ { Only process the first overloaded procdef }
+ hp:=FProcs;
+ { Find callparanode corresponding to the argument }
+ pt:=tcallparanode(FParanode);
+ currparanr:=FParalength;
+ while assigned(pt) and
+ (currparanr>hp^.wrongparanr) do
+ begin
+ pt:=tcallparanode(pt.right);
+ dec(currparanr);
+ end;
+ if (currparanr<>hp^.wrongparanr) or
+ not assigned(pt) then
+ internalerror(200212094);
+ { Show error message, when it was a var or out parameter
+ guess that it is a missing typeconv }
+ wrongpara:=tparavarsym(hp^.data.paras[hp^.wrongparaidx]);
+ if wrongpara.varspez in [vs_var,vs_out] then
+ begin
+ { Maybe passing the correct type but passing a const to var parameter }
+ if (compare_defs(pt.resulttype.def,wrongpara.vartype.def,pt.nodetype)<>te_incompatible) and
+ not valid_for_var(pt.left) then
+ CGMessagePos(pt.left.fileinfo,type_e_variable_id_expected)
+ else
+ CGMessagePos2(pt.left.fileinfo,parser_e_call_by_ref_without_typeconv,
+ FullTypeName(pt.left.resulttype.def,wrongpara.vartype.def),
+ FullTypeName(wrongpara.vartype.def,pt.left.resulttype.def))
+ end
+ else
+ CGMessagePos3(pt.left.fileinfo,type_e_wrong_parameter_type,tostr(hp^.wrongparanr),
+ FullTypeName(pt.left.resulttype.def,wrongpara.vartype.def),
+ FullTypeName(wrongpara.vartype.def,pt.left.resulttype.def));
+ end;
+
+
+end.
diff --git a/compiler/i386/ag386nsm.pas b/compiler/i386/ag386nsm.pas
new file mode 100644
index 0000000000..7cda5495c1
--- /dev/null
+++ b/compiler/i386/ag386nsm.pas
@@ -0,0 +1,906 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for the Nasm assembler with
+ Intel syntax 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.
+
+ ****************************************************************************
+}
+unit ag386nsm;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ aasmbase,aasmtai,aasmcpu,assemble,cgutils;
+
+ type
+ T386NasmAssembler = class(texternalassembler)
+ private
+ procedure WriteReference(var ref : treference);
+ procedure WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
+ procedure WriteOper_jmp(const o:toper; op : tasmop);
+ procedure WriteSection(atype:tasmsectiontype;const aname:string);
+ public
+ procedure WriteTree(p:taasmoutput);override;
+ procedure WriteAsmList;override;
+ procedure WriteExternals;
+ end;
+
+
+
+ implementation
+
+ uses
+ cutils,globtype,globals,systems,cclasses,
+ fmodule,finput,verbose,cpuinfo,cgbase
+ ;
+
+ const
+ line_length = 64;
+
+ nasm_regname_table : array[tregisterindex] of string[7] = (
+ {r386nasm.inc contains the Nasm name of each register.}
+ {$i r386nasm.inc}
+ );
+
+ var
+ lastfileinfo : tfileposinfo;
+ infile,
+ lastinfile : tinputfile;
+
+ function nasm_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=nasm_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function fixline(s:string):string;
+ {
+ return s with all leading and ending spaces and tabs removed
+ }
+ var
+ i,j,k : longint;
+ begin
+ i:=length(s);
+ while (i>0) and (s[i] in [#9,' ']) do
+ dec(i);
+ j:=1;
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ for k:=j to i do
+ if s[k] in [#0..#31,#127..#255] then
+ s[k]:='.';
+ fixline:=Copy(s,j,i-j+1);
+ end;
+
+ function single2str(d : single) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ single2str:=lower(hs);
+ end;
+
+ function double2str(d : double) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ double2str:=lower(hs);
+ end;
+
+ function extended2str(e : extended) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(e,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ extended2str:=lower(hs);
+ end;
+
+
+ function comp2str(d : bestreal) : string;
+ type
+ pdouble = ^double;
+ var
+ c : comp;
+ dd : pdouble;
+ begin
+{$ifdef FPC}
+ c:=comp(d);
+{$else}
+ c:=d;
+{$endif}
+ dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
+ comp2str:=double2str(dd^);
+ end;
+
+
+ function sizestr(s:topsize;dest:boolean):string;
+ begin
+ case s of
+ S_B : sizestr:='byte ';
+ S_W : sizestr:='word ';
+ S_L : sizestr:='dword ';
+ S_IS : sizestr:='word ';
+ S_IL : sizestr:='dword ';
+ S_IQ : sizestr:='qword ';
+ S_FS : sizestr:='dword ';
+ S_FL : sizestr:='qword ';
+ S_FX : sizestr:='tword ';
+ S_BW : if dest then
+ sizestr:='word '
+ else
+ sizestr:='byte ';
+ S_BL : if dest then
+ sizestr:='dword '
+ else
+ sizestr:='byte ';
+ S_WL : if dest then
+ sizestr:='dword '
+ else
+ sizestr:='word ';
+ else { S_NO }
+ sizestr:='';
+ end;
+ end;
+
+
+ Function PadTabs(const p:string;addch:char):string;
+ var
+ s : string;
+ i : longint;
+ begin
+ i:=length(p);
+ if addch<>#0 then
+ begin
+ inc(i);
+ s:=p+addch;
+ end
+ else
+ s:=p;
+ if i<8 then
+ PadTabs:=s+#9#9
+ else
+ PadTabs:=s+#9;
+ end;
+
+
+{****************************************************************************
+ T386NasmAssembler
+ ****************************************************************************}
+
+ procedure T386NasmAssembler.WriteReference(var ref : treference);
+ var
+ first : boolean;
+ begin
+ with ref do
+ begin
+ AsmWrite('[');
+ first:=true;
+ if (segment<>NR_NO) then
+ AsmWrite(nasm_regname(segment)+':');
+ if assigned(symbol) then
+ begin
+ AsmWrite(symbol.name);
+ first:=false;
+ end;
+ if (base<>NR_NO) then
+ begin
+ if not(first) then
+ AsmWrite('+')
+ else
+ first:=false;
+ AsmWrite(nasm_regname(base))
+ end;
+ if (index<>NR_NO) then
+ begin
+ if not(first) then
+ AsmWrite('+')
+ else
+ first:=false;
+ AsmWrite(nasm_regname(index));
+ if scalefactor<>0 then
+ AsmWrite('*'+tostr(scalefactor));
+ end;
+ if offset<0 then
+ begin
+ AsmWrite(tostr(offset));
+ first:=false;
+ end
+ else if (offset>0) then
+ begin
+ AsmWrite('+'+tostr(offset));
+ first:=false;
+ end;
+ if first then
+ AsmWrite('0');
+ AsmWrite(']');
+ end;
+ end;
+
+
+ procedure T386NasmAssembler.WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(nasm_regname(o.reg));
+ top_const :
+ begin
+ if (ops=1) and (opcode<>A_RET) then
+ AsmWrite(sizestr(s,dest));
+ AsmWrite(tostr(longint(o.val)));
+ end;
+ top_ref :
+ begin
+ if o.ref^.refaddr=addr_no then
+ begin
+ if not ((opcode = A_LEA) or (opcode = A_LGS) or
+ (opcode = A_LSS) or (opcode = A_LFS) or
+ (opcode = A_LES) or (opcode = A_LDS) or
+ (opcode = A_SHR) or (opcode = A_SHL) or
+ (opcode = A_SAR) or (opcode = A_SAL) or
+ (opcode = A_OUT) or (opcode = A_IN)) then
+ AsmWrite(sizestr(s,dest));
+ WriteReference(o.ref^);
+ end
+ else
+ begin
+ asmwrite('dword ');
+ if assigned(o.ref^.symbol) then
+ begin
+ asmwrite(o.ref^.symbol.name);
+ if o.ref^.offset=0 then
+ exit;
+ end;
+ if o.ref^.offset>0 then
+ asmwrite('+');
+ asmwrite(tostr(o.ref^.offset));
+ end;
+ end;
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ procedure T386NasmAssembler.WriteOper_jmp(const o:toper; op : tasmop);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(nasm_regname(o.reg));
+ top_ref :
+ if o.ref^.refaddr=addr_no then
+ WriteReference(o.ref^)
+ else
+ begin
+ if not(
+ (op=A_JCXZ) or (op=A_JECXZ) or
+ (op=A_LOOP) or (op=A_LOOPE) or
+ (op=A_LOOPNE) or (op=A_LOOPNZ) or
+ (op=A_LOOPZ)
+ ) then
+ AsmWrite('NEAR ');
+ AsmWrite(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ AsmWrite(tostr(o.ref^.offset));
+ end;
+ top_const :
+ AsmWrite(tostr(aint(o.val)));
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ var
+ LastSecType : TAsmSectionType;
+
+ const
+ ait_const2str : array[ait_const_128bit..ait_const_indirect_symbol] of string[20]=(
+ #9'FIXME128',#9'FIXME64',#9'DD'#9,#9'DW'#9,#9'DB'#9,
+ #9'FIXMESLEB',#9'FIXEMEULEB',
+ #9'RVA'#9,#9'FIXMEINDIRECT'#9
+ );
+
+ procedure T386NasmAssembler.WriteSection(atype:tasmsectiontype;const aname:string);
+ const
+ secnames : array[tasmsectiontype] of string[12] = ('',
+ '.text','.data','.rodata','.bss','.tbss',
+ 'common',
+ '.note',
+ '.text',
+ '.stab','.stabstr',
+ '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
+ '.eh_frame',
+ '.debug_frame',
+ '.fpc'
+ );
+ begin
+ AsmLn;
+ AsmWrite('SECTION ');
+ AsmWrite(secnames[atype]);
+ if use_smartlink_section and
+ (atype<>sec_bss) and
+ (aname<>'') then
+ begin
+ AsmWrite('.');
+ AsmWrite(aname);
+ end;
+ AsmLn;
+ LasTSecType:=atype;
+ end;
+
+ procedure T386NasmAssembler.WriteTree(p:taasmoutput);
+ var
+ s : string;
+ hp : tai;
+ hp1 : tailineinfo;
+ counter,
+ lines,
+ i,j,l : longint;
+ InlineLevel : longint;
+ consttyp : taitype;
+ found,
+ do_line,
+ quoted : boolean;
+ begin
+ if not assigned(p) then
+ exit;
+ InlineLevel:=0;
+ { lineinfo is only needed for al_procedures (PFV) }
+ do_line:=(cs_asm_source in aktglobalswitches) or
+ ((cs_lineinfo in aktmoduleswitches)
+ and (p=asmlist[al_procedures]));
+ hp:=tai(p.first);
+ while assigned(hp) do
+ begin
+
+ if not(hp.typ in SkipLineInfo) then
+ begin
+ hp1:=hp as tailineinfo;
+ aktfilepos:=hp1.fileinfo;
+ if do_line then
+ begin
+ { load infile }
+ if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
+ begin
+ infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
+ if assigned(infile) then
+ begin
+ { open only if needed !! }
+ if (cs_asm_source in aktglobalswitches) then
+ infile.open;
+ end;
+ { avoid unnecessary reopens of the same file !! }
+ lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
+ { be sure to change line !! }
+ lastfileinfo.line:=-1;
+ end;
+ { write source }
+ if (cs_asm_source in aktglobalswitches) and
+ assigned(infile) then
+ begin
+ if (infile<>lastinfile) then
+ begin
+ AsmWriteLn(target_asm.comment+'['+infile.name^+']');
+ if assigned(lastinfile) then
+ lastinfile.close;
+ end;
+ if (hp1.fileinfo.line<>lastfileinfo.line) and
+ ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
+ begin
+ if (hp1.fileinfo.line<>0) and
+ ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
+ AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
+ fixline(infile.GetLineStr(hp1.fileinfo.line)));
+ { set it to a negative value !
+ to make that is has been read already !! PM }
+ if (infile.linebuf^[hp1.fileinfo.line]>=0) then
+ infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
+ end;
+ end;
+ lastfileinfo:=hp1.fileinfo;
+ lastinfile:=infile;
+ end;
+ end;
+ case hp.typ of
+ ait_comment :
+ Begin
+ AsmWrite(target_asm.comment);
+ AsmWritePChar(tai_comment(hp).str);
+ AsmLn;
+ End;
+
+ ait_regalloc :
+ begin
+ if (cs_asm_regalloc in aktglobalswitches) then
+ AsmWriteLn(#9#9+target_asm.comment+'Register '+nasm_regname(tai_regalloc(hp).reg)+
+ regallocstr[tai_regalloc(hp).ratype]);
+ end;
+
+ ait_tempalloc :
+ begin
+ if (cs_asm_tempalloc in aktglobalswitches) then
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(tai_tempalloc(hp).problem) then
+ AsmWriteLn(target_asm.comment+tai_tempalloc(hp).problem^+' ('+tostr(tai_tempalloc(hp).temppos)+','+
+ tostr(tai_tempalloc(hp).tempsize)+')')
+ else
+{$endif EXTDEBUG}
+ AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
+ tostr(tai_tempalloc(hp).tempsize)+tempallocstr[tai_tempalloc(hp).allocation]);
+ end;
+ end;
+
+ ait_section :
+ begin
+ if tai_section(hp).sectype<>sec_none then
+ WriteSection(tai_section(hp).sectype,tai_section(hp).name^);
+ LasTSecType:=tai_section(hp).sectype;
+ end;
+
+ ait_align :
+ begin
+ { nasm gives warnings when it finds align in bss as it
+ wants to store data }
+ if (lastsectype<>sec_bss) and
+ (tai_align(hp).aligntype>1) then
+ AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype));
+ end;
+
+ ait_datablock :
+ begin
+ if tai_datablock(hp).is_global then
+ begin
+ AsmWrite(#9'GLOBAL ');
+ AsmWriteLn(tai_datablock(hp).sym.name);
+ end;
+ AsmWrite(PadTabs(tai_datablock(hp).sym.name,':'));
+ AsmWriteLn('RESB'#9+tostr(tai_datablock(hp).size));
+ end;
+
+ ait_const_uleb128bit,
+ ait_const_sleb128bit,
+ ait_const_128bit,
+ ait_const_64bit,
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_const_indirect_symbol :
+ begin
+ AsmWrite(ait_const2str[hp.typ]);
+ consttyp:=hp.typ;
+ l:=0;
+ repeat
+ if assigned(tai_const(hp).sym) then
+ begin
+ if assigned(tai_const(hp).endsym) then
+ s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
+ else
+ s:=tai_const(hp).sym.name;
+ if tai_const(hp).value<>0 then
+ s:=s+tostr_with_plus(tai_const(hp).value);
+ end
+ else
+ s:=tostr(tai_const(hp).value);
+ AsmWrite(s);
+ inc(l,length(s));
+ if (l>line_length) or
+ (hp.next=nil) or
+ (tai(hp.next).typ<>consttyp) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmLn;
+ end;
+
+ ait_real_32bit :
+ AsmWriteLn(#9#9'DD'#9+single2str(tai_real_32bit(hp).value));
+
+ ait_real_64bit :
+ AsmWriteLn(#9#9'DQ'#9+double2str(tai_real_64bit(hp).value));
+
+ ait_real_80bit :
+ AsmWriteLn(#9#9'DT'#9+extended2str(tai_real_80bit(hp).value));
+
+ ait_comp_64bit :
+ AsmWriteLn(#9#9'DQ'#9+comp2str(tai_real_80bit(hp).value));
+
+ ait_string :
+ begin
+ counter := 0;
+ lines := tai_string(hp).len div line_length;
+ { separate lines in different parts }
+ if tai_string(hp).len > 0 then
+ Begin
+ for j := 0 to lines-1 do
+ begin
+ AsmWrite(#9#9'DB'#9);
+ quoted:=false;
+ for i:=counter to counter+line_length-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'"') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('"');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and ord('"') }
+ else
+ begin
+ if quoted then
+ AsmWrite('"');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then AsmWrite('"');
+ AsmWrite(target_info.newline);
+ inc(counter,line_length);
+ end; { end for j:=0 ... }
+ { do last line of lines }
+ if counter<tai_string(hp).len then
+ AsmWrite(#9#9'DB'#9);
+ quoted:=false;
+ for i:=counter to tai_string(hp).len-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'"') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('"');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and " }
+ else
+ begin
+ if quoted then
+ AsmWrite('"');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then
+ AsmWrite('"');
+ end;
+ AsmLn;
+ end;
+
+ ait_label :
+ begin
+ if tai_label(hp).l.is_used then
+ AsmWriteLn(tai_label(hp).l.name+':');
+ end;
+
+ ait_symbol :
+ begin
+ if tai_symbol(hp).is_global then
+ begin
+ AsmWrite(#9'GLOBAL ');
+ AsmWriteLn(tai_symbol(hp).sym.name);
+ end;
+ AsmWrite(tai_symbol(hp).sym.name);
+ if assigned(hp.next) and not(tai(hp.next).typ in
+ [ait_const_32bit,ait_const_16bit,ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
+ AsmWriteLn(':')
+ end;
+
+ ait_symbol_end : ;
+
+ ait_instruction :
+ begin
+ taicpu(hp).CheckNonCommutativeOpcodes;
+ { We need intel order, no At&t }
+ taicpu(hp).SetOperandOrder(op_intel);
+ s:='';
+ if ((taicpu(hp).opcode=A_FADDP) or
+ (taicpu(hp).opcode=A_FMULP))
+ and (taicpu(hp).ops=0) then
+ begin
+ taicpu(hp).allocate_oper(2);
+ taicpu(hp).oper[0]^.typ:=top_reg;
+ taicpu(hp).oper[0]^.reg:=NR_ST1;
+ taicpu(hp).oper[1]^.typ:=top_reg;
+ taicpu(hp).oper[1]^.reg:=NR_ST;
+ end;
+ if taicpu(hp).opcode=A_FWAIT then
+ AsmWriteln(#9#9'DB'#9'09bh')
+ else
+ begin
+ { We need to explicitely set
+ word prefix to get selectors
+ to be pushed in 2 bytes PM }
+ if (taicpu(hp).opsize=S_W) and
+ ((taicpu(hp).opcode=A_PUSH) or
+ (taicpu(hp).opcode=A_POP)) and
+ (taicpu(hp).oper[0]^.typ=top_reg) and
+ (is_segment_reg(taicpu(hp).oper[0]^.reg)) then
+ AsmWriteln(#9#9'DB'#9'066h');
+ AsmWrite(#9#9+std_op2str[taicpu(hp).opcode]+cond2str[taicpu(hp).condition]);
+ if taicpu(hp).ops<>0 then
+ begin
+ if is_calljmp(taicpu(hp).opcode) then
+ begin
+ AsmWrite(#9);
+ WriteOper_jmp(taicpu(hp).oper[0]^,taicpu(hp).opcode);
+ end
+ else
+ begin
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ if i=0 then
+ AsmWrite(#9)
+ else
+ AsmWrite(',');
+ WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,taicpu(hp).opcode,taicpu(hp).ops,(i=2));
+ end;
+ end;
+ end;
+ AsmLn;
+ end;
+ end;
+
+ ait_stab,
+ ait_force_line,
+ ait_function_name : ;
+
+ ait_cutobject :
+ begin
+ { only reset buffer if nothing has changed }
+ if AsmSize=AsmStartSize then
+ AsmClear
+ else
+ begin
+ AsmClose;
+ DoAssemble;
+ AsmCreate(tai_cutobject(hp).place);
+ end;
+ { avoid empty files }
+ while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
+ begin
+ if tai(hp.next).typ=ait_section then
+ lasTSectype:=tai_section(hp.next).sectype;
+ hp:=tai(hp.next);
+ end;
+ if lasTSectype<>sec_none then
+ WriteSection(tai_section(hp).sectype,tai_section(hp).name^);
+ AsmStartSize:=AsmSize;
+ end;
+
+ ait_marker :
+ if tai_marker(hp).kind=InlineStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=InlineEnd then
+ dec(InlineLevel);
+
+ ait_directive :
+ begin
+ case tai_directive(hp).directive of
+ asd_nasm_import :
+ AsmWrite('import ');
+ asd_extern :
+ AsmWrite('EXTERN ');
+ else
+ internalerror(200509191);
+ end;
+ if assigned(tai_directive(hp).name) then
+ AsmWrite(tai_directive(hp).name^);
+ AsmLn;
+ end;
+
+ else
+ internalerror(10000);
+ end;
+ hp:=tai(hp.next);
+ end;
+ end;
+
+
+ var
+ currentasmlist : TExternalAssembler;
+
+ procedure writeexternal(p:tnamedindexitem;arg:pointer);
+ begin
+ if tasmsymbol(p).defbind=AB_EXTERNAL then
+ currentasmlist.AsmWriteln('EXTERN'#9+p.name);
+ end;
+
+ procedure T386NasmAssembler.WriteExternals;
+ begin
+ currentasmlist:=self;
+ objectlibrary.symbolsearch.foreach_static(@writeexternal,nil);
+ end;
+
+
+ procedure T386NasmAssembler.WriteAsmList;
+ var
+ hal : tasmlist;
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Start writing nasm-styled assembler output for '+current_module.mainsource^);
+{$endif}
+ LasTSecType:=sec_none;
+ AsmWriteLn('BITS 32');
+ AsmLn;
+
+ lastfileinfo.line:=-1;
+ lastfileinfo.fileindex:=0;
+ lastinfile:=nil;
+
+ WriteExternals;
+
+ for hal:=low(Tasmlist) to high(Tasmlist) do
+ begin
+ AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
+ writetree(asmlist[hal]);
+ AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
+ end;
+
+ AsmLn;
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Done writing nasm-styled assembler output for '+current_module.mainsource^);
+{$endif EXTDEBUG}
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_i386_nasmcoff_info : tasminfo =
+ (
+ id : as_i386_nasmcoff;
+ idtxt : 'NASMCOFF';
+ asmbin : 'nasm';
+ asmcmd : '-f coff -o $OBJ $ASM';
+ supported_target : system_i386_go32v2;
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmwin32_info : tasminfo =
+ (
+ id : as_i386_nasmwin32;
+ idtxt : 'NASMWIN32';
+ asmbin : 'nasm';
+ asmcmd : '-f win32 -o $OBJ $ASM';
+ supported_target : system_i386_win32;
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmobj_info : tasminfo =
+ (
+ id : as_i386_nasmobj;
+ idtxt : 'NASMOBJ';
+ asmbin : 'nasm';
+ asmcmd : '-f obj -o $OBJ $ASM';
+ supported_target : system_any; { what should I write here ?? }
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmwdosx_info : tasminfo =
+ (
+ id : as_i386_nasmwdosx;
+ idtxt : 'NASMWDOSX';
+ asmbin : 'nasm';
+ asmcmd : '-f win32 -o $OBJ $ASM';
+ supported_target : system_i386_wdosx;
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+
+ as_i386_nasmelf_info : tasminfo =
+ (
+ id : as_i386_nasmelf;
+ idtxt : 'NASMELF';
+ asmbin : 'nasm';
+ asmcmd : '-f elf -o $OBJ $ASM';
+ supported_target : system_i386_linux;
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmbeos_info : tasminfo =
+ (
+ id : as_i386_nasmbeos;
+ idtxt : 'NASMELF';
+ asmbin : 'nasm';
+ asmcmd : '-f elf -o $OBJ $ASM';
+ supported_target : system_i386_beos;
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+
+initialization
+ RegisterAssembler(as_i386_nasmcoff_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmwin32_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmwdosx_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmobj_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmbeos_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmelf_info,T386NasmAssembler);
+end.
diff --git a/compiler/i386/aopt386.pas b/compiler/i386/aopt386.pas
new file mode 100644
index 0000000000..e1ad5e2035
--- /dev/null
+++ b/compiler/i386/aopt386.pas
@@ -0,0 +1,119 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe
+
+ This unit calls the optimization procedures to optimize the assembler
+ code for 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.
+
+ ****************************************************************************
+}
+Unit aopt386;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Uses
+ aasmbase,aasmtai,aasmcpu;
+
+Procedure Optimize(AsmL: TAasmOutput);
+
+
+Implementation
+
+Uses
+ globtype,
+ globals,
+ DAOpt386,POpt386,CSOpt386;
+
+
+Procedure Optimize(AsmL: TAAsmOutput);
+Var
+ BlockStart, BlockEnd, HP: Tai;
+ pass: longint;
+ slowopt, changed, lastLoop: boolean;
+Begin
+ slowopt := (cs_slowoptimize in aktglobalswitches);
+ pass := 0;
+ changed := false;
+ dfa := TDFAObj.create(asml);
+ repeat
+ lastLoop :=
+ not(slowopt) or
+ (not changed and (pass > 2)) or
+ { prevent endless loops }
+ (pass = 4);
+ changed := false;
+ { Setup labeltable, always necessary }
+ blockstart := tai(asml.first);
+ blockend := dfa.pass_1(blockstart);
+ { Blockend now either contains an ait_marker with Kind = AsmBlockStart, }
+ { or nil }
+ While Assigned(BlockStart) Do
+ Begin
+ if pass = 0 then
+ PrePeepHoleOpts(AsmL, BlockStart, BlockEnd);
+ { Peephole optimizations }
+ PeepHoleOptPass1(AsmL, BlockStart, BlockEnd);
+ { Only perform them twice in the first pass }
+ if pass = 0 then
+ PeepHoleOptPass1(AsmL, BlockStart, BlockEnd);
+ { Data flow analyzer }
+ If (cs_fastoptimize in aktglobalswitches) Then
+ begin
+ if dfa.pass_2 then
+ { common subexpression elimination }
+ changed := CSE(asmL, blockStart, blockEnd, pass) or changed;
+ end;
+ { More peephole optimizations }
+ PeepHoleOptPass2(AsmL, BlockStart, BlockEnd);
+ if lastLoop then
+ PostPeepHoleOpts(AsmL, BlockStart, BlockEnd);
+
+ { Free memory }
+ dfa.clear;
+
+ { Continue where we left off, BlockEnd is either the start of an }
+ { assembler block or nil }
+ BlockStart := BlockEnd;
+ While Assigned(BlockStart) And
+ (BlockStart.typ = ait_Marker) And
+ (Tai_Marker(BlockStart).Kind = AsmBlockStart) Do
+ Begin
+ { We stopped at an assembler block, so skip it }
+ Repeat
+ BlockStart := Tai(BlockStart.Next);
+ Until (BlockStart.Typ = Ait_Marker) And
+ (Tai_Marker(Blockstart).Kind = AsmBlockEnd);
+ { Blockstart now contains a Tai_marker(asmblockend) }
+ If GetNextInstruction(BlockStart, HP) And
+ ((HP.typ <> ait_Marker) Or
+ (Tai_Marker(HP).Kind <> AsmBlockStart)) Then
+ { There is no assembler block anymore after the current one, so }
+ { optimize the next block of "normal" instructions }
+ BlockEnd := dfa.pass_1(blockstart)
+ { Otherwise, skip the next assembler block }
+ else
+ blockStart := hp;
+ End;
+ End;
+ inc(pass);
+ until lastLoop;
+ dfa.free;
+
+End;
+
+End.
diff --git a/compiler/i386/cgcpu.pas b/compiler/i386/cgcpu.pas
new file mode 100644
index 0000000000..0a9f58e2a8
--- /dev/null
+++ b/compiler/i386/cgcpu.pas
@@ -0,0 +1,750 @@
+{
+ 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.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cgbase,cgobj,cg64f32,cgx86,
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,parabase,cgutils,
+ symconst,symdef
+ ;
+
+ type
+ tcg386 = class(tcgx86)
+ procedure init_register_allocators;override;
+ { passing parameter using push instead of mov }
+ procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : tcgpara);override;
+ procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : tcgpara);override;
+ procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : tcgpara);override;
+ procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const cgpara : tcgpara);override;
+
+ procedure g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);override;
+ procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);override;
+
+ procedure g_exception_reason_save(list : taasmoutput; const href : treference);override;
+ procedure g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aint);override;
+ procedure g_exception_reason_load(list : taasmoutput; const href : treference);override;
+ procedure g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ end;
+
+ tcg64f386 = class(tcg64f32)
+ procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
+ procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+ procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
+ private
+ procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
+ end;
+
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ paramgr,procinfo,fmodule,
+ rgcpu,rgx86;
+
+ function use_push(const cgpara:tcgpara):boolean;
+ begin
+ result:=assigned(cgpara.location) and
+ (cgpara.location^.loc=LOC_REFERENCE) and
+ (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
+ end;
+
+
+ procedure Tcg386.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ if cs_create_pic in aktmoduleswitches then
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
+ else
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
+ rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBWHOLE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
+ rgfpu:=Trgx86fpu.create;
+ end;
+
+
+ procedure tcg386.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : tcgpara);
+ var
+ pushsize : tcgsize;
+ begin
+ check_register_size(size,r);
+ if use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
+ pushsize:=cgpara.location^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+ list.concat(taicpu.op_reg(A_PUSH,tcgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
+ end
+ else
+ inherited a_param_reg(list,size,r,cgpara);
+ end;
+
+
+ procedure tcg386.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : tcgpara);
+ var
+ pushsize : tcgsize;
+ begin
+ if use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
+ pushsize:=cgpara.location^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+ list.concat(taicpu.op_const(A_PUSH,tcgsize2opsize[pushsize],a));
+ end
+ else
+ inherited a_param_const(list,size,a,cgpara);
+ end;
+
+
+ procedure tcg386.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : tcgpara);
+
+ procedure pushdata(paraloc:pcgparalocation;ofs:aint);
+ var
+ pushsize : tcgsize;
+ tmpreg : tregister;
+ href : treference;
+ begin
+ if not assigned(paraloc) then
+ exit;
+ if (paraloc^.loc<>LOC_REFERENCE) or
+ (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
+ (tcgsize2size[paraloc^.size]>sizeof(aint)) then
+ internalerror(200501162);
+ { Pushes are needed in reverse order, add the size of the
+ current location to the offset where to load from. This
+ prevents wrong calculations for the last location when
+ the size is not a power of 2 }
+ if assigned(paraloc^.next) then
+ pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
+ { Push the data starting at ofs }
+ href:=r;
+ inc(href.offset,ofs);
+ if tcgsize2size[paraloc^.size]>cgpara.alignment then
+ pushsize:=paraloc^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+ if tcgsize2size[paraloc^.size]<cgpara.alignment then
+ begin
+ tmpreg:=getintregister(list,pushsize);
+ a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
+ list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],tmpreg));
+ end
+ else
+ list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[pushsize],href));
+ end;
+
+ var
+ len : aint;
+ href : treference;
+ begin
+ { cgpara.size=OS_NO requires a copy on the stack }
+ if use_push(cgpara) then
+ begin
+ { Record copy? }
+ if (cgpara.size in [OS_NO,OS_F64]) or (size=OS_NO) then
+ begin
+ cgpara.check_simple_location;
+ len:=align(cgpara.intsize,cgpara.alignment);
+ g_stackpointer_alloc(list,len);
+ reference_reset_base(href,NR_STACK_POINTER_REG,0);
+ g_concatcopy(list,r,href,len);
+ end
+ else
+ begin
+ if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
+ internalerror(200501161);
+ { We need to push the data in reverse order,
+ therefor we use a recursive algorithm }
+ pushdata(cgpara.location,0);
+ end
+ end
+ else
+ inherited a_param_ref(list,size,r,cgpara);
+ end;
+
+
+ procedure tcg386.a_paramaddr_ref(list : taasmoutput;const r : treference;const cgpara : tcgpara);
+ var
+ tmpreg : tregister;
+ opsize : topsize;
+ begin
+ with r do
+ begin
+{$ifndef segment_threadvars}
+ if (segment<>NR_NO) then
+ cgmessage(cg_e_cant_use_far_pointer_there);
+{$endif}
+ if use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ opsize:=tcgsize2opsize[OS_ADDR];
+ if (segment=NR_NO) and (base=NR_NO) and (index=NR_NO) then
+ begin
+ if assigned(symbol) then
+ list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
+ else
+ list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
+ end
+ else if (segment=NR_NO) and (base=NR_NO) and (index<>NR_NO) and
+ (offset=0) and (scalefactor=0) and (symbol=nil) then
+ list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
+ else if (segment=NR_NO) and (base<>NR_NO) and (index=NR_NO) and
+ (offset=0) and (symbol=nil) then
+ list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
+ else
+ begin
+ tmpreg:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
+ end;
+ end
+ else
+ inherited a_paramaddr_ref(list,r,cgpara);
+ end;
+ end;
+
+
+ procedure tcg386.g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);
+ var
+ stacksize : longint;
+ begin
+ { Release PIC register }
+ if cs_create_pic in aktmoduleswitches then
+ list.concat(tai_regalloc.dealloc(NR_PIC_OFFSET_REG,nil));
+
+ { MMX needs to call EMMS }
+ if assigned(rg[R_MMXREGISTER]) and
+ (rg[R_MMXREGISTER].uses_registers) then
+ list.concat(Taicpu.op_none(A_EMMS,S_NO));
+
+ { remove stackframe }
+ if not nostackframe then
+ begin
+ if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+ begin
+ stacksize:=current_procinfo.calc_stackframe_size;
+ if (stacksize<>0) then
+ cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
+ end
+ else
+ list.concat(Taicpu.op_none(A_LEAVE,S_NO));
+ list.concat(tai_regalloc.dealloc(NR_FRAME_POINTER_REG,nil));
+ end;
+
+ { return from proc }
+ if (po_interrupt in current_procinfo.procdef.procoptions) then
+ begin
+ if (current_procinfo.procdef.funcretloc[calleeside].loc<>LOC_VOID) and
+ (current_procinfo.procdef.funcretloc[calleeside].loc=LOC_REGISTER) then
+ list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
+ else
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EAX));
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EBX));
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ECX));
+
+ if (current_procinfo.procdef.funcretloc[calleeside].loc=LOC_REGISTER) and
+ (current_procinfo.procdef.funcretloc[calleeside].size in [OS_64,OS_S64]) then
+ list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
+ else
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDX));
+
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ESI));
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDI));
+ { .... also the segment registers }
+ list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
+ list.concat(Taicpu.Op_reg(A_POP,S_W,NR_ES));
+ list.concat(Taicpu.Op_reg(A_POP,S_W,NR_FS));
+ list.concat(Taicpu.Op_reg(A_POP,S_W,NR_GS));
+ { this restores the flags }
+ list.concat(Taicpu.Op_none(A_IRET,S_NO));
+ end
+ { Routines with the poclearstack flag set use only a ret }
+ else if current_procinfo.procdef.proccalloption in clearstack_pocalls then
+ begin
+ { complex return values are removed from stack in C code PM }
+ if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,
+ current_procinfo.procdef.proccalloption) then
+ list.concat(Taicpu.Op_const(A_RET,S_W,sizeof(aint)))
+ else
+ list.concat(Taicpu.Op_none(A_RET,S_NO));
+ end
+ { ... also routines with parasize=0 }
+ else if (parasize=0) then
+ list.concat(Taicpu.Op_none(A_RET,S_NO))
+ else
+ begin
+ { parameters are limited to 65535 bytes because ret allows only imm16 }
+ if (parasize>65535) then
+ CGMessage(cg_e_parasize_too_big);
+ list.concat(Taicpu.Op_const(A_RET,S_W,parasize));
+ end;
+ end;
+
+
+ procedure tcg386.g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);
+ var
+ power,len : longint;
+ opsize : topsize;
+{$ifndef __NOWINPECOFF__}
+ again,ok : tasmlabel;
+{$endif}
+ begin
+ { get stack space }
+ getcpuregister(list,NR_EDI);
+ a_load_loc_reg(list,OS_INT,lenloc,NR_EDI);
+ list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
+ if (elesize<>1) then
+ begin
+ if ispowerof2(elesize, power) then
+ list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
+ else
+ list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
+ end;
+{$ifndef __NOWINPECOFF__}
+ { windows guards only a few pages for stack growing, }
+ { so we have to access every page first }
+ if target_info.system=system_i386_win32 then
+ begin
+ objectlibrary.getjumplabel(again);
+ objectlibrary.getjumplabel(ok);
+ a_label(list,again);
+ list.concat(Taicpu.op_const_reg(A_CMP,S_L,winstackpagesize,NR_EDI));
+ a_jmp_cond(list,OC_B,ok);
+ list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,NR_ESP));
+ list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EDI));
+ list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize,NR_EDI));
+ a_jmp_always(list,again);
+
+ a_label(list,ok);
+ list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
+ ungetcpuregister(list,NR_EDI);
+ { now reload EDI }
+ getcpuregister(list,NR_EDI);
+ a_load_loc_reg(list,OS_INT,lenloc,NR_EDI);
+ list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
+
+ if (elesize<>1) then
+ begin
+ if ispowerof2(elesize, power) then
+ list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
+ else
+ list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
+ end;
+ end
+ else
+{$endif __NOWINPECOFF__}
+ list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
+ { align stack on 4 bytes }
+ list.concat(Taicpu.op_const_reg(A_AND,S_L,aint($fffffff4),NR_ESP));
+ { load destination, don't use a_load_reg_reg, that will add a move instruction
+ that can confuse the reg allocator }
+ list.concat(Taicpu.Op_reg_reg(A_MOV,S_L,NR_ESP,NR_EDI));
+
+ { Allocate other registers }
+ getcpuregister(list,NR_ECX);
+ getcpuregister(list,NR_ESI);
+
+ { load count }
+ a_load_loc_reg(list,OS_INT,lenloc,NR_ECX);
+
+ { load source }
+ a_loadaddr_ref_reg(list,ref,NR_ESI);
+
+ { scheduled .... }
+ list.concat(Taicpu.op_reg(A_INC,S_L,NR_ECX));
+
+ { calculate size }
+ len:=elesize;
+ opsize:=S_B;
+ if (len and 3)=0 then
+ begin
+ opsize:=S_L;
+ len:=len shr 2;
+ end
+ else
+ if (len and 1)=0 then
+ begin
+ opsize:=S_W;
+ len:=len shr 1;
+ end;
+
+ if len<>0 then
+ begin
+ if ispowerof2(len, power) then
+ list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_ECX))
+ else
+ list.concat(Taicpu.op_const_reg(A_IMUL,S_L,len,NR_ECX));
+ end;
+ list.concat(Taicpu.op_none(A_REP,S_NO));
+ case opsize of
+ S_B : list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
+ S_W : list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
+ S_L : list.concat(Taicpu.Op_none(A_MOVSD,S_NO));
+ end;
+ ungetcpuregister(list,NR_EDI);
+ ungetcpuregister(list,NR_ECX);
+ ungetcpuregister(list,NR_ESI);
+
+ { patch the new address, but don't use a_load_reg_reg, that will add a move instruction
+ that can confuse the reg allocator }
+ list.concat(Taicpu.Op_reg_reg(A_MOV,S_L,NR_ESP,destreg));
+ end;
+
+
+ procedure tcg386.g_exception_reason_save(list : taasmoutput; const href : treference);
+ begin
+ list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG));
+ end;
+
+
+ procedure tcg386.g_exception_reason_save_const(list : taasmoutput;const href : treference; a: aint);
+ begin
+ list.concat(Taicpu.op_const(A_PUSH,tcgsize2opsize[OS_INT],a));
+ end;
+
+
+ procedure tcg386.g_exception_reason_load(list : taasmoutput; const href : treference);
+ begin
+ list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG));
+ end;
+
+
+
+ procedure tcg386.g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);
+ {
+ possible calling conventions:
+ default stdcall cdecl pascal register
+ default(0): OK OK OK(1) OK OK
+ virtual(2): OK OK OK(3) OK OK
+
+ (0):
+ set self parameter to correct value
+ jmp mangledname
+
+ (1): The code is the following
+ set self parameter to correct value
+ call mangledname
+ set self parameter to interface value
+
+ (2): The wrapper code use %eax to reach the virtual method address
+ set self to correct value
+ move self,%eax
+ mov 0(%eax),%eax ; load vmt
+ jmp vmtoffs(%eax) ; method offs
+
+ (3): The wrapper code use %eax to reach the virtual method address
+ set self to correct value
+ move self,%eax
+ mov 0(%eax),%eax ; load vmt
+ jmp vmtoffs(%eax) ; method offs
+ set self parameter to interface value
+
+
+ (4): Virtual use values pushed on stack to reach the method address
+ so the following code be generated:
+ set self to correct value
+ push %ebx ; allocate space for function address
+ push %eax
+ mov self,%eax
+ mov 0(%eax),%eax ; load vmt
+ mov vmtoffs(%eax),eax ; method offs
+ mov %eax,4(%esp)
+ pop %eax
+ ret 0; jmp the address
+
+ }
+
+ procedure getselftoeax(offs: longint);
+ var
+ href : treference;
+ selfoffsetfromsp : longint;
+ begin
+ { mov offset(%esp),%eax }
+ if (procdef.proccalloption<>pocall_register) then
+ begin
+ { framepointer is pushed for nested procs }
+ if procdef.parast.symtablelevel>normal_function_level then
+ selfoffsetfromsp:=2*sizeof(aint)
+ else
+ selfoffsetfromsp:=sizeof(aint);
+ reference_reset_base(href,NR_ESP,selfoffsetfromsp+offs);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
+ end;
+ end;
+
+ procedure loadvmttoeax;
+ var
+ href : treference;
+ begin
+ { mov 0(%eax),%eax ; load vmt}
+ reference_reset_base(href,NR_EAX,0);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
+ end;
+
+ procedure op_oneaxmethodaddr(op: TAsmOp);
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_EAX,procdef._class.vmtmethodoffset(procdef.extnumber));
+ list.concat(taicpu.op_ref(op,S_L,href));
+ end;
+
+ procedure loadmethodoffstoeax;
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { mov vmtoffs(%eax),%eax ; method offs }
+ reference_reset_base(href,NR_EAX,procdef._class.vmtmethodoffset(procdef.extnumber));
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
+ end;
+
+ var
+ lab : tasmsymbol;
+ make_global : boolean;
+ href : treference;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef._class) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>objectsymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ (cs_create_smart in aktmoduleswitches) or
+ (af_smartlink_sections in target_asm.flags) or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ { case 1 or 2 }
+ if (procdef.proccalloption in clearstack_pocalls) then
+ begin
+ if po_virtualmethod in procdef.procoptions then
+ begin
+ { case 2 }
+ getselftoeax(0);
+ loadvmttoeax;
+ op_oneaxmethodaddr(A_CALL);
+ end
+ else
+ begin
+ { case 1 }
+ cg.a_call_name(list,procdef.mangledname);
+ end;
+ { restore param1 value self to interface }
+ g_adjust_self_value(list,procdef,-ioffset);
+ end
+ else if po_virtualmethod in procdef.procoptions then
+ begin
+ if (procdef.proccalloption=pocall_register) then
+ begin
+ { case 4 }
+ list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EBX)); { allocate space for address}
+ list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EAX));
+ getselftoeax(8);
+ loadvmttoeax;
+ loadmethodoffstoeax;
+ { mov %eax,4(%esp) }
+ reference_reset_base(href,NR_ESP,4);
+ list.concat(taicpu.op_reg_ref(A_MOV,S_L,NR_EAX,href));
+ { pop %eax }
+ list.concat(taicpu.op_reg(A_POP,S_L,NR_EAX));
+ { ret ; jump to the address }
+ list.concat(taicpu.op_none(A_RET,S_L));
+ end
+ else
+ begin
+ { case 3 }
+ getselftoeax(0);
+ loadvmttoeax;
+ op_oneaxmethodaddr(A_JMP);
+ end;
+ end
+ { case 0 }
+ else
+ begin
+ lab:=objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION);
+ list.concat(taicpu.op_sym(A_JMP,S_NO,lab));
+ end;
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+
+{ ************* 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;size : tcgsize;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;size : tcgsize;regsrc,regdst : tregister64);
+ var
+ op1,op2 : TAsmOp;
+ begin
+ case op of
+ OP_NEG :
+ begin
+ if (regsrc.reglo<>regdst.reglo) then
+ a_load64_reg_reg(list,regsrc,regdst);
+ list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
+ list.concat(taicpu.op_reg(A_NEG,S_L,regdst.reglo));
+ list.concat(taicpu.op_const_reg(A_SBB,S_L,-1,regdst.reghi));
+ exit;
+ end;
+ OP_NOT :
+ begin
+ if (regsrc.reglo<>regdst.reglo) then
+ a_load64_reg_reg(list,regsrc,regdst);
+ list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
+ list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reglo));
+ exit;
+ end;
+ end;
+ 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;size : tcgsize;value : int64;reg : tregister64);
+ var
+ op1,op2 : TAsmOp;
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_const_reg(list,op,OS_32,aint(lo(value)),reg.reglo);
+ cg.a_op_const_reg(list,op,OS_32,aint(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,aint(lo(value)),reg.reglo));
+ list.concat(taicpu.op_const_reg(op2,S_L,aint(hi(value)),reg.reghi));
+ end;
+ else
+ internalerror(200204021);
+ end;
+ end;
+
+
+ procedure tcg64f386.a_op64_const_ref(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;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.
diff --git a/compiler/i386/cpubase.inc b/compiler/i386/cpubase.inc
new file mode 100644
index 0000000000..a85c35549a
--- /dev/null
+++ b/compiler/i386/cpubase.inc
@@ -0,0 +1,171 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
+
+ Contains the basic declarations for the i386 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.
+
+ ****************************************************************************
+}
+{ This include file contains the basic declarations for the i386 architecture.
+}
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_Q,S_BW,S_BL,S_WL,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_FV,S_FXX,
+ S_MD,
+ S_NEAR,S_FAR,S_SHORT,
+ S_T,
+ S_XMM
+ );
+
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+ const
+ {# Standard opcode string table (for each tasmop enumeration). The
+ opcode strings should conform to the names as defined by the
+ processor manufacturer.
+ }
+ std_op2str:op2strtable={$i i386int.inc}
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+ c_countusableregsint = 4;
+
+{
+ firstsaveintreg = RS_EAX;
+ lastsaveintreg = RS_EDX;
+ firstsavefpureg = RS_INVALID;
+ lastsavefpureg = RS_INVALID;
+ firstsavemmreg = RS_MM0;
+ lastsavemmreg = RS_MM7;
+
+ general_superregisters = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
+
+ maxvarregs = 4;
+ varregs : array[1..maxvarregs] of tsuperregister =
+ (RS_EBX,RS_EDX,RS_ECX,RS_EAX);
+
+ maxfpuvarregs = 8;
+
+ maxmmvarregs = 8;
+}
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from i386.c (dbx_register_map) and i386.h
+ (FIXED_REGISTERS) from GCC 3.x source code
+
+ }
+ reg_stab_table : array[tregisterindex] of shortint = (
+ {$i r386stab.inc}
+ );
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F80;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M64;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_ESP;
+ RS_STACK_POINTER_REG = RS_ESP;
+ {# Frame pointer register }
+ RS_FRAME_POINTER_REG = RS_EBP;
+ NR_FRAME_POINTER_REG = NR_EBP;
+ { Return address for DWARF }
+ NR_RETURN_ADDRESS_REG = NR_EIP;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+ NR_PIC_OFFSET_REG = NR_EBX;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_EAX;
+ RS_FUNCTION_RETURN_REG = RS_EAX;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_EAX;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_EAX;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_EDX;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_EDX;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ { WARNING: don't change to R_ST0!! See comments above implementation of }
+ { a_loadfpu* methods in rgcpu (JM) }
+ NR_fpu_result_reg = NR_ST;
+ NR_mm_result_reg = NR_MM0;
+
+ { Offset where the parent framepointer is pushed }
+ PARENT_FRAMEPOINTER_OFFSET = 8;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..2] of tsuperregister = (RS_EBX,RS_ESI,RS_EDI);
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4;
+
+
diff --git a/compiler/i386/cpuinfo.pas b/compiler/i386/cpuinfo.pas
new file mode 100644
index 0000000000..bfdb82727a
--- /dev/null
+++ b/compiler/i386/cpuinfo.pas
@@ -0,0 +1,94 @@
+{
+ Copyright (c) 1998-2004 by Florian Klaempfl
+
+ Basic Processor information
+
+ 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 cpuinfo;
+
+{$i fpcdefs.inc}
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = type extended;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors =
+ (no_processor,
+ Class386,
+ ClassPentium,
+ ClassPentium2,
+ ClassPentium3,
+ ClassPentium4
+ );
+
+ tfputype =
+ (no_fpuprocessor,
+ fpu_soft,
+ fpu_x87,
+ fpu_sse,
+ fpu_sse2
+ );
+
+
+Const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_register,
+ pocall_safecall,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl,
+ pocall_far16,
+ pocall_pascal,
+ pocall_oldfpccall
+ ];
+
+ processorsstr : array[tprocessors] of string[10] = ('',
+ '386',
+ 'PENTIUM',
+ 'PENTIUM2',
+ 'PENTIUM3',
+ 'PENTIUM4'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'SOFT',
+ 'X87',
+ 'SSE',
+ 'SSE2'
+ );
+
+ sse_singlescalar : set of tfputype = [fpu_sse,fpu_sse2];
+ sse_doublescalar : set of tfputype = [fpu_sse2];
+
+Implementation
+
+end.
diff --git a/compiler/i386/cpunode.pas b/compiler/i386/cpunode.pas
new file mode 100644
index 0000000000..857a2241a3
--- /dev/null
+++ b/compiler/i386/cpunode.pas
@@ -0,0 +1,59 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the i386 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
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,
+ ncgld,
+ ncgflw,
+ ncgcnv,
+ ncgmem,
+ ncgmat,
+ ncgcon,
+ ncgcal,
+ ncgset,
+ ncginl,
+ ncgopt,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ nx86set,
+ nx86con,
+ nx86cnv,
+
+ n386add,
+ n386cal,
+ n386mem,
+ n386set,
+ n386inl,
+ n386mat
+ ;
+
+end.
diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas
new file mode 100644
index 0000000000..05e55b6c9c
--- /dev/null
+++ b/compiler/i386/cpupara.pas
@@ -0,0 +1,623 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generates the argument location information for 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 bymethodpointer
+ 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 cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ aasmtai,cpubase,cgbase,
+ symconst,symtype,symsym,symdef,
+ parabase,paramgr;
+
+ type
+ ti386paramanager = class(tparamanager)
+ function param_use_paraloc(const cgpara:tcgpara):boolean;override;
+ function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function get_para_align(calloption : tproccalloption):byte;override;
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+ { Returns the location for the nr-st 32 Bit int parameter
+ if every parameter before is an 32 Bit int parameter as well
+ and if the calling conventions for the helper routines of the
+ rtl are used.
+ }
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ procedure createtempparaloc(list: taasmoutput;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);override;
+ private
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ procedure create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
+ procedure create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parareg,parasize:longint);
+ end;
+
+
+ implementation
+
+ uses
+ cutils,
+ systems,verbose,
+ defutil,
+ cgutils;
+
+ const
+ parasupregs : array[0..2] of tsuperregister = (RS_EAX,RS_EDX,RS_ECX);
+
+{****************************************************************************
+ TI386PARAMANAGER
+****************************************************************************}
+
+ function ti386paramanager.param_use_paraloc(const cgpara:tcgpara):boolean;
+ var
+ paraloc : pcgparalocation;
+ begin
+ if not assigned(cgpara.location) then
+ internalerror(200410102);
+ result:=true;
+ { All locations are LOC_REFERENCE }
+ paraloc:=cgpara.location;
+ while assigned(paraloc) do
+ begin
+ if (paraloc^.loc<>LOC_REFERENCE) then
+ begin
+ result:=false;
+ exit;
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ function ti386paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ case target_info.system of
+ system_i386_win32 :
+ begin
+ case def.deftype of
+ recorddef :
+ begin
+ { Win32 GCC returns small records in the FUNCTION_RETURN_REG.
+ For stdcall we follow delphi instead of GCC }
+ if (calloption in [pocall_cdecl,pocall_cppdecl]) and
+ (def.size<=8) then
+ begin
+ result:=false;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ system_i386_darwin :
+ begin
+ case def.deftype of
+ recorddef :
+ begin
+ if (def.size <= 8) then
+ begin
+ result := false;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ end;
+ result:=inherited ret_in_param(def,calloption);
+ end;
+
+
+ function ti386paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out always require address }
+ if varspez in [vs_var,vs_out] then
+ begin
+ result:=true;
+ exit;
+ end;
+ { Only vs_const, vs_value here }
+ case def.deftype of
+ variantdef :
+ begin
+ { variants are small enough to be passed by value except if
+ required by the windows api
+ }
+ if (target_info.system=system_i386_win32) and
+ (calloption=pocall_stdcall) and
+ (varspez=vs_const) then
+ result:=true
+ else
+ result:=false;
+ end;
+ formaldef :
+ result:=true;
+ recorddef :
+ begin
+ { Win32 stdcall passes small records on the stack for call by
+ value }
+ if (target_info.system=system_i386_win32) and
+ (calloption=pocall_stdcall) and
+ (varspez=vs_value) and
+ (def.size<=16) then
+ result:=false
+ else
+ result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (def.size>sizeof(aint));
+ end;
+ arraydef :
+ begin
+ { Win32 stdcall passes arrays on the stack for call by
+ value }
+ if (target_info.system=system_i386_win32) and
+ (calloption=pocall_stdcall) and
+ (varspez=vs_value) and
+ (tarraydef(def).highrange>=tarraydef(def).lowrange) then
+ result:=false
+ else
+ { array of const values are pushed on the stack as
+ well as dyn. arrays }
+ if (calloption in [pocall_cdecl,pocall_cppdecl]) then
+ result:=not(is_array_of_const(def) or
+ is_dynamic_array(def))
+ else
+ begin
+ result:=(
+ (tarraydef(def).highrange>=tarraydef(def).lowrange) and
+ (def.size>sizeof(aint))
+ ) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ end;
+ end;
+ objectdef :
+ result:=is_object(def);
+ stringdef :
+ result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (tstringdef(def).string_typ in [st_shortstring,st_longstring]);
+ procvardef :
+ result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (po_methodpointer in tprocvardef(def).procoptions);
+ setdef :
+ result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (tsetdef(def).settype<>smallset);
+ end;
+ end;
+
+
+ function ti386paramanager.get_para_align(calloption : tproccalloption):byte;
+ begin
+ if calloption=pocall_oldfpccall then
+ begin
+ if target_info.system in [system_i386_go32v2,system_i386_watcom] then
+ result:=2
+ else
+ result:=4;
+ end
+ else
+ result:=std_param_align;
+ end;
+
+
+ function ti386paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ case calloption of
+ pocall_internproc :
+ result:=[];
+ pocall_register,
+ pocall_safecall,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl :
+ result:=[RS_EAX,RS_EDX,RS_ECX];
+ pocall_far16,
+ pocall_pascal,
+ pocall_oldfpccall :
+ result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX];
+ else
+ internalerror(200309071);
+ end;
+ end;
+
+
+ function ti386paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[0..first_fpu_imreg-1];
+ end;
+
+
+ function ti386paramanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[0..first_mm_imreg-1];
+ end;
+
+
+ procedure ti386paramanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.intsize:=tcgsize2size[OS_INT];
+ cgpara.alignment:=get_para_align(calloption);
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ if calloption=pocall_register then
+ begin
+ if (nr<=high(parasupregs)+1) then
+ begin
+ if nr=0 then
+ internalerror(200309271);
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,parasupregs[nr-1],R_SUBWHOLE);
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=sizeof(aint)*nr;
+ end;
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=sizeof(aint)*nr;
+ end;
+ end;
+ end;
+
+
+ procedure ti386paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ var
+ retcgsize : tcgsize;
+ begin
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ retcgsize:=OS_ADDR
+ else
+ retcgsize:=def_cgsize(p.rettype.def);
+
+ location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
+ { void has no location }
+ if is_void(p.rettype.def) then
+ begin
+ location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
+ exit;
+ end;
+ { Return in FPU register? }
+ if p.rettype.def.deftype=floatdef then
+ begin
+ p.funcretloc[side].loc:=LOC_FPUREGISTER;
+ p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+ p.funcretloc[side].size:=retcgsize;
+ end
+ else
+ { Return in register? }
+ if not ret_in_param(p.rettype.def,p.proccalloption) then
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { low 32bits }
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].size:=OS_64;
+ if side=callerside then
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+ { high 32bits }
+ if side=callerside then
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].size:=retcgsize;
+ if side=callerside then
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+ else
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+ end;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REFERENCE;
+ p.funcretloc[side].size:=retcgsize;
+ end;
+ end;
+
+
+ procedure ti386paramanager.create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
+ var
+ i : integer;
+ hp : tparavarsym;
+ paraloc : pcgparalocation;
+ l,
+ paralen,
+ varalign : longint;
+ paraalign : shortint;
+ pushaddr : boolean;
+ paracgsize : tcgsize;
+ begin
+ paraalign:=get_para_align(p.proccalloption);
+ { we push Flags and CS as long
+ to cope with the IRETD
+ and we save 6 register + 4 selectors }
+ if po_interrupt in p.procoptions then
+ inc(parasize,8+6*4+4*2);
+ { Offset is calculated like:
+ sub esp,12
+ mov [esp+8],para3
+ mov [esp+4],para2
+ mov [esp],para1
+ call function
+ That means for pushes the para with the
+ highest offset (see para3) needs to be pushed first
+ }
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ pushaddr:=push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption);
+ if pushaddr then
+ begin
+ paralen:=sizeof(aint);
+ paracgsize:=OS_ADDR;
+ end
+ else
+ begin
+ paralen:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
+ paracgsize:=def_cgsize(hp.vartype.def);
+ end;
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].Alignment:=paraalign;
+ { Copy to stack? }
+ if paracgsize=OS_NO then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=paracgsize;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ if side=calleeside then
+ inc(paraloc^.reference.offset,target_info.first_parm_offset);
+ parasize:=align(parasize+paralen,varalign);
+ end
+ else
+ begin
+ if paralen=0 then
+ internalerror(200501163);
+ while (paralen>0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ { single and double need a single location }
+ if (paracgsize in [OS_F64,OS_F32]) then
+ begin
+ paraloc^.size:=paracgsize;
+ l:=paralen;
+ end
+ else
+ begin
+ { We can allocate at maximum 32 bits per location }
+ if paralen>sizeof(aint) then
+ l:=sizeof(aint)
+ else
+ l:=paralen;
+ paraloc^.size:=int_cgsize(l);
+ end;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(l),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ if side=calleeside then
+ inc(paraloc^.reference.offset,target_info.first_parm_offset);
+ parasize:=align(parasize+l,varalign);
+ dec(paralen,l);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure ti386paramanager.create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var parareg,parasize:longint);
+ var
+ hp : tparavarsym;
+ paraloc : pcgparalocation;
+ paracgsize : tcgsize;
+ i : integer;
+ l,
+ paralen,
+ varalign : longint;
+ pushaddr : boolean;
+ paraalign : shortint;
+ begin
+ paraalign:=get_para_align(p.proccalloption);
+ { Register parameters are assigned from left to right }
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ pushaddr:=push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption);
+ if pushaddr then
+ begin
+ paralen:=sizeof(aint);
+ paracgsize:=OS_ADDR;
+ end
+ else
+ begin
+ paralen:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
+ paracgsize:=def_cgsize(hp.vartype.def);
+ end;
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].Alignment:=paraalign;
+ {
+ EAX
+ EDX
+ ECX
+ Stack
+ Stack
+
+ 64bit values,floats,arrays and records are always
+ on the stack.
+ }
+ if (parareg<=high(parasupregs)) and
+ (paralen<=sizeof(aint)) and
+ (
+ not(hp.vartype.def.deftype in [floatdef,recorddef,arraydef]) or
+ pushaddr
+ ) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.size:=paracgsize;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(paracgsize));
+ inc(parareg);
+ end
+ else
+ begin
+ { Copy to stack? }
+ if paracgsize=OS_NO then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=paracgsize;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ if side=calleeside then
+ inc(paraloc^.reference.offset,target_info.first_parm_offset);
+ parasize:=align(parasize+paralen,varalign);
+ end
+ else
+ begin
+ if paralen=0 then
+ internalerror(200501163);
+ while (paralen>0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ { Extended and double need a single location }
+ if (paracgsize in [OS_F64,OS_F32]) then
+ begin
+ paraloc^.size:=paracgsize;
+ l:=paralen;
+ end
+ else
+ begin
+ { We can allocate at maximum 32 bits per location }
+ if paralen>sizeof(aint) then
+ l:=sizeof(aint)
+ else
+ l:=paralen;
+ paraloc^.size:=int_cgsize(l);
+ end;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(l),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ if side=calleeside then
+ inc(paraloc^.reference.offset,target_info.first_parm_offset);
+ parasize:=align(parasize+l,varalign);
+ dec(paralen,l);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ function ti386paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ parasize,
+ parareg : longint;
+ begin
+ parasize:=0;
+ parareg:=0;
+ case p.proccalloption of
+ pocall_register :
+ create_register_paraloc_info(p,side,p.paras,parareg,parasize);
+ pocall_internproc :
+ begin
+ { Use default calling }
+ if (pocall_default=pocall_register) then
+ create_register_paraloc_info(p,side,p.paras,parareg,parasize)
+ else
+ create_stdcall_paraloc_info(p,side,p.paras,parasize);
+ end;
+ else
+ create_stdcall_paraloc_info(p,side,p.paras,parasize);
+ end;
+ create_funcretloc_info(p,side);
+ result:=parasize;
+ end;
+
+
+ function ti386paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ parasize : longint;
+ begin
+ parasize:=0;
+ { calculate the registers for the normal parameters }
+ create_stdcall_paraloc_info(p,callerside,p.paras,parasize);
+ { append the varargs }
+ create_stdcall_paraloc_info(p,callerside,varargspara,parasize);
+ result:=parasize;
+ end;
+
+
+ procedure ti386paramanager.createtempparaloc(list: taasmoutput;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ paraloc:=parasym.paraloc[callerside].location;
+ { No need for temps when value is pushed }
+ if assigned(paraloc) and
+ (paraloc^.loc=LOC_REFERENCE) and
+ (paraloc^.reference.index=NR_STACK_POINTER_REG) then
+ duplicateparaloc(list,calloption,parasym,cgpara)
+ else
+ inherited createtempparaloc(list,calloption,parasym,cgpara);
+ end;
+
+
+begin
+ paramanager:=ti386paramanager.create;
+end.
diff --git a/compiler/i386/cpupi.pas b/compiler/i386/cpupi.pas
new file mode 100644
index 0000000000..c714ef0791
--- /dev/null
+++ b/compiler/i386/cpupi.pas
@@ -0,0 +1,69 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ 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 contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ psub,procinfo;
+
+ type
+ ti386procinfo = class(tcgprocinfo)
+ constructor create(aparent:tprocinfo);override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+
+ implementation
+
+ uses
+ cutils,
+ systems,globals,
+ tgobj,
+ cpubase;
+
+ constructor ti386procinfo.create(aparent:tprocinfo);
+ begin
+ inherited create(aparent);
+ got:=NR_EBX;
+ end;
+
+
+ function ti386procinfo.calc_stackframe_size:longint;
+ begin
+ { align to 4 bytes at least
+ otherwise all those subl $2,%esp are meaningless PM }
+ if (target_info.system <> system_i386_darwin) then
+ result:=Align(tg.direction*tg.lasttemp,min(aktalignment.localalignmin,4))
+ else
+ result:=Align(tg.direction*tg.lasttemp,min(aktalignment.localalignmin,16));
+ end;
+
+
+
+begin
+ cprocinfo:=ti386procinfo;
+end.
diff --git a/compiler/i386/cpuswtch.pas b/compiler/i386/cpuswtch.pas
new file mode 100644
index 0000000000..5893bbe508
--- /dev/null
+++ b/compiler/i386/cpuswtch.pas
@@ -0,0 +1,115 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ interprets the commandline options which are i386 specific
+
+ 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 cpuswtch;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ options;
+
+type
+ toption386=class(toption)
+ procedure interpret_proc_specific_options(const opt:string);override;
+ end;
+
+implementation
+
+uses
+ cutils,globtype,systems,globals,cpuinfo;
+
+procedure toption386.interpret_proc_specific_options(const opt:string);
+var
+ j : longint;
+ More : string;
+begin
+ More:=Upper(copy(opt,3,length(opt)-2));
+ case opt[2] of
+ 'O' : Begin
+ j := 3;
+ While (j <= Length(Opt)) Do
+ Begin
+ case opt[j] of
+ '-' :
+ begin
+ initglobalswitches:=initglobalswitches-[cs_optimize,cs_fastoptimize,cs_slowoptimize,cs_littlesize,
+ cs_regvars,cs_uncertainopts];
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+ end;
+ 'a' :
+ begin
+ UpdateAlignmentStr(Copy(Opt,j+1,255),ParaAlignment);
+ j:=length(Opt);
+ end;
+ 'g' : initglobalswitches:=initglobalswitches+[cs_littlesize];
+ 'G' : initglobalswitches:=initglobalswitches-[cs_littlesize];
+ 'r' :
+ begin
+ initglobalswitches:=initglobalswitches+[cs_regvars];
+ Simplify_ppu:=false;
+ end;
+ 'u' : initglobalswitches:=initglobalswitches+[cs_uncertainopts];
+ '1' : initglobalswitches:=initglobalswitches-[cs_fastoptimize,cs_slowoptimize]+[cs_optimize];
+ '2' : initglobalswitches:=initglobalswitches-[cs_slowoptimize]+[cs_optimize,cs_fastoptimize];
+ '3' : initglobalswitches:=initglobalswitches+[cs_optimize,cs_fastoptimize,cs_slowoptimize];
+ 'p' :
+ Begin
+ If j < Length(Opt) Then
+ Begin
+ Case opt[j+1] Of
+ '1': initoptprocessor := Class386;
+ '2': initoptprocessor := ClassPentium;
+ '3': initoptprocessor := ClassPentium2;
+ '4': initoptprocessor := ClassPentium4;
+ Else IllegalPara(Opt)
+ End;
+ Inc(j);
+ End
+ Else IllegalPara(opt)
+ End;
+ else IllegalPara(opt);
+ End;
+ Inc(j)
+ end;
+ end;
+ 'R' : begin
+ if More='ATT' then
+ initasmmode:=asmmode_i386_att
+ else
+ if More='INTEL' then
+ initasmmode:=asmmode_i386_intel
+ else
+ if (More='STANDARD') or (More='DEFAULT') then
+ initasmmode:=asmmode_standard
+ else
+ IllegalPara(opt);
+ end;
+ else
+ IllegalPara(opt);
+ end;
+end;
+
+
+initialization
+ coption:=toption386;
+end.
diff --git a/compiler/i386/cputarg.pas b/compiler/i386/cputarg.pas
new file mode 100644
index 0000000000..ebad2d1290
--- /dev/null
+++ b/compiler/i386/cputarg.pas
@@ -0,0 +1,116 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the i386 dependent target units
+
+ 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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETBSD}
+ ,t_bsd
+ {$endif}
+ {$ifndef NOTARGETSUNOS}
+ ,t_sunos
+ {$endif}
+ {$ifndef NOTARGETEMX}
+ ,t_emx
+ {$endif}
+ {$ifndef NOTARGETOS2}
+ ,t_os2
+ {$endif}
+ {$ifndef NOTARGETWIN}
+ ,t_win
+ {$endif}
+ {$ifndef NOTARGETNETWARE}
+ ,t_nwm
+ {$endif}
+ {$ifndef NOTARGETNETWLIBC}
+ ,t_nwl
+ {$endif}
+ {$ifndef NOTARGETGO32V2}
+ ,t_go32v2
+ {$endif}
+ {$ifndef NOTARGETBEOS}
+ ,t_beos
+ {$endif}
+ {$ifndef NOTARGETWDOSX}
+ ,t_wdosx
+ {$endif}
+ {$ifndef NOTARGETWATCOM}
+ ,t_watcom
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAG386ATT}
+ ,agx86att
+ {$endif}
+ {$ifndef NOAG386NSM}
+ ,ag386nsm
+ {$endif}
+ {$ifndef NOAG386INT}
+ ,agx86int
+ {$endif}
+
+ ,ogcoff
+ ,ogelf
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRa386Int}
+ ,ra386int
+ {$endif NoRa386Int}
+ {$ifndef NoRa386Att}
+ ,ra386att
+ {$endif NoRa386Att}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+ ;
+
+end.
diff --git a/compiler/i386/csopt386.pas b/compiler/i386/csopt386.pas
new file mode 100644
index 0000000000..4ced3a816a
--- /dev/null
+++ b/compiler/i386/csopt386.pas
@@ -0,0 +1,2218 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ development team
+
+ This unit contains the common subexpression elimination procedure.
+
+ 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 CSOpt386;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses aasmbase,aasmtai,aasmcpu, cpuinfo, cpubase, optbase, cgbase;
+
+function CSE(asml: TAAsmoutput; first, last: tai; pass: longint): boolean;
+
+function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
+function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
+function storeBack(start, current: tai; orgReg, newReg: tsuperregister): boolean;
+function NoHardCodedRegs(p: taicpu; orgReg, newReg: tsuperregister): boolean;
+function RegSizesOK(oldReg,newReg: tsuperregister; p: taicpu): boolean;
+
+implementation
+
+uses
+{$ifdef csdebug}
+ cutils,
+{$else}
+ {$ifdef replaceregdebug}cutils,{$endif}
+{$endif}
+ globtype, verbose, procinfo, globals, daopt386, rgobj, rropt386,cgutils;
+
+{
+function TaiInSequence(P: tai; Const Seq: TContent): Boolean;
+var P1: tai;
+ Counter: Byte;
+ TmpResult: Boolean;
+begin
+ TmpResult := False;
+ P1 := Seq.StartMod;
+ Counter := 1;
+ while not(TmpResult) and
+ (Counter <= Seq.NrofMods) do
+ begin
+ if (P = P1) then TmpResult := True;
+ inc(Counter);
+ p1 := tai(p1.Next);
+ end;
+ TaiInSequence := TmpResult;
+end;
+}
+
+function modifiesConflictingMemLocation(p1: tai; supreg: tsuperregister; c: tregContent;
+ var regsStillValid: tregset; onlymem: boolean; var invalsmemwrite: boolean): boolean;
+var
+ p, hp: taicpu;
+ tmpRef: treference;
+ r,regCounter: tsuperregister;
+ opCount: longint;
+ dummy: boolean;
+begin
+ modifiesConflictingMemLocation := false;
+ invalsmemwrite := false;
+ if p1.typ <> ait_instruction then
+ exit;
+ p := taicpu(p1);
+ case p.opcode of
+ A_MOV,A_MOVSX,A_MOVZX:
+ if p.oper[1]^.typ = top_ref then
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if p.oper[0]^.typ<>top_reg then
+ break;
+ if writeToMemDestroysContents(getsupreg(p.oper[0]^.reg),p.oper[1]^.ref^,
+ regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end
+ else
+{ if is_reg_var[getsupreg(p.oper[1]^.reg)] then }
+ if not onlymem then
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end
+ end;
+ A_DIV, A_IDIV, A_MUL, A_IMUL:
+ begin
+ if not onlymem then
+ if (p.ops = 1) then
+ begin
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeToRegDestroysContents(RS_EDX,regCounter,c[regCounter]) then
+ begin
+ exclude(regsStillValid,RS_EDX);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if writeToRegDestroysContents(RS_EAX,regCounter,c[regCounter]) then
+ begin
+ exclude(regsStillValid,RS_EAX);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ end
+ end
+ else
+ { only possible for imul }
+ { last operand is always destination }
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[p.ops-1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end
+ end
+ end;
+ else
+ for opCount := 1 to maxinschanges do
+ case InsProp[p.opcode].Ch[opCount] of
+ Ch_MOp1,CH_WOp1,CH_RWOp1:
+ if not(onlymem) or
+ (p.oper[0]^.typ = top_ref) then
+{ or ((p.oper[0]^.typ = top_reg) and }
+{ is_reg_var[getsupreg(p.oper[0]^.reg)]) then }
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[0]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end;
+ Ch_MOp2,CH_WOp2,CH_RWOp2:
+ if not(onlymem) or
+ (p.oper[1]^.typ = top_ref) then
+{ or ((p.oper[1]^.typ = top_reg) and }
+{ is_reg_var[getsupreg(p.oper[1]^.reg)]) then }
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end;
+ Ch_MOp3,CH_WOp3,CH_RWOp3:
+ if not(onlymem) or
+ (p.oper[2]^.typ = top_ref) then
+{ or ((p.oper[2]^.typ = top_reg) and }
+{ is_reg_var[getsupreg(p.oper[2]^.reg)]) then }
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[2]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end;
+ Ch_WMemEDI:
+ begin
+ fillchar(tmpref,sizeof(tmpref),0);
+ tmpRef.base := NR_EDI;
+ tmpRef.index := NR_EDI;
+ for regCounter := RS_EAX to RS_EDI do
+ if writeToMemDestroysContents(RS_INVALID,tmpRef,regCounter,OS_32,c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end;
+ end;
+ end;
+end;
+
+
+function isSimpleMemLoc(const ref: treference): boolean;
+begin
+{ isSimpleMemLoc :=
+ (ref.index = RS_NO) and
+ not(ref.base in (rg.usableregsint+[RS_EDI]));}
+ isSimpleMemLoc :=
+ (ref.index = NR_NO) and
+ ((ref.base = NR_NO) or
+ not(getsupreg(ref.base) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]));
+end;
+
+
+{checks whether the current instruction sequence (starting with p) and the
+ one between StartMod and EndMod of Reg are the same. if so, the number of
+ instructions that match is stored in Found and true is returned, otherwise
+ Found holds the number of instructions between StartMod and EndMod and false
+ is returned}
+function CheckSequence(p: tai; var prev: tai; supreg: tsuperregister; var Found: Longint;
+ var reginfo: toptreginfo; findPrevSeqs: boolean): Boolean;
+
+var
+ regsNotRead, regsStillValid : tregset;
+ checkingPrevSequences,
+ passedFlagsModifyingInstr,
+ invalsmemwrite : boolean;
+
+ function getPrevSequence(p: tai; supreg: tsuperregister; currentPrev: tai; var newPrev: tai): tsuperregister;
+
+ const
+ current_reg: tsuperregister = RS_INVALID;
+
+ function stillValid(p: tai): boolean;
+ var
+ hp: tai;
+ begin
+ { only regvars are still used at jump instructions }
+ if (cs_regvars in aktglobalswitches) and
+ (p.typ = ait_instruction) and
+ taicpu(p).is_jmp then
+ regsstillvalid := regsstillvalid - ptaiprop(p.optinfo)^.usedregs;
+
+ stillValid :=
+ (p.typ = ait_instruction) and
+ (taicpu(p).opcode <> a_jmp) and
+ (ptaiprop(p.optinfo)^.regs[supreg].wstate =
+ ptaiprop(currentPrev.optinfo)^.regs[supreg].wstate) and
+ { in case destroyreg is called with doIncState = false }
+ (ptaiprop(p.optinfo)^.regs[supreg].typ =
+ ptaiprop(currentPrev.optinfo)^.regs[supreg].typ) and
+ (supreg in (regsNotRead * regsStillValid));
+ { stop if the register was still used right before a (conditional) }
+ { jump, since in that case its current contents could still be }
+ { used in the other path of the jump) }
+ if (p.typ = ait_instruction) and
+ (taicpu(p).is_jmp) and
+ getlastinstruction(p,hp) then
+ stillValid := stillValid and
+ not(supreg in ptaiprop(hp.optinfo)^.usedregs);
+ passedFlagsModifyingInstr := passedFlagsModifyingInstr or
+ instrWritesFlags(currentPrev);
+ end;
+
+
+ function findChangedRegister(p: tai): tsuperregister;
+ var
+ regCounter, loopstart: tsuperregister;
+ begin
+ if (current_reg <> RS_INVALID) then
+ loopstart := succ(current_reg)
+ else
+ loopstart := RS_EAX;
+ for regCounter := loopstart to RS_EDI do
+ with ptaiprop(p.optinfo)^.regs[regCounter] do
+ if ((startmod <>
+ ptaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or
+ (nrofMods <>
+ ptaiprop(currentPrev.optinfo)^.regs[regCounter].nrofMods)) and
+ (ptaiprop(p.optinfo)^.regs[regCounter].typ in [con_ref,con_noRemoveRef]) then
+ begin
+ findChangedRegister := regCounter;
+ current_reg := regCounter;
+ exit;
+ end;
+ current_reg := RS_INVALID;
+ findChangedRegister := RS_INVALID;
+ end;
+
+
+ var
+ hp, prevFound: tai;
+ tmpResult, regCounter: tsuperregister;
+ invalsmemwrite: boolean;
+ begin
+ if (current_reg <> RS_EDI) and
+ (current_reg <> RS_INVALID) then
+ begin
+ tmpResult := findChangedRegister(currentPrev);
+ if tmpResult <> RS_INVALID then
+ begin
+ getPrevSequence := tmpResult;
+ exit;
+ end;
+ end;
+
+ getPrevSequence := RS_INVALID;
+ passedFlagsModifyingInstr := passedFlagsModifyingInstr or
+ instrWritesFlags(currentPrev);
+ if (cs_regvars in aktglobalswitches) and
+ (currentprev.typ = ait_instruction) and
+ taicpu(currentprev).is_jmp then
+ regsstillvalid := regsstillvalid - ptaiprop(currentprev.optinfo)^.usedregs;
+
+ if not getLastInstruction(currentPrev,hp) then
+ exit;
+
+ prevFound := currentPrev;
+ tmpResult := RS_INVALID;
+
+ while (tmpResult = RS_INVALID) and
+ stillValid(hp) and
+ (ptaiprop(prevFound.optinfo)^.canBeRemoved or
+ not(modifiesConflictingMemLocation(prevFound,supreg,
+ ptaiprop(p.optinfo)^.regs,regsStillValid,false, invalsmemwrite))) do
+ begin
+ { only update the regsread for the instructions we already passed }
+ if not(ptaiprop(prevFound.optinfo)^.canBeRemoved) then
+ for regCounter := RS_EAX to RS_EDI do
+ if regReadByInstruction(regCounter,prevFound) then
+ exclude(regsNotRead,regCounter);
+
+ { in case getPreviousInstruction fails and sets hp to nil in the }
+ { next iteration }
+ prevFound := hp;
+ if not(ptaiprop(hp.optinfo)^.canBeRemoved) then
+ tmpResult := findChangedRegister(hp);
+ if not getLastInstruction(hp,hp) then
+ break;
+ end;
+ getPrevSequence := tmpResult;
+ if tmpResult <> RS_INVALID then
+ newPrev := prevFound;
+ end;
+
+
+ function getNextRegToTest(var prev: tai; currentReg: tsuperregister): tsuperregister;
+ begin
+ if not checkingPrevSequences then
+ begin
+ if (currentreg = RS_INVALID) then
+ currentreg := RS_EAX
+ else
+ inc(currentreg);
+ while (currentReg <= RS_EDI) and
+ not(ptaiprop(prev.optinfo)^.regs[currentReg].typ in [con_ref,con_noRemoveRef]) do
+ inc(currentReg);
+ if currentReg > RS_EDI then
+ begin
+ if (taicpu(p).oper[0]^.typ <> top_ref) or
+ isSimpleMemLoc(taicpu(p).oper[0]^.ref^) then
+ begin
+ checkingPrevSequences := true;
+ end
+ else
+ getNextRegToTest := RS_INVALID;
+ end
+ else
+ getNextRegToTest := currentReg;
+ end;
+ if checkingPrevSequences then
+ if findPrevSeqs then
+ getNextRegToTest :=
+ getPrevSequence(p,supreg,prev,prev)
+ else
+ getNextRegToTest := RS_INVALID;
+ end;
+
+
+ function changedreginvalidatedbetween(const oldreginfo: toptreginfo; var newreginfo: toptreginfo; startp,endp,current: tai): boolean;
+ var
+ orgdiffregs,diffregs: tregset;
+ runner: tai;
+ invalsmemwrite: boolean;
+ begin
+ diffregs := newreginfo.newregsencountered - oldreginfo.newregsencountered;
+ orgdiffregs := diffregs;
+ if diffregs <> [] then
+ begin
+ runner := startp;
+ repeat
+ modifiesConflictingMemLocation(runner,RS_EAX { dummy },ptaiprop(current.optinfo)^.regs,diffregs,true,invalsmemwrite);
+ if orgdiffregs <> diffregs then
+ begin
+ changedreginvalidatedbetween := true;
+ newreginfo := oldreginfo;
+ exit;
+ end;
+ getnextinstruction(runner,runner);
+ until (runner = endp);
+ end;
+ changedreginvalidatedbetween := false;
+ end;
+
+var
+ prevreginfo: toptreginfo;
+ hp2, hp3{, EndMod},highPrev, orgPrev, pprev: tai;
+ {Cnt,} OldNrofMods: Longint;
+ startRegInfo, OrgRegInfo, HighRegInfo: toptreginfo;
+ regModified, lastregloadremoved: array[RS_EAX..RS_ESP] of boolean;
+ HighFound, OrgRegFound: longint;
+ regcounter, regCounter2, tmpreg, base, index: tsuperregister;
+ OrgRegResult: Boolean;
+ TmpResult, flagResultsNeeded, stopchecking: Boolean;
+begin {CheckSequence}
+ TmpResult := False;
+ FillChar(OrgRegInfo, Sizeof(OrgRegInfo), 0);
+ FillChar(startRegInfo, sizeof(startRegInfo), 0);
+ OrgRegFound := 0;
+ HighFound := 0;
+ OrgRegResult := False;
+ with startRegInfo do
+ begin
+ newRegsEncountered := [RS_EBP, RS_ESP];
+ fillword(new2oldreg,sizeof(new2oldreg),RS_INVALID);
+ new2OldReg[RS_EBP] := RS_EBP;
+ new2OldReg[RS_ESP] := RS_ESP;
+ oldRegsEncountered := newRegsEncountered;
+ end;
+
+ checkingPrevSequences := false;
+ passedFlagsModifyingInstr := false;
+ flagResultsNeeded := false;
+ regsNotRead := [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESP,RS_EBP,RS_EDI,RS_ESI];
+ regsStillValid := regsNotRead;
+ GetLastInstruction(p, prev);
+ pprev := prev;
+ tmpreg:=RS_INVALID;
+ regCounter := getNextRegToTest(prev,tmpreg);
+ while (regcounter <> RS_INVALID) do
+ begin
+ fillchar(regModified,sizeof(regModified),0);
+ fillchar(lastregloadremoved,sizeof(lastregloadremoved),0);
+ reginfo := startRegInfo;
+ Found := 0;
+ hp2 := ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod;
+ if (prev <> ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod) then
+ OldNrofMods := ptaiprop(prev.optinfo)^.Regs[regcounter].NrofMods
+ else
+ OldNrofMods := 1;
+ hp3 := p;
+ if checkingprevsequences then
+ prevreginfo := reginfo;
+ stopchecking := false;
+ while (Found <> OldNrofMods) and
+ { old new }
+ InstructionsEquivalent(hp2, hp3, reginfo) and
+ (not(checkingprevsequences) or
+ not(changedreginvalidatedbetween(prevreginfo,reginfo,prev,p,hp3))) do
+ begin
+ if checkingprevsequences then
+ begin
+ prevreginfo := reginfo;
+ end;
+ if (hp3.typ = ait_instruction) and
+ ((taicpu(hp3).opcode = A_MOV) or
+ (taicpu(hp3).opcode = A_MOVZX) or
+ (taicpu(hp3).opcode = A_LEA) or
+ (taicpu(hp3).opcode = A_MOVSX)) and
+ (taicpu(hp3).oper[1]^.typ = top_reg) and
+ not(regInOp(getsupreg(taicpu(hp3).oper[1]^.reg),taicpu(hp3).oper[0]^)) then
+ begin
+ tmpreg := getsupreg(taicpu(hp3).oper[1]^.reg);
+ lastregloadremoved[tmpreg] := ptaiprop(hp2.optinfo)^.canberemoved;
+ reginfo.lastReload[tmpreg] := hp3;
+ case taicpu(hp3).oper[0]^.typ of
+ top_ref:
+ begin
+ base := getsupreg(taicpu(hp3).oper[0]^.ref^.base);
+ index := getsupreg(taicpu(hp3).oper[0]^.ref^.index);
+ if (found <> 0) and
+ ((taicpu(hp3).oper[0]^.ref^.base = NR_NO) or
+ regModified[base] or
+ (base = getsupreg(current_procinfo.framepointer))) and
+ ((taicpu(hp3).oper[0]^.ref^.index = NR_NO) or
+ regModified[index]) and
+ not(regInRef(tmpReg,taicpu(hp3).oper[0]^.ref^)) then
+ begin
+ with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
+ if nrofMods > (oldNrofMods - found) then
+ oldNrofMods := found + nrofMods;
+ { next is safe because instructions are equivalent }
+ with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
+ if nrofMods > (oldNrofMods - found) then
+ oldNrofMods := found + nrofMods;
+ end;
+ end;
+ top_reg:
+ if regModified[getsupreg(taicpu(hp3).oper[0]^.reg)] then
+ begin
+ with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
+ if nrofMods > (oldNrofMods - found) then
+ oldNrofMods := found + nrofMods;
+ with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
+ if nrofMods > (oldNrofMods - found) then
+ oldNrofMods := found + nrofMods;
+ end;
+ end;
+ end;
+ for regCounter2 := RS_EAX to RS_EDI do
+ regModified[regCounter2] := regModified[regCounter2] or
+ regModifiedByInstruction(regCounter2,hp3);
+ if flagResultsNeeded then
+ flagResultsNeeded := not instrReadsFlags(hp3);
+ if not flagResultsNeeded then
+ flagResultsNeeded := ptaiprop(hp3.optinfo)^.FlagsUsed;
+ inc(Found);
+ if (Found <> OldNrofMods) then
+ if not GetNextInstruction(hp2, hp2) or
+ not GetNextInstruction(hp3, hp3) then
+ break;
+ end;
+
+ getnextinstruction(hp3,hp3);
+{
+a) movl -4(%ebp),%edx
+ movl -12(%ebp),%ecx
+ ...
+ movl -8(%ebp),%eax
+ movl -12(%ebp),%edx (marked as removable)
+ movl (%eax,%edx),%eax (replaced by "movl (%eax,%ecx),%eax")
+ ...
+ movl -8(%ebp),%eax
+ movl -12(%ebp),%edx
+ movl (%eax,%edx),%eax
+ movl (%edx),%edx
+
+-> the "movl -12(ebp),%edx" can't be removed in the last sequence, because
+ edx has not been replaced with ecx there, and edx is still used after the
+ sequence
+
+b) tests/webtbs/tw4266.pp
+}
+
+ for regCounter2 := RS_EAX to RS_EDI do
+ if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
+ (regCounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
+ { case a) above }
+ ((not regLoadedWithNewValue(regCounter2,false,hp3) and
+ lastregloadremoved[regcounter2]) or
+ { case b) above }
+ ((ptaiprop(pprev.optinfo)^.regs[regcounter2].wstate <>
+ ptaiprop(hp2.optinfo)^.regs[regcounter2].wstate))) then
+ begin
+ found := 0;
+ end;
+
+ if checkingPrevSequences then
+ begin
+ for regCounter2 := RS_EAX to RS_EDI do
+ if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
+ (reginfo.new2OldReg[regCounter2] <> regCounter2) and
+ (not(regCounter2 in (regsNotRead * regsStillValid)) or
+ not(reginfo.new2OldReg[regCounter2] in regsStillValid)) then
+ begin
+ found := 0;
+ break;
+ end;
+ if passedFlagsModifyingInstr and flagResultsNeeded then
+ found := 0;
+ end;
+
+ TmpResult := true;
+ if (found <> OldNrofMods) then
+ TmpResult := false
+ else if assigned(hp3) then
+ for regcounter2 := RS_EAX to RS_EDI do
+ if (regcounter2 in reginfo.regsLoadedforRef) and
+ regModified[regcounter2] and
+ (regcounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
+ not regLoadedWithNewValue(regcounter2,false,hp3) then
+ begin
+ TmpResult := False;
+ if (found > 0) then
+ {this is correct because we only need to turn off the CanBeRemoved flag
+ when an instruction has already been processed by CheckSequence
+ (otherwise CanBeRemoved can't be true and thus can't have to be turned off).
+ if it has already been processed by CheckSequence and flagged to be
+ removed, it means that it has been checked against a previous sequence
+ and that it was equal (otherwise CheckSequence would have returned false
+ and the instruction wouldn't have been removed). if this "if found > 0"
+ check is left out, incorrect optimizations are performed.}
+ Found := ptaiprop(tai(p).optinfo)^.Regs[supreg].NrofMods;
+ break;
+ end;
+
+ if TmpResult and
+ (Found > HighFound) then
+ begin
+ highPrev := prev;
+ HighFound := Found;
+ HighRegInfo := reginfo;
+ end;
+ if (regcounter = supreg) then
+ begin
+ orgPrev := prev;
+ OrgRegFound := Found;
+ OrgRegResult := TmpResult;
+ OrgRegInfo := reginfo
+ end;
+ regCounter := getNextRegToTest(prev,regCounter);
+ end;
+ if (HighFound > 0) and
+ (not(OrgRegResult) Or
+ (HighFound > OrgRegFound))
+ then
+ begin
+{$ifndef fpc}
+ TmpResult := True;
+{$else fpc}
+ CheckSequence := True;
+{$endif fpc}
+ prev := highPrev;
+ reginfo := HighRegInfo;
+ Found := HighFound
+ end
+ else
+ begin
+{$ifndef fpc}
+ TmpResult := OrgRegResult;
+{$else fpc}
+ CheckSequence := OrgRegResult;
+{$endif fpc}
+ prev := orgPrev;
+ Found := OrgRegFound;
+ reginfo := OrgRegInfo;
+ end;
+{$ifndef fpc}
+ CheckSequence := TmpResult;
+{$endif fpc}
+end; {CheckSequence}
+
+
+procedure SetAlignReg(p: tai);
+Const alignSearch = 12;
+var regsUsable: TRegSet;
+ prevInstrCount, nextInstrCount: Longint;
+ prevState, nextWState,nextRState: Array[RS_EAX..RS_EDI] of byte;
+ regCounter, lastRemoved: tsuperregister;
+ prev, next: tai;
+{$ifdef alignregdebug}
+ temp: tai;
+{$endif alignregdebug}
+begin
+ regsUsable := [RS_EAX,RS_ECX,RS_EDX,RS_EBX,{R_ESP,RS_EBP,}RS_ESI,RS_EDI];
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ prevState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].wState;
+ nextWState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].wState;
+ nextRState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].rState;
+ end;
+ getLastInstruction(p,prev);
+ getNextInstruction(p,next);
+ lastRemoved := getsupreg(tai_align(p).reg);
+ nextInstrCount := 0;
+ prevInstrCount := 0;
+ while ((assigned(prev) and
+ assigned(prev.optinfo) and
+ (prevInstrCount < alignSearch)) or
+ (assigned(next) and
+ assigned(next.optinfo) and
+ (nextInstrCount < alignSearch))) and
+ (regsUsable <> []) do
+ begin
+{$ifdef alignregdebug}
+ if assigned(prev) then
+ begin
+ temp := tai_comment.Create(strpnew('got here'));
+ temp.next := prev.next;
+ temp.previous := prev;
+ prev.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ end;
+{$endif alignregdebug}
+ if assigned(prev) and assigned(prev.optinfo) and
+ (prevInstrCount < alignSearch) then
+ begin
+ if (prev.typ = ait_instruction) and
+ (insProp[taicpu(prev).opcode].ch[1] <> Ch_ALL) and
+ (taicpu(prev).opcode <> A_JMP) then
+ begin
+ inc(prevInstrCount);
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if (regCounter in regsUsable) and
+ (ptaiprop(prev.optinfo)^.Regs[regCounter].wState <>
+ prevState[regCounter]) then
+ begin
+ lastRemoved := regCounter;
+ exclude(regsUsable,regCounter);
+{$ifdef alignregdebug}
+ temp := tai_comment.Create(strpnew(
+ std_regname(newreg(R_INTREGISTER,regCounter,R_SUBWHOLE))+' removed')));
+ temp.next := prev.next;
+ temp.previous := prev;
+ prev.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ if regsUsable = [] then
+ begin
+ temp := tai_comment.Create(strpnew(
+ 'regsUsable empty here')));
+ temp.next := prev.next;
+ temp.previous := prev;
+ prev.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ end;
+{$endif alignregdebug}
+ end;
+ prevState[regCounter] :=
+ ptaiprop(prev.optinfo)^.Regs[regCounter].wState;
+ end;
+ getLastInstruction(prev,prev);
+ end
+ else
+ if GetLastInstruction(prev,prev) and
+ assigned(prev.optinfo) then
+ for regCounter := RS_EAX to RS_EDI do
+ prevState[regCounter] :=
+ ptaiprop(prev.optinfo)^.Regs[regCounter].wState
+ end;
+ if assigned(next) and assigned(next.optinfo) and
+ (nextInstrCount < alignSearch) then
+ begin
+ if (next.typ = ait_instruction) and
+ (insProp[taicpu(next).opcode].ch[1] <> Ch_ALL) and
+ (taicpu(next).opcode <> A_JMP) then
+ begin
+ inc(nextInstrCount);
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if (regCounter in regsUsable) and
+ ((ptaiprop(next.optinfo)^.Regs[regCounter].wState <>
+ nextWState[regCounter]) or
+ (ptaiprop(next.optinfo)^.Regs[regCounter].rState <>
+ nextRState[regCounter])) then
+ begin
+ lastRemoved := regCounter;
+ exclude(regsUsable,regCounter);
+{$ifdef alignregdebug}
+ temp := tai_comment.Create(strpnew(
+ std_regname(newreg(R_INTREGISTER,regCounter,R_SUBWHOLE))+' removed')));
+ temp.next := next.next;
+ temp.previous := next;
+ next.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ if regsUsable = [] then
+ begin
+ temp := tai_comment.Create(strpnew(
+ 'regsUsable empty here')));
+ temp.next := next.next;
+ temp.previous := next;
+ next.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ end;
+{$endif alignregdebug}
+ end;
+ nextWState[regCounter] :=
+ ptaiprop(next.optinfo)^.Regs[regCounter].wState;
+ nextRState[regCounter] :=
+ ptaiprop(next.optinfo)^.Regs[regCounter].rState;
+ end
+ end
+ else
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ nextWState[regCounter] :=
+ ptaiprop(next.optinfo)^.Regs[regCounter].wState;
+ nextRState[regCounter] :=
+ ptaiprop(next.optinfo)^.Regs[regCounter].rState;
+ end;
+ getNextInstruction(next,next);
+ end;
+ end;
+ if regsUsable <> [] then
+ for regCounter := RS_EAX to RS_EDI do
+ if regCounter in regsUsable then
+ begin
+ lastRemoved := regCounter;
+ break
+ end;
+{$ifdef alignregdebug}
+ next := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,lastremoved,R_SUBWHOLE))+
+ ' chosen as alignment register')));
+ next.next := p.next;
+ next.previous := p;
+ p.next := next;
+ if assigned(next.next) then
+ next.next.previous := next;
+{$endif alignregdebug}
+ tai_align(p).reg := newreg(R_INTREGISTER,lastRemoved,R_SUBWHOLE);
+end;
+
+
+procedure clearmemwrites(p: tai; supreg: tsuperregister);
+var
+ beginmemwrite: tai;
+begin
+ beginmemwrite := ptaiprop(p.optinfo)^.regs[supreg].memwrite;
+ repeat
+ ptaiprop(p.optinfo)^.regs[supreg].memwrite := nil;
+ until not getnextinstruction(p,p) or
+ (ptaiprop(p.optinfo)^.regs[supreg].memwrite <> beginmemwrite);
+end;
+
+
+procedure ClearRegContentsFrom(supreg: tsuperregister; p, endP: tai);
+{ first clears the contents of reg from p till endP. then the contents are }
+{ cleared until the first instruction that changes reg }
+var
+{$ifdef replaceregdebug}
+ hp: tai;
+ l: longint;
+{$endif replaceregdebug}
+ regcounter: tsuperregister;
+ oldStartmod: tai;
+begin
+{$ifdef replaceregdebug}
+ l := random(1000);
+ hp := tai_comment.Create(strpnew(
+ 'cleared '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' from here... '+tostr(l)));
+ hp.next := p;
+ hp.previous := p.previous;
+ p.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;
+{$endif replaceregdebug}
+ ptaiprop(p.optinfo)^.Regs[supreg].typ := con_unknown;
+ while (p <> endP) do
+ begin
+ for regcounter := RS_EAX to RS_EDI do
+ if (regcounter <> supreg) and
+ assigned(ptaiprop(p.optinfo)^.regs[supreg].memwrite) and
+ reginref(regcounter,ptaiprop(p.optinfo)^.regs[supreg].memwrite.oper[1]^.ref^) then
+ clearmemwrites(p,regcounter);
+ with ptaiprop(p.optinfo)^.Regs[supreg] do
+ begin
+ typ := con_unknown;
+ memwrite := nil;
+ end;
+ getNextInstruction(p,p);
+ end;
+ oldStartmod := ptaiprop(p.optinfo)^.Regs[supreg].startmod;
+ repeat
+ with ptaiprop(p.optinfo)^.Regs[supreg] do
+ begin
+ typ := con_unknown;
+ memwrite := nil;
+ end;
+ until not getNextInstruction(p,p) or
+ (ptaiprop(p.optinfo)^.Regs[supreg].startmod <> oldStartmod);
+{$ifdef replaceregdebug}
+ if assigned(p) then
+ begin
+ hp := tai_comment.Create(strpnew(
+ 'cleared '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' till here... '+tostr(l)));
+ hp.next := p;
+ hp.previous := p.previous;
+ p.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;
+ end;
+{$endif replaceregdebug}
+end;
+
+procedure RestoreRegContentsTo(supreg: tsuperregister; const c: TContent; p, endP: tai);
+var
+{$ifdef replaceregdebug}
+ l: longint;
+{$endif replaceregdebug}
+ hp: tai;
+ dummyregs: tregset;
+ tmpState, newrstate: byte;
+ prevcontenttyp: byte;
+ memconflict: boolean;
+ invalsmemwrite: boolean;
+begin
+{$ifdef replaceregdebug}
+ l := random(1000);
+ hp := tai_comment.Create(strpnew(
+ 'restored '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' with data from here... '+tostr(l)));
+ hp.next := p;
+ hp.previous := p.previous;
+ p.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;
+{$endif replaceregdebug}
+{ ptaiprop(p.optinfo)^.Regs[reg] := c;}
+ newrstate := c.rstate;
+ incstate(newrstate,$7f);
+ while (p <> endP) do
+ begin
+ if not(ptaiprop(p.optinfo)^.canberemoved) and
+ regreadbyinstruction(supreg,p) then
+ incstate(newrstate,1);
+ ptaiprop(p.optinfo)^.Regs[supreg] := c;
+ ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
+ getNextInstruction(p,p);
+ end;
+ tmpState := ptaiprop(p.optinfo)^.Regs[supreg].wState;
+ if (newrstate = ptaiprop(p.optinfo)^.Regs[supreg].rState) then
+ begin
+ incstate(ptaiprop(p.optinfo)^.regs[supreg].rstate,63);
+ if not getnextinstruction(p,hp) then
+ exit;
+ if (ptaiprop(hp.optinfo)^.regs[supreg].rstate = ptaiprop(p.optinfo)^.regs[supreg].rstate) then
+ internalerror(2004122710);
+ end;
+ dummyregs := [supreg];
+ repeat
+ newrstate := ptaiprop(p.optinfo)^.Regs[supreg].rState;
+ prevcontenttyp := ptaiprop(p.optinfo)^.Regs[supreg].typ;
+ // is this a write to memory that destroys the contents we are restoring?
+ memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,dummyregs,true,invalsmemwrite);
+ if not memconflict and not invalsmemwrite then
+ begin
+ ptaiprop(p.optinfo)^.Regs[supreg] := c;
+ ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
+ end;
+ until invalsmemwrite or
+ memconflict or
+ not getNextInstruction(p,p) or
+ (ptaiprop(p.optinfo)^.Regs[supreg].wState <> tmpState) or
+ (p.typ = ait_label) or
+ ((prevcontenttyp <> con_invalid) and
+ (ptaiprop(p.optinfo)^.Regs[supreg].typ = con_invalid));
+ if assigned(p) and
+ (p.typ <> ait_marker) then
+ if ((p.typ = ait_label) or
+ memconflict or
+ invalsmemwrite) then
+ clearRegContentsFrom(supreg,p,p)
+ else if (ptaiprop(p.optinfo)^.Regs[supreg].rstate = newrstate) then
+ incstate(ptaiprop(p.optinfo)^.Regs[supreg].rstate,20);
+{$ifdef replaceregdebug}
+ if assigned(p) then
+ begin
+ hp := tai_comment.Create(strpnew(
+ 'restored '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' till here... '+tostr(l)));
+ hp.next := p;
+ hp.previous := p.previous;
+ p.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;
+ end;
+{$endif replaceregdebug}
+end;
+
+function NoHardCodedRegs(p: taicpu; orgReg, newReg: tsuperregister): boolean;
+var
+ chCount: byte;
+begin
+ case p.opcode of
+ A_IMUL: noHardCodedRegs := p.ops <> 1;
+ A_SHL,A_SHR,A_SHLD,A_SHRD: noHardCodedRegs :=
+ (p.oper[0]^.typ <> top_reg) or
+ ((orgReg <> RS_ECX) and (newReg <> RS_ECX));
+ else
+ begin
+ NoHardCodedRegs := true;
+ with InsProp[p.opcode] do
+ for chCount := 1 to maxinschanges do
+ if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
+ begin
+ NoHardCodedRegs := false;
+ break
+ end;
+ end;
+ end;
+end;
+
+
+function ChangeReg(var Reg: TRegister; newReg, orgReg: tsuperregister): boolean;
+begin
+ changereg := false;
+ if (reg <> NR_NO) and
+ (getregtype(reg) = R_INTREGISTER) and
+ (getsupreg(reg) = newreg) then
+ begin
+ changereg := true;
+ setsupreg(reg,orgreg);
+ end;
+end;
+
+
+function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
+var
+ tmpresult: boolean;
+begin
+ changeOp := false;
+ case o.typ of
+ top_reg: changeOp := changeReg(o.reg,newReg,orgReg);
+ top_ref:
+ begin
+ tmpresult := changeReg(o.ref^.base,newReg,orgReg);
+ changeop := changeReg(o.ref^.index,newReg,orgReg) or tmpresult;
+ end;
+ end;
+end;
+
+
+procedure updateStates(orgReg,newReg: tsuperregister; hp: tai; writeStateToo: boolean);
+var
+ prev: tai;
+ newOrgRegRState, newOrgRegWState: byte;
+begin
+ if getLastInstruction(hp,prev) then
+ with ptaiprop(prev.optinfo)^ do
+ begin
+ newOrgRegRState := byte(longint(regs[orgReg].rState) +
+ longint(ptaiprop(hp.optinfo)^.regs[newReg].rState) - regs[newReg].rstate);
+ if writeStateToo then
+ newOrgRegWState := byte(longint(regs[orgReg].wState) +
+ longint(ptaiprop(hp.optinfo)^.regs[newReg].wState) - regs[newReg].wstate);
+ end
+ else
+ with ptaiprop(hp.optinfo)^.regs[newReg] do
+ begin
+ newOrgRegRState := rState;
+ if writeStateToo then
+ newOrgRegWState := wState;
+ end;
+ with ptaiprop(hp.optinfo)^.regs[orgReg] do
+ begin
+ rState := newOrgRegRState;
+ if writeStateToo then
+ wState := newOrgRegwState;
+ end;
+end;
+
+
+function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
+var
+ opCount: longint;
+ tmpResult: boolean;
+begin
+ tmpresult := false;
+ for opCount := 0 to hp.ops-1 do
+ tmpResult :=
+ changeOp(hp.oper[opCount]^,newReg,orgReg) or tmpResult;
+ doReplaceReg := tmpResult;
+end;
+
+
+function RegSizesOK(oldReg,newReg: tsuperregister; p: taicpu): boolean;
+{ oldreg and newreg must be 32bit components }
+var
+ opCount: longint;
+ tmpreg: tsuperregister;
+begin
+ RegSizesOK := true;
+ { if only one of them is a general purpose register ... }
+ if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
+ begin
+ for opCount := 0 to p.ops-1 do
+ if (p.oper[opCount]^.typ = top_reg) and
+ (getsubreg(p.oper[opCount]^.reg) in [R_SUBL,R_SUBH]) then
+ begin
+ tmpreg := getsupreg(p.oper[opCount]^.reg);
+ if (tmpreg = oldreg) or
+ (tmpreg = newreg) then
+ begin
+ RegSizesOK := false;
+ break
+ end
+ end;
+ end;
+end;
+
+
+function doReplaceReadReg(p: taicpu; newReg,orgReg: tsuperregister): boolean;
+var
+ opCount: longint;
+begin
+ doReplaceReadReg := false;
+ { handle special case }
+ case p.opcode of
+ A_IMUL:
+ begin
+ case p.ops of
+ 1: internalerror(1301001);
+ 2,3:
+ begin
+ if changeOp(p.oper[0]^,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ if p.ops = 3 then
+ if changeOp(p.oper[1]^,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ end;
+ end;
+ end;
+ A_DIV,A_IDIV,A_MUL: internalerror(1301002);
+ else
+ begin
+ for opCount := 0 to p.ops-1 do
+ if p.oper[opCount]^.typ = top_ref then
+ if changeOp(p.oper[opCount]^,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ for opCount := 1 to maxinschanges do
+ case InsProp[p.opcode].Ch[opCount] of
+ Ch_ROp1:
+ if p.oper[0]^.typ = top_reg then
+ if changeReg(p.oper[0]^.reg,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ Ch_ROp2:
+ if p.oper[1]^.typ = top_reg then
+ if changeReg(p.oper[1]^.reg,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ Ch_ROp3:
+ if p.oper[2]^.typ = top_reg then
+ if changeReg(p.oper[2]^.reg,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+procedure updateState(supreg: tsuperregister; p: tai);
+{ this procedure updates the read and write states of the instructions }
+{ coming after p. It's called when the read/write state of p has been }
+{ changed and this change has to be propagated to the following }
+{ instructions as well }
+var
+ newRState, newWState: byte;
+ prevRState, prevWState: byte;
+ doRState, doWState: boolean;
+begin
+ { get the new read/write states from p }
+ with ptaiprop(p.optinfo)^.regs[supreg] do
+ begin
+ newRState := rState;
+ newWState := wState;
+ end;
+ if not GetNextInstruction(p,p) then
+ exit;
+ { get the old read/write states from the next instruction, to know }
+ { when we can stop updating }
+ with ptaiprop(p.optinfo)^.regs[supreg] do
+ begin
+ prevRState := rState;
+ prevWState := wState;
+ end;
+ { adjust the states if this next instruction reads/writes the register }
+ if regReadByInstruction(supreg,p) then
+ incState(newRState,1);
+ if regModifiedByInstruction(supreg,p) then
+ incState(newWState,1);
+ { do we still have to update the read and/or write states? }
+ doRState := true;
+ doWState := true;
+ repeat
+ { update the states }
+ with ptaiprop(p.optinfo)^.regs[supreg] do
+ begin
+ if doRState then
+ rState := newRState;
+ if doWState then
+ wState := newWState;
+ end;
+ if not getNextInstruction(p,p) then
+ break;
+ with ptaiprop(p.optinfo)^.regs[supreg] do
+ begin
+ { stop updating the read state if it changes }
+ doRState :=
+ doRState and (rState = prevRState);
+ { if, by accident, this changed state is the same as the one }
+ { we've been using, change it to a value that's definitely }
+ { different from the previous and next state }
+ if not doRState and
+ (rState = newRState) then
+ begin
+ incState(newRState,1);
+ prevRState := rState;
+ doRState := true;
+ end;
+ { ditto for the write state }
+ doWState :=
+ doWState and (WState = prevWState);
+ if not doWState and
+ (wState = newWState) then
+ begin
+ incState(newWState,1);
+ prevWState := wState;
+ doWState := true;
+ end;
+ end;
+ { stop when we don't have to update either state anymore }
+ until not(doRState or doWState);
+end;
+
+
+function storeBack(start, current: tai; orgReg, newReg: tsuperregister): boolean;
+{ returns true if p1 contains an instruction that stores the contents }
+{ of newReg back to orgReg }
+begin
+ storeback := false;
+ if (current.typ = ait_instruction) and
+ (taicpu(current).opcode = A_MOV) and
+ (taicpu(current).oper[0]^.typ = top_reg) and
+ (getsupreg(taicpu(current).oper[0]^.reg) = newReg) and
+ (taicpu(current).oper[1]^.typ = top_reg) and
+ (getsupreg(taicpu(current).oper[1]^.reg) = orgReg) then
+ case taicpu(current).opsize of
+ S_B:
+ storeback := true;
+ S_W:
+ storeback := taicpu(start).opsize <> S_B;
+ S_L:
+ storeback := taicpu(start).opsize = S_L;
+ else
+ internalerror(2003121501);
+ end;
+end;
+
+
+function canreplacereg(orgsupreg, newsupreg: tsuperregister; p: tai;
+ orgRegCanBeModified: boolean; var resnewregmodified, resorgregread, resremovelast: boolean; var returnendp: tai): boolean;
+var
+ endP, hp: tai;
+ removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: boolean;
+begin
+ canreplacereg := false;
+ tmpResult := true;
+ sequenceEnd := false;
+ newRegModified := false;
+ orgRegRead := false;
+ removeLast := false;
+ endP := p;
+ while tmpResult and not sequenceEnd do
+ begin
+ tmpResult :=
+ getNextInstruction(endP,endP) and
+ (endp.typ = ait_instruction) and
+ not(taicpu(endp).is_jmp);
+ if tmpresult and not assigned(endp.optinfo) then
+ begin
+{ hp := tai_comment.Create(strpnew('next no optinfo'));
+ hp.next := endp;
+ hp.previous := endp.previous;
+ endp.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;}
+ exit;
+ end;
+ if tmpResult and
+ { don't take into account instructions that will be removed }
+ not (ptaiprop(endp.optinfo)^.canBeRemoved) then
+ begin
+ { if the newsupreg gets stored back to the oldReg, we can change }
+ { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
+ { %oldReg" to "<operations on %oldReg>" }
+ removeLast := storeBack(p,endP, orgsupreg, newsupreg);
+ sequenceEnd :=
+ { no support for (i)div, mul and imul with hardcoded operands }
+ noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
+ { if newsupreg gets loaded with a new value, we can stop }
+ { replacing newsupreg with oldReg here (possibly keeping }
+ { the original contents of oldReg so we still know them }
+ { afterwards) }
+ (RegLoadedWithNewValue(newsupreg,true,taicpu(endP)) or
+ { we can also stop if we reached the end of the use of }
+ { newReg's current contents }
+ (GetNextInstruction(endp,hp) and
+ FindRegDealloc(newsupreg,hp)));
+ { to be able to remove the first and last instruction of }
+ { movl %reg1, %reg2 }
+ { <operations on %reg2> (replacing reg2 with reg1 here) }
+ { movl %reg2, %reg1 }
+ { %reg2 must not be use afterwards (it can be as the }
+ { result of a peepholeoptimization) }
+ removeLast := removeLast and sequenceEnd;
+ newRegModified :=
+ newRegModified or
+ (not(regLoadedWithNewValue(newsupreg,true,taicpu(endP))) and
+ RegModifiedByInstruction(newsupreg,endP));
+ orgRegRead := newRegModified and RegReadByInstruction(orgsupreg,endP);
+ sequenceEnd := SequenceEnd and
+ (removeLast or
+ { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
+ { gets modified if orgsupreg is still read afterwards (since after }
+ { replacing, this would mean that orgsupreg first gets modified and then }
+ { gets read in the assumption it still contains the unmodified value) }
+ not(newRegModified and orgRegRead)) (* and
+ { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
+ { gets modified if orgRegCanBeModified = false }
+
+ { this now gets checked after the loop (JM) }
+ (orgRegCanBeModified or not(newRegModified)) *);
+ tmpResult :=
+ not(removeLast) and
+ not(newRegModified and orgRegRead) and
+(* (orgRegCanBeModified or not(newRegModified)) and *)
+(* already checked at the top
+ (endp.typ = ait_instruction) and *)
+ NoHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
+ RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
+ not RegModifiedByInstruction(orgsupreg,endP);
+ end;
+ end;
+ canreplacereg := sequenceEnd and
+ (removeLast or
+ (orgRegCanBeModified or not(newRegModified))) and
+ (not(assigned(endp)) or
+ not(endp.typ = ait_instruction) or
+ (noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
+ RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
+ not(newRegModified and
+ (orgsupreg in ptaiprop(endp.optinfo)^.usedRegs) and
+ not(RegLoadedWithNewValue(orgsupreg,true,taicpu(endP))))));
+ if canreplacereg then
+ begin
+ resnewregmodified := newregmodified;
+ resorgregread := orgregread;
+ resremovelast := removelast;
+ returnendp := endp;
+ end;
+end;
+
+
+
+function ReplaceReg(asml: TAAsmOutput; orgsupreg, newsupreg: tsuperregister; p,
+ seqstart: tai; const c: TContent; orgRegCanBeModified: Boolean;
+ var returnEndP: tai): Boolean;
+{ Tries to replace orgsupreg with newsupreg in all instructions coming after p }
+{ until orgsupreg gets loaded with a new value. Returns true if successful, }
+{ false otherwise. if successful, the contents of newsupreg are set to c, }
+{ which should hold the contents of newsupreg before the current sequence }
+{ started }
+{ if the function returns true, returnEndP holds the last instruction }
+{ where newsupreg was replaced by orgsupreg }
+var
+ endP, hp: tai;
+ removeLast, sequenceEnd, newRegModified, orgRegRead,
+ stateChanged, readStateChanged: Boolean;
+
+begin
+ replacereg := false;
+ if canreplacereg(orgsupreg,newsupreg,p,orgregcanbemodified,newregmodified, orgregread, removelast,endp) then
+ begin
+{$ifdef replaceregdebug}
+ hp := tai_comment.Create(strpnew(
+ 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
+ ' from here...'));
+ hp.next := p;
+ hp.previous := p.previous;
+ p.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;
+
+ hp := tai_comment.Create(strpnew(
+ 'replaced '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
+ ' till here'));
+ hp.next := endp.next;
+ hp.previous := endp;
+ endp.next := hp;
+ if assigned(hp.next) then
+ hp.next.previous := hp;
+{$endif replaceregdebug}
+ replaceReg := true;
+ returnEndP := endP;
+
+ if not getNextInstruction(p,hp) then
+ exit;
+ stateChanged := false;
+ while hp <> endP do
+ begin
+ if {not(ptaiprop(hp.optinfo)^.canBeRemoved) and }
+ (hp.typ = ait_instruction) then
+ stateChanged :=
+ doReplaceReg(taicpu(hp),newsupreg,orgsupreg) or stateChanged;
+ if stateChanged then
+ updateStates(orgsupreg,newsupreg,hp,true);
+ getNextInstruction(hp,hp)
+ end;
+ if assigned(endp) and (endp.typ = ait_instruction) then
+ readStateChanged :=
+ doReplaceReadReg(taicpu(endP),newsupreg,orgsupreg);
+ if stateChanged or readStateChanged then
+ updateStates(orgsupreg,newsupreg,endP,stateChanged);
+
+ if stateChanged or readStateChanged then
+ updateState(orgsupreg,endP);
+
+{ We replaced newreg with oldreg between p and endp, so restore the contents }
+{ of newreg there with its contents from before the sequence. }
+ if removeLast or
+ RegLoadedWithNewValue(newsupreg,true,endP) then
+ GetLastInstruction(endP,hp)
+ else hp := endP;
+ RestoreRegContentsTo(newsupreg,c,seqstart,hp);
+
+{ Ot is possible that the new register was modified (e.g. an add/sub), so if }
+{ it was replaced by oldreg in that instruction, oldreg's contents have been }
+{ changed. To take this into account, we simply set the contents of orgsupreg }
+{ to "unknown" after this sequence }
+ if newRegModified then
+ ClearRegContentsFrom(orgsupreg,p,hp);
+ if removeLast then
+ ptaiprop(endp.optinfo)^.canBeRemoved := true;
+ allocRegBetween(asml,newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE),p,endP,ptaiprop(p.optinfo)^.usedregs);
+
+ end
+{$ifdef replaceregdebug}
+ else
+ begin
+ hp := tai_comment.Create(strpnew(
+ 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
+ ' from here...'));
+ hp.previous := p.previous;
+ hp.next := p;
+ p.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;
+
+ hp := tai_comment.Create(strpnew(
+ 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
+ ' failed here'));
+ hp.next := endp.next;
+ hp.previous := endp;
+ endp.next := hp;
+ if assigned(hp.next) then
+ hp.next.previous := hp;
+ end;
+{$endif replaceregdebug}
+end;
+
+
+function FindRegWithConst(p: tai; size: topsize; l: aint; var Res: TRegister): Boolean;
+{Finds a register which contains the constant l}
+var
+ Counter: tsuperregister;
+{$ifdef testing}
+ hp: tai;
+{$endif testing}
+begin
+ Result:=false;
+ Counter := RS_EAX;
+ repeat
+{$ifdef testing}
+ if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
+ begin
+ hp := tai_comment.Create(strpnew(
+ 'checking const load of '+tostr(l)+' here...'));
+ hp.next := ptaiprop(p.optinfo)^.Regs[Counter].StartMod;
+ hp.previous := ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous;
+ ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;
+ end;
+{$endif testing}
+ if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) and
+ (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).opsize = size) and
+ (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.typ = top_const) and
+ (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.val = l) then
+ begin
+ res:=taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[1]^.reg;
+ result:=true;
+ exit;
+ end;
+ inc(counter);
+ until (Counter > RS_EDI);
+end;
+
+
+procedure removePrevNotUsedLoad(p: tai; supreg: tsuperregister; check: boolean);
+{ if check = true, it means the procedure has to check whether it isn't }
+{ possible that the contents are still used after p (used when removing }
+{ instructions because of a "call"), otherwise this is not necessary }
+{ (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
+{ value of %eax isn't used anymore later on) }
+var
+ hp1, next, beforestartmod: tai;
+begin
+ if getLastInstruction(p,hp1) then
+ with ptaiprop(hp1.optinfo)^.regs[supreg] do
+ if (typ in [con_ref,con_invalid,con_const]) and
+ (nrofMods = 1) and
+ (rState = ptaiprop(startmod.optinfo)^.regs[supreg].rState) and
+ (not(check) or
+ (not(regInInstruction(supreg,p)) and
+ (not(supreg in ptaiprop(hp1.optinfo)^.usedRegs) or
+ findRegDealloc(supreg,p)))) then
+ begin
+ ptaiprop(startMod.optinfo)^.canBeRemoved := true;
+ getnextinstruction(p,next);
+ { give the register that was modified by this instruction again }
+ { the contents it had before this instruction }
+ if getlastinstruction(startmod,beforestartmod) then
+ RestoreRegContentsTo(supreg,ptaiprop(beforestartmod.optinfo)^.regs[supreg],
+ startmod,hp1)
+ else
+ ClearRegContentsFrom(supreg,startmod,hp1);
+ end;
+end;
+
+
+{$ifdef notused}
+function is_mov_for_div(p: taicpu): boolean;
+begin
+ is_mov_for_div :=
+ (p.opcode = A_MOV) and
+ (p.oper[0]^.typ = top_const) and
+ (p.oper[1]^.typ = top_reg) and
+ (p.oper[1]^.reg = RS_EDX) and
+ getNextInstruction(p,p) and
+ (p.typ = ait_instruction) and
+ ((p.opcode = A_DIV) or
+ (p.opcode = A_IDIV));
+end;
+{$endif notused}
+
+
+function memtoreg(t: taicpu; const ref: treference; var startp: tai): tregister;
+var
+ hp: tai;
+ p: ptaiprop;
+ regcounter: tsuperregister;
+ optimizable: boolean;
+begin
+ if not getlastinstruction(t,hp) or
+ not issimplememloc(ref) then
+ begin
+ memtoreg := NR_NO;
+ exit;
+ end;
+ p := ptaiprop(hp.optinfo);
+ optimizable := false;
+ for regcounter := RS_EAX to RS_EDI do
+ begin
+ if (assigned(p^.regs[regcounter].memwrite) and
+ refsequal(ref,p^.regs[regcounter].memwrite.oper[1]^.ref^)) then
+ begin
+ optimizable := true;
+ hp := p^.regs[regcounter].memwrite;
+ end
+ else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
+ (p^.regs[regcounter].nrofmods = 1) and
+ ((taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
+ (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
+ (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
+ (taicpu(p^.regs[regcounter].startmod).oper[0]^.typ = top_ref) and
+ refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0]^.ref^)) then
+ begin
+ optimizable := true;
+ hp := p^.regs[regcounter].startmod;
+ end;
+ if optimizable then
+ if ((t.opsize <> S_B) or
+ not(regcounter in [RS_ESI,RS_EDI])) and
+ sizescompatible(taicpu(hp).opsize,t.opsize) then
+ begin
+ case t.opsize of
+ S_B:
+ begin
+ memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBL)
+ end;
+ S_W,S_BW:
+ begin
+ memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBW);
+ if (t.opsize = S_BW) then
+ begin
+ t.opcode := A_MOV;
+ t.opsize := S_W;
+ end;
+ end;
+ S_L,S_BL,S_WL:
+ begin
+ memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBWHOLE);
+ if (t.opsize <> S_L) then
+ begin
+ t.opcode := A_MOV;
+ t.opsize := S_L;
+ end;
+ end;
+ end;
+ startp := hp;
+ exit;
+ end;
+ end;
+ memtoreg := NR_NO;
+end;
+
+
+procedure removeLocalStores(const t1: tai);
+{var
+ p: tai;
+ regcount: tregister; }
+begin
+{
+ for regcount := LoGPReg to HiGPReg do
+ if assigned(pTaiProp(t1.optinfo)^.regs[regcount].memwrite) and
+ (taicpu(pTaiProp(t1.optinfo)^.regs[regcount].memwrite).oper[1]^.ref^.base
+ = current_procinfo.framepointer) then
+ begin
+ pTaiProp(pTaiProp(t1.optinfo)^.regs[regcount].memwrite.optinfo)^.canberemoved := true;
+ clearmemwrites(pTaiProp(t1.optinfo)^.regs[regcount].memwrite,regcount);
+ end;
+}
+end;
+
+
+procedure loadcseregs(asml: taasmoutput; const reginfo: toptreginfo; curseqend, prevseqstart, curseqstart, curprev: tai; cnt: longint);
+var
+ regsloaded: tregset;
+ regloads, reguses: array[RS_EAX..RS_EDI] of tai;
+ regcounter, substreg: tsuperregister;
+ hp, hp2: tai;
+ insertpos, prevseq_next: tai;
+ i: longint;
+ opc: tasmop;
+begin
+ regsloaded := [];
+ fillchar(regloads,sizeof(regloads),0);
+ fillchar(reguses,sizeof(reguses),0);
+ getnextinstruction(prevseqstart,prevseq_next);
+ for regcounter := RS_EAX To RS_EDI do
+ if (reginfo.new2oldreg[regcounter] <> RS_INVALID) Then
+ begin
+ include(regsloaded,regcounter);
+ if assigned(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod) then
+ AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
+ ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod,curseqstart,
+ ptaiprop(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod.optinfo)^.usedregs)
+ else
+ AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
+ prevseqstart,curseqstart,ptaiprop(prevseqstart.optinfo)^.usedregs);
+
+ if curprev <> prevseqstart then
+ begin
+ if assigned(reginfo.lastReload[regCounter]) then
+ getLastInstruction(reginfo.lastReload[regCounter],hp)
+ else if assigned(reginfo.lastReload[reginfo.new2oldreg[regCounter]]) then
+ getLastInstruction(reginfo.lastReload[reginfo.new2OldReg[regCounter]],hp)
+ else
+ hp := curprev;
+ clearRegContentsFrom(regCounter,prevSeq_next,hp);
+ getnextInstruction(hp,hp);
+ allocRegBetween(asml,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prevseqstart,hp,
+ ptaiprop(prevseqstart.optinfo)^.usedregs);
+ end;
+ if not(regcounter in reginfo.RegsLoadedforRef) and
+ {old reg new reg}
+ (reginfo.new2oldreg[regcounter] <> regcounter) then
+ begin
+ getLastInstruction(curseqend,hp);
+ if (curprev <> prevseqstart) or
+ {not(regCounter in rg.usableregsint + [RS_EDI,RS_ESI]) or}
+ not(regCounter in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_EDI,RS_ESI]) or
+ not ReplaceReg(asml,reginfo.new2oldreg[regcounter],
+ regCounter,hp,curseqstart,
+ ptaiprop(prevseqstart.optinfo)^.Regs[regCounter],true,hp2) then
+ begin
+ opc := A_MOV;
+ insertpos := prevseq_next;
+ if assigned(reguses[regcounter]) then
+ if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
+ opc := A_XCHG
+ else
+ insertpos := tai(reguses[regcounter].next)
+ else
+ if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
+ insertpos := regloads[reginfo.new2oldreg[regcounter]];
+ hp := Tai_Marker.Create(NoPropInfoStart);
+ InsertLLItem(asml, insertpos.previous,insertpos, hp);
+ hp2 := taicpu.Op_Reg_Reg(opc, S_L,
+ {old reg new reg}
+ newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE), newreg(R_INTREGISTER,regcounter,R_SUBWHOLE));
+ regloads[regcounter] := hp2;
+ reguses[reginfo.new2oldreg[regcounter]] := hp2;
+ new(ptaiprop(hp2.optinfo));
+ ptaiprop(hp2.optinfo)^ := ptaiprop(insertpos.optinfo)^;
+ ptaiprop(hp2.optinfo)^.canBeRemoved := false;
+ InsertLLItem(asml, insertpos.previous, insertpos, hp2);
+ hp := Tai_Marker.Create(NoPropInfoEnd);
+ InsertLLItem(asml, insertpos.previous, insertpos, hp);
+ { adjusts states in previous instruction so that it will }
+ { definitely be different from the previous or next state }
+ incstate(ptaiprop(hp2.optinfo)^.
+ regs[reginfo.new2oldreg[regcounter]].rstate,20);
+ incstate(ptaiprop(hp2.optinfo)^.
+ regs[regCounter].wstate,20);
+ updateState(reginfo.new2oldreg[regcounter],hp2);
+ updateState(regcounter,hp2);
+ end
+ else
+ begin
+ // replace the new register with the old register in the
+ // sequence itself as well so later comparisons get the
+ // correct knowledge about which registers are used
+ hp2 := curseqstart;
+ // curseqend = instruction following last instruction of this
+ // sequence
+ while hp2 <> curseqend do
+ begin
+ doreplacereg(taicpu(hp2),regcounter,reginfo.new2oldreg[regcounter]);
+ getnextinstruction(hp2,hp2);
+ end;
+ end;
+ end
+ else
+ { imagine the following code: }
+ { normal wrong optimized }
+ { movl 8(%ebp), %eax movl 8(%ebp), %eax }
+ { movl (%eax), %eax movl (%eax), %eax }
+ { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
+ { jne l1 jne l1 }
+ { movl 8(%ebp), %eax }
+ { movl (%eax), %edi movl %eax, %edi }
+ { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
+ { movl 8(%ebp), %eax }
+ { pushl 70(%eax) pushl 70(%eax) }
+ { }
+ { The error is that at the moment that the last instruction is executed, }
+ { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
+ { registers that are completely removed from a sequence (= registers in }
+ { RegLoadedforRef), have to be changed to their contents from before the }
+ { sequence. }
+ { if regcounter in reginfo.RegsLoadedforRef then }
+ begin
+ hp := curseqstart;
+ { cnt still holds the number of instructions }
+ { of the sequence, so go to the end of it }
+ for i := 1 to pred(cnt) do
+ getNextInstruction(hp,hp);
+ { curprev = instruction prior to start of sequence }
+ restoreRegContentsTo(regCounter,
+ ptaiprop(curprev.optinfo)^.Regs[regcounter],
+ curseqstart,hp);
+ end;
+ end;
+end;
+
+
+procedure replaceoperandwithreg(asml: taasmoutput; p: tai; opnr: byte; reg: tregister);
+var
+ hp: tai;
+begin
+ { new instruction -> it's info block is not in the big one allocated at the start }
+ hp := Tai_Marker.Create(NoPropInfoStart);
+ InsertLLItem(asml, p.previous,p, hp);
+ { duplicate the original instruction and replace it's designated operant with the register }
+ hp := tai(p.getcopy);
+ taicpu(hp).loadreg(opnr,reg);
+ { add optimizer state info }
+ new(ptaiprop(hp.optinfo));
+ ptaiprop(hp.optinfo)^ := ptaiprop(p.optinfo)^;
+ { new instruction can not be removed }
+ ptaiprop(hp.optinfo)^.canBeRemoved := false;
+ { but the old one can }
+ ptaiprop(p.optinfo)^.canBeRemoved := true;
+ { insert end marker }
+ InsertLLItem(asml, p.previous, p, hp);
+ hp := Tai_Marker.Create(NoPropInfoEnd);
+ InsertLLItem(asml, p.previous, p, hp);
+end;
+
+
+procedure doCSE(asml: TAAsmOutput; First, Last: tai; findPrevSeqs, doSubOpts: boolean);
+{marks the instructions that can be removed by RemoveInstructs. They're not
+ removed immediately because sometimes an instruction needs to be checked in
+ two different sequences}
+var cnt, cnt2, {cnt3,} orgNrofMods: longint;
+ p, hp1, hp2, prevSeq: tai;
+ hp3, hp4: tai;
+ hp5 : tai;
+ reginfo: toptreginfo;
+ memreg: tregister;
+ regcounter: tsuperregister;
+begin
+ p := First;
+ SkipHead(p);
+ while (p <> Last) do
+ begin
+ case p.typ of
+ ait_align:
+ if not(tai_align(p).use_op) then
+ SetAlignReg(p);
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+{
+ Does not work anymore with register calling because the registers are
+ released before the call
+ A_CALL:
+ for regCounter := RS_EAX to RS_EBX do
+ removePrevNotUsedLoad(p,regCounter,true);
+}
+ A_CLD: if GetLastInstruction(p, hp1) and
+ (ptaiprop(hp1.optinfo)^.DirFlag = F_NotSet) then
+ ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
+ A_LEA, A_MOV, A_MOVZX, A_MOVSX:
+ begin
+ hp2 := p;
+ case taicpu(p).oper[0]^.typ of
+ top_ref, top_reg:
+ if (taicpu(p).oper[1]^.typ = top_reg) then
+ begin
+ With ptaiprop(p.optinfo)^.Regs[getsupreg(taicpu(p).oper[1]^.reg)] do
+ begin
+ if (startmod = p) then
+ orgNrofMods := nrofMods
+ else
+ orgNrofMods := 0;
+ if (p = StartMod) and
+ GetLastInstruction (p, hp1) and
+ not(hp1.typ in [ait_marker,ait_label]) then
+{so we don't try to check a sequence when p is the first instruction of the block}
+ begin
+{$ifdef csdebug}
+ hp5 := tai_comment.Create(strpnew(
+ 'cse checking '+std_regname(taicpu(p).oper[1]^.reg)));
+ insertLLItem(asml,p,p.next,hp5);
+{$endif csdebug}
+ if CheckSequence(p,prevSeq,getsupreg(taicpu(p).oper[1]^.reg), Cnt, reginfo, findPrevSeqs) and
+ (Cnt > 0) then
+ begin
+(*
+ hp1 := nil;
+{ although it's perfectly ok to remove an instruction which doesn't contain }
+{ the register that we've just checked (CheckSequence takes care of that), }
+{ the sequence containing this other register should also be completely }
+{ checked and removed, otherwise we may get situations like this: }
+{ }
+{ movl 12(%ebp), %edx movl 12(%ebp), %edx }
+{ movl 16(%ebp), %eax movl 16(%ebp), %eax }
+{ movl 8(%edx), %edx movl 8(%edx), %edx }
+{ movl (%eax), eax movl (%eax), eax }
+{ cmpl %eax, %edx cmpl %eax, %edx }
+{ jnz l123 getting converted to jnz l123 }
+{ movl 12(%ebp), %edx movl 4(%eax), eax }
+{ movl 16(%ebp), %eax }
+{ movl 8(%edx), %edx }
+{ movl 4(%eax), eax }
+*)
+
+{ not anymore: if the start of a new sequence is found while checking (e.g. }
+{ above that of eax while checking edx, this new sequence is automatically }
+{ also checked }
+ Cnt2 := 1;
+ while Cnt2 <= Cnt do
+ begin
+{$ifndef noremove}
+ ptaiprop(p.optinfo)^.CanBeRemoved := True
+{$endif noremove}
+ ; inc(Cnt2);
+ GetNextInstruction(p, p);
+ end;
+ {hp4 is used to get the contents of the registers before the sequence}
+ GetLastInstruction(hp2, hp4);
+
+{$IfDef CSDebug}
+ for regcounter := RS_EAX To RS_EDI do
+ if (regcounter in reginfo.RegsLoadedforRef) then
+ begin
+ hp5 := tai_comment.Create(strpnew('New: '+std_regname(newreg(R_INTREGISTER,regcounter,R_SUBNONE))+', Old: '+
+ std_regname(newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBNONE))));
+ InsertLLItem(asml, tai(hp2.previous), hp2, hp5);
+ end;
+{$EndIf CSDebug}
+ { if some registers were different in the old and the new sequence, move }
+ { the contents of those old registers to the new ones }
+ loadcseregs(asml,reginfo,p,prevseq,hp2,hp4,cnt);
+ continue;
+ end
+ end;
+ end;
+ { try to replace the new reg with the old reg }
+ if not(ptaiprop(p.optinfo)^.canBeRemoved) then
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ { only remove if we're not storing something in a regvar }
+ (getsupreg(taicpu(p).oper[1]^.reg) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) and
+{ (taicpu(p).oper[1]^.reg in (rg.usableregsint+[RS_EDI])) and}
+ (taicpu(p).opcode = A_MOV) and
+ getLastInstruction(p,hp4) and
+ { we only have to start replacing from the instruction after the mov, }
+ { but replacereg only starts with getnextinstruction(p,p) }
+ replaceReg(asml,getsupreg(taicpu(p).oper[0]^.reg),
+ getsupreg(taicpu(p).oper[1]^.reg),p,p,
+ ptaiprop(hp4.optinfo)^.regs[getsupreg(taicpu(p).oper[1]^.reg)],false,hp1) then
+ begin
+ ptaiprop(p.optinfo)^.canBeRemoved := true;
+ { this is just a regular move that was here, so the source register should be }
+ { allocated already at this point -> only allocate from here onwards }
+ if not(getsupreg(taicpu(p).oper[0]^.reg) in pTaiProp(p.optinfo)^.usedregs) then
+ internalerror(2004101011);
+ allocRegBetween(asml,taicpu(p).oper[0]^.reg,
+ p,hp1,pTaiProp(p.optinfo)^.usedregs)
+ end
+ else
+ begin
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ not regInOp(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^) then
+ removePrevNotUsedLoad(p,getsupreg(taicpu(p).oper[1]^.reg),false);
+ if doSubOpts and
+ (taicpu(p).opcode <> A_LEA) and
+ (taicpu(p).oper[0]^.typ = top_ref) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[0]^.ref^,hp5);
+ if memreg <> NR_NO then
+ if (taicpu(p).opcode = A_MOV) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.reg = memreg) then
+ begin
+ pTaiProp(p.optinfo)^.canberemoved := true;
+ allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
+ end
+ else
+ begin
+ replaceoperandwithreg(asml,p,0,memreg);
+ allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,p);
+ end;
+ end;
+ end;
+ { at first, only try optimizations of large blocks, because doing }
+ { doing smaller ones may prevent bigger ones from completing in }
+ { in the next pass }
+ if not doSubOpts and (orgNrofMods <> 0) then
+ begin
+ p := hp2;
+ for cnt := 1 to pred(orgNrofMods) do
+ getNextInstruction(p,p);
+ end;
+ end;
+ top_Const:
+ begin
+ case taicpu(p).oper[1]^.typ of
+ Top_Reg:
+ begin
+ regCounter := getsupreg(taicpu(p).oper[1]^.reg);
+ if GetLastInstruction(p, hp1) then
+ With ptaiprop(hp1.optinfo)^.Regs[regCounter] do
+ if (typ in [con_const,con_noRemoveConst]) and
+ (taicpu(startMod).opsize >= taicpu(p).opsize) and
+ opsequal(taicpu(StartMod).oper[0]^,taicpu(p).oper[0]^) then
+ begin
+ ptaiprop(p.optinfo)^.CanBeRemoved := True;
+ allocRegBetween(asml,taicpu(p).oper[1]^.reg,startmod,p,
+ ptaiprop(startmod.optinfo)^.usedregs);
+ end
+ else
+ removePrevNotUsedLoad(p,getsupreg(taicpu(p).oper[1]^.reg),false);
+
+ end;
+ Top_Ref:
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ getLastInstruction(p,hp1) and
+ findRegWithConst(hp1,taicpu(p).opsize,taicpu(p).oper[0]^.val,memreg) then
+ begin
+ taicpu(p).loadreg(0,memreg);
+ allocRegBetween(asml,memreg,
+ ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod,p,
+ ptaiprop(ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod.optinfo)^.usedregs);
+ end;
+ end;
+ end;
+ end;
+
+ end;
+ A_LEAVE:
+ begin
+ if getlastinstruction(p,hp1) then
+ removeLocalStores(hp1);
+ end;
+ A_STD: if GetLastInstruction(p, hp1) and
+ (ptaiprop(hp1.optinfo)^.DirFlag = F_Set) then
+ ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
+ else
+ begin
+ for cnt := 1 to maxinschanges do
+ begin
+ case InsProp[taicpu(p).opcode].Ch[cnt] of
+ Ch_ROp1:
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ ((taicpu(p).opcode < A_F2XM1) or
+ ((taicpu(p).opcode > A_IN) and
+ (taicpu(p).opcode < A_OUT)) or
+ (taicpu(p).opcode = A_PUSH) or
+ ((taicpu(p).opcode >= A_RCL) and
+ (taicpu(p).opcode <= A_XOR))) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[0]^.ref^,hp5);
+ if memreg <> NR_NO then
+ begin
+ replaceoperandwithreg(asml,p,0,memreg);
+ allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,p);
+ end;
+ end;
+ Ch_MOp1:
+ if not(CS_LittleSize in aktglobalswitches) and
+ (taicpu(p).oper[0]^.typ = top_ref) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[0]^.ref^,hp5);
+ if (memreg <> NR_NO) and
+ (not getNextInstruction(p,hp1) or
+ (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
+ FindRegDealloc(getsupreg(memreg),hp1))) then
+ begin
+ hp1 := Tai_Marker.Create(NoPropInfoEnd);
+ insertllitem(asml,p,p.next,hp1);
+ hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
+ memreg,taicpu(p).oper[0]^.ref^);
+ new(ptaiprop(hp1.optinfo));
+ pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
+ insertllitem(asml,p,p.next,hp1);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,hp1);
+ hp1 := Tai_Marker.Create(NoPropInfoStart);
+ insertllitem(asml,p,p.next,hp1);
+ replaceoperandwithreg(asml,p,0,memreg);
+ allocregbetween(asml,memreg,hp5,
+ tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
+ ClearRegContentsFrom(regcounter,hp5,p);
+ end;
+ end;
+ Ch_ROp2:
+ if ((taicpu(p).opcode = A_CMP) or
+ (taicpu(p).opcode = A_TEST)) and
+ (taicpu(p).oper[1]^.typ = top_ref) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[1]^.ref^,hp5);
+ if memreg <> NR_NO then
+ begin
+ replaceoperandwithreg(asml,p,1,memreg);
+ allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,p);
+ end;
+ end;
+ Ch_MOp2:
+ if not(cs_littlesize in aktglobalswitches) and
+ (taicpu(p).oper[1]^.typ = top_ref) and
+ ((taicpu(p).opcode < A_BT) or
+ ((taicpu(p).opcode > A_IN) and
+ (taicpu(p).opcode < A_OUT)) or
+ (taicpu(p).opcode = A_PUSH) or
+ ((taicpu(p).opcode >= A_RCL) and
+ (taicpu(p).opcode <= A_XOR))) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[1]^.ref^,hp5);
+ if (memreg <> NR_NO) and
+ (not getNextInstruction(p,hp1) or
+ (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
+ FindRegDealloc(getsupreg(memreg),hp1))) then
+ begin
+ hp1 := Tai_Marker.Create(NoPropInfoEnd);
+ insertllitem(asml,p,p.next,hp1);
+ hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
+ memreg,taicpu(p).oper[1]^.ref^);
+ new(ptaiprop(hp1.optinfo));
+ pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
+ insertllitem(asml,p,p.next,hp1);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,hp1);
+ hp1 := Tai_Marker.Create(NoPropInfoStart);
+ insertllitem(asml,p,p.next,hp1);
+ replaceoperandwithreg(asml,p,1,memreg);
+ allocregbetween(asml,memreg,hp5,
+ tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
+ ClearRegContentsFrom(regcounter,hp5,p);
+ end;
+ end;
+ end;
+ end;
+ end;
+ end
+ end;
+ end;
+ GetNextInstruction(p, p);
+ end;
+end;
+
+function removeInstructs(asml: TAAsmoutput; first, last: tai): boolean;
+{ Removes the marked instructions and disposes the PTaiProps of the other }
+{ instructions }
+var
+ p, hp1: tai;
+ nopropinfolevel: longint;
+begin
+ removeInstructs := false;
+ p := First;
+ nopropinfolevel := 0;
+ while (p <> Last) do
+ begin
+ if (p.typ = ait_marker) and
+ (Tai_marker(p).kind = noPropInfoStart) then
+ begin
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ nopropinfolevel := 1;
+ while (nopropinfolevel <> 0) do
+ begin
+ p := tai(hp1.next);
+{$ifndef noinstremove}
+ { allocregbetween can insert new ait_regalloc objects }
+ { without optinfo }
+ if (hp1.typ = ait_marker) then
+ begin
+ case Tai_marker(hp1).kind of
+ { they can be nested! }
+ noPropInfoStart: inc(nopropinfolevel);
+ noPropInfoEnd: dec(nopropinfolevel);
+ else
+ begin
+ hp1 := p;
+ continue;
+ end;
+ end;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else if assigned(hp1.optinfo) then
+ if ptaiprop(hp1.optinfo)^.canBeRemoved then
+ begin
+ dispose(ptaiprop(hp1.optinfo));
+ hp1.optinfo := nil;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else
+{$endif noinstremove}
+ begin
+ dispose(ptaiprop(hp1.optinfo));
+ hp1.optinfo := nil;
+ end;
+ hp1 := p;
+ end;
+ end
+ else
+{$ifndef noinstremove}
+ if assigned(p.optinfo) and
+ ptaiprop(p.optinfo)^.canBeRemoved then
+ begin
+ hp1 := tai(p.next);
+ asml.Remove(p);
+ p.free;
+ p := hp1;
+ removeInstructs := true;
+ end
+ else
+{$endif noinstremove}
+ begin
+ p.optinfo := nil;
+ p := tai(p.next);;
+ end;
+ end;
+end;
+
+function CSE(asml: TAAsmOutput; First, Last: tai; pass: longint): boolean;
+begin
+ doCSE(asml, First, Last, not(cs_slowoptimize in aktglobalswitches) or (pass >= 2),
+ not(cs_slowoptimize in aktglobalswitches) or (pass >= 1));
+ { register renaming }
+ if not(cs_slowoptimize in aktglobalswitches) or (pass > 0) then
+ doRenaming(asml, first, last);
+ cse := removeInstructs(asml, first, last);
+end;
+
+end.
diff --git a/compiler/i386/daopt386.pas b/compiler/i386/daopt386.pas
new file mode 100644
index 0000000000..7c08d9f667
--- /dev/null
+++ b/compiler/i386/daopt386.pas
@@ -0,0 +1,2796 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Freepascal
+ development team
+
+ This unit contains the data flow analyzer and several helper procedures
+ and functions.
+
+ 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 daopt386;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,
+ cclasses,aasmbase,aasmtai,aasmcpu,cgbase,cgutils,
+ cpubase,optbase;
+
+{******************************* Constants *******************************}
+
+const
+
+{ Possible register content types }
+ con_Unknown = 0;
+ con_ref = 1;
+ con_const = 2;
+ { The contents aren't usable anymore for CSE, but they may still be }
+ { usefull for detecting whether the result of a load is actually used }
+ con_invalid = 3;
+ { the reverse of the above (in case a (conditional) jump is encountered): }
+ { CSE is still possible, but the original instruction can't be removed }
+ con_noRemoveRef = 4;
+ { same, but for constants }
+ con_noRemoveConst = 5;
+
+
+const
+ topsize2tcgsize: array[topsize] of tcgsize = (OS_NO,
+ OS_8,OS_16,OS_32,OS_64,OS_16,OS_32,OS_32,
+ OS_16,OS_32,OS_64,
+ OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,
+ OS_M32,
+ OS_ADDR,OS_NO,OS_NO,
+ OS_NO,
+ OS_NO);
+
+
+
+{********************************* Types *********************************}
+
+type
+ TRegArray = Array[RS_EAX..RS_ESP] of tsuperregister;
+ TRegSet = Set of RS_EAX..RS_ESP;
+ toptreginfo = Record
+ NewRegsEncountered, OldRegsEncountered: TRegSet;
+ RegsLoadedForRef: TRegSet;
+ lastReload: array[RS_EAX..RS_ESP] of tai;
+ New2OldReg: TRegArray;
+ end;
+
+{possible actions on an operand: read, write or modify (= read & write)}
+ TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
+
+{the possible states of a flag}
+ TFlagContents = (F_Unknown, F_notSet, F_Set);
+
+ TContent = Packed Record
+ {start and end of block instructions that defines the
+ content of this register.}
+ StartMod: tai;
+ MemWrite: taicpu;
+ {how many instructions starting with StarMod does the block consist of}
+ NrOfMods: Word;
+ {the type of the content of the register: unknown, memory, constant}
+ Typ: Byte;
+ case byte of
+ {starts at 0, gets increased everytime the register is written to}
+ 1: (WState: Byte;
+ {starts at 0, gets increased everytime the register is read from}
+ RState: Byte);
+ { to compare both states in one operation }
+ 2: (state: word);
+ end;
+
+{Contents of the integer registers}
+ TRegContent = Array[RS_EAX..RS_ESP] Of TContent;
+
+{contents of the FPU registers}
+// TRegFPUContent = Array[RS_ST..RS_ST7] Of TContent;
+
+{$ifdef tempOpts}
+{ linked list which allows searching/deleting based on value, no extra frills}
+ PSearchLinkedListItem = ^TSearchLinkedListItem;
+ TSearchLinkedListItem = object(TLinkedList_Item)
+ constructor init;
+ function equals(p: PSearchLinkedListItem): boolean; virtual;
+ end;
+
+ PSearchDoubleIntItem = ^TSearchDoubleInttem;
+ TSearchDoubleIntItem = object(TLinkedList_Item)
+ constructor init(_int1,_int2: longint);
+ function equals(p: PSearchLinkedListItem): boolean; virtual;
+ private
+ int1, int2: longint;
+ end;
+
+ PSearchLinkedList = ^TSearchLinkedList;
+ TSearchLinkedList = object(TLinkedList)
+ function searchByValue(p: PSearchLinkedListItem): boolean;
+ procedure removeByValue(p: PSearchLinkedListItem);
+ end;
+{$endif tempOpts}
+
+{information record with the contents of every register. Every tai object
+ gets one of these assigned: a pointer to it is stored in the OptInfo field}
+ TtaiProp = Record
+ Regs: TRegContent;
+{ FPURegs: TRegFPUContent;} {currently not yet used}
+ { allocated Registers }
+ UsedRegs: TRegSet;
+ { status of the direction flag }
+ DirFlag: TFlagContents;
+{$ifdef tempOpts}
+ { currently used temps }
+ tempAllocs: PSearchLinkedList;
+{$endif tempOpts}
+ { can this instruction be removed? }
+ CanBeRemoved: Boolean;
+ { are the resultflags set by this instruction used? }
+ FlagsUsed: Boolean;
+ end;
+
+ ptaiprop = ^TtaiProp;
+
+ TtaiPropBlock = Array[1..250000] Of TtaiProp;
+ PtaiPropBlock = ^TtaiPropBlock;
+
+ TInstrSinceLastMod = Array[RS_EAX..RS_ESP] Of Word;
+
+ TLabelTableItem = Record
+ taiObj: tai;
+{$ifDef JumpAnal}
+ InstrNr: Longint;
+ RefsFound: Word;
+ JmpsProcessed: Word
+{$endif JumpAnal}
+ end;
+ TLabelTable = Array[0..2500000] Of TLabelTableItem;
+ PLabelTable = ^TLabelTable;
+
+
+{*********************** procedures and functions ************************}
+
+procedure InsertLLItem(AsmL: TAAsmOutput; prev, foll, new_one: TLinkedListItem);
+
+
+function RefsEqual(const R1, R2: TReference): Boolean;
+function isgp32reg(supreg: tsuperregister): Boolean;
+function reginref(supreg: tsuperregister; const ref: treference): boolean;
+function RegReadByInstruction(supreg: tsuperregister; hp: tai): boolean;
+function RegModifiedByInstruction(supreg: tsuperregister; p1: tai): boolean;
+function RegInInstruction(supreg: tsuperregister; p1: tai): boolean;
+function reginop(supreg: tsuperregister; const o:toper): boolean;
+function instrWritesFlags(p: tai): boolean;
+function instrReadsFlags(p: tai): boolean;
+
+function writeToMemDestroysContents(regWritten: tsuperregister; const ref: treference;
+ supreg: tsuperregister; size: tcgsize; const c: tcontent; var invalsmemwrite: boolean): boolean;
+function writeToRegDestroysContents(destReg, supreg: tsuperregister;
+ const c: tcontent): boolean;
+function writeDestroysContents(const op: toper; supreg: tsuperregister; size: tcgsize;
+ const c: tcontent; var memwritedestroyed: boolean): boolean;
+
+
+function GetNextInstruction(Current: tai; var Next: tai): Boolean;
+function GetLastInstruction(Current: tai; var Last: tai): Boolean;
+procedure SkipHead(var p: tai);
+function labelCanBeSkipped(p: tai_label): boolean;
+
+procedure RemoveLastDeallocForFuncRes(asmL: TAAsmOutput; p: tai);
+function regLoadedWithNewValue(supreg: tsuperregister; canDependOnPrevValue: boolean;
+ hp: tai): boolean;
+procedure UpdateUsedRegs(var UsedRegs: TRegSet; p: tai);
+procedure AllocRegBetween(asml: taasmoutput; reg: tregister; p1, p2: tai; const initialusedregs: tregset);
+function FindRegDealloc(supreg: tsuperregister; p: tai): boolean;
+
+function InstructionsEquivalent(p1, p2: tai; var RegInfo: toptreginfo): Boolean;
+function sizescompatible(loadsize,newsize: topsize): boolean;
+function OpsEqual(const o1,o2:toper): Boolean;
+
+
+type
+ tdfaobj = class
+ constructor create(_list: taasmoutput); virtual;
+
+ function pass_1(_blockstart: tai): tai;
+ function pass_2: boolean;
+ procedure clear;
+
+ function getlabelwithsym(sym: tasmlabel): tai;
+
+ private
+ { Walks through the list to find the lowest and highest label number, inits the }
+ { labeltable and fixes/optimizes some regallocs }
+ procedure initlabeltable;
+
+ function initdfapass2: boolean;
+ procedure dodfapass2;
+
+ { asm list we're working on }
+ list: taasmoutput;
+
+ { current part of the asm list }
+ blockstart, blockend: tai;
+
+ { the amount of taiObjects in the current part of the assembler list }
+ nroftaiobjs: longint;
+
+ { Array which holds all TtaiProps }
+ taipropblock: ptaipropblock;
+
+ { all labels in the current block: their value mapped to their location }
+ lolab, hilab, labdif: longint;
+ labeltable: plabeltable;
+ end;
+
+
+function FindLabel(L: tasmlabel; var hp: tai): Boolean;
+
+procedure incState(var S: Byte; amount: longint);
+
+{******************************* Variables *******************************}
+
+var
+ dfa: tdfaobj;
+
+{*********************** end of Interface section ************************}
+
+
+Implementation
+
+Uses
+{$ifdef csdebug}
+ cutils,
+{$else}
+ {$ifdef statedebug}
+ cutils,
+ {$else}
+ {$ifdef allocregdebug}
+ cutils,
+ {$endif}
+ {$endif}
+{$endif}
+ globals, systems, verbose, symconst, cgobj,procinfo;
+
+Type
+ TRefCompare = function(const r1, r2: treference; size1, size2: tcgsize): boolean;
+
+var
+ {How many instructions are between the current instruction and the last one
+ that modified the register}
+ NrOfInstrSinceLastMod: TInstrSinceLastMod;
+
+{$ifdef tempOpts}
+ constructor TSearchLinkedListItem.init;
+ begin
+ end;
+
+ function TSearchLinkedListItem.equals(p: PSearchLinkedListItem): boolean;
+ begin
+ equals := false;
+ end;
+
+ constructor TSearchDoubleIntItem.init(_int1,_int2: longint);
+ begin
+ int1 := _int1;
+ int2 := _int2;
+ end;
+
+ function TSearchDoubleIntItem.equals(p: PSearchLinkedListItem): boolean;
+ begin
+ equals := (TSearchDoubleIntItem(p).int1 = int1) and
+ (TSearchDoubleIntItem(p).int2 = int2);
+ end;
+
+ function TSearchLinkedList.searchByValue(p: PSearchLinkedListItem): boolean;
+ var temp: PSearchLinkedListItem;
+ begin
+ temp := first;
+ while (temp <> last.next) and
+ not(temp.equals(p)) do
+ temp := temp.next;
+ searchByValue := temp <> last.next;
+ end;
+
+ procedure TSearchLinkedList.removeByValue(p: PSearchLinkedListItem);
+ begin
+ temp := first;
+ while (temp <> last.next) and
+ not(temp.equals(p)) do
+ temp := temp.next;
+ if temp <> last.next then
+ begin
+ remove(temp);
+ dispose(temp,done);
+ end;
+ end;
+
+procedure updateTempAllocs(var UsedRegs: TRegSet; p: tai);
+{updates UsedRegs with the RegAlloc Information coming after p}
+begin
+ repeat
+ while assigned(p) and
+ ((p.typ in (SkipInstr - [ait_RegAlloc])) or
+ ((p.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current)))) Do
+ p := tai(p.next);
+ while assigned(p) and
+ (p.typ=ait_RegAlloc) Do
+ begin
+ case tai_regalloc(p).ratype of
+ ra_alloc :
+ UsedRegs := UsedRegs + [tai_regalloc(p).reg];
+ ra_dealloc :
+ UsedRegs := UsedRegs - [tai_regalloc(p).reg];
+ end;
+ p := tai(p.next);
+ end;
+ until not(assigned(p)) or
+ (not(p.typ in SkipInstr) and
+ not((p.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current))));
+end;
+
+{$endif tempOpts}
+
+{************************ Create the Label table ************************}
+
+function findregalloc(supreg: tsuperregister; starttai: tai; ratyp: tregalloctype): boolean;
+{ Returns true if a ait_alloc object for reg is found in the block of tai's }
+{ starting with Starttai and ending with the next "real" instruction }
+begin
+ findregalloc := false;
+ repeat
+ while assigned(starttai) and
+ ((starttai.typ in (skipinstr - [ait_regalloc])) or
+ ((starttai.typ = ait_label) and
+ labelcanbeskipped(tai_label(starttai)))) do
+ starttai := tai(starttai.next);
+ if assigned(starttai) and
+ (starttai.typ = ait_regalloc) then
+ begin
+ if (tai_regalloc(Starttai).ratype = ratyp) and
+ (getsupreg(tai_regalloc(Starttai).reg) = supreg) then
+ begin
+ findregalloc:=true;
+ break;
+ end;
+ starttai := tai(starttai.next);
+ end
+ else
+ break;
+ until false;
+end;
+
+procedure RemoveLastDeallocForFuncRes(asml: taasmoutput; p: tai);
+
+ procedure DoRemoveLastDeallocForFuncRes(asml: taasmoutput; supreg: tsuperregister);
+ var
+ hp2: tai;
+ begin
+ hp2 := p;
+ repeat
+ hp2 := tai(hp2.previous);
+ if assigned(hp2) and
+ (hp2.typ = ait_regalloc) and
+ (tai_regalloc(hp2).ratype=ra_dealloc) and
+ (getregtype(tai_regalloc(hp2).reg) = R_INTREGISTER) and
+ (getsupreg(tai_regalloc(hp2).reg) = supreg) then
+ begin
+ asml.remove(hp2);
+ hp2.free;
+ break;
+ end;
+ until not(assigned(hp2)) or regInInstruction(supreg,hp2);
+ end;
+
+begin
+ case current_procinfo.procdef.rettype.def.deftype of
+ arraydef,recorddef,pointerdef,
+ stringdef,enumdef,procdef,objectdef,errordef,
+ filedef,setdef,procvardef,
+ classrefdef,forwarddef:
+ DoRemoveLastDeallocForFuncRes(asml,RS_EAX);
+ orddef:
+ if current_procinfo.procdef.rettype.def.size <> 0 then
+ begin
+ DoRemoveLastDeallocForFuncRes(asml,RS_EAX);
+ { for int64/qword }
+ if current_procinfo.procdef.rettype.def.size = 8 then
+ DoRemoveLastDeallocForFuncRes(asml,RS_EDX);
+ end;
+ end;
+end;
+
+procedure getNoDeallocRegs(var regs: tregset);
+var
+ regCounter: TSuperRegister;
+begin
+ regs := [];
+ case current_procinfo.procdef.rettype.def.deftype of
+ arraydef,recorddef,pointerdef,
+ stringdef,enumdef,procdef,objectdef,errordef,
+ filedef,setdef,procvardef,
+ classrefdef,forwarddef:
+ regs := [RS_EAX];
+ orddef:
+ if current_procinfo.procdef.rettype.def.size <> 0 then
+ begin
+ regs := [RS_EAX];
+ { for int64/qword }
+ if current_procinfo.procdef.rettype.def.size = 8 then
+ regs := regs + [RS_EDX];
+ end;
+ end;
+ for regCounter := RS_EAX to RS_EBX do
+{ if not(regCounter in rg.usableregsint) then}
+ include(regs,regcounter);
+end;
+
+
+procedure AddRegDeallocFor(asml: taasmoutput; reg: tregister; p: tai);
+var
+ hp1: tai;
+ funcResRegs: tregset;
+ funcResReg: boolean;
+begin
+{ if not(supreg in rg.usableregsint) then
+ exit;}
+{ if not(supreg in [RS_EDI]) then
+ exit;}
+ getNoDeallocRegs(funcresregs);
+{ funcResRegs := funcResRegs - rg.usableregsint;}
+{ funcResRegs := funcResRegs - [RS_EDI];}
+{ funcResRegs := funcResRegs - [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI]; }
+ funcResReg := getsupreg(reg) in funcresregs;
+
+ hp1 := p;
+{
+
+
+ while not(funcResReg and
+ (p.typ = ait_instruction) and
+ (taicpu(p).opcode = A_JMP) and
+ (tasmlabel(taicpu(p).oper[0]^.sym) = aktexit2label)) and
+ getLastInstruction(p, p) and
+ not(regInInstruction(supreg, p)) do
+ hp1 := p;
+}
+ { don't insert a dealloc for registers which contain the function result }
+ { if they are followed by a jump to the exit label (for exit(...)) }
+{ if not(funcResReg) or
+ not((hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_JMP) and
+ (tasmlabel(taicpu(hp1).oper[0]^.sym) = aktexit2label)) then }
+ begin
+ p := tai_regalloc.deAlloc(reg,nil);
+ insertLLItem(AsmL, hp1.previous, hp1, p);
+ end;
+end;
+
+
+
+{************************ Search the Label table ************************}
+
+function findlabel(l: tasmlabel; var hp: tai): boolean;
+
+{searches for the specified label starting from hp as long as the
+ encountered instructions are labels, to be able to optimize constructs like
+
+ jne l2 jmp l2
+ jmp l3 and l1:
+ l1: l2:
+ l2:}
+
+var
+ p: tai;
+
+begin
+ p := hp;
+ while assigned(p) and
+ (p.typ in SkipInstr + [ait_label,ait_align]) Do
+ if (p.typ <> ait_Label) or
+ (tai_label(p).l <> l) then
+ GetNextInstruction(p, p)
+ else
+ begin
+ hp := p;
+ findlabel := true;
+ exit
+ end;
+ findlabel := false;
+end;
+
+{************************ Some general functions ************************}
+
+function tch2reg(ch: tinschange): tsuperregister;
+{converts a TChange variable to a TRegister}
+const
+ ch2reg: array[CH_REAX..CH_REDI] of tsuperregister = (RS_EAX,RS_ECX,RS_EDX,RS_EBX,RS_ESP,RS_EBP,RS_ESI,RS_EDI);
+begin
+ if (ch <= CH_REDI) then
+ tch2reg := ch2reg[ch]
+ else if (ch <= CH_WEDI) then
+ tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_REDI))]
+ else if (ch <= CH_RWEDI) then
+ tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_WEDI))]
+ else if (ch <= CH_MEDI) then
+ tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_RWEDI))]
+ else
+ InternalError($db)
+end;
+
+
+{ inserts new_one between prev and foll }
+
+procedure InsertLLItem(AsmL: TAAsmOutput; prev, foll, new_one: TLinkedListItem);
+begin
+ if assigned(prev) then
+ if assigned(foll) then
+ begin
+ if assigned(new_one) then
+ begin
+ new_one.previous := prev;
+ new_one.next := foll;
+ prev.next := new_one;
+ foll.previous := new_one;
+ { shgould we update line information }
+ if (not (tai(new_one).typ in SkipLineInfo)) and
+ (not (tai(foll).typ in SkipLineInfo)) then
+ tailineinfo(new_one).fileinfo := tailineinfo(foll).fileinfo;
+ end;
+ end
+ else
+ asml.Concat(new_one)
+ else
+ if assigned(foll) then
+ asml.Insert(new_one)
+end;
+
+{********************* Compare parts of tai objects *********************}
+
+function regssamesize(reg1, reg2: tregister): boolean;
+{returns true if Reg1 and Reg2 are of the same size (so if they're both
+ 8bit, 16bit or 32bit)}
+begin
+ if (reg1 = NR_NO) or (reg2 = NR_NO) then
+ internalerror(2003111602);
+ regssamesize := getsubreg(reg1) = getsubreg(reg2);
+end;
+
+
+procedure AddReg2RegInfo(OldReg, NewReg: TRegister; var RegInfo: toptreginfo);
+{updates the ???RegsEncountered and ???2???reg fields of RegInfo. Assumes that
+ OldReg and NewReg have the same size (has to be chcked in advance with
+ RegsSameSize) and that neither equals RS_INVALID}
+var
+ newsupreg, oldsupreg: tsuperregister;
+begin
+ if (newreg = NR_NO) or (oldreg = NR_NO) then
+ internalerror(2003111601);
+ newsupreg := getsupreg(newreg);
+ oldsupreg := getsupreg(oldreg);
+ with RegInfo Do
+ begin
+ NewRegsEncountered := NewRegsEncountered + [newsupreg];
+ OldRegsEncountered := OldRegsEncountered + [oldsupreg];
+ New2OldReg[newsupreg] := oldsupreg;
+ end;
+end;
+
+
+procedure AddOp2RegInfo(const o:toper; var reginfo: toptreginfo);
+begin
+ case o.typ Of
+ top_reg:
+ if (o.reg <> NR_NO) then
+ AddReg2RegInfo(o.reg, o.reg, RegInfo);
+ top_ref:
+ begin
+ if o.ref^.base <> NR_NO then
+ AddReg2RegInfo(o.ref^.base, o.ref^.base, RegInfo);
+ if o.ref^.index <> NR_NO then
+ AddReg2RegInfo(o.ref^.index, o.ref^.index, RegInfo);
+ end;
+ end;
+end;
+
+
+function RegsEquivalent(oldreg, newreg: tregister; const oldinst, newinst: taicpu; var reginfo: toptreginfo; opact: topaction): Boolean;
+begin
+ if not((oldreg = NR_NO) or (newreg = NR_NO)) then
+ if RegsSameSize(oldreg, newreg) then
+ with reginfo do
+{here we always check for the 32 bit component, because it is possible that
+ the 8 bit component has not been set, event though NewReg already has been
+ processed. This happens if it has been compared with a register that doesn't
+ have an 8 bit component (such as EDI). in that case the 8 bit component is
+ still set to RS_NO and the comparison in the else-part will fail}
+ if (getsupreg(oldReg) in OldRegsEncountered) then
+ if (getsupreg(NewReg) in NewRegsEncountered) then
+ RegsEquivalent := (getsupreg(oldreg) = New2OldReg[getsupreg(newreg)])
+
+ { if we haven't encountered the new register yet, but we have encountered the
+ old one already, the new one can only be correct if it's being written to
+ (and consequently the old one is also being written to), otherwise
+
+ movl -8(%ebp), %eax and movl -8(%ebp), %eax
+ movl (%eax), %eax movl (%edx), %edx
+
+ are considered equivalent}
+
+ else
+ if (opact = opact_write) then
+ begin
+ AddReg2RegInfo(oldreg, newreg, reginfo);
+ RegsEquivalent := true
+ end
+ else
+ Regsequivalent := false
+ else
+ if not(getsupreg(newreg) in NewRegsEncountered) and
+ ((opact = opact_write) or
+ ((newreg = oldreg) and
+ (ptaiprop(oldinst.optinfo)^.regs[getsupreg(oldreg)].wstate =
+ ptaiprop(newinst.optinfo)^.regs[getsupreg(oldreg)].wstate) and
+ not(regmodifiedbyinstruction(getsupreg(oldreg),oldinst)))) then
+ begin
+ AddReg2RegInfo(oldreg, newreg, reginfo);
+ RegsEquivalent := true
+ end
+ else
+ RegsEquivalent := false
+ else
+ RegsEquivalent := false
+ else
+ RegsEquivalent := oldreg = newreg
+end;
+
+
+function RefsEquivalent(const r1, r2: treference; const oldinst, newinst: taicpu; var regInfo: toptreginfo): boolean;
+begin
+ RefsEquivalent :=
+ (r1.offset = r2.offset) and
+ RegsEquivalent(r1.base, r2.base, oldinst, newinst, reginfo, OpAct_Read) and
+ RegsEquivalent(r1.index, r2.index, oldinst, newinst, reginfo, OpAct_Read) and
+ (r1.segment = r2.segment) and (r1.scalefactor = r2.scalefactor) and
+ (r1.symbol = r2.symbol) and (r1.refaddr = r2.refaddr) and
+ (r1.relsymbol = r2.relsymbol);
+end;
+
+
+function refsequal(const r1, r2: treference): boolean;
+begin
+ refsequal :=
+ (r1.offset = r2.offset) and
+ (r1.segment = r2.segment) and (r1.base = r2.base) and
+ (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and
+ (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and
+ (r1.relsymbol = r2.relsymbol);
+end;
+
+
+{$ifdef q+}
+{$q-}
+{$define overflowon}
+{$endif q+}
+
+// checks whether a write to r2 of size "size" contains address r1
+function refsoverlapping(const r1, r2: treference; size1, size2: tcgsize): boolean;
+var
+ realsize1, realsize2: aint;
+begin
+ realsize1 := tcgsize2size[size1];
+ realsize2 := tcgsize2size[size2];
+ refsoverlapping :=
+ (r2.offset <= r1.offset+realsize1) and
+ (r1.offset <= r2.offset+realsize2) and
+ (r1.segment = r2.segment) and (r1.base = r2.base) and
+ (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and
+ (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and
+ (r1.relsymbol = r2.relsymbol);
+end;
+
+{$ifdef overflowon}
+{$q+}
+{$undef overflowon}
+{$endif overflowon}
+
+
+function isgp32reg(supreg: tsuperregister): boolean;
+{Checks if the register is a 32 bit general purpose register}
+begin
+ isgp32reg := false;
+ if (supreg >= RS_EAX) and (supreg <= RS_EBX) then
+ isgp32reg := true
+end;
+
+
+function reginref(supreg: tsuperregister; const ref: treference): boolean;
+begin {checks whether ref contains a reference to reg}
+ reginref :=
+ ((ref.base <> NR_NO) and
+ (getsupreg(ref.base) = supreg)) or
+ ((ref.index <> NR_NO) and
+ (getsupreg(ref.index) = supreg))
+end;
+
+
+function RegReadByInstruction(supreg: tsuperregister; hp: tai): boolean;
+var
+ p: taicpu;
+ opcount: longint;
+begin
+ RegReadByInstruction := false;
+ if hp.typ <> ait_instruction then
+ exit;
+ p := taicpu(hp);
+ case p.opcode of
+ A_CALL:
+ regreadbyinstruction := true;
+ A_IMUL:
+ case p.ops of
+ 1:
+ regReadByInstruction :=
+ (supreg = RS_EAX) or reginop(supreg,p.oper[0]^);
+ 2,3:
+ regReadByInstruction :=
+ reginop(supreg,p.oper[0]^) or
+ reginop(supreg,p.oper[1]^);
+ end;
+ A_IDIV,A_DIV,A_MUL:
+ begin
+ regReadByInstruction :=
+ reginop(supreg,p.oper[0]^) or (supreg in [RS_EAX,RS_EDX]);
+ end;
+ else
+ begin
+ for opcount := 0 to p.ops-1 do
+ if (p.oper[opCount]^.typ = top_ref) and
+ reginref(supreg,p.oper[opcount]^.ref^) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ for opcount := 1 to maxinschanges do
+ case insprop[p.opcode].ch[opcount] of
+ CH_REAX..CH_REDI,CH_RWEAX..CH_MEDI:
+ if supreg = tch2reg(insprop[p.opcode].ch[opcount]) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ CH_RWOP1,CH_ROP1,CH_MOP1:
+ if //(p.oper[0]^.typ = top_reg) and
+ reginop(supreg,p.oper[0]^) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ Ch_RWOP2,Ch_ROP2,Ch_MOP2:
+ if //(p.oper[1]^.typ = top_reg) and
+ reginop(supreg,p.oper[1]^) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ Ch_RWOP3,Ch_ROP3,Ch_MOP3:
+ if //(p.oper[2]^.typ = top_reg) and
+ reginop(supreg,p.oper[2]^) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+function regInInstruction(supreg: tsuperregister; p1: tai): boolean;
+{ Checks if reg is used by the instruction p1 }
+{ Difference with "regReadBysinstruction() or regModifiedByInstruction()": }
+{ this one ignores CH_ALL opcodes, while regModifiedByInstruction doesn't }
+var
+ p: taicpu;
+ opcount: longint;
+begin
+ regInInstruction := false;
+ if p1.typ <> ait_instruction then
+ exit;
+ p := taicpu(p1);
+ case p.opcode of
+ A_CALL:
+ regininstruction := true;
+ A_IMUL:
+ case p.ops of
+ 1:
+ regInInstruction :=
+ (supreg = RS_EAX) or reginop(supreg,p.oper[0]^);
+ 2,3:
+ regInInstruction :=
+ reginop(supreg,p.oper[0]^) or
+ reginop(supreg,p.oper[1]^) or
+ (assigned(p.oper[2]) and
+ reginop(supreg,p.oper[2]^));
+ end;
+ A_IDIV,A_DIV,A_MUL:
+ regInInstruction :=
+ reginop(supreg,p.oper[0]^) or
+ (supreg in [RS_EAX,RS_EDX])
+ else
+ begin
+ for opcount := 1 to maxinschanges do
+ case insprop[p.opcode].Ch[opCount] of
+ CH_REAX..CH_MEDI:
+ if tch2reg(InsProp[p.opcode].Ch[opCount]) = supreg then
+ begin
+ regInInstruction := true;
+ exit;
+ end;
+ CH_ROp1..CH_MOp1:
+ if reginop(supreg,p.oper[0]^) then
+ begin
+ regInInstruction := true;
+ exit
+ end;
+ Ch_ROp2..Ch_MOp2:
+ if reginop(supreg,p.oper[1]^) then
+ begin
+ regInInstruction := true;
+ exit
+ end;
+ Ch_ROp3..Ch_MOp3:
+ if reginop(supreg,p.oper[2]^) then
+ begin
+ regInInstruction := true;
+ exit
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+function reginop(supreg: tsuperregister; const o:toper): boolean;
+begin
+ reginop := false;
+ case o.typ Of
+ top_reg:
+ reginop :=
+ (getregtype(o.reg) = R_INTREGISTER) and
+ (supreg = getsupreg(o.reg));
+ top_ref:
+ reginop :=
+ ((o.ref^.base <> NR_NO) and
+ (supreg = getsupreg(o.ref^.base))) or
+ ((o.ref^.index <> NR_NO) and
+ (supreg = getsupreg(o.ref^.index)));
+ end;
+end;
+
+
+function RegModifiedByInstruction(supreg: tsuperregister; p1: tai): boolean;
+var
+ InstrProp: TInsProp;
+ TmpResult: Boolean;
+ Cnt: Word;
+begin
+ TmpResult := False;
+ if supreg = RS_INVALID then
+ exit;
+ if (p1.typ = ait_instruction) then
+ case taicpu(p1).opcode of
+ A_IMUL:
+ With taicpu(p1) Do
+ TmpResult :=
+ ((ops = 1) and (supreg in [RS_EAX,RS_EDX])) or
+ ((ops = 2) and (getsupreg(oper[1]^.reg) = supreg)) or
+ ((ops = 3) and (getsupreg(oper[2]^.reg) = supreg));
+ A_DIV, A_IDIV, A_MUL:
+ With taicpu(p1) Do
+ TmpResult :=
+ (supreg in [RS_EAX,RS_EDX]);
+ else
+ begin
+ Cnt := 1;
+ InstrProp := InsProp[taicpu(p1).OpCode];
+ while (Cnt <= maxinschanges) and
+ (InstrProp.Ch[Cnt] <> Ch_None) and
+ not(TmpResult) Do
+ begin
+ case InstrProp.Ch[Cnt] Of
+ Ch_WEAX..Ch_MEDI:
+ TmpResult := supreg = tch2reg(InstrProp.Ch[Cnt]);
+ Ch_RWOp1,Ch_WOp1,Ch_Mop1:
+ TmpResult := (taicpu(p1).oper[0]^.typ = top_reg) and
+ reginop(supreg,taicpu(p1).oper[0]^);
+ Ch_RWOp2,Ch_WOp2,Ch_Mop2:
+ TmpResult := (taicpu(p1).oper[1]^.typ = top_reg) and
+ reginop(supreg,taicpu(p1).oper[1]^);
+ Ch_RWOp3,Ch_WOp3,Ch_Mop3:
+ TmpResult := (taicpu(p1).oper[2]^.typ = top_reg) and
+ reginop(supreg,taicpu(p1).oper[2]^);
+ Ch_FPU: TmpResult := false; // supreg is supposed to be an intreg!! supreg in [RS_ST..RS_ST7,RS_MM0..RS_MM7];
+ Ch_ALL: TmpResult := true;
+ end;
+ inc(Cnt)
+ end
+ end
+ end;
+ RegModifiedByInstruction := TmpResult
+end;
+
+
+function instrWritesFlags(p: tai): boolean;
+var
+ l: longint;
+begin
+ instrWritesFlags := true;
+ case p.typ of
+ ait_instruction:
+ begin
+ for l := 1 to maxinschanges do
+ if InsProp[taicpu(p).opcode].Ch[l] in [Ch_WFlags,Ch_RWFlags,Ch_All] then
+ exit;
+ end;
+ ait_label:
+ exit;
+ end;
+ instrWritesFlags := false;
+end;
+
+
+function instrReadsFlags(p: tai): boolean;
+var
+ l: longint;
+begin
+ instrReadsFlags := true;
+ case p.typ of
+ ait_instruction:
+ begin
+ for l := 1 to maxinschanges do
+ if InsProp[taicpu(p).opcode].Ch[l] in [Ch_RFlags,Ch_RWFlags,Ch_All] then
+ exit;
+ end;
+ ait_label:
+ exit;
+ end;
+ instrReadsFlags := false;
+end;
+
+
+{********************* GetNext and GetLastInstruction *********************}
+function GetNextInstruction(Current: tai; var Next: tai): Boolean;
+{ skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the }
+{ next tai object in Next. Returns false if there isn't any }
+begin
+ repeat
+ if (Current.typ = ait_marker) and
+ (tai_Marker(current).Kind = AsmBlockStart) then
+ begin
+ GetNextInstruction := False;
+ Next := Nil;
+ Exit
+ end;
+ Current := tai(current.Next);
+ while assigned(Current) and
+ ((current.typ in skipInstr) or
+ ((current.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current)))) do
+ Current := tai(current.Next);
+{ if assigned(Current) and
+ (current.typ = ait_Marker) and
+ (tai_Marker(current).Kind = NoPropInfoStart) then
+ begin
+ while assigned(Current) and
+ ((current.typ <> ait_Marker) or
+ (tai_Marker(current).Kind <> NoPropInfoend)) Do
+ Current := tai(current.Next);
+ end;}
+ until not(assigned(Current)) or
+ (current.typ <> ait_Marker) or
+ not(tai_Marker(current).Kind in [NoPropInfoStart,NoPropInfoend]);
+ Next := Current;
+ if assigned(Current) and
+ not((current.typ in SkipInstr) or
+ ((current.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current))))
+ then
+ GetNextInstruction :=
+ not((current.typ = ait_marker) and
+ (tai_marker(current).kind = asmBlockStart))
+ else
+ begin
+ GetNextInstruction := False;
+ Next := nil;
+ end;
+end;
+
+
+function GetLastInstruction(Current: tai; var Last: tai): boolean;
+{skips the ait-types in SkipInstr puts the previous tai object in
+ Last. Returns false if there isn't any}
+begin
+ repeat
+ Current := tai(current.previous);
+ while assigned(Current) and
+ (((current.typ = ait_Marker) and
+ not(tai_Marker(current).Kind in [AsmBlockend{,NoPropInfoend}])) or
+ (current.typ in SkipInstr) or
+ ((current.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current)))) Do
+ Current := tai(current.previous);
+{ if assigned(Current) and
+ (current.typ = ait_Marker) and
+ (tai_Marker(current).Kind = NoPropInfoend) then
+ begin
+ while assigned(Current) and
+ ((current.typ <> ait_Marker) or
+ (tai_Marker(current).Kind <> NoPropInfoStart)) Do
+ Current := tai(current.previous);
+ end;}
+ until not(assigned(Current)) or
+ (current.typ <> ait_Marker) or
+ not(tai_Marker(current).Kind in [NoPropInfoStart,NoPropInfoend]);
+ if not(assigned(Current)) or
+ (current.typ in SkipInstr) or
+ ((current.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current))) or
+ ((current.typ = ait_Marker) and
+ (tai_Marker(current).Kind = AsmBlockend))
+ then
+ begin
+ Last := nil;
+ GetLastInstruction := False
+ end
+ else
+ begin
+ Last := Current;
+ GetLastInstruction := True;
+ end;
+end;
+
+
+procedure SkipHead(var p: tai);
+var
+ oldp: tai;
+begin
+ repeat
+ oldp := p;
+ if (p.typ in SkipInstr) or
+ ((p.typ = ait_marker) and
+ (tai_Marker(p).Kind in [AsmBlockend,inlinestart,inlineend])) then
+ GetNextInstruction(p,p)
+ else if ((p.Typ = Ait_Marker) and
+ (tai_Marker(p).Kind = nopropinfostart)) then
+ {a marker of the NoPropInfoStart can't be the first instruction of a
+ TAAsmoutput list}
+ GetNextInstruction(tai(p.previous),p);
+ until p = oldp
+end;
+
+
+function labelCanBeSkipped(p: tai_label): boolean;
+begin
+ labelCanBeSkipped := not(p.l.is_used) or (p.l.labeltype<>alt_jump);
+end;
+
+{******************* The Data Flow Analyzer functions ********************}
+
+function regLoadedWithNewValue(supreg: tsuperregister; canDependOnPrevValue: boolean;
+ hp: tai): boolean;
+{ assumes reg is a 32bit register }
+var
+ p: taicpu;
+begin
+ if not assigned(hp) or
+ (hp.typ <> ait_instruction) then
+ begin
+ regLoadedWithNewValue := false;
+ exit;
+ end;
+ p := taicpu(hp);
+ regLoadedWithNewValue :=
+ (((p.opcode = A_MOV) or
+ (p.opcode = A_MOVZX) or
+ (p.opcode = A_MOVSX) or
+ (p.opcode = A_LEA)) and
+ (p.oper[1]^.typ = top_reg) and
+ (getsupreg(p.oper[1]^.reg) = supreg) and
+ (canDependOnPrevValue or
+ (p.oper[0]^.typ <> top_ref) or
+ not regInRef(supreg,p.oper[0]^.ref^)) or
+ ((p.opcode = A_POP) and
+ (getsupreg(p.oper[0]^.reg) = supreg)));
+end;
+
+procedure UpdateUsedRegs(var UsedRegs: TRegSet; p: tai);
+{updates UsedRegs with the RegAlloc Information coming after p}
+begin
+ repeat
+ while assigned(p) and
+ ((p.typ in (SkipInstr - [ait_RegAlloc])) or
+ ((p.typ = ait_label) and
+ labelCanBeSkipped(tai_label(p))) or
+ ((p.typ = ait_marker) and
+ (tai_Marker(p).Kind in [AsmBlockend,inlinestart,inlineend]))) do
+ p := tai(p.next);
+ while assigned(p) and
+ (p.typ=ait_RegAlloc) Do
+ begin
+ if (getregtype(tai_regalloc(p).reg) = R_INTREGISTER) then
+ begin
+ case tai_regalloc(p).ratype of
+ ra_alloc :
+ UsedRegs := UsedRegs + [getsupreg(tai_regalloc(p).reg)];
+ ra_dealloc :
+ UsedRegs := UsedRegs - [getsupreg(tai_regalloc(p).reg)];
+ end;
+ end;
+ p := tai(p.next);
+ end;
+ until not(assigned(p)) or
+ (not(p.typ in SkipInstr) and
+ not((p.typ = ait_label) and
+ labelCanBeSkipped(tai_label(p))));
+end;
+
+
+procedure AllocRegBetween(asml: taasmoutput; reg: tregister; p1, p2: tai; const initialusedregs: tregset);
+{ allocates register reg between (and including) instructions p1 and p2 }
+{ the type of p1 and p2 must not be in SkipInstr }
+{ note that this routine is both called from the peephole optimizer }
+{ where optinfo is not yet initialised) and from the cse (where it is) }
+var
+ hp: tai;
+ lastRemovedWasDealloc: boolean;
+ supreg: tsuperregister;
+begin
+{$ifdef EXTDEBUG}
+ if assigned(p1.optinfo) and
+ (ptaiprop(p1.optinfo)^.usedregs <> initialusedregs) then
+ internalerror(2004101010);
+{$endif EXTDEBUG}
+ supreg := getsupreg(reg);
+{ if not(supreg in rg.usableregsint+[RS_EDI,RS_ESI]) or
+ not(assigned(p1)) then}
+ if not(supreg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_EDI,RS_ESI]) or
+ not(assigned(p1)) then
+ { this happens with registers which are loaded implicitely, outside the }
+ { current block (e.g. esi with self) }
+ exit;
+ { make sure we allocate it for this instruction }
+ getnextinstruction(p2,p2);
+ lastRemovedWasDealloc := false;
+{$ifdef allocregdebug}
+ hp := tai_comment.Create(strpnew('allocating '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
+ ' from here...'));
+ insertllitem(asml,p1.previous,p1,hp);
+ hp := tai_comment.Create(strpnew('allocated '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
+ ' till here...'));
+ insertllitem(asml,p2,p1.next,hp);
+{$endif allocregdebug}
+ if not(supreg in initialusedregs) then
+ begin
+ hp := tai_regalloc.alloc(reg,nil);
+ insertllItem(asmL,p1.previous,p1,hp);
+ end;
+ while assigned(p1) and
+ (p1 <> p2) do
+ begin
+ if assigned(p1.optinfo) then
+ include(ptaiprop(p1.optinfo)^.usedregs,supreg);
+ p1 := tai(p1.next);
+ repeat
+ while assigned(p1) and
+ (p1.typ in (SkipInstr-[ait_regalloc])) Do
+ p1 := tai(p1.next);
+{ remove all allocation/deallocation info about the register in between }
+ if assigned(p1) and
+ (p1.typ = ait_regalloc) then
+ if (getsupreg(tai_regalloc(p1).reg) = supreg) then
+ begin
+ lastRemovedWasDealloc := (tai_regalloc(p1).ratype=ra_dealloc);
+ hp := tai(p1.Next);
+ asml.Remove(p1);
+ p1.free;
+ p1 := hp;
+ end
+ else p1 := tai(p1.next);
+ until not(assigned(p1)) or
+ not(p1.typ in SkipInstr);
+ end;
+ if assigned(p1) then
+ begin
+ if lastRemovedWasDealloc then
+ begin
+ hp := tai_regalloc.DeAlloc(reg,nil);
+ insertLLItem(asmL,p1.previous,p1,hp);
+ end;
+ end;
+end;
+
+
+function FindRegDealloc(supreg: tsuperregister; p: tai): boolean;
+var
+ hp: tai;
+ first: boolean;
+begin
+ findregdealloc := false;
+ first := true;
+ while assigned(p.previous) and
+ ((tai(p.previous).typ in (skipinstr+[ait_align])) or
+ ((tai(p.previous).typ = ait_label) and
+ labelCanBeSkipped(tai_label(p.previous)))) do
+ begin
+ p := tai(p.previous);
+ if (p.typ = ait_regalloc) and
+ (getsupreg(tai_regalloc(p).reg) = supreg) then
+ if (tai_regalloc(p).ratype=ra_dealloc) then
+ if first then
+ begin
+ findregdealloc := true;
+ break;
+ end
+ else
+ begin
+ findRegDealloc :=
+ getNextInstruction(p,hp) and
+ regLoadedWithNewValue(supreg,false,hp);
+ break
+ end
+ else
+ first := false;
+ end
+end;
+
+
+
+procedure incState(var S: Byte; amount: longint);
+{increases S by 1, wraps around at $ffff to 0 (so we won't get overflow
+ errors}
+begin
+ if (s <= $ff - amount) then
+ inc(s, amount)
+ else s := longint(s) + amount - $ff;
+end;
+
+
+function sequenceDependsonReg(const Content: TContent; seqreg: tsuperregister; supreg: tsuperregister): Boolean;
+{ Content is the sequence of instructions that describes the contents of }
+{ seqReg. reg is being overwritten by the current instruction. if the }
+{ content of seqReg depends on reg (ie. because of a }
+{ "movl (seqreg,reg), seqReg" instruction), this function returns true }
+var
+ p: tai;
+ Counter: Word;
+ TmpResult: Boolean;
+ RegsChecked: TRegSet;
+begin
+ RegsChecked := [];
+ p := Content.StartMod;
+ TmpResult := False;
+ Counter := 1;
+ while not(TmpResult) and
+ (Counter <= Content.NrOfMods) Do
+ begin
+ if (p.typ = ait_instruction) and
+ ((taicpu(p).opcode = A_MOV) or
+ (taicpu(p).opcode = A_MOVZX) or
+ (taicpu(p).opcode = A_MOVSX) or
+ (taicpu(p).opcode = A_LEA)) and
+ (taicpu(p).oper[0]^.typ = top_ref) then
+ With taicpu(p).oper[0]^.ref^ Do
+ if ((base = current_procinfo.FramePointer) or
+ (assigned(symbol) and (base = NR_NO))) and
+ (index = NR_NO) then
+ begin
+ RegsChecked := RegsChecked + [getsupreg(taicpu(p).oper[1]^.reg)];
+ if supreg = getsupreg(taicpu(p).oper[1]^.reg) then
+ break;
+ end
+ else
+ tmpResult :=
+ regReadByInstruction(supreg,p) and
+ regModifiedByInstruction(seqReg,p)
+ else
+ tmpResult :=
+ regReadByInstruction(supreg,p) and
+ regModifiedByInstruction(seqReg,p);
+ inc(Counter);
+ GetNextInstruction(p,p)
+ end;
+ sequenceDependsonReg := TmpResult
+end;
+
+
+procedure invalidateDependingRegs(p1: ptaiprop; supreg: tsuperregister);
+var
+ counter: tsuperregister;
+begin
+ for counter := RS_EAX to RS_EDI do
+ if counter <> supreg then
+ with p1^.regs[counter] Do
+ begin
+ if (typ in [con_ref,con_noRemoveRef]) and
+ sequenceDependsOnReg(p1^.Regs[counter],counter,supreg) then
+ if typ in [con_ref, con_invalid] then
+ typ := con_invalid
+ { con_noRemoveRef = con_unknown }
+ else
+ typ := con_unknown;
+ if assigned(memwrite) and
+ regInRef(counter,memwrite.oper[1]^.ref^) then
+ memwrite := nil;
+ end;
+end;
+
+
+procedure DestroyReg(p1: ptaiprop; supreg: tsuperregister; doincState:Boolean);
+{Destroys the contents of the register reg in the ptaiprop p1, as well as the
+ contents of registers are loaded with a memory location based on reg.
+ doincState is false when this register has to be destroyed not because
+ it's contents are directly modified/overwritten, but because of an indirect
+ action (e.g. this register holds the contents of a variable and the value
+ of the variable in memory is changed) }
+begin
+ { the following happens for fpu registers }
+ if (supreg < low(NrOfInstrSinceLastMod)) or
+ (supreg > high(NrOfInstrSinceLastMod)) then
+ exit;
+ NrOfInstrSinceLastMod[supreg] := 0;
+ with p1^.regs[supreg] do
+ begin
+ if doincState then
+ begin
+ incState(wstate,1);
+ typ := con_unknown;
+ startmod := nil;
+ end
+ else
+ if typ in [con_ref,con_const,con_invalid] then
+ typ := con_invalid
+ { con_noRemoveRef = con_unknown }
+ else
+ typ := con_unknown;
+ memwrite := nil;
+ end;
+ invalidateDependingRegs(p1,supreg);
+end;
+
+{procedure AddRegsToSet(p: tai; var RegSet: TRegSet);
+begin
+ if (p.typ = ait_instruction) then
+ begin
+ case taicpu(p).oper[0]^.typ Of
+ top_reg:
+ if not(taicpu(p).oper[0]^.reg in [RS_NO,RS_ESP,current_procinfo.FramePointer]) then
+ RegSet := RegSet + [taicpu(p).oper[0]^.reg];
+ top_ref:
+ With TReference(taicpu(p).oper[0]^) Do
+ begin
+ if not(base in [current_procinfo.FramePointer,RS_NO,RS_ESP])
+ then RegSet := RegSet + [base];
+ if not(index in [current_procinfo.FramePointer,RS_NO,RS_ESP])
+ then RegSet := RegSet + [index];
+ end;
+ end;
+ case taicpu(p).oper[1]^.typ Of
+ top_reg:
+ if not(taicpu(p).oper[1]^.reg in [RS_NO,RS_ESP,current_procinfo.FramePointer]) then
+ if RegSet := RegSet + [TRegister(TwoWords(taicpu(p).oper[1]^).Word1];
+ top_ref:
+ With TReference(taicpu(p).oper[1]^) Do
+ begin
+ if not(base in [current_procinfo.FramePointer,RS_NO,RS_ESP])
+ then RegSet := RegSet + [base];
+ if not(index in [current_procinfo.FramePointer,RS_NO,RS_ESP])
+ then RegSet := RegSet + [index];
+ end;
+ end;
+ end;
+end;}
+
+function OpsEquivalent(const o1, o2: toper; const oldinst, newinst: taicpu; var RegInfo: toptreginfo; OpAct: TopAction): Boolean;
+begin {checks whether the two ops are equivalent}
+ OpsEquivalent := False;
+ if o1.typ=o2.typ then
+ case o1.typ Of
+ top_reg:
+ OpsEquivalent :=RegsEquivalent(o1.reg,o2.reg, oldinst, newinst, RegInfo, OpAct);
+ top_ref:
+ OpsEquivalent := RefsEquivalent(o1.ref^, o2.ref^, oldinst, newinst, RegInfo);
+ Top_Const:
+ OpsEquivalent := o1.val = o2.val;
+ Top_None:
+ OpsEquivalent := True
+ end;
+end;
+
+
+function OpsEqual(const o1,o2:toper): Boolean;
+begin {checks whether the two ops are equal}
+ OpsEqual := False;
+ if o1.typ=o2.typ then
+ case o1.typ Of
+ top_reg :
+ OpsEqual:=o1.reg=o2.reg;
+ top_ref :
+ OpsEqual := RefsEqual(o1.ref^, o2.ref^);
+ Top_Const :
+ OpsEqual:=o1.val=o2.val;
+ Top_None :
+ OpsEqual := True
+ end;
+end;
+
+
+function sizescompatible(loadsize,newsize: topsize): boolean;
+ begin
+ case loadsize of
+ S_B,S_BW,S_BL:
+ sizescompatible := (newsize = loadsize) or (newsize = S_B);
+ S_W,S_WL:
+ sizescompatible := (newsize = loadsize) or (newsize = S_W);
+ else
+ sizescompatible := newsize = S_L;
+ end;
+ end;
+
+
+function opscompatible(p1,p2: taicpu): boolean;
+begin
+ case p1.opcode of
+ A_MOVZX,A_MOVSX:
+ opscompatible :=
+ ((p2.opcode = p1.opcode) or (p2.opcode = A_MOV)) and
+ sizescompatible(p1.opsize,p2.opsize);
+ else
+ opscompatible :=
+ (p1.opcode = p2.opcode) and
+ (p1.ops = p2.ops) and
+ (p1.opsize = p2.opsize);
+ end;
+end;
+
+
+function InstructionsEquivalent(p1, p2: tai; var RegInfo: toptreginfo): Boolean;
+{$ifdef csdebug}
+var
+ hp: tai;
+{$endif csdebug}
+begin {checks whether two taicpu instructions are equal}
+ if assigned(p1) and assigned(p2) and
+ (tai(p1).typ = ait_instruction) and
+ (tai(p2).typ = ait_instruction) and
+ opscompatible(taicpu(p1),taicpu(p2)) and
+ (not(assigned(taicpu(p1).oper[0])) or
+ (taicpu(p1).oper[0]^.typ = taicpu(p2).oper[0]^.typ)) and
+ (not(assigned(taicpu(p1).oper[1])) or
+ (taicpu(p1).oper[1]^.typ = taicpu(p2).oper[1]^.typ)) and
+ (not(assigned(taicpu(p1).oper[2])) or
+ (taicpu(p1).oper[2]^.typ = taicpu(p2).oper[2]^.typ)) then
+ {both instructions have the same structure:
+ "<operator> <operand of type1>, <operand of type 2>"}
+ if ((taicpu(p1).opcode = A_MOV) or
+ (taicpu(p1).opcode = A_MOVZX) or
+ (taicpu(p1).opcode = A_MOVSX) or
+ (taicpu(p1).opcode = A_LEA)) and
+ (taicpu(p1).oper[0]^.typ = top_ref) {then .oper[1]^t = top_reg} then
+ if not(RegInRef(getsupreg(taicpu(p1).oper[1]^.reg), taicpu(p1).oper[0]^.ref^)) then
+ {the "old" instruction is a load of a register with a new value, not with
+ a value based on the contents of this register (so no "mov (reg), reg")}
+ if not(RegInRef(getsupreg(taicpu(p2).oper[1]^.reg), taicpu(p2).oper[0]^.ref^)) and
+ RefsEquivalent(taicpu(p1).oper[0]^.ref^, taicpu(p2).oper[0]^.ref^,taicpu(p1), taicpu(p2), reginfo) then
+ {the "new" instruction is also a load of a register with a new value, and
+ this value is fetched from the same memory location}
+ begin
+ With taicpu(p2).oper[0]^.ref^ Do
+ begin
+ if (base <> NR_NO) and
+ (not(getsupreg(base) in [getsupreg(current_procinfo.FramePointer), RS_ESP])) then
+ include(RegInfo.RegsLoadedForRef, getsupreg(base));
+ if (index <> NR_NO) and
+ (not(getsupreg(index) in [getsupreg(current_procinfo.FramePointer), RS_ESP])) then
+ include(RegInfo.RegsLoadedForRef, getsupreg(index));
+ end;
+ {add the registers from the reference (.oper[0]^) to the RegInfo, all registers
+ from the reference are the same in the old and in the new instruction
+ sequence}
+ AddOp2RegInfo(taicpu(p1).oper[0]^, RegInfo);
+ {the registers from .oper[1]^ have to be equivalent, but not necessarily equal}
+ InstructionsEquivalent :=
+ RegsEquivalent(taicpu(p1).oper[1]^.reg,
+ taicpu(p2).oper[1]^.reg, taicpu(p1), taicpu(p2), RegInfo, OpAct_Write);
+ end
+ {the registers are loaded with values from different memory locations. if
+ this was allowed, the instructions "mov -4(esi),eax" and "mov -4(ebp),eax"
+ would be considered equivalent}
+ else
+ InstructionsEquivalent := False
+ else
+ {load register with a value based on the current value of this register}
+ begin
+ With taicpu(p2).oper[0]^.ref^ Do
+ begin
+ if (base <> NR_NO) and
+ (not(getsupreg(base) in [getsupreg(current_procinfo.FramePointer),
+ getsupreg(taicpu(p2).oper[1]^.reg),RS_ESP])) then
+ {it won't do any harm if the register is already in RegsLoadedForRef}
+ begin
+ include(RegInfo.RegsLoadedForRef, getsupreg(base));
+{$ifdef csdebug}
+ Writeln(std_regname(base), ' added');
+{$endif csdebug}
+ end;
+ if (index <> NR_NO) and
+ (not(getsupreg(index) in [getsupreg(current_procinfo.FramePointer),
+ getsupreg(taicpu(p2).oper[1]^.reg),RS_ESP])) then
+ begin
+ include(RegInfo.RegsLoadedForRef, getsupreg(index));
+{$ifdef csdebug}
+ Writeln(std_regname(index), ' added');
+{$endif csdebug}
+ end;
+
+ end;
+ if (taicpu(p2).oper[1]^.reg <> NR_NO) and
+ (not(getsupreg(taicpu(p2).oper[1]^.reg) in [getsupreg(current_procinfo.FramePointer),RS_ESP])) then
+ begin
+ RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef -
+ [getsupreg(taicpu(p2).oper[1]^.reg)];
+{$ifdef csdebug}
+ Writeln(std_regname(newreg(R_INTREGISTER,getsupreg(taicpu(p2).oper[1]^.reg),R_SUBWHOLE)), ' removed');
+{$endif csdebug}
+ end;
+ InstructionsEquivalent :=
+ OpsEquivalent(taicpu(p1).oper[0]^, taicpu(p2).oper[0]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Read) and
+ OpsEquivalent(taicpu(p1).oper[1]^, taicpu(p2).oper[1]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Write)
+ end
+ else
+ {an instruction <> mov, movzx, movsx}
+ begin
+ {$ifdef csdebug}
+ hp := tai_comment.Create(strpnew('checking if equivalent'));
+ hp.previous := p2;
+ hp.next := p2.next;
+ p2.next.previous := hp;
+ p2.next := hp;
+ {$endif csdebug}
+ InstructionsEquivalent :=
+ (not(assigned(taicpu(p1).oper[0])) or
+ OpsEquivalent(taicpu(p1).oper[0]^, taicpu(p2).oper[0]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Unknown)) and
+ (not(assigned(taicpu(p1).oper[1])) or
+ OpsEquivalent(taicpu(p1).oper[1]^, taicpu(p2).oper[1]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Unknown)) and
+ (not(assigned(taicpu(p1).oper[2])) or
+ OpsEquivalent(taicpu(p1).oper[2]^, taicpu(p2).oper[2]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Unknown))
+ end
+ {the instructions haven't even got the same structure, so they're certainly
+ not equivalent}
+ else
+ begin
+ {$ifdef csdebug}
+ hp := tai_comment.Create(strpnew('different opcodes/format'));
+ hp.previous := p2;
+ hp.next := p2.next;
+ p2.next.previous := hp;
+ p2.next := hp;
+ {$endif csdebug}
+ InstructionsEquivalent := False;
+ end;
+ {$ifdef csdebug}
+ hp := tai_comment.Create(strpnew('instreq: '+tostr(byte(instructionsequivalent))));
+ hp.previous := p2;
+ hp.next := p2.next;
+ p2.next.previous := hp;
+ p2.next := hp;
+ {$endif csdebug}
+end;
+
+(*
+function InstructionsEqual(p1, p2: tai): Boolean;
+begin {checks whether two taicpu instructions are equal}
+ InstructionsEqual :=
+ assigned(p1) and assigned(p2) and
+ ((tai(p1).typ = ait_instruction) and
+ (tai(p1).typ = ait_instruction) and
+ (taicpu(p1).opcode = taicpu(p2).opcode) and
+ (taicpu(p1).oper[0]^.typ = taicpu(p2).oper[0]^.typ) and
+ (taicpu(p1).oper[1]^.typ = taicpu(p2).oper[1]^.typ) and
+ OpsEqual(taicpu(p1).oper[0]^.typ, taicpu(p1).oper[0]^, taicpu(p2).oper[0]^) and
+ OpsEqual(taicpu(p1).oper[1]^.typ, taicpu(p1).oper[1]^, taicpu(p2).oper[1]^))
+end;
+*)
+
+procedure readreg(p: ptaiprop; supreg: tsuperregister);
+begin
+ if supreg in [RS_EAX..RS_EDI] then
+ incState(p^.regs[supreg].rstate,1)
+end;
+
+
+procedure readref(p: ptaiprop; const ref: preference);
+begin
+ if ref^.base <> NR_NO then
+ readreg(p, getsupreg(ref^.base));
+ if ref^.index <> NR_NO then
+ readreg(p, getsupreg(ref^.index));
+end;
+
+
+procedure ReadOp(p: ptaiprop;const o:toper);
+begin
+ case o.typ Of
+ top_reg: readreg(p, getsupreg(o.reg));
+ top_ref: readref(p, o.ref);
+ end;
+end;
+
+
+function RefInInstruction(const ref: TReference; p: tai;
+ RefsEq: TRefCompare; size: tcgsize): Boolean;
+{checks whehter ref is used in p}
+var
+ mysize: tcgsize;
+ TmpResult: Boolean;
+begin
+ TmpResult := False;
+ if (p.typ = ait_instruction) then
+ begin
+ mysize := topsize2tcgsize[taicpu(p).opsize];
+ if (taicpu(p).ops >= 1) and
+ (taicpu(p).oper[0]^.typ = top_ref) then
+ TmpResult := RefsEq(taicpu(p).oper[0]^.ref^,ref,mysize,size);
+ if not(TmpResult) and
+ (taicpu(p).ops >= 2) and
+ (taicpu(p).oper[1]^.typ = top_ref) then
+ TmpResult := RefsEq(taicpu(p).oper[1]^.ref^,ref,mysize,size);
+ if not(TmpResult) and
+ (taicpu(p).ops >= 3) and
+ (taicpu(p).oper[2]^.typ = top_ref) then
+ TmpResult := RefsEq(taicpu(p).oper[2]^.ref^,ref,mysize,size);
+ end;
+ RefInInstruction := TmpResult;
+end;
+
+
+function RefInSequence(const ref: TReference; Content: TContent;
+ RefsEq: TRefCompare; size: tcgsize): Boolean;
+{checks the whole sequence of Content (so StartMod and and the next NrOfMods
+ tai objects) to see whether ref is used somewhere}
+var p: tai;
+ Counter: Word;
+ TmpResult: Boolean;
+begin
+ p := Content.StartMod;
+ TmpResult := False;
+ Counter := 1;
+ while not(TmpResult) and
+ (Counter <= Content.NrOfMods) Do
+ begin
+ if (p.typ = ait_instruction) and
+ RefInInstruction(ref, p, RefsEq, size)
+ then TmpResult := True;
+ inc(Counter);
+ GetNextInstruction(p,p)
+ end;
+ RefInSequence := TmpResult
+end;
+
+{$ifdef q+}
+{$q-}
+{$define overflowon}
+{$endif q+}
+// checks whether a write to r2 of size "size" contains address r1
+function arrayrefsoverlapping(const r1, r2: treference; size1, size2: tcgsize): Boolean;
+var
+ realsize1, realsize2: aint;
+begin
+ realsize1 := tcgsize2size[size1];
+ realsize2 := tcgsize2size[size2];
+ arrayrefsoverlapping :=
+ (r2.offset <= r1.offset+realsize1) and
+ (r1.offset <= r2.offset+realsize2) and
+ (r1.segment = r2.segment) and
+ (r1.symbol=r2.symbol) and
+ (r1.base = r2.base)
+end;
+{$ifdef overflowon}
+{$q+}
+{$undef overflowon}
+{$endif overflowon}
+
+function isSimpleRef(const ref: treference): boolean;
+{ returns true if ref is reference to a local or global variable, to a }
+{ parameter or to an object field (this includes arrays). Returns false }
+{ otherwise. }
+begin
+ isSimpleRef :=
+ assigned(ref.symbol) or
+ (ref.base = current_procinfo.framepointer);
+end;
+
+
+function containsPointerRef(p: tai): boolean;
+{ checks if an instruction contains a reference which is a pointer location }
+var
+ hp: taicpu;
+ count: longint;
+begin
+ containsPointerRef := false;
+ if p.typ <> ait_instruction then
+ exit;
+ hp := taicpu(p);
+ for count := 0 to hp.ops-1 do
+ begin
+ case hp.oper[count]^.typ of
+ top_ref:
+ if not isSimpleRef(hp.oper[count]^.ref^) then
+ begin
+ containsPointerRef := true;
+ exit;
+ end;
+ top_none:
+ exit;
+ end;
+ end;
+end;
+
+
+function containsPointerLoad(c: tcontent): boolean;
+{ checks whether the contents of a register contain a pointer reference }
+var
+ p: tai;
+ count: longint;
+begin
+ containsPointerLoad := false;
+ p := c.startmod;
+ for count := c.nrOfMods downto 1 do
+ begin
+ if containsPointerRef(p) then
+ begin
+ containsPointerLoad := true;
+ exit;
+ end;
+ getnextinstruction(p,p);
+ end;
+end;
+
+
+function writeToMemDestroysContents(regWritten: tsuperregister; const ref: treference;
+ supreg: tsuperregister; size: tcgsize; const c: tcontent; var invalsmemwrite: boolean): boolean;
+{ returns whether the contents c of reg are invalid after regWritten is }
+{ is written to ref }
+var
+ refsEq: trefCompare;
+begin
+ if isSimpleRef(ref) then
+ begin
+ if (ref.index <> NR_NO) or
+ (assigned(ref.symbol) and
+ (ref.base <> NR_NO)) then
+ { local/global variable or parameter which is an array }
+ refsEq := {$ifdef fpc}@{$endif}arrayRefsOverlapping
+ else
+ { local/global variable or parameter which is not an array }
+ refsEq := {$ifdef fpc}@{$endif}refsOverlapping;
+ invalsmemwrite :=
+ assigned(c.memwrite) and
+ ((not(cs_uncertainOpts in aktglobalswitches) and
+ containsPointerRef(c.memwrite)) or
+ refsEq(c.memwrite.oper[1]^.ref^,ref,topsize2tcgsize[c.memwrite.opsize],size));
+ if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
+ begin
+ writeToMemDestroysContents := false;
+ exit;
+ end;
+
+ { write something to a parameter, a local or global variable, so }
+ { * with uncertain optimizations on: }
+ { - destroy the contents of registers whose contents have somewhere a }
+ { "mov?? (ref), %reg". WhichReg (this is the register whose contents }
+ { are being written to memory) is not destroyed if it's StartMod is }
+ { of that form and NrOfMods = 1 (so if it holds ref, but is not a }
+ { expression based on ref) }
+ { * with uncertain optimizations off: }
+ { - also destroy registers that contain any pointer }
+ with c do
+ writeToMemDestroysContents :=
+ (typ in [con_ref,con_noRemoveRef]) and
+ ((not(cs_uncertainOpts in aktglobalswitches) and
+ containsPointerLoad(c)
+ ) or
+ (refInSequence(ref,c,refsEq,size) and
+ ((supreg <> regWritten) or
+ not((nrOfMods = 1) and
+ {StarMod is always of the type ait_instruction}
+ (taicpu(StartMod).oper[0]^.typ = top_ref) and
+ refsEq(taicpu(StartMod).oper[0]^.ref^, ref, topsize2tcgsize[taicpu(StartMod).opsize],size)
+ )
+ )
+ )
+ );
+ end
+ else
+ { write something to a pointer location, so }
+ { * with uncertain optimzations on: }
+ { - do not destroy registers which contain a local/global variable or }
+ { a parameter, except if DestroyRefs is called because of a "movsl" }
+ { * with uncertain optimzations off: }
+ { - destroy every register which contains a memory location }
+ begin
+ invalsmemwrite :=
+ assigned(c.memwrite) and
+ (not(cs_UncertainOpts in aktglobalswitches) or
+ containsPointerRef(c.memwrite));
+ if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
+ begin
+ writeToMemDestroysContents := false;
+ exit;
+ end;
+ with c do
+ writeToMemDestroysContents :=
+ (typ in [con_ref,con_noRemoveRef]) and
+ (not(cs_UncertainOpts in aktglobalswitches) or
+ { for movsl }
+ ((ref.base = NR_EDI) and (ref.index = NR_EDI)) or
+ { don't destroy if reg contains a parameter, local or global variable }
+ containsPointerLoad(c)
+ );
+ end;
+end;
+
+
+function writeToRegDestroysContents(destReg, supreg: tsuperregister;
+ const c: tcontent): boolean;
+{ returns whether the contents c of reg are invalid after destReg is }
+{ modified }
+begin
+ writeToRegDestroysContents :=
+ (c.typ in [con_ref,con_noRemoveRef,con_invalid]) and
+ sequenceDependsOnReg(c,supreg,destReg);
+end;
+
+
+function writeDestroysContents(const op: toper; supreg: tsuperregister; size: tcgsize;
+ const c: tcontent; var memwritedestroyed: boolean): boolean;
+{ returns whether the contents c of reg are invalid after regWritten is }
+{ is written to op }
+begin
+ memwritedestroyed := false;
+ case op.typ of
+ top_reg:
+ writeDestroysContents :=
+ writeToRegDestroysContents(getsupreg(op.reg),supreg,c);
+ top_ref:
+ writeDestroysContents :=
+ writeToMemDestroysContents(RS_INVALID,op.ref^,supreg,size,c,memwritedestroyed);
+ else
+ writeDestroysContents := false;
+ end;
+end;
+
+
+procedure destroyRefs(p: tai; const ref: treference; regwritten: tsuperregister; size: tcgsize);
+{ destroys all registers which possibly contain a reference to ref, regWritten }
+{ is the register whose contents are being written to memory (if this proc }
+{ is called because of a "mov?? %reg, (mem)" instruction) }
+var
+ counter: tsuperregister;
+ destroymemwrite: boolean;
+begin
+ for counter := RS_EAX to RS_EDI Do
+ begin
+ if writeToMemDestroysContents(regwritten,ref,counter,size,
+ ptaiprop(p.optInfo)^.regs[counter],destroymemwrite) then
+ destroyReg(ptaiprop(p.optInfo), counter, false)
+ else if destroymemwrite then
+ ptaiprop(p.optinfo)^.regs[counter].MemWrite := nil;
+ end;
+end;
+
+
+procedure DestroyAllRegs(p: ptaiprop; read, written: boolean);
+var Counter: tsuperregister;
+begin {initializes/desrtoys all registers}
+ For Counter := RS_EAX To RS_EDI Do
+ begin
+ if read then
+ readreg(p, Counter);
+ DestroyReg(p, Counter, written);
+ p^.regs[counter].MemWrite := nil;
+ end;
+ p^.DirFlag := F_Unknown;
+end;
+
+
+procedure DestroyOp(taiObj: tai; const o:Toper);
+{$ifdef statedebug}
+var
+ hp: tai;
+{$endif statedebug}
+begin
+ case o.typ Of
+ top_reg:
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+std_regname(o.reg)));
+ hp.next := taiobj.next;
+ hp.previous := taiobj;
+ taiobj.next := hp;
+ if assigned(hp.next) then
+ hp.next.previous := hp;
+{$endif statedebug}
+ DestroyReg(ptaiprop(taiObj.OptInfo), getsupreg(o.reg), true);
+ end;
+ top_ref:
+ begin
+ readref(ptaiprop(taiObj.OptInfo), o.ref);
+ DestroyRefs(taiObj, o.ref^, RS_INVALID,topsize2tcgsize[(taiobj as taicpu).opsize]);
+ end;
+ end;
+end;
+
+
+procedure AddInstr2RegContents({$ifdef statedebug} asml: taasmoutput; {$endif}
+p: taicpu; supreg: tsuperregister);
+{$ifdef statedebug}
+var
+ hp: tai;
+{$endif statedebug}
+begin
+ With ptaiprop(p.optinfo)^.regs[supreg] Do
+ if (typ in [con_ref,con_noRemoveRef]) then
+ begin
+ incState(wstate,1);
+ { also store how many instructions are part of the sequence in the first }
+ { instructions ptaiprop, so it can be easily accessed from within }
+ { CheckSequence}
+ inc(NrOfMods, NrOfInstrSinceLastMod[supreg]);
+ ptaiprop(tai(StartMod).OptInfo)^.Regs[supreg].NrOfMods := NrOfMods;
+ NrOfInstrSinceLastMod[supreg] := 0;
+ invalidateDependingRegs(p.optinfo,supreg);
+ ptaiprop(p.optinfo)^.regs[supreg].memwrite := nil;
+{$ifdef StateDebug}
+ hp := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+': '+tostr(ptaiprop(p.optinfo)^.Regs[supreg].WState)
+ + ' -- ' + tostr(ptaiprop(p.optinfo)^.Regs[supreg].nrofmods)));
+ InsertLLItem(AsmL, p, p.next, hp);
+{$endif StateDebug}
+ end
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))));
+ insertllitem(asml,p,p.next,hp);
+{$endif statedebug}
+ DestroyReg(ptaiprop(p.optinfo), supreg, true);
+{$ifdef StateDebug}
+ hp := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+': '+tostr(ptaiprop(p.optinfo)^.Regs[supreg].WState)));
+ InsertLLItem(AsmL, p, p.next, hp);
+{$endif StateDebug}
+ end
+end;
+
+
+procedure AddInstr2OpContents({$ifdef statedebug} asml: TAAsmoutput; {$endif}
+p: taicpu; const oper: TOper);
+begin
+ if oper.typ = top_reg then
+ AddInstr2RegContents({$ifdef statedebug} asml, {$endif}p, getsupreg(oper.reg))
+ else
+ begin
+ ReadOp(ptaiprop(p.optinfo), oper);
+ DestroyOp(p, oper);
+ end
+end;
+
+
+{*************************************************************************************}
+{************************************** TDFAOBJ **************************************}
+{*************************************************************************************}
+
+constructor tdfaobj.create(_list: taasmoutput);
+begin
+ list := _list;
+ blockstart := nil;
+ blockend := nil;
+ nroftaiobjs := 0;
+ taipropblock := nil;
+ lolab := 0;
+ hilab := 0;
+ labdif := 0;
+ labeltable := nil;
+end;
+
+
+procedure tdfaobj.initlabeltable;
+var
+ labelfound: boolean;
+ p, prev: tai;
+ hp1, hp2: tai;
+{$ifdef i386}
+ regcounter,
+ supreg : tsuperregister;
+{$endif i386}
+ usedregs, nodeallocregs: tregset;
+begin
+ labelfound := false;
+ lolab := maxlongint;
+ hilab := 0;
+ p := blockstart;
+ prev := p;
+ while assigned(p) do
+ begin
+ if (tai(p).typ = ait_label) then
+ if not labelcanbeskipped(tai_label(p)) then
+ begin
+ labelfound := true;
+ if (tai_Label(p).l.labelnr < lolab) then
+ lolab := tai_label(p).l.labelnr;
+ if (tai_Label(p).l.labelnr > hilab) then
+ hilab := tai_label(p).l.labelnr;
+ end;
+ prev := p;
+ getnextinstruction(p, p);
+ end;
+ if (prev.typ = ait_marker) and
+ (tai_marker(prev).kind = asmblockstart) then
+ blockend := prev
+ else blockend := nil;
+ if labelfound then
+ labdif := hilab+1-lolab
+ else labdif := 0;
+
+ usedregs := [];
+ if (labdif <> 0) then
+ begin
+ getmem(labeltable, labdif*sizeof(tlabeltableitem));
+ fillchar(labeltable^, labdif*sizeof(tlabeltableitem), 0);
+ end;
+ p := blockstart;
+ prev := p;
+ while (p <> blockend) do
+ begin
+ case p.typ of
+ ait_label:
+ if not labelcanbeskipped(tai_label(p)) then
+ labeltable^[tai_label(p).l.labelnr-lolab].taiobj := p;
+{$ifdef i386}
+ ait_regalloc:
+ begin
+ supreg:=getsupreg(tai_regalloc(p).reg);
+ case tai_regalloc(p).ratype of
+ ra_alloc :
+ begin
+ if not(supreg in usedregs) then
+ include(usedregs, supreg)
+ else
+ begin
+ //addregdeallocfor(list, tai_regalloc(p).reg, p);
+ hp1 := tai(p.previous);
+ list.remove(p);
+ p.free;
+ p := hp1;
+ end;
+ end;
+ ra_dealloc :
+ begin
+ exclude(usedregs, supreg);
+ hp1 := p;
+ hp2 := nil;
+ while not(findregalloc(supreg,tai(hp1.next),ra_alloc)) and
+ getnextinstruction(hp1, hp1) and
+ regininstruction(getsupreg(tai_regalloc(p).reg), hp1) Do
+ hp2 := hp1;
+ if hp2 <> nil then
+ begin
+ hp1 := tai(p.previous);
+ list.remove(p);
+ insertllitem(list, hp2, tai(hp2.next), p);
+ p := hp1;
+ end
+ else if findregalloc(getsupreg(tai_regalloc(p).reg), tai(p.next),ra_alloc)
+ and getnextinstruction(p,hp1) then
+ begin
+ hp1 := tai(p.previous);
+ list.remove(p);
+ p.free;
+ p := hp1;
+// don't include here, since then the allocation will be removed when it's processed
+// include(usedregs,supreg);
+ end;
+ end;
+ end;
+ end;
+{$endif i386}
+ end;
+ repeat
+ prev := p;
+ p := tai(p.next);
+ until not(assigned(p)) or
+ (p = blockend) or
+ not(p.typ in (skipinstr - [ait_regalloc]));
+ end;
+{$ifdef i386}
+ { don't add deallocation for function result variable or for regvars}
+ getNoDeallocRegs(noDeallocRegs);
+ usedRegs := usedRegs - noDeallocRegs;
+ for regCounter := RS_EAX to RS_EDI do
+ if regCounter in usedRegs then
+ addRegDeallocFor(list,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prev);
+{$endif i386}
+end;
+
+
+function tdfaobj.pass_1(_blockstart: tai): tai;
+begin
+ blockstart := _blockstart;
+ initlabeltable;
+ pass_1 := blockend;
+end;
+
+
+
+function tdfaobj.initdfapass2: boolean;
+{reserves memory for the PtaiProps in one big memory block when not using
+ TP, returns False if not enough memory is available for the optimizer in all
+ cases}
+var
+ p: tai;
+ count: Longint;
+{ TmpStr: String; }
+begin
+ p := blockstart;
+ skiphead(p);
+ nroftaiobjs := 0;
+ while (p <> blockend) do
+ begin
+{$ifDef JumpAnal}
+ case p.typ of
+ ait_label:
+ begin
+ if not labelcanbeskipped(tai_label(p)) then
+ labeltable^[tai_label(p).l.labelnr-lolab].instrnr := nroftaiobjs
+ end;
+ ait_instruction:
+ begin
+ if taicpu(p).is_jmp then
+ begin
+ if (tasmlabel(taicpu(p).oper[0]^.sym).labelnr >= lolab) and
+ (tasmlabel(taicpu(p).oper[0]^.sym).labelnr <= hilab) then
+ inc(labeltable^[tasmlabel(taicpu(p).oper[0]^.sym).labelnr-lolab].refsfound);
+ end;
+ end;
+{ ait_instruction:
+ begin
+ if (taicpu(p).opcode = A_PUSH) and
+ (taicpu(p).oper[0]^.typ = top_symbol) and
+ (PCSymbol(taicpu(p).oper[0]^)^.offset = 0) then
+ begin
+ TmpStr := StrPas(PCSymbol(taicpu(p).oper[0]^)^.symbol);
+ if}
+ end;
+{$endif JumpAnal}
+ inc(NrOftaiObjs);
+ getnextinstruction(p,p);
+ end;
+ if nroftaiobjs <> 0 then
+ begin
+ initdfapass2 := True;
+ getmem(taipropblock, nroftaiobjs*sizeof(ttaiprop));
+ fillchar(taiPropblock^,nroftaiobjs*sizeof(ttaiprop),0);
+ p := blockstart;
+ skiphead(p);
+ for count := 1 To nroftaiobjs do
+ begin
+ ptaiprop(p.optinfo) := @taipropblock^[count];
+ getnextinstruction(p, p);
+ end;
+ end
+ else
+ initdfapass2 := false;
+end;
+
+
+procedure tdfaobj.dodfapass2;
+{Analyzes the Data Flow of an assembler list. Starts creating the reg
+ contents for the instructions starting with p. Returns the last tai which has
+ been processed}
+var
+ curprop, LastFlagsChangeProp: ptaiprop;
+ Cnt, InstrCnt : Longint;
+ InstrProp: TInsProp;
+ UsedRegs: TRegSet;
+ prev,p : tai;
+ tmpref: TReference;
+ tmpsupreg: tsuperregister;
+{$ifdef statedebug}
+ hp : tai;
+{$endif}
+{$ifdef AnalyzeLoops}
+ hp : tai;
+ TmpState: Byte;
+{$endif AnalyzeLoops}
+begin
+ p := BlockStart;
+ LastFlagsChangeProp := nil;
+ prev := nil;
+ UsedRegs := [];
+ UpdateUsedregs(UsedRegs, p);
+ SkipHead(p);
+ BlockStart := p;
+ InstrCnt := 1;
+ fillchar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0);
+ while (p <> Blockend) Do
+ begin
+ curprop := @taiPropBlock^[InstrCnt];
+ if assigned(prev)
+ then
+ begin
+{$ifdef JumpAnal}
+ if (p.Typ <> ait_label) then
+{$endif JumpAnal}
+ begin
+ curprop^.regs := ptaiprop(prev.OptInfo)^.Regs;
+ curprop^.DirFlag := ptaiprop(prev.OptInfo)^.DirFlag;
+ curprop^.FlagsUsed := false;
+ end
+ end
+ else
+ begin
+ fillchar(curprop^, SizeOf(curprop^), 0);
+{ For tmpreg := RS_EAX to RS_EDI Do
+ curprop^.regs[tmpreg].WState := 1;}
+ end;
+ curprop^.UsedRegs := UsedRegs;
+ curprop^.CanBeRemoved := False;
+ UpdateUsedRegs(UsedRegs, tai(p.Next));
+ For tmpsupreg := RS_EAX To RS_EDI Do
+ if NrOfInstrSinceLastMod[tmpsupreg] < 255 then
+ inc(NrOfInstrSinceLastMod[tmpsupreg])
+ else
+ begin
+ NrOfInstrSinceLastMod[tmpsupreg] := 0;
+ curprop^.regs[tmpsupreg].typ := con_unknown;
+ end;
+ case p.typ Of
+ ait_marker:;
+ ait_label:
+{$ifndef JumpAnal}
+ if not labelCanBeSkipped(tai_label(p)) then
+ DestroyAllRegs(curprop,false,false);
+{$else JumpAnal}
+ begin
+ if not labelCanBeSkipped(tai_label(p)) then
+ With LTable^[tai_Label(p).l^.labelnr-LoLab] Do
+{$ifDef AnalyzeLoops}
+ if (RefsFound = tai_Label(p).l^.RefCount)
+{$else AnalyzeLoops}
+ if (JmpsProcessed = tai_Label(p).l^.RefCount)
+{$endif AnalyzeLoops}
+ then
+{all jumps to this label have been found}
+{$ifDef AnalyzeLoops}
+ if (JmpsProcessed > 0)
+ then
+{$endif AnalyzeLoops}
+ {we've processed at least one jump to this label}
+ begin
+ if (GetLastInstruction(p, hp) and
+ not(((hp.typ = ait_instruction)) and
+ (taicpu_labeled(hp).is_jmp))
+ then
+ {previous instruction not a JMP -> the contents of the registers after the
+ previous intruction has been executed have to be taken into account as well}
+ For tmpsupreg := RS_EAX to RS_EDI Do
+ begin
+ if (curprop^.regs[tmpsupreg].WState <>
+ ptaiprop(hp.OptInfo)^.Regs[tmpsupreg].WState)
+ then DestroyReg(curprop, tmpsupreg, true)
+ end
+ end
+{$ifDef AnalyzeLoops}
+ else
+ {a label from a backward jump (e.g. a loop), no jump to this label has
+ already been processed}
+ if GetLastInstruction(p, hp) and
+ not(hp.typ = ait_instruction) and
+ (taicpu_labeled(hp).opcode = A_JMP))
+ then
+ {previous instruction not a jmp, so keep all the registers' contents from the
+ previous instruction}
+ begin
+ curprop^.regs := ptaiprop(hp.OptInfo)^.Regs;
+ curprop.DirFlag := ptaiprop(hp.OptInfo)^.DirFlag;
+ end
+ else
+ {previous instruction a jmp and no jump to this label processed yet}
+ begin
+ hp := p;
+ Cnt := InstrCnt;
+ {continue until we find a jump to the label or a label which has already
+ been processed}
+ while GetNextInstruction(hp, hp) and
+ not((hp.typ = ait_instruction) and
+ (taicpu(hp).is_jmp) and
+ (tasmlabel(taicpu(hp).oper[0]^.sym).labelnr = tai_Label(p).l^.labelnr)) and
+ not((hp.typ = ait_label) and
+ (LTable^[tai_Label(hp).l^.labelnr-LoLab].RefsFound
+ = tai_Label(hp).l^.RefCount) and
+ (LTable^[tai_Label(hp).l^.labelnr-LoLab].JmpsProcessed > 0)) Do
+ inc(Cnt);
+ if (hp.typ = ait_label)
+ then
+ {there's a processed label after the current one}
+ begin
+ curprop^.regs := taiPropBlock^[Cnt].Regs;
+ curprop.DirFlag := taiPropBlock^[Cnt].DirFlag;
+ end
+ else
+ {there's no label anymore after the current one, or they haven't been
+ processed yet}
+ begin
+ GetLastInstruction(p, hp);
+ curprop^.regs := ptaiprop(hp.OptInfo)^.Regs;
+ curprop.DirFlag := ptaiprop(hp.OptInfo)^.DirFlag;
+ DestroyAllRegs(ptaiprop(hp.OptInfo),true,true)
+ end
+ end
+{$endif AnalyzeLoops}
+ else
+{not all references to this label have been found, so destroy all registers}
+ begin
+ GetLastInstruction(p, hp);
+ curprop^.regs := ptaiprop(hp.OptInfo)^.Regs;
+ curprop.DirFlag := ptaiprop(hp.OptInfo)^.DirFlag;
+ DestroyAllRegs(curprop,true,true)
+ end;
+ end;
+{$endif JumpAnal}
+
+ ait_stab, ait_force_line, ait_function_name:;
+ ait_align: ; { may destroy flags !!! }
+ ait_instruction:
+ begin
+ if taicpu(p).is_jmp or
+ (taicpu(p).opcode = A_JMP) then
+ begin
+{$ifNDef JumpAnal}
+ for tmpsupreg := RS_EAX to RS_EDI do
+ with curprop^.regs[tmpsupreg] do
+ case typ of
+ con_ref: typ := con_noRemoveRef;
+ con_const: typ := con_noRemoveConst;
+ con_invalid: typ := con_unknown;
+ end;
+{$else JumpAnal}
+ With LTable^[tasmlabel(taicpu(p).oper[0]^.sym).labelnr-LoLab] Do
+ if (RefsFound = tasmlabel(taicpu(p).oper[0]^.sym).RefCount) then
+ begin
+ if (InstrCnt < InstrNr)
+ then
+ {forward jump}
+ if (JmpsProcessed = 0) then
+ {no jump to this label has been processed yet}
+ begin
+ taiPropBlock^[InstrNr].Regs := curprop^.regs;
+ taiPropBlock^[InstrNr].DirFlag := curprop.DirFlag;
+ inc(JmpsProcessed);
+ end
+ else
+ begin
+ For tmpreg := RS_EAX to RS_EDI Do
+ if (taiPropBlock^[InstrNr].Regs[tmpreg].WState <>
+ curprop^.regs[tmpreg].WState) then
+ DestroyReg(@taiPropBlock^[InstrNr], tmpreg, true);
+ inc(JmpsProcessed);
+ end
+{$ifdef AnalyzeLoops}
+ else
+{ backward jump, a loop for example}
+{ if (JmpsProcessed > 0) or
+ not(GetLastInstruction(taiObj, hp) and
+ (hp.typ = ait_labeled_instruction) and
+ (taicpu_labeled(hp).opcode = A_JMP))
+ then}
+{instruction prior to label is not a jmp, or at least one jump to the label
+ has yet been processed}
+ begin
+ inc(JmpsProcessed);
+ For tmpreg := RS_EAX to RS_EDI Do
+ if (taiPropBlock^[InstrNr].Regs[tmpreg].WState <>
+ curprop^.regs[tmpreg].WState)
+ then
+ begin
+ TmpState := taiPropBlock^[InstrNr].Regs[tmpreg].WState;
+ Cnt := InstrNr;
+ while (TmpState = taiPropBlock^[Cnt].Regs[tmpreg].WState) Do
+ begin
+ DestroyReg(@taiPropBlock^[Cnt], tmpreg, true);
+ inc(Cnt);
+ end;
+ while (Cnt <= InstrCnt) Do
+ begin
+ inc(taiPropBlock^[Cnt].Regs[tmpreg].WState);
+ inc(Cnt)
+ end
+ end;
+ end
+{ else }
+{instruction prior to label is a jmp and no jumps to the label have yet been
+ processed}
+{ begin
+ inc(JmpsProcessed);
+ For tmpreg := RS_EAX to RS_EDI Do
+ begin
+ TmpState := taiPropBlock^[InstrNr].Regs[tmpreg].WState;
+ Cnt := InstrNr;
+ while (TmpState = taiPropBlock^[Cnt].Regs[tmpreg].WState) Do
+ begin
+ taiPropBlock^[Cnt].Regs[tmpreg] := curprop^.regs[tmpreg];
+ inc(Cnt);
+ end;
+ TmpState := taiPropBlock^[InstrNr].Regs[tmpreg].WState;
+ while (TmpState = taiPropBlock^[Cnt].Regs[tmpreg].WState) Do
+ begin
+ DestroyReg(@taiPropBlock^[Cnt], tmpreg, true);
+ inc(Cnt);
+ end;
+ while (Cnt <= InstrCnt) Do
+ begin
+ inc(taiPropBlock^[Cnt].Regs[tmpreg].WState);
+ inc(Cnt)
+ end
+ end
+ end}
+{$endif AnalyzeLoops}
+ end;
+{$endif JumpAnal}
+ end
+ else
+ begin
+ InstrProp := InsProp[taicpu(p).opcode];
+ case taicpu(p).opcode Of
+ A_MOV, A_MOVZX, A_MOVSX:
+ begin
+ case taicpu(p).oper[0]^.typ Of
+ top_ref, top_reg:
+ case taicpu(p).oper[1]^.typ Of
+ top_reg:
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+std_regname(taicpu(p).oper[1]^.reg)));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+
+ readOp(curprop, taicpu(p).oper[0]^);
+ tmpsupreg := getsupreg(taicpu(p).oper[1]^.reg);
+ if reginop(tmpsupreg, taicpu(p).oper[0]^) and
+ (curprop^.regs[tmpsupreg].typ in [con_ref,con_noRemoveRef]) then
+ begin
+ with curprop^.regs[tmpsupreg] Do
+ begin
+ incState(wstate,1);
+ { also store how many instructions are part of the sequence in the first }
+ { instruction's ptaiprop, so it can be easily accessed from within }
+ { CheckSequence }
+ inc(nrOfMods, nrOfInstrSinceLastMod[tmpsupreg]);
+ ptaiprop(startmod.optinfo)^.regs[tmpsupreg].nrOfMods := nrOfMods;
+ nrOfInstrSinceLastMod[tmpsupreg] := 0;
+ { Destroy the contents of the registers }
+ { that depended on the previous value of }
+ { this register }
+ invalidateDependingRegs(curprop,tmpsupreg);
+ curprop^.regs[tmpsupreg].memwrite := nil;
+ end;
+ end
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying & initing '+std_regname(newreg(R_INTREGISTER,tmpsupreg,R_SUBWHOLE))));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+ destroyReg(curprop, tmpsupreg, true);
+ if not(reginop(tmpsupreg, taicpu(p).oper[0]^)) then
+ with curprop^.regs[tmpsupreg] Do
+ begin
+ typ := con_ref;
+ startmod := p;
+ nrOfMods := 1;
+ end
+ end;
+{$ifdef StateDebug}
+ hp := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,tmpsupreg,R_SUBWHOLE))+': '+tostr(curprop^.regs[tmpsupreg].WState)));
+ insertllitem(list,p,p.next,hp);
+{$endif StateDebug}
+ end;
+ top_ref:
+ begin
+ readref(curprop, taicpu(p).oper[1]^.ref);
+ if taicpu(p).oper[0]^.typ = top_reg then
+ begin
+ readreg(curprop, getsupreg(taicpu(p).oper[0]^.reg));
+ DestroyRefs(p, taicpu(p).oper[1]^.ref^, getsupreg(taicpu(p).oper[0]^.reg),topsize2tcgsize[taicpu(p).opsize]);
+ ptaiprop(p.optinfo)^.regs[getsupreg(taicpu(p).oper[0]^.reg)].memwrite :=
+ taicpu(p);
+ end
+ else
+ DestroyRefs(p, taicpu(p).oper[1]^.ref^, RS_INVALID,topsize2tcgsize[taicpu(p).opsize]);
+ end;
+ end;
+ top_Const:
+ begin
+ case taicpu(p).oper[1]^.typ Of
+ top_reg:
+ begin
+ tmpsupreg := getsupreg(taicpu(p).oper[1]^.reg);
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+std_regname(newreg(R_INTREGISTER,tmpsupreg,R_SUBWHOLE))));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+ With curprop^.regs[tmpsupreg] Do
+ begin
+ DestroyReg(curprop, tmpsupreg, true);
+ typ := Con_Const;
+ StartMod := p;
+ end
+ end;
+ top_ref:
+ begin
+ readref(curprop, taicpu(p).oper[1]^.ref);
+ DestroyRefs(p, taicpu(p).oper[1]^.ref^, RS_INVALID,topsize2tcgsize[taicpu(p).opsize]);
+ end;
+ end;
+ end;
+ end;
+ end;
+ A_DIV, A_IDIV, A_MUL:
+ begin
+ ReadOp(curprop, taicpu(p).oper[0]^);
+ readreg(curprop,RS_EAX);
+ if (taicpu(p).OpCode = A_IDIV) or
+ (taicpu(p).OpCode = A_DIV) then
+ begin
+ readreg(curprop,RS_EDX);
+ end;
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying eax and edx'));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+{ DestroyReg(curprop, RS_EAX, true);}
+ AddInstr2RegContents({$ifdef statedebug}list,{$endif}
+ taicpu(p), RS_EAX);
+ DestroyReg(curprop, RS_EDX, true);
+ LastFlagsChangeProp := curprop;
+ end;
+ A_IMUL:
+ begin
+ ReadOp(curprop,taicpu(p).oper[0]^);
+ if (taicpu(p).ops >= 2) then
+ ReadOp(curprop,taicpu(p).oper[1]^);
+ if (taicpu(p).ops <= 2) then
+ if (taicpu(p).oper[1]^.typ = top_none) then
+ begin
+ readreg(curprop,RS_EAX);
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying eax and edx'));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+{ DestroyReg(curprop, RS_EAX, true); }
+ AddInstr2RegContents({$ifdef statedebug}list,{$endif}
+ taicpu(p), RS_EAX);
+ DestroyReg(curprop,RS_EDX, true)
+ end
+ else
+ AddInstr2OpContents(
+ {$ifdef statedebug}list,{$endif}
+ taicpu(p), taicpu(p).oper[1]^)
+ else
+ AddInstr2OpContents({$ifdef statedebug}list,{$endif}
+ taicpu(p), taicpu(p).oper[2]^);
+ LastFlagsChangeProp := curprop;
+ end;
+ A_LEA:
+ begin
+ readop(curprop,taicpu(p).oper[0]^);
+ if reginref(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^.ref^) then
+ AddInstr2RegContents({$ifdef statedebug}list,{$endif}
+ taicpu(p), getsupreg(taicpu(p).oper[1]^.reg))
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying & initing'+
+ std_regname(taicpu(p).oper[1]^.reg)));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+ destroyreg(curprop,getsupreg(taicpu(p).oper[1]^.reg),true);
+ with curprop^.regs[getsupreg(taicpu(p).oper[1]^.reg)] Do
+ begin
+ typ := con_ref;
+ startmod := p;
+ nrOfMods := 1;
+ end
+ end;
+ end;
+ else
+ begin
+ Cnt := 1;
+ while (Cnt <= maxinschanges) and
+ (InstrProp.Ch[Cnt] <> Ch_None) Do
+ begin
+ case InstrProp.Ch[Cnt] Of
+ Ch_REAX..Ch_REDI:
+ begin
+ tmpsupreg:=tch2reg(InstrProp.Ch[Cnt]);
+ readreg(curprop,tmpsupreg);
+ end;
+ Ch_WEAX..Ch_RWEDI:
+ begin
+ if (InstrProp.Ch[Cnt] >= Ch_RWEAX) then
+ begin
+ tmpsupreg:=tch2reg(InstrProp.Ch[Cnt]);
+ readreg(curprop,tmpsupreg);
+ end;
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+
+ std_regname(tch2reg(InstrProp.Ch[Cnt]))));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+ tmpsupreg:=tch2reg(InstrProp.Ch[Cnt]);
+ DestroyReg(curprop,tmpsupreg, true);
+ end;
+ Ch_MEAX..Ch_MEDI:
+ begin
+ tmpsupreg:=tch2reg(InstrProp.Ch[Cnt]);
+ AddInstr2RegContents({$ifdef statedebug} list,{$endif}
+ taicpu(p),tmpsupreg);
+ end;
+ Ch_CDirFlag: curprop^.DirFlag := F_notSet;
+ Ch_SDirFlag: curprop^.DirFlag := F_Set;
+ Ch_Rop1: ReadOp(curprop, taicpu(p).oper[0]^);
+ Ch_Rop2: ReadOp(curprop, taicpu(p).oper[1]^);
+ Ch_ROp3: ReadOp(curprop, taicpu(p).oper[2]^);
+ Ch_Wop1..Ch_RWop1:
+ begin
+ if (InstrProp.Ch[Cnt] in [Ch_RWop1]) then
+ ReadOp(curprop, taicpu(p).oper[0]^);
+ DestroyOp(p, taicpu(p).oper[0]^);
+ end;
+ Ch_Mop1:
+ AddInstr2OpContents({$ifdef statedebug} list, {$endif}
+ taicpu(p), taicpu(p).oper[0]^);
+ Ch_Wop2..Ch_RWop2:
+ begin
+ if (InstrProp.Ch[Cnt] = Ch_RWop2) then
+ ReadOp(curprop, taicpu(p).oper[1]^);
+ DestroyOp(p, taicpu(p).oper[1]^);
+ end;
+ Ch_Mop2:
+ AddInstr2OpContents({$ifdef statedebug} list, {$endif}
+ taicpu(p), taicpu(p).oper[1]^);
+ Ch_WOp3..Ch_RWOp3:
+ begin
+ if (InstrProp.Ch[Cnt] = Ch_RWOp3) then
+ ReadOp(curprop, taicpu(p).oper[2]^);
+ DestroyOp(p, taicpu(p).oper[2]^);
+ end;
+ Ch_Mop3:
+ AddInstr2OpContents({$ifdef statedebug} list, {$endif}
+ taicpu(p), taicpu(p).oper[2]^);
+ Ch_WMemEDI:
+ begin
+ readreg(curprop, RS_EDI);
+ fillchar(tmpref, SizeOf(tmpref), 0);
+ tmpref.base := NR_EDI;
+ tmpref.index := NR_EDI;
+ DestroyRefs(p, tmpref,RS_INVALID,OS_32)
+ end;
+ Ch_RFlags:
+ if assigned(LastFlagsChangeProp) then
+ LastFlagsChangeProp^.FlagsUsed := true;
+ Ch_WFlags:
+ LastFlagsChangeProp := curprop;
+ Ch_RWFlags:
+ begin
+ if assigned(LastFlagsChangeProp) then
+ LastFlagsChangeProp^.FlagsUsed := true;
+ LastFlagsChangeProp := curprop;
+ end;
+ Ch_FPU:;
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew(
+ 'destroying all regs for prev instruction'));
+ insertllitem(list,p, p.next,hp);
+{$endif statedebug}
+ DestroyAllRegs(curprop,true,true);
+ LastFlagsChangeProp := curprop;
+ end;
+ end;
+ inc(Cnt);
+ end
+ end;
+ end;
+ end;
+ end
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew(
+ 'destroying all regs: unknown tai: '+tostr(ord(p.typ))));
+ insertllitem(list,p, p.next,hp);
+{$endif statedebug}
+ DestroyAllRegs(curprop,true,true);
+ end;
+ end;
+ inc(InstrCnt);
+ prev := p;
+ GetNextInstruction(p, p);
+ end;
+end;
+
+
+function tdfaobj.pass_2: boolean;
+begin
+ if initdfapass2 then
+ begin
+ dodfapass2;
+ pass_2 := true
+ end
+ else
+ pass_2 := false;
+end;
+
+{$ifopt r+}
+{$define rangewason}
+{$r-}
+{$endif}
+function tdfaobj.getlabelwithsym(sym: tasmlabel): tai;
+begin
+ if (sym.labelnr >= lolab) and
+ (sym.labelnr <= hilab) then { range check, a jump can go past an assembler block! }
+ getlabelwithsym := labeltable^[sym.labelnr-lolab].taiobj
+ else
+ getlabelwithsym := nil;
+end;
+{$ifdef rangewason}
+{$r+}
+{$undef rangewason}
+{$endif}
+
+
+procedure tdfaobj.clear;
+begin
+ if labdif <> 0 then
+ begin
+ freemem(labeltable);
+ labeltable := nil;
+ end;
+ if assigned(taipropblock) then
+ begin
+ freemem(taipropblock, nroftaiobjs*sizeof(ttaiprop));
+ taipropblock := nil;
+ end;
+end;
+
+
+end.
diff --git a/compiler/i386/i386att.inc b/compiler/i386/i386att.inc
new file mode 100644
index 0000000000..895be5db74
--- /dev/null
+++ b/compiler/i386/i386att.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+'none',
+'aaa',
+'aad',
+'aam',
+'aas',
+'adc',
+'add',
+'and',
+'arpl',
+'bound',
+'bsf',
+'bsr',
+'bswap',
+'bt',
+'btc',
+'btr',
+'bts',
+'call',
+'cbtw',
+'cltd',
+'clc',
+'cld',
+'cli',
+'clts',
+'cmc',
+'cmp',
+'cmpsb',
+'cmpsl',
+'cmpsw',
+'cmpxchg',
+'cmpxchg486',
+'cmpxchg8b',
+'cpuid',
+'cwd',
+'cwtl',
+'daa',
+'das',
+'dec',
+'div',
+'emms',
+'enter',
+'f2xm1',
+'fabs',
+'fadd',
+'faddp',
+'fbld',
+'fbstp',
+'fchs',
+'fclex',
+'fcmovb',
+'fcmovbe',
+'fcmove',
+'fcmovnb',
+'fcmovnbe',
+'fcmovne',
+'fcmovnu',
+'fcmovu',
+'fcom',
+'fcomi',
+'fcomip',
+'fcomp',
+'fcompp',
+'fcos',
+'fdecstp',
+'fdisi',
+'fdiv',
+'fdivp',
+'fdivr',
+'fdivrp',
+'femms',
+'feni',
+'ffree',
+'fiadd',
+'ficom',
+'ficomp',
+'fidiv',
+'fidivr',
+'fild',
+'fimul',
+'fincstp',
+'finit',
+'fist',
+'fistp',
+'fisttp',
+'fisub',
+'fisubr',
+'fld',
+'fld1',
+'fldcw',
+'fldenv',
+'fldl2e',
+'fldl2t',
+'fldlg2',
+'fldln2',
+'fldpi',
+'fldz',
+'fmul',
+'fmulp',
+'fnclex',
+'fndisi',
+'fneni',
+'fninit',
+'fnop',
+'fnsave',
+'fnstcw',
+'fnstenv',
+'fnstsw',
+'fpatan',
+'fprem',
+'fprem1',
+'fptan',
+'frndint',
+'frstor',
+'fsave',
+'fscale',
+'fsetpm',
+'fsin',
+'fsincos',
+'fsqrt',
+'fst',
+'fstcw',
+'fstenv',
+'fstp',
+'fstsw',
+'fsub',
+'fsubp',
+'fsubr',
+'fsubrp',
+'ftst',
+'fucom',
+'fucomi',
+'fucomip',
+'fucomp',
+'fucompp',
+'fwait',
+'fxam',
+'fxch',
+'fxtract',
+'fyl2x',
+'fyl2xp1',
+'hlt',
+'ibts',
+'icebp',
+'idiv',
+'imul',
+'in',
+'inc',
+'insb',
+'insl',
+'insw',
+'int',
+'int01',
+'int1',
+'int03',
+'int3',
+'into',
+'invd',
+'invlpg',
+'iret',
+'iret',
+'iretw',
+'jcxz',
+'jecxz',
+'jmp',
+'lahf',
+'lar',
+'lcall',
+'lds',
+'lea',
+'leave',
+'les',
+'lfs',
+'lgdt',
+'lgs',
+'lidt',
+'ljmp',
+'lldt',
+'lmsw',
+'loadall',
+'loadall286',
+'lock',
+'lodsb',
+'lodsl',
+'lodsw',
+'loop',
+'loope',
+'loopne',
+'loopnz',
+'loopz',
+'lsl',
+'lss',
+'ltr',
+'monitor',
+'mov',
+'movd',
+'movq',
+'movsb',
+'movsl',
+'movsq',
+'movsw',
+'movs',
+'movz',
+'mul',
+'mwait',
+'neg',
+'nop',
+'not',
+'or',
+'out',
+'outsb',
+'outsl',
+'outsw',
+'packssdw',
+'packsswb',
+'packuswb',
+'paddb',
+'paddd',
+'paddsb',
+'paddsiw',
+'paddsw',
+'paddusb',
+'paddusw',
+'paddw',
+'pand',
+'pandn',
+'paveb',
+'pavgusb',
+'pcmpeqb',
+'pcmpeqd',
+'pcmpeqw',
+'pcmpgtb',
+'pcmpgtd',
+'pcmpgtw',
+'pdistib',
+'pf2id',
+'pfacc',
+'pfadd',
+'pfcmpeq',
+'pfcmpge',
+'pfcmpgt',
+'pfmax',
+'pfmin',
+'pfmul',
+'pfrcp',
+'pfrcpit1',
+'pfrcpit2',
+'pfrsqit1',
+'pfrsqrt',
+'pfsub',
+'pfsubr',
+'pi2fd',
+'pmachriw',
+'pmaddwd',
+'pmagw',
+'pmulhriw',
+'pmulhrwa',
+'pmulhrwc',
+'pmulhw',
+'pmullw',
+'pmvgezb',
+'pmvlzb',
+'pmvnzb',
+'pmvzb',
+'pop',
+'popa',
+'popal',
+'popaw',
+'popf',
+'popfl',
+'popfw',
+'por',
+'prefetch',
+'prefetchw',
+'pslld',
+'pslldq',
+'psllq',
+'psllw',
+'psrad',
+'psraw',
+'psrld',
+'psrlq',
+'psrlw',
+'psubb',
+'psubd',
+'psubsb',
+'psubsiw',
+'psubsw',
+'psubusb',
+'psubusw',
+'psubw',
+'punpckhbw',
+'punpckhdq',
+'punpckhwd',
+'punpcklbw',
+'punpckldq',
+'punpcklwd',
+'push',
+'pusha',
+'pushal',
+'pushaw',
+'pushf',
+'pushfl',
+'pushfw',
+'pxor',
+'rcl',
+'rcr',
+'rdshr',
+'rdmsr',
+'rdpmc',
+'rdtsc',
+'rep',
+'repe',
+'repne',
+'repnz',
+'repz',
+'ret',
+'lret',
+'ret',
+'rol',
+'ror',
+'rsdc',
+'rsldt',
+'rsm',
+'sahf',
+'sal',
+'salc',
+'sar',
+'sbb',
+'scasb',
+'scasl',
+'scasw',
+'cs',
+'ds',
+'es',
+'fs',
+'gs',
+'ss',
+'sgdt',
+'shl',
+'shld',
+'shr',
+'shrd',
+'sidt',
+'sldt',
+'smi',
+'smint',
+'smintold',
+'smsw',
+'stc',
+'std',
+'sti',
+'stosb',
+'stosl',
+'stosw',
+'str',
+'sub',
+'svdc',
+'svldt',
+'svts',
+'syscall',
+'sysenter',
+'sysexit',
+'sysret',
+'test',
+'ud1',
+'ud2',
+'umov',
+'verr',
+'verw',
+'wait',
+'wbinvd',
+'wrshr',
+'wrmsr',
+'xadd',
+'xbts',
+'xchg',
+'xlat',
+'xlatb',
+'xor',
+'xstore',
+'cmov',
+'j',
+'set',
+'addps',
+'addss',
+'andnps',
+'andps',
+'cmpeqps',
+'cmpeqss',
+'cmpleps',
+'cmpless',
+'cmpltps',
+'cmpltss',
+'cmpneqps',
+'cmpneqss',
+'cmpnleps',
+'cmpnless',
+'cmpnltps',
+'cmpnltss',
+'cmpordps',
+'cmpordss',
+'cmpunordps',
+'cmpunordss',
+'cmpps',
+'cmpss',
+'comiss',
+'cvtpi2ps',
+'cvtps2pi',
+'cvtsi2ss',
+'cvtss2si',
+'cvttps2pi',
+'cvttss2si',
+'divps',
+'divss',
+'ldmxcsr',
+'maxps',
+'maxss',
+'minps',
+'minss',
+'movaps',
+'movhps',
+'movlhps',
+'movlps',
+'movhlps',
+'movmskps',
+'movntps',
+'movss',
+'movups',
+'mulps',
+'mulss',
+'orps',
+'rcpps',
+'rcpss',
+'rsqrtps',
+'rsqrtss',
+'shufps',
+'sqrtps',
+'sqrtss',
+'stmxcsr',
+'subps',
+'subss',
+'ucomiss',
+'unpckhps',
+'unpcklps',
+'xorps',
+'fxrstor',
+'fxsave',
+'prefetchnta',
+'prefetcht0',
+'prefetcht1',
+'prefetcht2',
+'sfence',
+'maskmovq',
+'movntq',
+'pavgb',
+'pavgw',
+'pextrw',
+'pinsrw',
+'pmaxsw',
+'pmaxub',
+'pminsw',
+'pminub',
+'pmovmskb',
+'pmulhuw',
+'psadbw',
+'pshufw',
+'pfnacc',
+'pfpnacc',
+'pi2fw',
+'pf2iw',
+'pswapd',
+'ffreep',
+'maskmovdqu',
+'clflush',
+'movntdq',
+'movnti',
+'movntpd',
+'pause',
+'lfence',
+'mfence',
+'movdqa',
+'movdqu',
+'movdq2q',
+'movq2dq',
+'paddq',
+'pmuludq',
+'pshufd',
+'pshufhw',
+'pshuflw',
+'psrldq',
+'psubq',
+'punpckhqdq',
+'punpcklqdq',
+'addpd',
+'addsd',
+'andnpd',
+'andpd',
+'cmpeqpd',
+'cmpeqsd',
+'cmplepd',
+'cmplesd',
+'cmpltpd',
+'cmpltsd',
+'cmpneqpd',
+'cmpnlepd',
+'cmpnlesd',
+'cmpnltpd',
+'cmpnltsd',
+'cmpordpd',
+'cmpordsd',
+'cmpunordpd',
+'cmpunordsd',
+'cmppd',
+'comisd',
+'cvtdq2pd',
+'cvtdq2ps',
+'cvtpd2dq',
+'cvtpd2pi',
+'cvtpd2ps',
+'cvtpi2pd',
+'cvtps2dq',
+'cvtps2pd',
+'cvtsd2si',
+'cvtsd2ss',
+'cvtsi2sd',
+'cvtss2sd',
+'cvttpd2pi',
+'cvttpd2dq',
+'cvttps2dq',
+'cvttsd2si',
+'divpd',
+'divsd',
+'maxpd',
+'maxsd',
+'minpd',
+'minsd',
+'movapd',
+'movhpd',
+'movlpd',
+'movmskpd',
+'movupd',
+'mulpd',
+'mulsd',
+'orpd',
+'shufpd',
+'sqrtpd',
+'sqrtsd',
+'subpd',
+'subsd',
+'ucomisd',
+'unpckhpd',
+'unpcklpd',
+'xorpd',
+'addsubpd',
+'addsubps',
+'haddpd',
+'haddps',
+'hsubpd',
+'hsubps',
+'lddqu',
+'movddup',
+'movshdup',
+'movsldup',
+'movabs',
+'movslq',
+'cqto'
+);
diff --git a/compiler/i386/i386atts.inc b/compiler/i386/i386atts.inc
new file mode 100644
index 0000000000..b6584499f8
--- /dev/null
+++ b/compiler/i386/i386atts.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufNONE,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufFPU,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufINT,
+attsufNONE,
+attsufFPU,
+attsufINT,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE
+);
diff --git a/compiler/i386/i386int.inc b/compiler/i386/i386int.inc
new file mode 100644
index 0000000000..428a64f8cf
--- /dev/null
+++ b/compiler/i386/i386int.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+'none',
+'aaa',
+'aad',
+'aam',
+'aas',
+'adc',
+'add',
+'and',
+'arpl',
+'bound',
+'bsf',
+'bsr',
+'bswap',
+'bt',
+'btc',
+'btr',
+'bts',
+'call',
+'cbw',
+'cdq',
+'clc',
+'cld',
+'cli',
+'clts',
+'cmc',
+'cmp',
+'cmpsb',
+'cmpsd',
+'cmpsw',
+'cmpxchg',
+'cmpxchg486',
+'cmpxchg8b',
+'cpuid',
+'cwd',
+'cwde',
+'daa',
+'das',
+'dec',
+'div',
+'emms',
+'enter',
+'f2xm1',
+'fabs',
+'fadd',
+'faddp',
+'fbld',
+'fbstp',
+'fchs',
+'fclex',
+'fcmovb',
+'fcmovbe',
+'fcmove',
+'fcmovnb',
+'fcmovnbe',
+'fcmovne',
+'fcmovnu',
+'fcmovu',
+'fcom',
+'fcomi',
+'fcomip',
+'fcomp',
+'fcompp',
+'fcos',
+'fdecstp',
+'fdisi',
+'fdiv',
+'fdivp',
+'fdivr',
+'fdivrp',
+'femms',
+'feni',
+'ffree',
+'fiadd',
+'ficom',
+'ficomp',
+'fidiv',
+'fidivr',
+'fild',
+'fimul',
+'fincstp',
+'finit',
+'fist',
+'fistp',
+'fisttp',
+'fisub',
+'fisubr',
+'fld',
+'fld1',
+'fldcw',
+'fldenv',
+'fldl2e',
+'fldl2t',
+'fldlg2',
+'fldln2',
+'fldpi',
+'fldz',
+'fmul',
+'fmulp',
+'fnclex',
+'fndisi',
+'fneni',
+'fninit',
+'fnop',
+'fnsave',
+'fnstcw',
+'fnstenv',
+'fnstsw',
+'fpatan',
+'fprem',
+'fprem1',
+'fptan',
+'frndint',
+'frstor',
+'fsave',
+'fscale',
+'fsetpm',
+'fsin',
+'fsincos',
+'fsqrt',
+'fst',
+'fstcw',
+'fstenv',
+'fstp',
+'fstsw',
+'fsub',
+'fsubp',
+'fsubr',
+'fsubrp',
+'ftst',
+'fucom',
+'fucomi',
+'fucomip',
+'fucomp',
+'fucompp',
+'fwait',
+'fxam',
+'fxch',
+'fxtract',
+'fyl2x',
+'fyl2xp1',
+'hlt',
+'ibts',
+'icebp',
+'idiv',
+'imul',
+'in',
+'inc',
+'insb',
+'insd',
+'insw',
+'int',
+'int01',
+'int1',
+'int03',
+'int3',
+'into',
+'invd',
+'invlpg',
+'iret',
+'iretd',
+'iretw',
+'jcxz',
+'jecxz',
+'jmp',
+'lahf',
+'lar',
+'lcall',
+'lds',
+'lea',
+'leave',
+'les',
+'lfs',
+'lgdt',
+'lgs',
+'lidt',
+'ljmp',
+'lldt',
+'lmsw',
+'loadall',
+'loadall286',
+'lock',
+'lodsb',
+'lodsd',
+'lodsw',
+'loop',
+'loope',
+'loopne',
+'loopnz',
+'loopz',
+'lsl',
+'lss',
+'ltr',
+'monitor',
+'mov',
+'movd',
+'movq',
+'movsb',
+'movsd',
+'movsq',
+'movsw',
+'movsx',
+'movzx',
+'mul',
+'mwait',
+'neg',
+'nop',
+'not',
+'or',
+'out',
+'outsb',
+'outsd',
+'outsw',
+'packssdw',
+'packsswb',
+'packuswb',
+'paddb',
+'paddd',
+'paddsb',
+'paddsiw',
+'paddsw',
+'paddusb',
+'paddusw',
+'paddw',
+'pand',
+'pandn',
+'paveb',
+'pavgusb',
+'pcmpeqb',
+'pcmpeqd',
+'pcmpeqw',
+'pcmpgtb',
+'pcmpgtd',
+'pcmpgtw',
+'pdistib',
+'pf2id',
+'pfacc',
+'pfadd',
+'pfcmpeq',
+'pfcmpge',
+'pfcmpgt',
+'pfmax',
+'pfmin',
+'pfmul',
+'pfrcp',
+'pfrcpit1',
+'pfrcpit2',
+'pfrsqit1',
+'pfrsqrt',
+'pfsub',
+'pfsubr',
+'pi2fd',
+'pmachriw',
+'pmaddwd',
+'pmagw',
+'pmulhriw',
+'pmulhrwa',
+'pmulhrwc',
+'pmulhw',
+'pmullw',
+'pmvgezb',
+'pmvlzb',
+'pmvnzb',
+'pmvzb',
+'pop',
+'popa',
+'popad',
+'popaw',
+'popf',
+'popfd',
+'popfw',
+'por',
+'prefetch',
+'prefetchw',
+'pslld',
+'pslldq',
+'psllq',
+'psllw',
+'psrad',
+'psraw',
+'psrld',
+'psrlq',
+'psrlw',
+'psubb',
+'psubd',
+'psubsb',
+'psubsiw',
+'psubsw',
+'psubusb',
+'psubusw',
+'psubw',
+'punpckhbw',
+'punpckhdq',
+'punpckhwd',
+'punpcklbw',
+'punpckldq',
+'punpcklwd',
+'push',
+'pusha',
+'pushad',
+'pushaw',
+'pushf',
+'pushfd',
+'pushfw',
+'pxor',
+'rcl',
+'rcr',
+'rdshr',
+'rdmsr',
+'rdpmc',
+'rdtsc',
+'rep',
+'repe',
+'repne',
+'repnz',
+'repz',
+'ret',
+'retf',
+'retn',
+'rol',
+'ror',
+'rsdc',
+'rsldt',
+'rsm',
+'sahf',
+'sal',
+'salc',
+'sar',
+'sbb',
+'scasb',
+'scasd',
+'scasw',
+'segcs',
+'segds',
+'seges',
+'segfs',
+'seggs',
+'segss',
+'sgdt',
+'shl',
+'shld',
+'shr',
+'shrd',
+'sidt',
+'sldt',
+'smi',
+'smint',
+'smintold',
+'smsw',
+'stc',
+'std',
+'sti',
+'stosb',
+'stosd',
+'stosw',
+'str',
+'sub',
+'svdc',
+'svldt',
+'svts',
+'syscall',
+'sysenter',
+'sysexit',
+'sysret',
+'test',
+'ud1',
+'ud2',
+'umov',
+'verr',
+'verw',
+'wait',
+'wbinvd',
+'wrshr',
+'wrmsr',
+'xadd',
+'xbts',
+'xchg',
+'xlat',
+'xlatb',
+'xor',
+'xstore',
+'cmov',
+'j',
+'set',
+'addps',
+'addss',
+'andnps',
+'andps',
+'cmpeqps',
+'cmpeqss',
+'cmpleps',
+'cmpless',
+'cmpltps',
+'cmpltss',
+'cmpneqps',
+'cmpneqss',
+'cmpnleps',
+'cmpnless',
+'cmpnltps',
+'cmpnltss',
+'cmpordps',
+'cmpordss',
+'cmpunordps',
+'cmpunordss',
+'cmpps',
+'cmpss',
+'comiss',
+'cvtpi2ps',
+'cvtps2pi',
+'cvtsi2ss',
+'cvtss2si',
+'cvttps2pi',
+'cvttss2si',
+'divps',
+'divss',
+'ldmxcsr',
+'maxps',
+'maxss',
+'minps',
+'minss',
+'movaps',
+'movhps',
+'movlhps',
+'movlps',
+'movhlps',
+'movmskps',
+'movntps',
+'movss',
+'movups',
+'mulps',
+'mulss',
+'orps',
+'rcpps',
+'rcpss',
+'rsqrtps',
+'rsqrtss',
+'shufps',
+'sqrtps',
+'sqrtss',
+'stmxcsr',
+'subps',
+'subss',
+'ucomiss',
+'unpckhps',
+'unpcklps',
+'xorps',
+'fxrstor',
+'fxsave',
+'prefetchnta',
+'prefetcht0',
+'prefetcht1',
+'prefetcht2',
+'sfence',
+'maskmovq',
+'movntq',
+'pavgb',
+'pavgw',
+'pextrw',
+'pinsrw',
+'pmaxsw',
+'pmaxub',
+'pminsw',
+'pminub',
+'pmovmskb',
+'pmulhuw',
+'psadbw',
+'pshufw',
+'pfnacc',
+'pfpnacc',
+'pi2fw',
+'pf2iw',
+'pswapd',
+'ffreep',
+'maskmovdqu',
+'clflush',
+'movntdq',
+'movnti',
+'movntpd',
+'pause',
+'lfence',
+'mfence',
+'movdqa',
+'movdqu',
+'movdq2q',
+'movq2dq',
+'paddq',
+'pmuludq',
+'pshufd',
+'pshufhw',
+'pshuflw',
+'psrldq',
+'psubq',
+'punpckhqdq',
+'punpcklqdq',
+'addpd',
+'addsd',
+'andnpd',
+'andpd',
+'cmpeqpd',
+'cmpeqsd',
+'cmplepd',
+'cmplesd',
+'cmpltpd',
+'cmpltsd',
+'cmpneqpd',
+'cmpnlepd',
+'cmpnlesd',
+'cmpnltpd',
+'cmpnltsd',
+'cmpordpd',
+'cmpordsd',
+'cmpunordpd',
+'cmpunordsd',
+'cmppd',
+'comisd',
+'cvtdq2pd',
+'cvtdq2ps',
+'cvtpd2dq',
+'cvtpd2pi',
+'cvtpd2ps',
+'cvtpi2pd',
+'cvtps2dq',
+'cvtps2pd',
+'cvtsd2si',
+'cvtsd2ss',
+'cvtsi2sd',
+'cvtss2sd',
+'cvttpd2pi',
+'cvttpd2dq',
+'cvttps2dq',
+'cvttsd2si',
+'divpd',
+'divsd',
+'maxpd',
+'maxsd',
+'minpd',
+'minsd',
+'movapd',
+'movhpd',
+'movlpd',
+'movmskpd',
+'movupd',
+'mulpd',
+'mulsd',
+'orpd',
+'shufpd',
+'sqrtpd',
+'sqrtsd',
+'subpd',
+'subsd',
+'ucomisd',
+'unpckhpd',
+'unpcklpd',
+'xorpd',
+'addsubpd',
+'addsubps',
+'haddpd',
+'haddps',
+'hsubpd',
+'hsubps',
+'lddqu',
+'movddup',
+'movshdup',
+'movsldup',
+'movabs',
+'movsxd',
+'cqo'
+);
diff --git a/compiler/i386/i386nop.inc b/compiler/i386/i386nop.inc
new file mode 100644
index 0000000000..b65a0310c4
--- /dev/null
+++ b/compiler/i386/i386nop.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from x86ins.dat }
+1650;
diff --git a/compiler/i386/i386op.inc b/compiler/i386/i386op.inc
new file mode 100644
index 0000000000..4c011681b0
--- /dev/null
+++ b/compiler/i386/i386op.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+A_NONE,
+A_AAA,
+A_AAD,
+A_AAM,
+A_AAS,
+A_ADC,
+A_ADD,
+A_AND,
+A_ARPL,
+A_BOUND,
+A_BSF,
+A_BSR,
+A_BSWAP,
+A_BT,
+A_BTC,
+A_BTR,
+A_BTS,
+A_CALL,
+A_CBW,
+A_CDQ,
+A_CLC,
+A_CLD,
+A_CLI,
+A_CLTS,
+A_CMC,
+A_CMP,
+A_CMPSB,
+A_CMPSD,
+A_CMPSW,
+A_CMPXCHG,
+A_CMPXCHG486,
+A_CMPXCHG8B,
+A_CPUID,
+A_CWD,
+A_CWDE,
+A_DAA,
+A_DAS,
+A_DEC,
+A_DIV,
+A_EMMS,
+A_ENTER,
+A_F2XM1,
+A_FABS,
+A_FADD,
+A_FADDP,
+A_FBLD,
+A_FBSTP,
+A_FCHS,
+A_FCLEX,
+A_FCMOVB,
+A_FCMOVBE,
+A_FCMOVE,
+A_FCMOVNB,
+A_FCMOVNBE,
+A_FCMOVNE,
+A_FCMOVNU,
+A_FCMOVU,
+A_FCOM,
+A_FCOMI,
+A_FCOMIP,
+A_FCOMP,
+A_FCOMPP,
+A_FCOS,
+A_FDECSTP,
+A_FDISI,
+A_FDIV,
+A_FDIVP,
+A_FDIVR,
+A_FDIVRP,
+A_FEMMS,
+A_FENI,
+A_FFREE,
+A_FIADD,
+A_FICOM,
+A_FICOMP,
+A_FIDIV,
+A_FIDIVR,
+A_FILD,
+A_FIMUL,
+A_FINCSTP,
+A_FINIT,
+A_FIST,
+A_FISTP,
+A_FISTTP,
+A_FISUB,
+A_FISUBR,
+A_FLD,
+A_FLD1,
+A_FLDCW,
+A_FLDENV,
+A_FLDL2E,
+A_FLDL2T,
+A_FLDLG2,
+A_FLDLN2,
+A_FLDPI,
+A_FLDZ,
+A_FMUL,
+A_FMULP,
+A_FNCLEX,
+A_FNDISI,
+A_FNENI,
+A_FNINIT,
+A_FNOP,
+A_FNSAVE,
+A_FNSTCW,
+A_FNSTENV,
+A_FNSTSW,
+A_FPATAN,
+A_FPREM,
+A_FPREM1,
+A_FPTAN,
+A_FRNDINT,
+A_FRSTOR,
+A_FSAVE,
+A_FSCALE,
+A_FSETPM,
+A_FSIN,
+A_FSINCOS,
+A_FSQRT,
+A_FST,
+A_FSTCW,
+A_FSTENV,
+A_FSTP,
+A_FSTSW,
+A_FSUB,
+A_FSUBP,
+A_FSUBR,
+A_FSUBRP,
+A_FTST,
+A_FUCOM,
+A_FUCOMI,
+A_FUCOMIP,
+A_FUCOMP,
+A_FUCOMPP,
+A_FWAIT,
+A_FXAM,
+A_FXCH,
+A_FXTRACT,
+A_FYL2X,
+A_FYL2XP1,
+A_HLT,
+A_IBTS,
+A_ICEBP,
+A_IDIV,
+A_IMUL,
+A_IN,
+A_INC,
+A_INSB,
+A_INSD,
+A_INSW,
+A_INT,
+A_INT01,
+A_INT1,
+A_INT03,
+A_INT3,
+A_INTO,
+A_INVD,
+A_INVLPG,
+A_IRET,
+A_IRETD,
+A_IRETW,
+A_JCXZ,
+A_JECXZ,
+A_JMP,
+A_LAHF,
+A_LAR,
+A_LCALL,
+A_LDS,
+A_LEA,
+A_LEAVE,
+A_LES,
+A_LFS,
+A_LGDT,
+A_LGS,
+A_LIDT,
+A_LJMP,
+A_LLDT,
+A_LMSW,
+A_LOADALL,
+A_LOADALL286,
+A_LOCK,
+A_LODSB,
+A_LODSD,
+A_LODSW,
+A_LOOP,
+A_LOOPE,
+A_LOOPNE,
+A_LOOPNZ,
+A_LOOPZ,
+A_LSL,
+A_LSS,
+A_LTR,
+A_MONITOR,
+A_MOV,
+A_MOVD,
+A_MOVQ,
+A_MOVSB,
+A_MOVSD,
+A_MOVSQ,
+A_MOVSW,
+A_MOVSX,
+A_MOVZX,
+A_MUL,
+A_MWAIT,
+A_NEG,
+A_NOP,
+A_NOT,
+A_OR,
+A_OUT,
+A_OUTSB,
+A_OUTSD,
+A_OUTSW,
+A_PACKSSDW,
+A_PACKSSWB,
+A_PACKUSWB,
+A_PADDB,
+A_PADDD,
+A_PADDSB,
+A_PADDSIW,
+A_PADDSW,
+A_PADDUSB,
+A_PADDUSW,
+A_PADDW,
+A_PAND,
+A_PANDN,
+A_PAVEB,
+A_PAVGUSB,
+A_PCMPEQB,
+A_PCMPEQD,
+A_PCMPEQW,
+A_PCMPGTB,
+A_PCMPGTD,
+A_PCMPGTW,
+A_PDISTIB,
+A_PF2ID,
+A_PFACC,
+A_PFADD,
+A_PFCMPEQ,
+A_PFCMPGE,
+A_PFCMPGT,
+A_PFMAX,
+A_PFMIN,
+A_PFMUL,
+A_PFRCP,
+A_PFRCPIT1,
+A_PFRCPIT2,
+A_PFRSQIT1,
+A_PFRSQRT,
+A_PFSUB,
+A_PFSUBR,
+A_PI2FD,
+A_PMACHRIW,
+A_PMADDWD,
+A_PMAGW,
+A_PMULHRIW,
+A_PMULHRWA,
+A_PMULHRWC,
+A_PMULHW,
+A_PMULLW,
+A_PMVGEZB,
+A_PMVLZB,
+A_PMVNZB,
+A_PMVZB,
+A_POP,
+A_POPA,
+A_POPAD,
+A_POPAW,
+A_POPF,
+A_POPFD,
+A_POPFW,
+A_POR,
+A_PREFETCH,
+A_PREFETCHW,
+A_PSLLD,
+A_PSLLDQ,
+A_PSLLQ,
+A_PSLLW,
+A_PSRAD,
+A_PSRAW,
+A_PSRLD,
+A_PSRLQ,
+A_PSRLW,
+A_PSUBB,
+A_PSUBD,
+A_PSUBSB,
+A_PSUBSIW,
+A_PSUBSW,
+A_PSUBUSB,
+A_PSUBUSW,
+A_PSUBW,
+A_PUNPCKHBW,
+A_PUNPCKHDQ,
+A_PUNPCKHWD,
+A_PUNPCKLBW,
+A_PUNPCKLDQ,
+A_PUNPCKLWD,
+A_PUSH,
+A_PUSHA,
+A_PUSHAD,
+A_PUSHAW,
+A_PUSHF,
+A_PUSHFD,
+A_PUSHFW,
+A_PXOR,
+A_RCL,
+A_RCR,
+A_RDSHR,
+A_RDMSR,
+A_RDPMC,
+A_RDTSC,
+A_REP,
+A_REPE,
+A_REPNE,
+A_REPNZ,
+A_REPZ,
+A_RET,
+A_RETF,
+A_RETN,
+A_ROL,
+A_ROR,
+A_RSDC,
+A_RSLDT,
+A_RSM,
+A_SAHF,
+A_SAL,
+A_SALC,
+A_SAR,
+A_SBB,
+A_SCASB,
+A_SCASD,
+A_SCASW,
+A_SEGCS,
+A_SEGDS,
+A_SEGES,
+A_SEGFS,
+A_SEGGS,
+A_SEGSS,
+A_SGDT,
+A_SHL,
+A_SHLD,
+A_SHR,
+A_SHRD,
+A_SIDT,
+A_SLDT,
+A_SMI,
+A_SMINT,
+A_SMINTOLD,
+A_SMSW,
+A_STC,
+A_STD,
+A_STI,
+A_STOSB,
+A_STOSD,
+A_STOSW,
+A_STR,
+A_SUB,
+A_SVDC,
+A_SVLDT,
+A_SVTS,
+A_SYSCALL,
+A_SYSENTER,
+A_SYSEXIT,
+A_SYSRET,
+A_TEST,
+A_UD1,
+A_UD2,
+A_UMOV,
+A_VERR,
+A_VERW,
+A_WAIT,
+A_WBINVD,
+A_WRSHR,
+A_WRMSR,
+A_XADD,
+A_XBTS,
+A_XCHG,
+A_XLAT,
+A_XLATB,
+A_XOR,
+A_XSTORE,
+A_CMOVcc,
+A_Jcc,
+A_SETcc,
+A_ADDPS,
+A_ADDSS,
+A_ANDNPS,
+A_ANDPS,
+A_CMPEQPS,
+A_CMPEQSS,
+A_CMPLEPS,
+A_CMPLESS,
+A_CMPLTPS,
+A_CMPLTSS,
+A_CMPNEQPS,
+A_CMPNEQSS,
+A_CMPNLEPS,
+A_CMPNLESS,
+A_CMPNLTPS,
+A_CMPNLTSS,
+A_CMPORDPS,
+A_CMPORDSS,
+A_CMPUNORDPS,
+A_CMPUNORDSS,
+A_CMPPS,
+A_CMPSS,
+A_COMISS,
+A_CVTPI2PS,
+A_CVTPS2PI,
+A_CVTSI2SS,
+A_CVTSS2SI,
+A_CVTTPS2PI,
+A_CVTTSS2SI,
+A_DIVPS,
+A_DIVSS,
+A_LDMXCSR,
+A_MAXPS,
+A_MAXSS,
+A_MINPS,
+A_MINSS,
+A_MOVAPS,
+A_MOVHPS,
+A_MOVLHPS,
+A_MOVLPS,
+A_MOVHLPS,
+A_MOVMSKPS,
+A_MOVNTPS,
+A_MOVSS,
+A_MOVUPS,
+A_MULPS,
+A_MULSS,
+A_ORPS,
+A_RCPPS,
+A_RCPSS,
+A_RSQRTPS,
+A_RSQRTSS,
+A_SHUFPS,
+A_SQRTPS,
+A_SQRTSS,
+A_STMXCSR,
+A_SUBPS,
+A_SUBSS,
+A_UCOMISS,
+A_UNPCKHPS,
+A_UNPCKLPS,
+A_XORPS,
+A_FXRSTOR,
+A_FXSAVE,
+A_PREFETCHNTA,
+A_PREFETCHT0,
+A_PREFETCHT1,
+A_PREFETCHT2,
+A_SFENCE,
+A_MASKMOVQ,
+A_MOVNTQ,
+A_PAVGB,
+A_PAVGW,
+A_PEXTRW,
+A_PINSRW,
+A_PMAXSW,
+A_PMAXUB,
+A_PMINSW,
+A_PMINUB,
+A_PMOVMSKB,
+A_PMULHUW,
+A_PSADBW,
+A_PSHUFW,
+A_PFNACC,
+A_PFPNACC,
+A_PI2FW,
+A_PF2IW,
+A_PSWAPD,
+A_FFREEP,
+A_MASKMOVDQU,
+A_CLFLUSH,
+A_MOVNTDQ,
+A_MOVNTI,
+A_MOVNTPD,
+A_PAUSE,
+A_LFENCE,
+A_MFENCE,
+A_MOVDQA,
+A_MOVDQU,
+A_MOVDQ2Q,
+A_MOVQ2DQ,
+A_PADDQ,
+A_PMULUDQ,
+A_PSHUFD,
+A_PSHUFHW,
+A_PSHUFLW,
+A_PSRLDQ,
+A_PSUBQ,
+A_PUNPCKHQDQ,
+A_PUNPCKLQDQ,
+A_ADDPD,
+A_ADDSD,
+A_ANDNPD,
+A_ANDPD,
+A_CMPEQPD,
+A_CMPEQSD,
+A_CMPLEPD,
+A_CMPLESD,
+A_CMPLTPD,
+A_CMPLTSD,
+A_CMPNEQPD,
+A_CMPNLEPD,
+A_CMPNLESD,
+A_CMPNLTPD,
+A_CMPNLTSD,
+A_CMPORDPD,
+A_CMPORDSD,
+A_CMPUNORDPD,
+A_CMPUNORDSD,
+A_CMPPD,
+A_COMISD,
+A_CVTDQ2PD,
+A_CVTDQ2PS,
+A_CVTPD2DQ,
+A_CVTPD2PI,
+A_CVTPD2PS,
+A_CVTPI2PD,
+A_CVTPS2DQ,
+A_CVTPS2PD,
+A_CVTSD2SI,
+A_CVTSD2SS,
+A_CVTSI2SD,
+A_CVTSS2SD,
+A_CVTTPD2PI,
+A_CVTTPD2DQ,
+A_CVTTPS2DQ,
+A_CVTTSD2SI,
+A_DIVPD,
+A_DIVSD,
+A_MAXPD,
+A_MAXSD,
+A_MINPD,
+A_MINSD,
+A_MOVAPD,
+A_MOVHPD,
+A_MOVLPD,
+A_MOVMSKPD,
+A_MOVUPD,
+A_MULPD,
+A_MULSD,
+A_ORPD,
+A_SHUFPD,
+A_SQRTPD,
+A_SQRTSD,
+A_SUBPD,
+A_SUBSD,
+A_UCOMISD,
+A_UNPCKHPD,
+A_UNPCKLPD,
+A_XORPD,
+A_ADDSUBPD,
+A_ADDSUBPS,
+A_HADDPD,
+A_HADDPS,
+A_HSUBPD,
+A_HSUBPS,
+A_LDDQU,
+A_MOVDDUP,
+A_MOVSHDUP,
+A_MOVSLDUP,
+A_MOVABS,
+A_MOVSXD,
+A_CQO
+);
diff --git a/compiler/i386/i386prop.inc b/compiler/i386/i386prop.inc
new file mode 100644
index 0000000000..df064ad42e
--- /dev/null
+++ b/compiler/i386/i386prop.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_MOp1, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_ROp1, Ch_All, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_CDirFlag, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_ROp2, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_none)),
+(Ch: (Ch_MEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_Wop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_WFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WEBP, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_RWECX, Ch_None, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_ROP1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_RWESP, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_RWESP, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFLAGS, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFLAGS, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_REAX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_WEAX, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_MOp3, Ch_RWFlags, Ch_Rop2)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_MOp3, Ch_RWFlags, Ch_Rop2)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_SDirFlag, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWop1, Ch_RWop2, Ch_None)),
+(Ch: (Ch_WEAX, Ch_REBX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_REBX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_WOp2, Ch_RFLAGS)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_RFLAGS, Ch_WOp1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_MRAX, Ch_WRDX, Ch_None))
+);
diff --git a/compiler/i386/i386tab.inc b/compiler/i386/i386tab.inc
new file mode 100644
index 0000000000..c9b7c0ac94
--- /dev/null
+++ b/compiler/i386/i386tab.inc
@@ -0,0 +1,11553 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+ (
+ opcode : A_NONE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #0;
+ flags : if_none
+ ),
+ (
+ opcode : A_AAA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#55;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#213#10;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AAD;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#213#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_AAM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#212#10;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AAM;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#212#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_AAS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#63;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#16#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#16#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#17#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#17#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#17#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#17#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#18#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#18#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#19#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#19#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#19#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#19#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#130#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#130#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#20#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#21#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#21#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#130#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#130#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#130#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#130#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#130#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#130#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#15#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#15#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#1#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#1#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#1#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#1#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#2#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#2#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#3#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#3#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#3#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#3#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#128#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#128#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#4#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#5#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#5#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#32#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#32#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#33#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#33#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#33#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#33#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#34#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#34#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#35#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#35#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#35#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#35#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#132#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#132#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#36#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#37#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#37#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#132#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#132#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#132#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#132#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#132#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#132#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ARPL;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #192#1#99#65;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_ARPL;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #192#1#99#65;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_BOUND;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#98#72;
+ flags : if_186
+ ),
+ (
+ opcode : A_BOUND;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#98#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#188#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#188#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#188#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#188#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#189#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#189#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#189#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#189#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSWAP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#1#15#8#200;
+ flags : if_486
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#163#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#163#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#163#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#163#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#2#15#186#132#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#2#15#186#132#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#187#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#187#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#187#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#187#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#2#15#186#135#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#2#15#186#135#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#179#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#179#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#179#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#179#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#2#15#186#134#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#2#15#186#134#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#171#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#171#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#171#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#171#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#2#15#186#133#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#2#15#186#133#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #211#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none);
+ code : #211#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_far,ot_none,ot_none);
+ code : #211#1#154#28#31;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #208#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#1#154#28#31;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #209#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#1#154#28#31;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none);
+ code : #211#1#154#29#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate or ot_bits16,ot_immediate,ot_none);
+ code : #208#1#154#25#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits16,ot_none);
+ code : #208#1#154#25#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate or ot_bits32,ot_immediate,ot_none);
+ code : #209#1#154#33#24;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits32,ot_none);
+ code : #209#1#154#33#24;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none);
+ code : #211#192#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#192#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#192#1#255#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none);
+ code : #211#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #211#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_CBW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#152;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CDQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#153;
+ flags : if_386
+ ),
+ (
+ opcode : A_CLC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#248;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#252;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#250;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLTS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#6;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_CMC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#245;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#56#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#56#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#57#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#57#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#57#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#57#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#58#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#58#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#59#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#59#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#59#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#59#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#135#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#135#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#60#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#61#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#61#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#135#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#135#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#135#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#135#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#135#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#135#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMPSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#1#166;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#209#1#167;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #217#3#242#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#217#3#242#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#208#1#167;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#2#15#176#65;
+ flags : if_pent or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#2#15#176#65;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#177#65;
+ flags : if_pent or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#177#65;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#177#65;
+ flags : if_pent or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#177#65;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#2#15#166#65;
+ flags : if_486 or if_sm or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#2#15#166#65;
+ flags : if_486 or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#167#65;
+ flags : if_486 or if_sm or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#167#65;
+ flags : if_486 or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#167#65;
+ flags : if_486 or if_sm or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#167#65;
+ flags : if_486 or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG8B;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#199#129;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CPUID;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#162;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CWD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#153;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CWDE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#152;
+ flags : if_386
+ ),
+ (
+ opcode : A_DAA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#39;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DAS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#47;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#8#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#8#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#254#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#129;
+ flags : if_386
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#134;
+ flags : if_386
+ ),
+ (
+ opcode : A_EMMS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#119;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_ENTER;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none);
+ code : #1#200#24#21;
+ flags : if_186
+ ),
+ (
+ opcode : A_F2XM1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FABS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#193;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#193;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#1#223#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBLD;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#223#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#1#223#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBSTP;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#223#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCHS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCLEX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#219#226;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#193;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#218#8#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#218#9#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#209;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#218#8#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#218#9#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#201;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#218#8#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#218#9#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#193;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#209;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#201;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#217;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#217;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#218#8#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#218#9#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#216#209;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#241;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#223#241;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#223#8#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#223#9#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#216#217;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMPP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#217;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#255;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FDECSTP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#246;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDISI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#219#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FEMMS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none or ot_signed);
+ code : #2#15#14;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_FENI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#219#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FFREE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#219#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#223#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#223#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FINCSTP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#247;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#219#227;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#219#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#223#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#219#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#223#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#223#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#221#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#219#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#223#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#217#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#221#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#1#219#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#217#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#217#133;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FLDENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#217#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDL2E;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#234;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDL2T;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDLG2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#236;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDLN2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#237;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDPI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#235;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#238;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNCLEX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#226;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNDISI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNENI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#227;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#221#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSTCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#217#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FNSTENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#217#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSTSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#221#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FNSTSW;
+ ops : 1;
+ optypes : (ot_reg_ax,ot_none,ot_none);
+ code : #2#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FPATAN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#243;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FPREM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FPREM1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#245;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FPTAN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#242;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FRNDINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#252;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FRSTOR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#221#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#155#221#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSCALE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#253;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSETPM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#228;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSIN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#254;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FSINCOS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#251;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FSQRT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#250;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#217#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#221#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#155#217#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FSTENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#155#217#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#217#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#221#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#1#219#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#155#221#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 1;
+ optypes : (ot_reg_ax,ot_none,ot_none);
+ code : #3#155#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FTST;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#228;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#221#225;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#224;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#221#9#224;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#233;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#223#233;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#223#8#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#223#9#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#221#233;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#232;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#221#9#232;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMPP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#233;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FWAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#155;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXAM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#229;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#217#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#217#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#217#9#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXTRACT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#244;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FYL2X;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FYL2XP1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_HLT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#244;
+ flags : if_8086 or if_priv
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#167#65;
+ flags : if_386 or if_sw or if_undoc
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#167#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#167#65;
+ flags : if_386 or if_sd or if_undoc
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#167#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_ICEBP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#135;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#175#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#175#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#175#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#175#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_memory,ot_immediate or ot_bits8 or ot_signed);
+ code : #208#193#1#107#72#14;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_immediate or ot_bits8 or ot_signed);
+ code : #208#193#1#107#72#14;
+ flags : if_286
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_memory,ot_immediate);
+ code : #208#193#1#105#72#26;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_immediate);
+ code : #208#193#1#105#72#26;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_memory,ot_immediate or ot_bits8 or ot_signed);
+ code : #209#193#1#107#72#14;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits8 or ot_signed);
+ code : #209#193#1#107#72#14;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_memory,ot_immediate);
+ code : #209#193#1#105#72#34;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate);
+ code : #209#193#1#105#72#34;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#1#107#64#13;
+ flags : if_286
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate,ot_none);
+ code : #208#1#105#64#25;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#1#107#64#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none);
+ code : #209#1#105#64#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#228#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#229#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#229#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_al,ot_reg_dx,ot_none);
+ code : #1#236;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_reg_dx,ot_none);
+ code : #208#1#237;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg_dx,ot_none);
+ code : #209#1#237;
+ flags : if_386
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#8#64;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#8#64;
+ flags : if_386
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#254#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_INSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#108;
+ flags : if_186
+ ),
+ (
+ opcode : A_INSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#109;
+ flags : if_386
+ ),
+ (
+ opcode : A_INSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#109;
+ flags : if_186
+ ),
+ (
+ opcode : A_INT;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#205#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_INT01;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_INT1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_INT03;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#204;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INT3;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#204;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INTO;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#206;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INVD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#8;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_INVLPG;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#135;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_IRET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#207;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IRETD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#207;
+ flags : if_386
+ ),
+ (
+ opcode : A_IRETW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#207;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JCXZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #208#1#227#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JECXZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #209#1#227#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_short,ot_none,ot_none);
+ code : #1#235#40;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #211#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none);
+ code : #211#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_far,ot_none,ot_none);
+ code : #211#1#234#28#31;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #208#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#1#234#28#31;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #209#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#1#234#28#31;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none);
+ code : #211#1#234#29#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits16,ot_none);
+ code : #208#1#234#25#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits32,ot_none);
+ code : #209#1#234#33#24;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none);
+ code : #211#192#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#192#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#192#1#255#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none);
+ code : #211#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #211#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_LAHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#159;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#2#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#2#72;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#2#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#2#72;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none);
+ code : #211#192#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#192#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#192#1#255#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none);
+ code : #211#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #211#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_LDS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#197#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LDS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#197#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#141#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#141#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #209#193#1#141#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEAVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#201;
+ flags : if_186
+ ),
+ (
+ opcode : A_LES;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#196#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LES;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#196#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LFS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#180#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LFS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#180#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LGDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#130;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LGS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#181#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LGS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#181#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LIDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#131;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none);
+ code : #211#192#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#192#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#192#1#255#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none);
+ code : #211#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #211#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_LLDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#130;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#130;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LLDT;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#1#15#15#130;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LMSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#134;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LMSW;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#2#15#1#134;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LMSW;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#2#15#1#134;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LOADALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#7;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_LOADALL286;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#5;
+ flags : if_286 or if_undoc
+ ),
+ (
+ opcode : A_LOCK;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#240;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_LODSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#172;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LODSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#173;
+ flags : if_386
+ ),
+ (
+ opcode : A_LODSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#173;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#226#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#226#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#226#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#225#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#224#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#224#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#225#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#3#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#3#72;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#3#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#3#72;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_LSS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#178#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LSS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#178#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LTR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#131;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LTR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#131;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LTR;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#1#15#15#131;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_MONITOR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#1#200;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MONITOR;
+ ops : 3;
+ optypes : (ot_reg_eax,ot_reg_ecx,ot_reg_edx);
+ code : #3#15#1#200;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg_cs,ot_none);
+ code : #208#192#1#140#129;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg_dess,ot_none);
+ code : #208#192#1#140#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg_fsgs,ot_none);
+ code : #208#192#1#140#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_cs,ot_none);
+ code : #208#192#1#140#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_dess,ot_none);
+ code : #208#192#1#140#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_fsgs,ot_none);
+ code : #208#192#1#140#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cs,ot_none);
+ code : #209#192#1#140#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_dess,ot_none);
+ code : #209#192#1#140#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_fsgs,ot_none);
+ code : #209#192#1#140#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dess,ot_memory,ot_none);
+ code : #208#193#1#142#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_fsgs,ot_memory,ot_none);
+ code : #208#193#1#142#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dess,ot_reg16,ot_none);
+ code : #208#193#1#142#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_fsgs,ot_reg16,ot_none);
+ code : #208#193#1#142#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dess,ot_regmem or ot_bits32,ot_none);
+ code : #209#193#1#142#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_fsgs,ot_regmem or ot_bits32,ot_none);
+ code : #209#193#1#142#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_al,ot_mem_offs,ot_none);
+ code : #193#1#160#29;
+ flags : if_8086 or if_sm or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_mem_offs,ot_none);
+ code : #193#208#1#161#29;
+ flags : if_8086 or if_sm or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_mem_offs,ot_none);
+ code : #193#209#1#161#29;
+ flags : if_386 or if_sm or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_al,ot_none);
+ code : #192#1#162#28;
+ flags : if_8086 or if_sm or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_ax,ot_none);
+ code : #192#208#1#163#28;
+ flags : if_8086 or if_sm or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_eax,ot_none);
+ code : #192#209#1#163#28;
+ flags : if_386 or if_sm or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_cr4,ot_none);
+ code : #2#15#32#132;
+ flags : if_pent or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_creg,ot_none);
+ code : #2#15#32#65;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_dreg,ot_none);
+ code : #2#15#33#65;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_treg,ot_none);
+ code : #2#15#36#65;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_cr4,ot_reg32,ot_none);
+ code : #2#15#34#140;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_creg,ot_reg32,ot_none);
+ code : #2#15#34#72;
+ flags : if_386 or if_priv
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dreg,ot_reg32,ot_none);
+ code : #2#15#35#72;
+ flags : if_386 or if_priv
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_treg,ot_reg32,ot_none);
+ code : #2#15#38#72;
+ flags : if_386 or if_priv
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#136#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#136#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#137#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#137#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#137#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#137#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#138#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#138#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#139#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#139#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#139#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#139#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_immediate,ot_none);
+ code : #8#176#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate,ot_none);
+ code : #208#8#184#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none);
+ code : #209#8#184#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#198#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#199#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#199#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#198#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#199#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#199#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#110#72;
+ flags : if_pent or if_mmx or if_sd
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_reg32,ot_none);
+ code : #2#15#110#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_memory,ot_mmxreg,ot_none);
+ code : #192#2#15#126#65;
+ flags : if_pent or if_mmx or if_sd
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_reg32,ot_mmxreg,ot_none);
+ code : #2#15#126#65;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32,ot_none);
+ code : #3#102#15#110#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#102#15#126#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#126#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#110#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#111#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#111#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_memory,ot_mmxreg,ot_none);
+ code : #192#2#15#127#65;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#127#65;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#126#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#214#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#126#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#164;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#165;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#16#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#17#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#242#15#17#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#16#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#165;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#190#72;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg8,ot_none);
+ code : #208#193#2#15#190#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regmem or ot_bits8,ot_none);
+ code : #209#193#2#15#190#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regmem or ot_bits16,ot_none);
+ code : #209#193#2#15#191#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#182#72;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg8,ot_none);
+ code : #208#193#2#15#182#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regmem or ot_bits8,ot_none);
+ code : #209#193#2#15#182#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regmem or ot_bits16,ot_none);
+ code : #209#193#2#15#183#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_MWAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#1#201;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MWAIT;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg_ecx,ot_none);
+ code : #3#15#1#201;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_NOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#8#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#8#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#9#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#9#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#9#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#9#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#10#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#10#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#11#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#11#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#11#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#11#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#129#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#129#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#12#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#13#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#13#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#129#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#129#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#129#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#129#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#129#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#129#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_al,ot_none);
+ code : #1#230#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ax,ot_none);
+ code : #208#1#231#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_eax,ot_none);
+ code : #209#1#231#20;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_al,ot_none);
+ code : #1#238;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_ax,ot_none);
+ code : #208#1#239;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_eax,ot_none);
+ code : #209#1#239;
+ flags : if_386
+ ),
+ (
+ opcode : A_OUTSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#110;
+ flags : if_186
+ ),
+ (
+ opcode : A_OUTSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#111;
+ flags : if_386
+ ),
+ (
+ opcode : A_OUTSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#111;
+ flags : if_186
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#107#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#107#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#107#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#107#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#99#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#99#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#99#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#99#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#103#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#103#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#103#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#103#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#252#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#252#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#252#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#252#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#254#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#254#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#254#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#254#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#236#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#236#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#236#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#236#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#81#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PADDSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#81#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#237#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#237#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#237#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#237#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#220#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#220#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#220#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#220#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#221#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#221#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#221#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#221#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#253#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#253#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#253#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#253#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#219#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#219#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#219#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#219#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#223#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#223#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#223#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#223#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAVEB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#80#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PAVEB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#80#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PAVGUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#191;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PAVGUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#191;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#116#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#116#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#116#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#116#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#118#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#118#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#118#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#118#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#117#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#117#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#117#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#117#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#100#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#100#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#100#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#100#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#102#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#102#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#102#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#102#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#101#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#101#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#101#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#101#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PDISTIB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#84#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PF2ID;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#29;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PF2ID;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#29;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#174;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#174;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFADD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#158;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFADD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#158;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFCMPEQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#176;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPEQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#176;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFCMPGE;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#144;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPGE;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#144;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFCMPGT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#160;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPGT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#160;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFMAX;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#164;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMAX;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#164;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFMIN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#148;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMIN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#148;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFMUL;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#180;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMUL;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#180;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRCP;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#150;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCP;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#150;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRCPIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#166;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCPIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#166;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRCPIT2;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#182;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCPIT2;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#182;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRSQIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#167;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRSQIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#167;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRSQRT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#151;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRSQRT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#151;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFSUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#154;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFSUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#154;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFSUBR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#170;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFSUBR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#170;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PI2FD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#13;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PI2FD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#13;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PMACHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#94#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#245#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#245#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#245#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#245#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMAGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#82#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMAGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#82#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#93#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#93#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRWA;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#183;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PMULHRWA;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#183;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PMULHRWC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#89#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRWC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#89#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#229#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#229#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#229#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#229#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#213#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#213#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#213#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#213#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMVGEZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#92#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVLZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#91#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVNZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#90#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#88#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#8#88;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#8#88;
+ flags : if_386
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#143#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#143#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_cs,ot_none,ot_none);
+ code : #1#15;
+ flags : if_8086 or if_undoc
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_dess,ot_none,ot_none);
+ code : #4;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_fsgs,ot_none,ot_none);
+ code : #1#15#5;
+ flags : if_386
+ ),
+ (
+ opcode : A_POPA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#97;
+ flags : if_186
+ ),
+ (
+ opcode : A_POPAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#97;
+ flags : if_386
+ ),
+ (
+ opcode : A_POPAW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#97;
+ flags : if_186
+ ),
+ (
+ opcode : A_POPF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#157;
+ flags : if_186
+ ),
+ (
+ opcode : A_POPFD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#157;
+ flags : if_386
+ ),
+ (
+ opcode : A_POPFW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#157;
+ flags : if_186
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#235#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#235#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#235#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#235#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PREFETCH;
+ ops : 1;
+ optypes : (ot_memory,ot_none or ot_signed,ot_none);
+ code : #2#15#13#128;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PREFETCHW;
+ ops : 1;
+ optypes : (ot_memory,ot_none or ot_signed,ot_none);
+ code : #2#15#13#129;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#242#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#242#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#114#134#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#242#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#242#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#114#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#115#135#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#243#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#243#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#115#134#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#243#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#243#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#115#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#241#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#241#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#113#134#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#241#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#241#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#113#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#226#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#226#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#114#132#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#226#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#226#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#114#132#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#225#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#225#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#113#132#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#225#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#225#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#113#132#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#210#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#210#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#114#130#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#210#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#210#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#114#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#211#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#211#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#115#130#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#211#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#211#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#115#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#209#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#209#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#113#130#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#209#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#209#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#113#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#248#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#248#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#248#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#248#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#250#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#250#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#250#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#250#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#232#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#232#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#232#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#232#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#85#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PSUBSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#85#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#233#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#233#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#233#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#233#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#216#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#216#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#216#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#216#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#217#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#217#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#217#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#217#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#249#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#249#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#249#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#249#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#104#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#104#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#104#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#104#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#106#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#106#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#106#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#106#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#105#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#105#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#105#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#105#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#96#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#96#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#96#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#96#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#98#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#98#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#98#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#98#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#97#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#97#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#97#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#97#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#8#80;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#8#80;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#134;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#134;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg_fsgs,ot_none,ot_none);
+ code : #1#15#7;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg_sreg,ot_none,ot_none);
+ code : #6;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #1#106#12;
+ flags : if_286 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #208#1#104#24;
+ flags : if_286 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #209#1#104#32;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSHA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#96;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#96;
+ flags : if_386
+ ),
+ (
+ opcode : A_PUSHAW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#96;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#156;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHFD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#156;
+ flags : if_386
+ ),
+ (
+ opcode : A_PUSHFW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#156;
+ flags : if_186
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#239#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#239#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#239#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#239#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#130#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#130#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#130#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#131#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#131#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#131#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_RDSHR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#54;
+ flags : if_p6 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RDMSR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#50;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_RDPMC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#51;
+ flags : if_p6
+ ),
+ (
+ opcode : A_RDTSC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#49;
+ flags : if_pent
+ ),
+ (
+ opcode : A_REP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPNE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#242;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPNZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#242;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_RET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#195;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RET;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#194#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_RETF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#203;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RETF;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#202#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_RETN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#195;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RETN;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#194#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#128#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#128#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#128#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#129#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#129#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#129;
+ flags : if_386
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#129;
+ flags : if_386
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#129#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_RSDC;
+ ops : 2;
+ optypes : (ot_reg_sreg,ot_memory or ot_bits80,ot_none);
+ code : #193#2#15#121#65;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RSLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#2#15#123#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RSM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#170;
+ flags : if_pent or if_smm
+ ),
+ (
+ opcode : A_SAHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#158;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#132#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_SALC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#214;
+ flags : if_8086 or if_undoc
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#135#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#135#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#135;
+ flags : if_386
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#135;
+ flags : if_386
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#135#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#24#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#24#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#25#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#25#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#25#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#25#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#26#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#26#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#27#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#27#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#27#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#27#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#131#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#131#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#28#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#29#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#29#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#131#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#131#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#131#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#131#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#131#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#131#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SCASB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#1#174;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SCASD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#209#1#175;
+ flags : if_386
+ ),
+ (
+ opcode : A_SCASW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#208#1#175;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SEGCS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#46;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGDS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#62;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGES;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#38;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGFS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#100;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGGS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#101;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGSS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#54;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SGDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#132#21;
+ flags : if_186 or if_sw
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#132#21;
+ flags : if_386 or if_sd
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg16,ot_immediate);
+ code : #192#208#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_immediate);
+ code : #192#208#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg32,ot_immediate);
+ code : #192#209#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate);
+ code : #192#209#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg16,ot_reg_cl);
+ code : #192#208#2#15#165#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_reg_cl);
+ code : #192#208#2#15#165#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg32,ot_reg_cl);
+ code : #192#209#2#15#165#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg_cl);
+ code : #192#209#2#15#165#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#133#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#133#21;
+ flags : if_186 or if_sw
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#133#21;
+ flags : if_386 or if_sd
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg16,ot_immediate);
+ code : #192#208#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_immediate);
+ code : #192#208#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg32,ot_immediate);
+ code : #192#209#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate);
+ code : #192#209#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg16,ot_reg_cl);
+ code : #192#208#2#15#173#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_reg_cl);
+ code : #192#208#2#15#173#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg32,ot_reg_cl);
+ code : #192#209#2#15#173#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg_cl);
+ code : #192#209#2#15#173#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SIDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#129;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#1#15#15#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#1#15#15#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_SMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_SMINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#56;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_SMINTOLD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#126;
+ flags : if_486 or if_cyrix
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#132;
+ flags : if_286
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#2#15#1#132;
+ flags : if_286
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#2#15#1#132;
+ flags : if_286
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#2#15#1#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_STC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#249;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#253;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#251;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STOSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#170;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STOSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#171;
+ flags : if_386
+ ),
+ (
+ opcode : A_STOSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#171;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#1#15#15#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#1#15#15#129;
+ flags : if_386 or if_prot
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#40#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#40#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#41#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#41#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#41#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#41#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#42#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#42#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#43#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#43#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#43#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#43#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#133#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#133#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#44#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#45#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#45#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#133#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#133#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#133#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#133#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#133#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#133#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SVDC;
+ ops : 2;
+ optypes : (ot_memory or ot_bits80,ot_reg_sreg,ot_none);
+ code : #192#2#15#120#65;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SVLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#2#15#122#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SVTS;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#2#15#124#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SYSCALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#5;
+ flags : if_p6 or if_amd
+ ),
+ (
+ opcode : A_SYSENTER;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#52;
+ flags : if_p6
+ ),
+ (
+ opcode : A_SYSEXIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#53;
+ flags : if_p6 or if_priv
+ ),
+ (
+ opcode : A_SYSRET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#7;
+ flags : if_p6 or if_priv or if_amd
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#132#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#132#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#133#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#133#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#133#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#133#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#132#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#133#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#133#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#168#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#169#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#169#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#246#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#247#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#247#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#246#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#247#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#247#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_UD1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#185;
+ flags : if_286 or if_undoc
+ ),
+ (
+ opcode : A_UD2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#11;
+ flags : if_286
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#2#15#16#65;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#2#15#16#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#17#65;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#17#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#17#65;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#17#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#2#15#18#72;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#2#15#18#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#19#72;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#19#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#19#72;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#19#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#1#15#15#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#1#15#15#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_WAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#155;
+ flags : if_8086
+ ),
+ (
+ opcode : A_WBINVD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#9;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_WRSHR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#55;
+ flags : if_p6 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_WRMSR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#48;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#2#15#192#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#2#15#192#65;
+ flags : if_486
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#193#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#193#65;
+ flags : if_486
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#193#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#193#65;
+ flags : if_486
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#166#72;
+ flags : if_386 or if_sw or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#166#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#166#72;
+ flags : if_386 or if_sd or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#166#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_reg16,ot_none);
+ code : #208#9#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg32,ot_none);
+ code : #209#9#144;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_ax,ot_none);
+ code : #208#8#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_eax,ot_none);
+ code : #209#8#144;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#134#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#134#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#135#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#135#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#135#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#135#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#134#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#134#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#135#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#135#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#135#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#135#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_XLAT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#215;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XLATB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#215;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#48#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#48#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#49#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#49#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#49#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#49#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#50#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#50#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#51#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#51#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#51#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#51#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#134#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#134#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#52#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#53#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#53#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#134#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#134#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#134#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#134#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#134#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#134#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XSTORE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#167#192;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#15#216#64#72;
+ flags : if_p6 or if_sm
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#15#216#64#72;
+ flags : if_p6
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#15#216#64#72;
+ flags : if_p6 or if_sm
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#15#216#64#72;
+ flags : if_p6
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none);
+ code : #211#1#15#216#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#1#15#216#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#1#15#216#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #216#112#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_short,ot_none,ot_none);
+ code : #216#112#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SETcc;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#216#144#128;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_SETcc;
+ ops : 1;
+ optypes : (ot_reg8,ot_none,ot_none);
+ code : #192#1#15#216#144#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ADDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ADDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDNPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#85#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDNPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#85#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#84#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#84#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#217#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #217#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#219#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #219#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_COMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#47#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_COMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#47#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTPI2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#42#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPI2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none);
+ code : #217#2#15#42#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#217#2#15#45#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #217#2#15#45#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTSI2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#42#72;
+ flags : if_katmai or if_sse or if_sd or if_ar1
+ ),
+ (
+ opcode : A_CVTSI2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32,ot_none);
+ code : #219#2#15#42#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #193#219#2#15#45#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #219#2#15#45#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#217#2#15#44#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #217#2#15#44#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #193#219#2#15#44#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #219#2#15#44#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_LDMXCSR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#130;
+ flags : if_katmai or if_sse or if_sd
+ ),
+ (
+ opcode : A_MAXPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MAXPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MAXSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MAXSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#40#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#2#15#41#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#40#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#41#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#22#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#2#15#23#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#22#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#18#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#2#15#19#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#18#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVMSKPS;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #2#15#80#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVNTPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #2#15#43#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#219#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#217#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#86#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#86#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SHUFPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#2#15#198#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHUFPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #2#15#198#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_STMXCSR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#131;
+ flags : if_katmai or if_sse or if_sd
+ ),
+ (
+ opcode : A_SUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SUBSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SUBSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UCOMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#46#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UCOMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#46#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#21#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#21#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#20#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#20#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_XORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#87#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_XORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#87#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_FXRSTOR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#129;
+ flags : if_p6 or if_sse or if_fpu
+ ),
+ (
+ opcode : A_FXSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#128;
+ flags : if_p6 or if_sse or if_fpu
+ ),
+ (
+ opcode : A_PREFETCHNTA;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#24#128;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT0;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#24#129;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT1;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#24#130;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT2;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#24#131;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_SFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#174#248;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_MASKMOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#247#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_MOVNTQ;
+ ops : 2;
+ optypes : (ot_memory,ot_mmxreg,ot_none);
+ code : #2#15#231#65;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#224#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#224#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#224#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#224#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#227#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#227#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#227#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#227#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_reg32,ot_mmxreg,ot_immediate);
+ code : #2#15#197#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_reg32,ot_xmmreg,ot_immediate);
+ code : #3#102#15#197#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_reg16,ot_immediate);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_reg32,ot_immediate);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory,ot_immediate);
+ code : #193#2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory or ot_bits16,ot_immediate);
+ code : #193#2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg16,ot_immediate);
+ code : #3#102#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg32,ot_immediate);
+ code : #3#102#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#3#102#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits16,ot_immediate);
+ code : #193#3#102#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#238#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#238#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#238#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#238#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#222#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#222#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#222#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#222#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#234#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#234#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#234#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#234#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#218#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#218#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#218#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#218#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMOVMSKB;
+ ops : 2;
+ optypes : (ot_reg32,ot_mmxreg,ot_none);
+ code : #2#15#215#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMOVMSKB;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#102#15#215#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#228#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#228#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#228#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#228#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#246#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#246#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#246#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#246#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSHUFW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_immediate);
+ code : #2#15#112#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory,ot_immediate);
+ code : #193#2#15#112#72#18;
+ flags : if_katmai or if_mmx or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PFNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#138;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#138;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFPNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#142;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFPNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#142;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PI2FW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#12;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PI2FW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#12;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PF2IW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#28;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PF2IW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#28;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PSWAPD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#187;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PSWAPD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#187;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_FFREEP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#223#8#192;
+ flags : if_pent or if_3dnow or if_fpu
+ ),
+ (
+ opcode : A_MASKMOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#247#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CLFLUSH;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#135;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVNTDQ;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#231#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVNTI;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #192#2#15#195#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVNTPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#43#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAUSE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #219#1#144;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_LFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#174#232;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#174#240;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#111#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#127#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#111#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#127#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#111#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #219#192#2#15#127#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#111#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#127#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQ2Q;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #3#242#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none);
+ code : #219#2#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#212#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#212#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#212#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#212#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#244#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#244#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#244#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#244#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSHUFD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #3#102#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#3#102#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFHW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #219#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFHW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#219#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFLW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #3#242#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFLW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#3#242#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSRLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#115#131#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#251#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#251#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#251#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#251#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#109#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKHQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#109#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#108#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKLQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#108#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#88#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#88#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#88#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ADDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#88#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ANDNPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#85#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ANDNPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#85#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ANDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#84#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ANDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#84#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#0;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#0;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPEQSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#0;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPEQSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#0;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#2;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#2;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#2;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#2;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#1;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#1;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#1;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#1;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#4;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#4;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#4;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#4;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#6;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#6;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#6;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#6;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#5;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#5;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#5;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#5;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#7;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#7;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#7;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#7;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPUNORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#3;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPUNORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#3;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPUNORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#3;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPUNORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#3;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #217#3#102#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#217#3#102#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_COMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#47#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_COMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#47#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#91#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#230#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #3#102#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#3#102#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#90#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPI2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none);
+ code : #3#102#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPI2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#91#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPS2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPS2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#242#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #193#3#242#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSI2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32,ot_none);
+ code : #3#242#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSI2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSS2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSS2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #3#102#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#3#102#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#230#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#91#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#242#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #193#3#242#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_DIVPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#94#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_DIVPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#94#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_DIVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#94#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_DIVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#94#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MAXPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#95#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MAXPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#95#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MAXSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#95#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MAXSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#95#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MINPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#93#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MINPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#93#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MINSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#93#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MINSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#93#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#40#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#41#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#41#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#40#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVHPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#23#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVHPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#22#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVLPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#19#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#18#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVMSKPD;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#102#15#80#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#16#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#17#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#17#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#16#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MULPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#89#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MULPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#89#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MULSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#89#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MULSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#89#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#86#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#86#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SHUFPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #3#102#15#198#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHUFPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#3#102#15#198#72#22;
+ flags : if_willamette or if_sse2 or if_sm or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SQRTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#81#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SQRTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#81#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SQRTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#81#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SQRTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#81#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#92#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#92#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SUBSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#92#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SUBSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#92#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UCOMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#46#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UCOMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#46#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UNPCKHPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#21#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UNPCKHPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#21#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_UNPCKLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#20#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UNPCKLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#20#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_XORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#87#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_XORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#87#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#208#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#208#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_ADDSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#208#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#208#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_HADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#124#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#124#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_HADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#124#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#124#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_HSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#125#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#125#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_HSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#125#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#125#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_LDDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #3#242#15#240#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVDDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVDDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSHDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#243#15#22#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSHDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#243#15#22#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSLDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#243#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSLDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#243#15#18#72;
+ flags : if_prescott or if_sse3
+ )
+);
diff --git a/compiler/i386/n386add.pas b/compiler/i386/n386add.pas
new file mode 100644
index 0000000000..92e9ef29ea
--- /dev/null
+++ b/compiler/i386/n386add.pas
@@ -0,0 +1,385 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Code generation for add nodes on 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.
+
+ ****************************************************************************
+}
+unit n386add;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,cpubase,nx86add;
+
+ type
+ ti386addnode = class(tx86addnode)
+ procedure second_add64bit;override;
+ procedure second_cmp64bit;override;
+ procedure second_mul;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmcpu,
+ cgbase,
+ ncon,nset,cgutils,tgobj,
+ cga,ncgutil,cgobj,cg64f32;
+
+{*****************************************************************************
+ Add64bit
+*****************************************************************************}
+
+ procedure ti386addnode.second_add64bit;
+ var
+ op : TOpCG;
+ op1,op2 : TAsmOp;
+ opsize : TOpSize;
+ hregister,
+ hregister2 : tregister;
+ hl4 : tasmlabel;
+ mboverflow,
+ unsigned:boolean;
+ r:Tregister;
+ begin
+ firstcomplex(self);
+ pass_left_right;
+
+ op1:=A_NONE;
+ op2:=A_NONE;
+ mboverflow:=false;
+ opsize:=S_L;
+ unsigned:=((left.resulttype.def.deftype=orddef) and
+ (torddef(left.resulttype.def).typ=u64bit)) or
+ ((right.resulttype.def.deftype=orddef) and
+ (torddef(right.resulttype.def).typ=u64bit));
+ case nodetype of
+ addn :
+ begin
+ op:=OP_ADD;
+ mboverflow:=true;
+ end;
+ subn :
+ begin
+ op:=OP_SUB;
+ op1:=A_SUB;
+ op2:=A_SBB;
+ mboverflow:=true;
+ end;
+ xorn:
+ op:=OP_XOR;
+ orn:
+ op:=OP_OR;
+ andn:
+ op:=OP_AND;
+ else
+ begin
+ { everything should be handled in pass_1 (JM) }
+ internalerror(200109051);
+ end;
+ end;
+
+ { left and right no register? }
+ { then one must be demanded }
+ if (left.location.loc<>LOC_REGISTER) then
+ begin
+ if (right.location.loc<>LOC_REGISTER) then
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_INT);
+ hregister2:=cg.getintregister(exprasmlist,OS_INT);
+ cg64.a_load64_loc_reg(exprasmlist,left.location,joinreg64(hregister,hregister2));
+ location_reset(left.location,LOC_REGISTER,OS_64);
+ left.location.register64.reglo:=hregister;
+ left.location.register64.reghi:=hregister2;
+ end
+ else
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end;
+ end;
+
+ { at this point, left.location.loc should be LOC_REGISTER }
+ if right.location.loc=LOC_REGISTER then
+ begin
+ { when swapped another result register }
+ if (nodetype=subn) and (nf_swaped in flags) then
+ begin
+ cg64.a_op64_reg_reg(exprasmlist,op,location.size,
+ left.location.register64,
+ right.location.register64);
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end
+ else
+ begin
+ cg64.a_op64_reg_reg(exprasmlist,op,location.size,
+ right.location.register64,
+ left.location.register64);
+ end;
+ end
+ else
+ begin
+ { right.location<>LOC_REGISTER }
+ if (nodetype=subn) and (nf_swaped in flags) then
+ begin
+ r:=cg.getintregister(exprasmlist,OS_INT);
+ cg64.a_load64low_loc_reg(exprasmlist,right.location,r);
+ emit_reg_reg(op1,opsize,left.location.register64.reglo,r);
+ emit_reg_reg(A_MOV,opsize,r,left.location.register64.reglo);
+ cg64.a_load64high_loc_reg(exprasmlist,right.location,r);
+ { the carry flag is still ok }
+ emit_reg_reg(op2,opsize,left.location.register64.reghi,r);
+ emit_reg_reg(A_MOV,opsize,r,left.location.register64.reghi);
+ end
+ else
+ begin
+ cg64.a_op64_loc_reg(exprasmlist,op,location.size,right.location,
+ left.location.register64);
+ end;
+ location_freetemp(exprasmlist,right.location);
+ end;
+
+ { only in case of overflow operations }
+ { produce overflow code }
+ { we must put it here directly, because sign of operation }
+ { is in unsigned VAR!! }
+ if mboverflow then
+ begin
+ if cs_check_overflow in aktlocalswitches then
+ begin
+ objectlibrary.getjumplabel(hl4);
+ if unsigned then
+ cg.a_jmp_flags(exprasmlist,F_AE,hl4)
+ else
+ cg.a_jmp_flags(exprasmlist,F_NO,hl4);
+ cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
+ cg.a_label(exprasmlist,hl4);
+ end;
+ end;
+
+ location_copy(location,left.location);
+ end;
+
+
+ procedure ti386addnode.second_cmp64bit;
+ var
+ hregister,
+ hregister2 : tregister;
+ href : treference;
+ unsigned : boolean;
+
+ procedure firstjmp64bitcmp;
+
+ var
+ oldnodetype : tnodetype;
+
+ begin
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn:
+ begin
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),truelabel);
+ { cheat a little bit for the negative test }
+ toggleflag(nf_swaped);
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),falselabel);
+ toggleflag(nf_swaped);
+ end;
+ lten,gten:
+ begin
+ oldnodetype:=nodetype;
+ if nodetype=lten then
+ nodetype:=ltn
+ else
+ nodetype:=gtn;
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),truelabel);
+ { cheat for the negative test }
+ if nodetype=ltn then
+ nodetype:=gtn
+ else
+ nodetype:=ltn;
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),falselabel);
+ nodetype:=oldnodetype;
+ end;
+ equaln:
+ cg.a_jmp_flags(exprasmlist,F_NE,falselabel);
+ unequaln:
+ cg.a_jmp_flags(exprasmlist,F_NE,truelabel);
+ end;
+ end;
+
+ procedure secondjmp64bitcmp;
+
+ begin
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn,lten,gten:
+ begin
+ { the comparisaion of the low dword have to be }
+ { always unsigned! }
+ cg.a_jmp_flags(exprasmlist,getresflags(true),truelabel);
+ cg.a_jmp_always(exprasmlist,falselabel);
+ end;
+ equaln:
+ begin
+ cg.a_jmp_flags(exprasmlist,F_NE,falselabel);
+ cg.a_jmp_always(exprasmlist,truelabel);
+ end;
+ unequaln:
+ begin
+ cg.a_jmp_flags(exprasmlist,F_NE,truelabel);
+ cg.a_jmp_always(exprasmlist,falselabel);
+ end;
+ end;
+ end;
+
+ begin
+ firstcomplex(self);
+
+ pass_left_right;
+
+ unsigned:=((left.resulttype.def.deftype=orddef) and
+ (torddef(left.resulttype.def).typ=u64bit)) or
+ ((right.resulttype.def.deftype=orddef) and
+ (torddef(right.resulttype.def).typ=u64bit));
+
+ { left and right no register? }
+ { then one must be demanded }
+ if (left.location.loc<>LOC_REGISTER) then
+ begin
+ if (right.location.loc<>LOC_REGISTER) then
+ begin
+ { we can reuse a CREGISTER for comparison }
+ if (left.location.loc<>LOC_CREGISTER) then
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_INT);
+ hregister2:=cg.getintregister(exprasmlist,OS_INT);
+ cg64.a_load64_loc_reg(exprasmlist,left.location,joinreg64(hregister,hregister2));
+ location_reset(left.location,LOC_REGISTER,OS_64);
+ left.location.register64.reglo:=hregister;
+ left.location.register64.reghi:=hregister2;
+ end;
+ end
+ else
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end;
+ end;
+
+ { at this point, left.location.loc should be LOC_REGISTER }
+ if right.location.loc=LOC_REGISTER then
+ begin
+ emit_reg_reg(A_CMP,S_L,right.location.register64.reghi,left.location.register64.reghi);
+ firstjmp64bitcmp;
+ emit_reg_reg(A_CMP,S_L,right.location.register64.reglo,left.location.register64.reglo);
+ secondjmp64bitcmp;
+ end
+ else
+ begin
+ case right.location.loc of
+ LOC_CREGISTER :
+ begin
+ emit_reg_reg(A_CMP,S_L,right.location.register64.reghi,left.location.register64.reghi);
+ firstjmp64bitcmp;
+ emit_reg_reg(A_CMP,S_L,right.location.register64.reglo,left.location.register64.reglo);
+ secondjmp64bitcmp;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ href:=right.location.reference;
+ inc(href.offset,4);
+ emit_ref_reg(A_CMP,S_L,href,left.location.register64.reghi);
+ firstjmp64bitcmp;
+ emit_ref_reg(A_CMP,S_L,right.location.reference,left.location.register64.reglo);
+ secondjmp64bitcmp;
+ cg.a_jmp_always(exprasmlist,falselabel);
+ location_freetemp(exprasmlist,right.location);
+ end;
+ LOC_CONSTANT :
+ begin
+ exprasmlist.concat(taicpu.op_const_reg(A_CMP,S_L,aint(hi(right.location.value64)),left.location.register64.reghi));
+ firstjmp64bitcmp;
+ exprasmlist.concat(taicpu.op_const_reg(A_CMP,S_L,aint(lo(right.location.value64)),left.location.register64.reglo));
+ secondjmp64bitcmp;
+ end;
+ else
+ internalerror(200203282);
+ end;
+ end;
+
+ location_freetemp(exprasmlist,left.location);
+
+ { we have LOC_JUMP as result }
+ location_reset(location,LOC_JUMP,OS_NO)
+ end;
+
+
+{*****************************************************************************
+ x86 MUL
+*****************************************************************************}
+
+ procedure ti386addnode.second_mul;
+
+ var r:Tregister;
+ hl4 : tasmlabel;
+
+ begin
+ {The location.register will be filled in later (JM)}
+ location_reset(location,LOC_REGISTER,OS_INT);
+ {Get a temp register and load the left value into it
+ and free the location.}
+ r:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_loc_reg(exprasmlist,OS_INT,left.location,r);
+ {Allocate EAX.}
+ cg.getcpuregister(exprasmlist,NR_EAX);
+ {Load the right value.}
+ cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,NR_EAX);
+ {Also allocate EDX, since it is also modified by a mul (JM).}
+ cg.getcpuregister(exprasmlist,NR_EDX);
+ emit_reg(A_MUL,S_L,r);
+ if cs_check_overflow in aktlocalswitches then
+ begin
+ objectlibrary.getjumplabel(hl4);
+ cg.a_jmp_flags(exprasmlist,F_AE,hl4);
+ cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
+ cg.a_label(exprasmlist,hl4);
+ end;
+ {Free EAX,EDX}
+ cg.ungetcpuregister(exprasmlist,NR_EDX);
+ cg.ungetcpuregister(exprasmlist,NR_EAX);
+ {Allocate a new register and store the result in EAX in it.}
+ location.register:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,NR_EAX,location.register);
+ location_freetemp(exprasmlist,left.location);
+ location_freetemp(exprasmlist,right.location);
+ end;
+
+
+begin
+ caddnode:=ti386addnode;
+end.
diff --git a/compiler/i386/n386cal.pas b/compiler/i386/n386cal.pas
new file mode 100644
index 0000000000..466b6f7fb7
--- /dev/null
+++ b/compiler/i386/n386cal.pas
@@ -0,0 +1,95 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for in call 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 n386cal;
+
+{$i fpcdefs.inc}
+
+interface
+
+{ $define AnsiStrRef}
+
+ uses
+ ncgcal;
+
+ type
+ ti386callnode = class(tcgcallnode)
+ protected
+ procedure pop_parasize(pop_size:longint);override;
+ procedure extra_interrupt_code;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ cgbase,
+ cpubase,paramgr,
+ aasmtai,aasmcpu,
+ ncal,nbas,nmem,nld,ncnv,
+ cga,cgobj,cpuinfo;
+
+
+{*****************************************************************************
+ TI386CALLNODE
+*****************************************************************************}
+
+
+ procedure ti386callnode.extra_interrupt_code;
+ begin
+ emit_none(A_PUSHF,S_L);
+ emit_reg(A_PUSH,S_L,NR_CS);
+ end;
+
+
+ procedure ti386callnode.pop_parasize(pop_size:longint);
+ var
+ hreg : tregister;
+ begin
+ { better than an add on all processors }
+ if pop_size=4 then
+ begin
+ hreg:=cg.getintregister(exprasmlist,OS_INT);
+ exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
+ end
+ { the pentium has two pipes and pop reg is pairable }
+ { but the registers must be different! }
+ else
+ if (pop_size=8) and
+ not(cs_littlesize in aktglobalswitches) and
+ (aktoptprocessor=ClassPentium) then
+ begin
+ hreg:=cg.getintregister(exprasmlist,OS_INT);
+ exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
+ hreg:=cg.getintregister(exprasmlist,OS_INT);
+ exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
+ end
+ else
+ if pop_size<>0 then
+ exprasmlist.concat(taicpu.op_const_reg(A_ADD,S_L,pop_size,NR_ESP));
+ end;
+
+
+begin
+ ccallnode:=ti386callnode;
+end.
diff --git a/compiler/i386/n386inl.pas b/compiler/i386/n386inl.pas
new file mode 100644
index 0000000000..4c28d2bc8a
--- /dev/null
+++ b/compiler/i386/n386inl.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 inline 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 n386inl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ nx86inl;
+
+ type
+ ti386inlinenode = class(tx86inlinenode)
+ end;
+
+implementation
+
+ uses
+ ninl;
+
+begin
+ cinlinenode:=ti386inlinenode;
+end.
diff --git a/compiler/i386/n386mat.pas b/compiler/i386/n386mat.pas
new file mode 100644
index 0000000000..8135b95f88
--- /dev/null
+++ b/compiler/i386/n386mat.pas
@@ -0,0 +1,324 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for math 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 n386mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat,nx86mat;
+
+ type
+ ti386moddivnode = class(tmoddivnode)
+ procedure pass_2;override;
+ end;
+
+ ti386shlshrnode = class(tshlshrnode)
+ procedure pass_2;override;
+ { everything will be handled in pass_2 }
+ function first_shlshr64bitint: tnode; override;
+ end;
+
+ ti386unaryminusnode = class(tx86unaryminusnode)
+ end;
+
+ ti386notnode = class(tx86notnode)
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,aasmbase,aasmtai,defutil,
+ cgbase,pass_2,
+ ncon,
+ cpubase,cpuinfo,
+ cga,ncgutil,cgobj,cgutils;
+
+{*****************************************************************************
+ TI386MODDIVNODE
+*****************************************************************************}
+
+ procedure ti386moddivnode.pass_2;
+
+ var hreg1,hreg2:Tregister;
+ power:longint;
+ hl:Tasmlabel;
+ op:Tasmop;
+
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ secondpass(right);
+ if codegenerror then
+ exit;
+
+ if is_64bitint(resulttype.def) then
+ { should be handled in pass_1 (JM) }
+ internalerror(200109052);
+ { put numerator in register }
+ location_reset(location,LOC_REGISTER,OS_INT);
+ location_force_reg(exprasmlist,left.location,OS_INT,false);
+ hreg1:=left.location.register;
+
+ if (nodetype=divn) and (right.nodetype=ordconstn) and
+ ispowerof2(tordconstnode(right).value,power) then
+ begin
+ { for signed numbers, the numerator must be adjusted before the
+ shift instruction, but not wih unsigned numbers! Otherwise,
+ "Cardinal($ffffffff) div 16" overflows! (JM) }
+ if is_signed(left.resulttype.def) Then
+ begin
+ if (aktOptProcessor <> class386) and
+ not(cs_littlesize in aktglobalswitches) then
+ { use a sequence without jumps, saw this in
+ comp.compilers (JM) }
+ begin
+ { no jumps, but more operations }
+ hreg2:=cg.getintregister(exprasmlist,OS_INT);
+ emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
+ {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
+ emit_const_reg(A_SAR,S_L,31,hreg2);
+ {If signed, hreg2=right value-1, otherwise 0.}
+ emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
+ { add to the left value }
+ emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
+ { do the shift }
+ emit_const_reg(A_SAR,S_L,power,hreg1);
+ end
+ else
+ begin
+ { a jump, but less operations }
+ emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
+ objectlibrary.getjumplabel(hl);
+ cg.a_jmp_flags(exprasmlist,F_NS,hl);
+ if power=1 then
+ emit_reg(A_INC,S_L,hreg1)
+ else
+ emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
+ cg.a_label(exprasmlist,hl);
+ emit_const_reg(A_SAR,S_L,power,hreg1);
+ end
+ end
+ else
+ emit_const_reg(A_SHR,S_L,power,hreg1);
+ location.register:=hreg1;
+ end
+ else
+ begin
+ cg.getcpuregister(exprasmlist,NR_EAX);
+ emit_reg_reg(A_MOV,S_L,hreg1,NR_EAX);
+ cg.getcpuregister(exprasmlist,NR_EDX);
+ {Sign extension depends on the left type.}
+ if torddef(left.resulttype.def).typ=u32bit then
+ emit_reg_reg(A_XOR,S_L,NR_EDX,NR_EDX)
+ else
+ emit_none(A_CDQ,S_NO);
+
+ {Division depends on the right type.}
+ if Torddef(right.resulttype.def).typ=u32bit then
+ op:=A_DIV
+ else
+ op:=A_IDIV;
+
+ if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ emit_ref(op,S_L,right.location.reference)
+ else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ emit_reg(op,S_L,right.location.register)
+ else
+ begin
+ hreg1:=cg.getintregister(exprasmlist,right.location.size);
+ cg.a_load_loc_reg(exprasmlist,OS_32,right.location,hreg1);
+ emit_reg(op,S_L,hreg1);
+ end;
+
+ {Copy the result into a new register. Release EAX & EDX.}
+ cg.ungetcpuregister(exprasmlist,NR_EDX);
+ cg.ungetcpuregister(exprasmlist,NR_EAX);
+ location.register:=cg.getintregister(exprasmlist,OS_INT);
+ if nodetype=divn then
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,NR_EAX,location.register)
+ else
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,NR_EDX,location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TI386SHLRSHRNODE
+*****************************************************************************}
+
+
+ function ti386shlshrnode.first_shlshr64bitint: tnode;
+
+ begin
+ result := nil;
+ end;
+
+ procedure ti386shlshrnode.pass_2;
+
+ var hreg64hi,hreg64lo:Tregister;
+ op:Tasmop;
+ v : TConstExprInt;
+ l1,l2,l3:Tasmlabel;
+
+ begin
+ secondpass(left);
+ secondpass(right);
+
+ { determine operator }
+ if nodetype=shln then
+ op:=A_SHL
+ else
+ op:=A_SHR;
+
+ if is_64bitint(left.resulttype.def) then
+ begin
+ location_reset(location,LOC_REGISTER,OS_64);
+
+ { load left operator in a register }
+ location_force_reg(exprasmlist,left.location,OS_64,false);
+ hreg64hi:=left.location.register64.reghi;
+ hreg64lo:=left.location.register64.reglo;
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ begin
+ v:=Tordconstnode(right).value and 63;
+ if v>31 then
+ begin
+ if nodetype=shln then
+ begin
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+ if ((v and 31) <> 0) then
+ emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
+ end
+ else
+ begin
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+ if ((v and 31) <> 0) then
+ emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
+ end;
+ location.register64.reghi:=hreg64lo;
+ location.register64.reglo:=hreg64hi;
+ end
+ else
+ begin
+ if nodetype=shln then
+ begin
+ emit_const_reg_reg(A_SHLD,S_L,v and 31,hreg64lo,hreg64hi);
+ emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
+ end
+ else
+ begin
+ emit_const_reg_reg(A_SHRD,S_L,v and 31,hreg64hi,hreg64lo);
+ emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
+ end;
+ location.register64.reglo:=hreg64lo;
+ location.register64.reghi:=hreg64hi;
+ end;
+ end
+ else
+ begin
+ { load right operators in a register }
+ cg.getcpuregister(exprasmlist,NR_ECX);
+ cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
+
+ { left operator is already in a register }
+ { hence are both in a register }
+ { is it in the case ECX ? }
+
+ { the damned shift instructions work only til a count of 32 }
+ { so we've to do some tricks here }
+ objectlibrary.getjumplabel(l1);
+ objectlibrary.getjumplabel(l2);
+ objectlibrary.getjumplabel(l3);
+ emit_const_reg(A_CMP,S_L,64,NR_ECX);
+ cg.a_jmp_flags(exprasmlist,F_L,l1);
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+ cg.a_jmp_always(exprasmlist,l3);
+ cg.a_label(exprasmlist,l1);
+ emit_const_reg(A_CMP,S_L,32,NR_ECX);
+ cg.a_jmp_flags(exprasmlist,F_L,l2);
+ emit_const_reg(A_SUB,S_L,32,NR_ECX);
+ if nodetype=shln then
+ begin
+ emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
+ emit_reg_reg(A_MOV,S_L,hreg64lo,hreg64hi);
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+ cg.a_jmp_always(exprasmlist,l3);
+ cg.a_label(exprasmlist,l2);
+ emit_reg_reg_reg(A_SHLD,S_L,NR_CL,hreg64lo,hreg64hi);
+ emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
+ end
+ else
+ begin
+ emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
+ emit_reg_reg(A_MOV,S_L,hreg64hi,hreg64lo);
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+ cg.a_jmp_always(exprasmlist,l3);
+ cg.a_label(exprasmlist,l2);
+ emit_reg_reg_reg(A_SHRD,S_L,NR_CL,hreg64hi,hreg64lo);
+ emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
+ end;
+ cg.a_label(exprasmlist,l3);
+
+ cg.ungetcpuregister(exprasmlist,NR_ECX);
+ location.register64.reglo:=hreg64lo;
+ location.register64.reghi:=hreg64hi;
+ end;
+ end
+ else
+ begin
+ { load left operators in a register }
+ location_copy(location,left.location);
+ location_force_reg(exprasmlist,location,OS_INT,false);
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
+ emit_const_reg(op,S_L,tordconstnode(right).value and 31,location.register)
+ else
+ begin
+ { load right operators in a ECX }
+ cg.getcpuregister(exprasmlist,NR_ECX);
+ cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
+
+ { right operand is in ECX }
+ cg.ungetcpuregister(exprasmlist,NR_ECX);
+ emit_reg_reg(op,S_L,NR_CL,location.register);
+ end;
+ end;
+ end;
+
+
+begin
+ cunaryminusnode:=ti386unaryminusnode;
+ cmoddivnode:=ti386moddivnode;
+ cshlshrnode:=ti386shlshrnode;
+ cnotnode:=ti386notnode;
+end.
diff --git a/compiler/i386/n386mem.pas b/compiler/i386/n386mem.pas
new file mode 100644
index 0000000000..f3939c9ed3
--- /dev/null
+++ b/compiler/i386/n386mem.pas
@@ -0,0 +1,140 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for in memory related 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 n386mem;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cgbase,cpuinfo,cpubase,
+ node,nmem,ncgmem;
+
+ type
+ ti386addrnode = class(tcgaddrnode)
+ procedure pass_2;override;
+ end;
+
+ ti386derefnode = class(tcgderefnode)
+ procedure pass_2;override;
+ end;
+
+ ti386vecnode = class(tcgvecnode)
+ procedure update_reference_reg_mul(reg:tregister;l:aint);override;
+ procedure pass_2;override;
+ end;
+
+implementation
+
+ uses
+ systems,
+ cutils,verbose,
+ symdef,paramgr,
+ aasmtai,
+ nld,ncon,nadd,
+ cgutils,cgobj;
+
+{*****************************************************************************
+ TI386ADDRNODE
+*****************************************************************************}
+
+ procedure ti386addrnode.pass_2;
+
+ begin
+ inherited pass_2;
+ { for use of other segments, not used }
+ {if left.location.reference.segment<>NR_NO then
+ location.segment:=left.location.reference.segment;}
+ end;
+
+
+{*****************************************************************************
+ TI386DEREFNODE
+*****************************************************************************}
+
+ procedure ti386derefnode.pass_2;
+ begin
+ inherited pass_2;
+ if tpointerdef(left.resulttype.def).is_far then
+ location.reference.segment:=NR_FS;
+ end;
+
+
+{*****************************************************************************
+ TI386VECNODE
+*****************************************************************************}
+
+ procedure ti386vecnode.update_reference_reg_mul(reg:tregister;l:aint);
+ var
+ l2 : integer;
+ hreg : tregister;
+ begin
+ { Optimized for x86 to use the index register and scalefactor }
+ if location.reference.index=NR_NO then
+ begin
+ { no preparations needed }
+ end
+ else if location.reference.base=NR_NO then
+ begin
+ case location.reference.scalefactor of
+ 2 : cg.a_op_const_reg(exprasmlist,OP_SHL,OS_ADDR,1,location.reference.index);
+ 4 : cg.a_op_const_reg(exprasmlist,OP_SHL,OS_ADDR,2,location.reference.index);
+ 8 : cg.a_op_const_reg(exprasmlist,OP_SHL,OS_ADDR,3,location.reference.index);
+ end;
+ location.reference.base:=location.reference.index;
+ end
+ else
+ begin
+ hreg := cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,location.reference,hreg);
+ reference_reset_base(location.reference,hreg,0);
+ end;
+ { insert the new index register and scalefactor or
+ do the multiplication manual }
+ case l of
+ 1,2,4,8 : location.reference.scalefactor:=l;
+ else
+ begin
+ if ispowerof2(l,l2) then
+ cg.a_op_const_reg(exprasmlist,OP_SHL,OS_ADDR,l2,reg)
+ else
+ cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
+ end;
+ end;
+ location.reference.index:=reg;
+ end;
+
+
+ procedure ti386vecnode.pass_2;
+ begin
+ inherited pass_2;
+ if nf_memseg in flags then
+ location.reference.segment:=NR_FS;
+ end;
+
+
+begin
+ caddrnode:=ti386addrnode;
+ cderefnode:=ti386derefnode;
+ cvecnode:=ti386vecnode;
+end.
diff --git a/compiler/i386/n386set.pas b/compiler/i386/n386set.pas
new file mode 100644
index 0000000000..9a52860b36
--- /dev/null
+++ b/compiler/i386/n386set.pas
@@ -0,0 +1,218 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 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 n386set;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ node,nset,pass_1,ncgset;
+
+ type
+ ti386casenode = class(tcgcasenode)
+ procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
+ function has_jumptable : boolean;override;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
+ procedure genlinearlist(hp : pcaselabel);override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,
+ symconst,symdef,defutil,
+ aasmbase,aasmtai,aasmcpu,
+ cgbase,pass_2,
+ ncon,
+ cpubase,cpuinfo,procinfo,
+ cga,cgutils,cgobj,ncgutil,
+ cgx86;
+
+
+{*****************************************************************************
+ TI386CASENODE
+*****************************************************************************}
+
+ procedure ti386casenode.optimizevalues(var max_linear_list:aint;var max_dist:aword);
+ begin
+ { a jump table crashes the pipeline! }
+ if aktoptprocessor=Class386 then
+ inc(max_linear_list,3)
+ else if aktoptprocessor=ClassPentium then
+ inc(max_linear_list,6)
+ else if aktoptprocessor in [ClassPentium2,ClassPentium3] then
+ inc(max_linear_list,9)
+ else if aktoptprocessor=ClassPentium4 then
+ inc(max_linear_list,14);
+ end;
+
+
+ function ti386casenode.has_jumptable : boolean;
+ begin
+ has_jumptable:=true;
+ end;
+
+
+ procedure ti386casenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ var
+ table : tasmlabel;
+ last : TConstExprInt;
+ indexreg : tregister;
+ href : treference;
+
+ procedure genitem(list:taasmoutput;t : pcaselabel);
+ var
+ i : aint;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ for i:=last+1 to t^._low-1 do
+ list.concat(Tai_const.Create_sym(elselabel));
+ for i:=t^._low to t^._high do
+ list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+ last:=t^._high;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+ begin
+ if not(jumptable_no_range) then
+ begin
+ { case expr less than min_ => goto elselabel }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_lt,aint(min_),hregister,elselabel);
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_gt,aint(max_),hregister,elselabel);
+ end;
+ objectlibrary.getjumplabel(table);
+ { make it a 32bit register }
+ indexreg:=cg.makeregsize(exprasmlist,hregister,OS_INT);
+ cg.a_load_reg_reg(exprasmlist,opsize,OS_INT,hregister,indexreg);
+ { create reference }
+ reference_reset_symbol(href,table,0);
+ href.offset:=(-aint(min_))*4;
+ href.index:=indexreg;
+ href.scalefactor:=4;
+ emit_ref(A_JMP,S_NO,href);
+ { generate jump table }
+ new_section(current_procinfo.aktlocaldata,sec_data,current_procinfo.procdef.mangledname,sizeof(aint));
+ current_procinfo.aktlocaldata.concat(Tai_label.Create(table));
+ last:=min_;
+ genitem(current_procinfo.aktlocaldata,hp);
+ end;
+
+
+ procedure ti386casenode.genlinearlist(hp : pcaselabel);
+ var
+ first : boolean;
+ lastrange : boolean;
+ last : TConstExprInt;
+ cond_lt,cond_le : tresflags;
+
+ procedure genitem(t : pcaselabel);
+ 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,opsize,jmp_lt,aint(t^._low),hregister,elselabel);
+ end;
+ if t^._low=t^._high then
+ begin
+ if t^._low-last=0 then
+ cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ,0,hregister,blocklabel(t^.blockid))
+ else
+ begin
+ cg.a_op_const_reg(exprasmlist, OP_SUB, opsize, aint(t^._low-last), hregister);
+ cg.a_jmp_flags(exprasmlist,F_E,blocklabel(t^.blockid));
+ end;
+ last:=t^._low;
+ lastrange:=false;
+ 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
+ cg.a_op_const_reg(exprasmlist, OP_SUB, opsize, aint(t^._low), hregister);
+ 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: }
+
+ cg.a_op_const_reg(exprasmlist, OP_SUB, opsize, aint(t^._low-last), hregister);
+ { no jump necessary here if the new range starts at }
+ { at the value following the previous one }
+ if ((t^._low-last) <> 1) or
+ (not lastrange) then
+ cg.a_jmp_flags(exprasmlist,cond_lt,elselabel);
+ end;
+ {we need to use A_SUB, because A_DEC does not set the correct flags, therefor
+ using a_op_const_reg(OP_SUB) is not possible }
+ emit_const_reg(A_SUB,TCGSize2OpSize[opsize],aint(t^._high-t^._low),hregister);
+ cg.a_jmp_flags(exprasmlist,cond_le,blocklabel(t^.blockid));
+ last:=t^._high;
+ lastrange:=true;
+ end;
+ first:=false;
+ if assigned(t^.greater) then
+ genitem(t^.greater);
+ end;
+
+ begin
+ if with_sign then
+ begin
+ cond_lt:=F_L;
+ cond_le:=F_LE;
+ end
+ else
+ begin
+ cond_lt:=F_B;
+ cond_le:=F_BE;
+ end;
+ { do we need to generate cmps? }
+ if (with_sign and (min_label<0)) then
+ genlinearcmplist(hp)
+ else
+ begin
+ last:=0;
+ lastrange:=false;
+ first:=true;
+ genitem(hp);
+ cg.a_jmp_always(exprasmlist,elselabel);
+ end;
+ end;
+
+begin
+ ccasenode:=ti386casenode;
+end.
diff --git a/compiler/i386/optbase.pas b/compiler/i386/optbase.pas
new file mode 100644
index 0000000000..e94e008d86
--- /dev/null
+++ b/compiler/i386/optbase.pas
@@ -0,0 +1,34 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ This routine contains the basic tables and information
+ for the generic optimizers and cpu specific optimizations.
+
+ 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 should define cpu specific information which is required
+ for the optimizers.
+}
+unit optbase;
+
+interface
+
+
+implementation
+
+
+end.
diff --git a/compiler/i386/popt386.pas b/compiler/i386/popt386.pas
new file mode 100644
index 0000000000..b38be5e40d
--- /dev/null
+++ b/compiler/i386/popt386.pas
@@ -0,0 +1,2033 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Jonas Maebe
+
+ This unit contains the peephole optimizer.
+
+ 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 popt386;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses Aasmbase,aasmtai,aasmcpu,verbose;
+
+procedure PrePeepHoleOpts(asml: taasmoutput; BlockStart, BlockEnd: tai);
+procedure PeepHoleOptPass1(asml: taasmoutput; BlockStart, BlockEnd: tai);
+procedure PeepHoleOptPass2(asml: taasmoutput; BlockStart, BlockEnd: tai);
+procedure PostPeepHoleOpts(asml: taasmoutput; BlockStart, BlockEnd: tai);
+
+implementation
+
+uses
+ globtype,systems,
+ globals,cgbase,procinfo,
+ symsym,
+{$ifdef finaldestdebug}
+ cobjects,
+{$endif finaldestdebug}
+ cpuinfo,cpubase,cgutils,daopt386;
+
+function RegUsedAfterInstruction(reg: Tregister; p: tai; var UsedRegs: TRegSet): Boolean;
+var
+ supreg: tsuperregister;
+begin
+ supreg := getsupreg(reg);
+ UpdateUsedRegs(UsedRegs, tai(p.Next));
+ RegUsedAfterInstruction :=
+ (supreg in UsedRegs) and
+ (not(getNextInstruction(p,p)) or
+ not(regLoadedWithNewValue(supreg,false,p)));
+end;
+
+
+function doFpuLoadStoreOpt(asmL: TAAsmoutput; var p: tai): boolean;
+{ returns true if a "continue" should be done after this optimization }
+var hp1, hp2: tai;
+begin
+ doFpuLoadStoreOpt := false;
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ getNextInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (((taicpu(hp1).opcode = A_FLD) and
+ (taicpu(p).opcode = A_FSTP)) or
+ ((taicpu(p).opcode = A_FISTP) and
+ (taicpu(hp1).opcode = A_FILD))) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) and
+ refsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
+ begin
+ { replacing fstp f;fld f by fst f is only valid for extended because of rounding }
+ if (taicpu(p).opsize=S_FX) and
+ getNextInstruction(hp1, hp2) and
+ (hp2.typ = ait_instruction) and
+ ((taicpu(hp2).opcode = A_LEAVE) or
+ (taicpu(hp2).opcode = A_RET)) and
+ (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
+ not(assigned(current_procinfo.procdef.funcretsym) and
+ (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
+ (taicpu(p).oper[0]^.ref^.index = NR_NO) then
+ begin
+ asml.remove(p);
+ asml.remove(hp1);
+ p.free;
+ hp1.free;
+ p := hp2;
+ removeLastDeallocForFuncRes(asmL, p);
+ doFPULoadStoreOpt := true;
+ end
+ { can't be done because the store operation rounds
+ else
+ { fst can't store an extended value! }
+ if (taicpu(p).opsize <> S_FX) and
+ (taicpu(p).opsize <> S_IQ) then
+ begin
+ if (taicpu(p).opcode = A_FSTP) then
+ taicpu(p).opcode := A_FST
+ else taicpu(p).opcode := A_FIST;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ }
+ end;
+end;
+
+
+procedure PrePeepHoleOpts(asml: taasmoutput; BlockStart, BlockEnd: tai);
+var
+ p,hp1: tai;
+ l: aint;
+ tmpRef: treference;
+begin
+ p := BlockStart;
+ while (p <> BlockEnd) Do
+ begin
+ case p.Typ Of
+ Ait_Instruction:
+ begin
+ case taicpu(p).opcode Of
+ A_IMUL:
+ {changes certain "imul const, %reg"'s to lea sequences}
+ begin
+ if (taicpu(p).oper[0]^.typ = Top_Const) and
+ (taicpu(p).oper[1]^.typ = Top_Reg) and
+ (taicpu(p).opsize = S_L) then
+ if (taicpu(p).oper[0]^.val = 1) then
+ if (taicpu(p).ops = 2) then
+ {remove "imul $1, reg"}
+ begin
+ hp1 := tai(p.Next);
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue;
+ end
+ else
+ {change "imul $1, reg1, reg2" to "mov reg1, reg2"}
+ begin
+ hp1 := taicpu.Op_Reg_Reg(A_MOV, S_L, taicpu(p).oper[1]^.reg,taicpu(p).oper[2]^.reg);
+ InsertLLItem(asml, p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end
+ else if
+ ((taicpu(p).ops <= 2) or
+ (taicpu(p).oper[2]^.typ = Top_Reg)) and
+ (aktoptprocessor < ClassPentium2) and
+ (taicpu(p).oper[0]^.val <= 12) and
+ not(CS_LittleSize in aktglobalswitches) and
+ (not(GetNextInstruction(p, hp1)) or
+ {GetNextInstruction(p, hp1) and}
+ not((tai(hp1).typ = ait_instruction) and
+ ((taicpu(hp1).opcode=A_Jcc) and
+ (taicpu(hp1).condition in [C_O,C_NO])))) then
+ begin
+ reference_reset(tmpref);
+ case taicpu(p).oper[0]^.val Of
+ 3: begin
+ {imul 3, reg1, reg2 to
+ lea (reg1,reg1,2), reg2
+ imul 3, reg1 to
+ lea (reg1,reg1,2), reg1}
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 2;
+ if (taicpu(p).ops = 2) then
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end;
+ 5: begin
+ {imul 5, reg1, reg2 to
+ lea (reg1,reg1,4), reg2
+ imul 5, reg1 to
+ lea (reg1,reg1,4), reg1}
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 4;
+ if (taicpu(p).ops = 2) then
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end;
+ 6: begin
+ {imul 6, reg1, reg2 to
+ lea (,reg1,2), reg2
+ lea (reg2,reg1,4), reg2
+ imul 6, reg1 to
+ lea (reg1,reg1,2), reg1
+ add reg1, reg1}
+ if (aktoptprocessor <= Class386) then
+ begin
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ if (taicpu(p).ops = 3) then
+ begin
+ TmpRef.base := taicpu(p).oper[2]^.reg;
+ TmpRef.ScaleFactor := 4;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ end
+ else
+ begin
+ hp1 := taicpu.op_reg_reg(A_ADD, S_L,
+ taicpu(p).oper[1]^.reg,taicpu(p).oper[1]^.reg);
+ end;
+ InsertLLItem(asml,p, p.next, hp1);
+ reference_reset(tmpref);
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 2;
+ if (taicpu(p).ops = 3) then
+ begin
+ TmpRef.base := NR_NO;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef,
+ taicpu(p).oper[2]^.reg);
+ end
+ else
+ begin
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ end;
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := tai(hp1.next);
+ end
+ end;
+ 9: begin
+ {imul 9, reg1, reg2 to
+ lea (reg1,reg1,8), reg2
+ imul 9, reg1 to
+ lea (reg1,reg1,8), reg1}
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 8;
+ if (taicpu(p).ops = 2) then
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end;
+ 10: begin
+ {imul 10, reg1, reg2 to
+ lea (reg1,reg1,4), reg2
+ add reg2, reg2
+ imul 10, reg1 to
+ lea (reg1,reg1,4), reg1
+ add reg1, reg1}
+ if (aktoptprocessor <= Class386) then
+ begin
+ if (taicpu(p).ops = 3) then
+ hp1 := taicpu.op_reg_reg(A_ADD, S_L,
+ taicpu(p).oper[2]^.reg,taicpu(p).oper[2]^.reg)
+ else
+ hp1 := taicpu.op_reg_reg(A_ADD, S_L,
+ taicpu(p).oper[1]^.reg,taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p, p.next, hp1);
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 4;
+ if (taicpu(p).ops = 3) then
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg)
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := tai(hp1.next);
+ end
+ end;
+ 12: begin
+ {imul 12, reg1, reg2 to
+ lea (,reg1,4), reg2
+ lea (,reg1,8) reg2
+ imul 12, reg1 to
+ lea (reg1,reg1,2), reg1
+ lea (,reg1,4), reg1}
+ if (aktoptprocessor <= Class386)
+ then
+ begin
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ if (taicpu(p).ops = 3) then
+ begin
+ TmpRef.base := taicpu(p).oper[2]^.reg;
+ TmpRef.ScaleFactor := 8;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ end
+ else
+ begin
+ TmpRef.base := NR_NO;
+ TmpRef.ScaleFactor := 4;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ end;
+ InsertLLItem(asml,p, p.next, hp1);
+ reference_reset(tmpref);
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ if (taicpu(p).ops = 3) then
+ begin
+ TmpRef.base := NR_NO;
+ TmpRef.ScaleFactor := 4;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ end
+ else
+ begin
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 2;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ end;
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := tai(hp1.next);
+ end
+ end
+ end;
+ end;
+ end;
+ A_SAR, A_SHR:
+ {changes the code sequence
+ shr/sar const1, x
+ shl const2, x
+ to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
+ begin
+ if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_SHL) and
+ (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) and
+ (taicpu(hp1).oper[1]^.typ = taicpu(p).oper[1]^.typ) and
+ OpsEqual(taicpu(hp1).oper[1]^, taicpu(p).oper[1]^) then
+ if (taicpu(p).oper[0]^.val > taicpu(hp1).oper[0]^.val) and
+ not(CS_LittleSize in aktglobalswitches) then
+ { shr/sar const1, %reg
+ shl const2, %reg
+ with const1 > const2 }
+ begin
+ taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val);
+ taicpu(hp1).opcode := A_AND;
+ l := (1 shl (taicpu(hp1).oper[0]^.val)) - 1;
+ case taicpu(p).opsize Of
+ S_L: taicpu(hp1).LoadConst(0,l Xor aint($ffffffff));
+ S_B: taicpu(hp1).LoadConst(0,l Xor $ff);
+ S_W: taicpu(hp1).LoadConst(0,l Xor $ffff);
+ end;
+ end
+ else if (taicpu(p).oper[0]^.val<taicpu(hp1).oper[0]^.val) and
+ not(CS_LittleSize in aktglobalswitches) then
+ { shr/sar const1, %reg
+ shl const2, %reg
+ with const1 < const2 }
+ begin
+ taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val-taicpu(p).oper[0]^.val);
+ taicpu(p).opcode := A_AND;
+ l := (1 shl (taicpu(p).oper[0]^.val))-1;
+ case taicpu(p).opsize Of
+ S_L: taicpu(p).LoadConst(0,l Xor aint($ffffffff));
+ S_B: taicpu(p).LoadConst(0,l Xor $ff);
+ S_W: taicpu(p).LoadConst(0,l Xor $ffff);
+ end;
+ end
+ else
+ { shr/sar const1, %reg
+ shl const2, %reg
+ with const1 = const2 }
+ if (taicpu(p).oper[0]^.val = taicpu(hp1).oper[0]^.val) then
+ begin
+ taicpu(p).opcode := A_AND;
+ l := (1 shl (taicpu(p).oper[0]^.val))-1;
+ case taicpu(p).opsize Of
+ S_B: taicpu(p).LoadConst(0,l Xor $ff);
+ S_W: taicpu(p).LoadConst(0,l Xor $ffff);
+ S_L: taicpu(p).LoadConst(0,l Xor aint($ffffffff));
+ end;
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ A_XOR:
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+ { temporarily change this to 'mov reg,0' to make it easier }
+ { for the CSE. Will be changed back in pass 2 }
+ begin
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).loadconst(0,0);
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next)
+ end;
+end;
+
+
+
+procedure PeepHoleOptPass1(Asml: taasmoutput; BlockStart, BlockEnd: tai);
+{First pass of peepholeoptimizations}
+
+var
+ l : longint;
+ p,hp1,hp2 : tai;
+ hp3,hp4: tai;
+
+ TmpRef: TReference;
+
+ UsedRegs, TmpUsedRegs: TRegSet;
+
+ TmpBool1, TmpBool2: Boolean;
+
+ function SkipLabels(hp: tai; var hp2: tai): boolean;
+ {skips all labels and returns the next "real" instruction}
+ begin
+ while assigned(hp.next) and
+ (tai(hp.next).typ in SkipInstr + [ait_label,ait_align]) Do
+ hp := tai(hp.next);
+ if assigned(hp.next) then
+ begin
+ SkipLabels := True;
+ hp2 := tai(hp.next)
+ end
+ else
+ begin
+ hp2 := hp;
+ SkipLabels := False
+ end;
+ end;
+
+ function GetFinalDestination(asml: taasmoutput; hp: taicpu; level: longint): boolean;
+ {traces sucessive jumps to their final destination and sets it, e.g.
+ je l1 je l3
+ <code> <code>
+ l1: becomes l1:
+ je l2 je l3
+ <code> <code>
+ l2: l2:
+ jmp l3 jmp l3
+
+ the level parameter denotes how deeep we have already followed the jump,
+ to avoid endless loops with constructs such as "l5: ; jmp l5" }
+
+ var p1, p2: tai;
+ l: tasmlabel;
+
+ function FindAnyLabel(hp: tai; var l: tasmlabel): Boolean;
+ begin
+ FindAnyLabel := false;
+ while assigned(hp.next) and
+ (tai(hp.next).typ in (SkipInstr+[ait_align])) Do
+ hp := tai(hp.next);
+ if assigned(hp.next) and
+ (tai(hp.next).typ = ait_label) then
+ begin
+ FindAnyLabel := true;
+ l := tai_label(hp.next).l;
+ end
+ end;
+
+ begin
+ GetfinalDestination := false;
+ if level > 20 then
+ exit;
+ p1 := dfa.getlabelwithsym(tasmlabel(hp.oper[0]^.ref^.symbol));
+ if assigned(p1) then
+ begin
+ SkipLabels(p1,p1);
+ if (tai(p1).typ = ait_instruction) and
+ (taicpu(p1).is_jmp) then
+ if { the next instruction after the label where the jump hp arrives}
+ { is unconditional or of the same type as hp, so continue }
+ (taicpu(p1).condition in [C_None,hp.condition]) or
+ { the next instruction after the label where the jump hp arrives}
+ { is the opposite of hp (so this one is never taken), but after }
+ { that one there is a branch that will be taken, so perform a }
+ { little hack: set p1 equal to this instruction (that's what the}
+ { last SkipLabels is for, only works with short bool evaluation)}
+ ((taicpu(p1).condition = inverse_cond(hp.condition)) and
+ SkipLabels(p1,p2) and
+ (p2.typ = ait_instruction) and
+ (taicpu(p2).is_jmp) and
+ (taicpu(p2).condition in [C_None,hp.condition]) and
+ SkipLabels(p1,p1)) then
+ begin
+ { quick check for loops of the form "l5: ; jmp l5 }
+ if (tasmlabel(taicpu(p1).oper[0]^.ref^.symbol).labelnr =
+ tasmlabel(hp.oper[0]^.ref^.symbol).labelnr) then
+ exit;
+ if not GetFinalDestination(asml, taicpu(p1),succ(level)) then
+ exit;
+ tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol:=taicpu(p1).oper[0]^.ref^.symbol;
+ tasmlabel(hp.oper[0]^.ref^.symbol).increfs;
+ end
+ else
+ if (taicpu(p1).condition = inverse_cond(hp.condition)) then
+ if not FindAnyLabel(p1,l) then
+ begin
+ {$ifdef finaldestdebug}
+ insertllitem(asml,p1,p1.next,tai_comment.Create(
+ strpnew('previous label inserted'))));
+ {$endif finaldestdebug}
+ objectlibrary.getjumplabel(l);
+ insertllitem(asml,p1,p1.next,tai_label.Create(l));
+ tasmlabel(taicpu(hp).oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol := l;
+ l.increfs;
+ { this won't work, since the new label isn't in the labeltable }
+ { so it will fail the rangecheck. Labeltable should become a }
+ { hashtable to support this: }
+ { GetFinalDestination(asml, hp); }
+ end
+ else
+ begin
+ {$ifdef finaldestdebug}
+ insertllitem(asml,p1,p1.next,tai_comment.Create(
+ strpnew('next label reused'))));
+ {$endif finaldestdebug}
+ l.increfs;
+ hp.oper[0]^.ref^.symbol := l;
+ if not GetFinalDestination(asml, hp,succ(level)) then
+ exit;
+ end;
+ end;
+ GetFinalDestination := true;
+ end;
+
+ function DoSubAddOpt(var p: tai): Boolean;
+ begin
+ DoSubAddOpt := False;
+ if GetLastInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) then
+ case taicpu(hp1).opcode Of
+ A_DEC:
+ if (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val+1);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ A_SUB:
+ if (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val+taicpu(hp1).oper[0]^.val);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ A_ADD:
+ if (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val);
+ asml.remove(hp1);
+ hp1.free;
+ if (taicpu(p).oper[0]^.val = 0) then
+ begin
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ if not GetLastInstruction(hp1, p) then
+ p := hp1;
+ DoSubAddOpt := True;
+ end
+ end;
+ end;
+ end;
+
+begin
+ p := BlockStart;
+ UsedRegs := [];
+ while (p <> BlockEnd) Do
+ begin
+ UpDateUsedRegs(UsedRegs, tai(p.next));
+ case p.Typ Of
+ ait_instruction:
+ begin
+ { Handle Jmp Optimizations }
+ if taicpu(p).is_jmp then
+ begin
+ {the following if-block removes all code between a jmp and the next label,
+ because it can never be executed}
+ if (taicpu(p).opcode = A_JMP) then
+ begin
+ while GetNextInstruction(p, hp1) and
+ (hp1.typ <> ait_label) do
+ if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
+ begin
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else break;
+ end;
+ { remove jumps to a label coming right after them }
+ if GetNextInstruction(p, hp1) then
+ begin
+ if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp1) and
+ {$warning FIXME removing the first instruction fails}
+ (p<>blockstart) then
+ begin
+ hp2:=tai(hp1.next);
+ asml.remove(p);
+ p.free;
+ p:=hp2;
+ continue;
+ end
+ else
+ begin
+ if hp1.typ = ait_label then
+ SkipLabels(hp1,hp1);
+ if (tai(hp1).typ=ait_instruction) and
+ (taicpu(hp1).opcode=A_JMP) and
+ GetNextInstruction(hp1, hp2) and
+ FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp2) then
+ begin
+ if taicpu(p).opcode=A_Jcc then
+ begin
+ taicpu(p).condition:=inverse_cond(taicpu(p).condition);
+ tai_label(hp2).l.decrefs;
+ taicpu(p).oper[0]^.ref^.symbol:=taicpu(hp1).oper[0]^.ref^.symbol;
+ taicpu(p).oper[0]^.ref^.symbol.increfs;
+ asml.remove(hp1);
+ hp1.free;
+ GetFinalDestination(asml, taicpu(p),0);
+ end
+ else
+ begin
+ GetFinalDestination(asml, taicpu(p),0);
+ p:=tai(p.next);
+ continue;
+ end;
+ end
+ else
+ GetFinalDestination(asml, taicpu(p),0);
+ end;
+ end;
+ end
+ else
+ { All other optimizes }
+ begin
+ for l := 0 to taicpu(p).ops-1 Do
+ if (taicpu(p).oper[l]^.typ = top_ref) then
+ With taicpu(p).oper[l]^.ref^ Do
+ begin
+ if (base = NR_NO) and
+ (index <> NR_NO) and
+ (scalefactor in [0,1]) then
+ begin
+ base := index;
+ index := NR_NO
+ end
+ end;
+ case taicpu(p).opcode Of
+ A_AND:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.reg = taicpu(hp1).oper[1]^.reg) then
+ {change "and const1, reg; and const2, reg" to "and (const1 and const2), reg"}
+ begin
+ taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val and taicpu(hp1).oper[0]^.val);
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else
+ {change "and x, reg; jxx" to "test x, reg", if reg is deallocated before the
+ jump, but only if it's a conditional jump (PFV) }
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).is_jmp) and
+ (taicpu(hp1).opcode<>A_JMP) and
+ not(getsupreg(taicpu(p).oper[1]^.reg) in UsedRegs) then
+ taicpu(p).opcode := A_TEST;
+ end;
+ A_CMP:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ in [top_reg,top_ref]) and
+ (taicpu(p).oper[0]^.val = 0) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).is_jmp) and
+ (taicpu(hp1).opcode=A_Jcc) and
+ (taicpu(hp1).condition in [C_LE,C_BE]) and
+ GetNextInstruction(hp1,hp2) and
+ (hp2.typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_DEC) and
+ OpsEqual(taicpu(hp2).oper[0]^,taicpu(p).oper[1]^) and
+ GetNextInstruction(hp2, hp3) and
+ (hp3.typ = ait_instruction) and
+ (taicpu(hp3).is_jmp) and
+ (taicpu(hp3).opcode = A_JMP) and
+ GetNextInstruction(hp3, hp4) and
+ FindLabel(tasmlabel(taicpu(hp1).oper[0]^.ref^.symbol),hp4) then
+ begin
+ taicpu(hp2).Opcode := A_SUB;
+ taicpu(hp2).Loadoper(1,taicpu(hp2).oper[0]^);
+ taicpu(hp2).LoadConst(0,1);
+ taicpu(hp2).ops:=2;
+ taicpu(hp3).Opcode := A_Jcc;
+ case taicpu(hp1).condition of
+ C_LE: taicpu(hp3).condition := C_GE;
+ C_BE: taicpu(hp3).condition := C_AE;
+ end;
+ asml.remove(p);
+ asml.remove(hp1);
+ p.free;
+ hp1.free;
+ p := hp2;
+ continue;
+ end
+ end;
+ A_FLD:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = Ait_Instruction) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = NR_ST) and
+ (taicpu(hp1).oper[1]^.reg = NR_ST1) then
+ { change to
+ fld reg fxxx reg,st
+ fxxxp st, st1 (hp1)
+ Remark: non commutative operations must be reversed!
+ }
+ begin
+ case taicpu(hp1).opcode Of
+ A_FMULP,A_FADDP,
+ A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
+ begin
+ case taicpu(hp1).opcode Of
+ A_FADDP: taicpu(hp1).opcode := A_FADD;
+ A_FMULP: taicpu(hp1).opcode := A_FMUL;
+ A_FSUBP: taicpu(hp1).opcode := A_FSUBR;
+ A_FSUBRP: taicpu(hp1).opcode := A_FSUB;
+ A_FDIVP: taicpu(hp1).opcode := A_FDIVR;
+ A_FDIVRP: taicpu(hp1).opcode := A_FDIV;
+ end;
+ taicpu(hp1).oper[0]^.reg := taicpu(p).oper[0]^.reg;
+ taicpu(hp1).oper[1]^.reg := NR_ST;
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue;
+ end;
+ end;
+ end
+ else
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ GetNextInstruction(p, hp2) and
+ (hp2.typ = Ait_Instruction) and
+ (taicpu(hp2).ops = 2) and
+ (taicpu(hp2).oper[0]^.typ = top_reg) and
+ (taicpu(hp2).oper[1]^.typ = top_reg) and
+ (taicpu(p).opsize in [S_FS, S_FL]) and
+ (taicpu(hp2).oper[0]^.reg = NR_ST) and
+ (taicpu(hp2).oper[1]^.reg = NR_ST1) then
+ if GetLastInstruction(p, hp1) and
+ (hp1.typ = Ait_Instruction) and
+ ((taicpu(hp1).opcode = A_FLD) or
+ (taicpu(hp1).opcode = A_FST)) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ RefsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
+ if ((taicpu(hp2).opcode = A_FMULP) or
+ (taicpu(hp2).opcode = A_FADDP)) then
+ { change to
+ fld/fst mem1 (hp1) fld/fst mem1
+ fld mem1 (p) fadd/
+ faddp/ fmul st, st
+ fmulp st, st1 (hp2) }
+ begin
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ if (taicpu(hp2).opcode = A_FADDP) then
+ taicpu(hp2).opcode := A_FADD
+ else
+ taicpu(hp2).opcode := A_FMUL;
+ taicpu(hp2).oper[1]^.reg := NR_ST;
+ end
+ else
+ { change to
+ fld/fst mem1 (hp1) fld/fst mem1
+ fld mem1 (p) fld st}
+ begin
+ taicpu(p).changeopsize(S_FL);
+ taicpu(p).loadreg(0,NR_ST);
+ end
+ else
+ begin
+ case taicpu(hp2).opcode Of
+ A_FMULP,A_FADDP,A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
+ { change to
+ fld/fst mem1 (hp1) fld/fst mem1
+ fld mem2 (p) fxxx mem2
+ fxxxp st, st1 (hp2) }
+
+ begin
+ case taicpu(hp2).opcode Of
+ A_FADDP: taicpu(p).opcode := A_FADD;
+ A_FMULP: taicpu(p).opcode := A_FMUL;
+ A_FSUBP: taicpu(p).opcode := A_FSUBR;
+ A_FSUBRP: taicpu(p).opcode := A_FSUB;
+ A_FDIVP: taicpu(p).opcode := A_FDIVR;
+ A_FDIVRP: taicpu(p).opcode := A_FDIV;
+ end;
+ asml.remove(hp2);
+ hp2.free;
+ end
+ end
+ end
+ end;
+ A_FSTP,A_FISTP:
+ if doFpuLoadStoreOpt(asmL,p) then
+ continue;
+ A_LEA:
+ begin
+ {removes seg register prefixes from LEA operations, as they
+ don't do anything}
+ taicpu(p).oper[0]^.ref^.Segment := NR_NO;
+ {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
+ if (taicpu(p).oper[0]^.ref^.base <> NR_NO) and
+ (getsupreg(taicpu(p).oper[0]^.ref^.base) in [RS_EAX..RS_ESP]) and
+ (taicpu(p).oper[0]^.ref^.index = NR_NO) and
+ (not(Assigned(taicpu(p).oper[0]^.ref^.Symbol))) then
+ if (taicpu(p).oper[0]^.ref^.base <> taicpu(p).oper[1]^.reg) and
+ (taicpu(p).oper[0]^.ref^.offset = 0) then
+ begin
+ hp1 := taicpu.op_reg_reg(A_MOV, S_L,taicpu(p).oper[0]^.ref^.base,
+ taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous,p.next, hp1);
+ p.free;
+ p := hp1;
+ continue;
+ end
+ else if (taicpu(p).oper[0]^.ref^.offset = 0) then
+ begin
+ hp1 := tai(p.Next);
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue;
+ end
+ else
+ with taicpu(p).oper[0]^.ref^ do
+ if (base = taicpu(p).oper[1]^.reg) then
+ begin
+ l := offset;
+ if (l=1) then
+ begin
+ taicpu(p).opcode := A_INC;
+ taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
+ taicpu(p).ops := 1
+ end
+ else if (l=-1) then
+ begin
+ taicpu(p).opcode := A_DEC;
+ taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
+ taicpu(p).ops := 1;
+ end
+ else
+ begin
+ taicpu(p).opcode := A_ADD;
+ taicpu(p).loadconst(0,l);
+ end;
+ end;
+ end;
+ A_MOV:
+ begin
+ TmpUsedRegs := UsedRegs;
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ (getsupreg(taicpu(p).oper[1]^.reg) in [RS_EAX, RS_EBX, RS_ECX, RS_EDX, RS_ESI, RS_EDI]) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_MOV) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ {we have "mov x, %treg; mov %treg, y}
+ if not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs)) then
+ {we've got "mov x, %treg; mov %treg, y; with %treg is not used after }
+ case taicpu(p).oper[0]^.typ Of
+ top_reg:
+ begin
+ { change "mov %reg, %treg; mov %treg, y"
+ to "mov %reg, y" }
+ taicpu(p).LoadOper(1,taicpu(hp1).oper[1]^);
+ asml.remove(hp1);
+ hp1.free;
+ continue;
+ end;
+ top_ref:
+ if (taicpu(hp1).oper[1]^.typ = top_reg) then
+ begin
+ { change "mov mem, %treg; mov %treg, %reg"
+ to "mov mem, %reg" }
+ taicpu(p).Loadoper(1,taicpu(hp1).oper[1]^);
+ asml.remove(hp1);
+ hp1.free;
+ continue;
+ end;
+ end
+ end
+ else
+ {Change "mov %reg1, %reg2; xxx %reg2, ???" to
+ "mov %reg1, %reg2; xxx %reg1, ???" to avoid a write/read
+ penalty}
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p,hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).ops >= 1) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+ {we have "mov %reg1, %reg2; XXX %reg2, ???"}
+ begin
+ if ((taicpu(hp1).opcode = A_OR) or
+ (taicpu(hp1).opcode = A_TEST)) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(hp1).oper[1]^.reg) then
+ {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
+ begin
+ TmpUsedRegs := UsedRegs;
+ { reg1 will be used after the first instruction, }
+ { so update the allocation info }
+ allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
+ if GetNextInstruction(hp1, hp2) and
+ (hp2.typ = ait_instruction) and
+ taicpu(hp2).is_jmp and
+ not(RegUsedAfterInstruction(taicpu(hp1).oper[0]^.reg, hp1, TmpUsedRegs)) then
+ { change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
+ "test %reg1, %reg1; jxx" }
+ begin
+ taicpu(hp1).Loadoper(0,taicpu(p).oper[0]^);
+ taicpu(hp1).Loadoper(1,taicpu(p).oper[0]^);
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue
+ end
+ else
+ {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
+ "mov %reg1, %reg2; test/or %reg1, %reg1"}
+ begin
+ taicpu(hp1).Loadoper(0,taicpu(p).oper[0]^);
+ taicpu(hp1).Loadoper(1,taicpu(p).oper[0]^);
+ end;
+ end
+{ else
+ if (taicpu(p.next)^.opcode
+ in [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
+ {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
+ "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
+ end
+ else
+ {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
+ x >= RetOffset) as it doesn't do anything (it writes either to a
+ parameter or to the temporary storage room for the function
+ result)}
+ if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) then
+ if ((taicpu(hp1).opcode = A_LEAVE) or
+ (taicpu(hp1).opcode = A_RET)) and
+ (taicpu(p).oper[1]^.typ = top_ref) and
+ (taicpu(p).oper[1]^.ref^.base = current_procinfo.FramePointer) and
+ not(assigned(current_procinfo.procdef.funcretsym) and
+ (taicpu(p).oper[1]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
+ (taicpu(p).oper[1]^.ref^.index = NR_NO) and
+ (taicpu(p).oper[0]^.typ = top_reg) then
+ begin
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ RemoveLastDeallocForFuncRes(asmL,p);
+ end
+ else
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_ref) and
+ (taicpu(p).opsize = taicpu(hp1).opsize) and
+ (taicpu(hp1).opcode = A_CMP) and
+ (taicpu(hp1).oper[1]^.typ = top_ref) and
+ RefsEqual(taicpu(p).oper[1]^.ref^, taicpu(hp1).oper[1]^.ref^) then
+ {change "mov reg1, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
+ begin
+ taicpu(hp1).loadreg(1,taicpu(p).oper[0]^.reg);
+ allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
+ end;
+ { Next instruction is also a MOV ? }
+ if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_MOV) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) then
+ begin
+ if (taicpu(hp1).oper[0]^.typ = taicpu(p).oper[1]^.typ) and
+ (taicpu(hp1).oper[1]^.typ = taicpu(p).oper[0]^.typ) then
+ {mov reg1, mem1 or mov mem1, reg1
+ mov mem2, reg2 mov reg2, mem2}
+ begin
+ if OpsEqual(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) then
+ {mov reg1, mem1 or mov mem1, reg1
+ mov mem2, reg1 mov reg2, mem1}
+ begin
+ if OpsEqual(taicpu(hp1).oper[0]^,taicpu(p).oper[1]^) then
+ { Removes the second statement from
+ mov reg1, mem1/reg2
+ mov mem1/reg2, reg1 }
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) then
+ AllocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else
+ begin
+ TmpUsedRegs := UsedRegs;
+ UpdateUsedRegs(TmpUsedRegs, tai(hp1.next));
+ if (taicpu(p).oper[1]^.typ = top_ref) and
+ { mov reg1, mem1
+ mov mem2, reg1 }
+ (taicpu(hp1).oper[0]^.ref^.refaddr = addr_no) and
+ GetNextInstruction(hp1, hp2) and
+ (hp2.typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_CMP) and
+ (taicpu(hp2).opsize = taicpu(p).opsize) and
+ (taicpu(hp2).oper[0]^.typ = TOp_Ref) and
+ (taicpu(hp2).oper[1]^.typ = TOp_Reg) and
+ RefsEqual(taicpu(hp2).oper[0]^.ref^, taicpu(p).oper[1]^.ref^) and
+ (taicpu(hp2).oper[1]^.reg= taicpu(p).oper[0]^.reg) and
+ not(RegUsedAfterInstruction(taicpu(p).oper[0]^.reg, hp2, TmpUsedRegs)) then
+ { change to
+ mov reg1, mem1 mov reg1, mem1
+ mov mem2, reg1 cmp reg1, mem2
+ cmp mem1, reg1 }
+ begin
+ asml.remove(hp2);
+ hp2.free;
+ taicpu(hp1).opcode := A_CMP;
+ taicpu(hp1).loadref(1,taicpu(hp1).oper[0]^.ref^);
+ taicpu(hp1).loadreg(0,taicpu(p).oper[0]^.reg);
+ end;
+ end;
+ end
+ else
+ begin
+ tmpUsedRegs := UsedRegs;
+ if GetNextInstruction(hp1, hp2) and
+ (taicpu(p).oper[0]^.typ = top_ref) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
+ (taicpu(hp1).oper[1]^.typ = top_ref) and
+ (tai(hp2).typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_MOV) and
+ (taicpu(hp2).opsize = taicpu(p).opsize) and
+ (taicpu(hp2).oper[1]^.typ = top_reg) and
+ (taicpu(hp2).oper[0]^.typ = top_ref) and
+ RefsEqual(taicpu(hp2).oper[0]^.ref^, taicpu(hp1).oper[1]^.ref^) then
+ if not regInRef(getsupreg(taicpu(hp2).oper[1]^.reg),taicpu(hp2).oper[0]^.ref^) and
+ not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,hp1,tmpUsedRegs)) then
+ { mov mem1, %reg1
+ mov %reg1, mem2
+ mov mem2, reg2
+ to:
+ mov mem1, reg2
+ mov reg2, mem2}
+ begin
+ AllocRegBetween(asmL,taicpu(hp2).oper[1]^.reg,p,hp2,usedregs);
+ taicpu(p).Loadoper(1,taicpu(hp2).oper[1]^);
+ taicpu(hp1).loadoper(0,taicpu(hp2).oper[1]^);
+ asml.remove(hp2);
+ hp2.free;
+ end
+ else
+ if (taicpu(p).oper[1]^.reg <> taicpu(hp2).oper[1]^.reg) and
+ not(RegInRef(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^.ref^)) and
+ not(RegInRef(getsupreg(taicpu(hp2).oper[1]^.reg),taicpu(hp2).oper[0]^.ref^)) then
+ { mov mem1, reg1 mov mem1, reg1
+ mov reg1, mem2 mov reg1, mem2
+ mov mem2, reg2 mov mem2, reg1
+ to: to:
+ mov mem1, reg1 mov mem1, reg1
+ mov mem1, reg2 mov reg1, mem2
+ mov reg1, mem2
+
+ or (if mem1 depends on reg1
+ and/or if mem2 depends on reg2)
+ to:
+ mov mem1, reg1
+ mov reg1, mem2
+ mov reg1, reg2
+ }
+ begin
+ taicpu(hp1).LoadRef(0,taicpu(p).oper[0]^.ref^);
+ taicpu(hp1).LoadReg(1,taicpu(hp2).oper[1]^.reg);
+ taicpu(hp2).LoadRef(1,taicpu(hp2).oper[0]^.ref^);
+ taicpu(hp2).LoadReg(0,taicpu(p).oper[1]^.reg);
+ allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2,usedregs);
+ if (taicpu(p).oper[0]^.ref^.base <> NR_NO) and
+ (getsupreg(taicpu(p).oper[0]^.ref^.base) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) then
+ allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.base,p,hp2,usedregs);
+ if (taicpu(p).oper[0]^.ref^.index <> NR_NO) and
+ (getsupreg(taicpu(p).oper[0]^.ref^.index) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) then
+ allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.index,p,hp2,usedregs);
+ end
+ else
+ if (taicpu(hp1).Oper[0]^.reg <> taicpu(hp2).Oper[1]^.reg) then
+ begin
+ taicpu(hp2).LoadReg(0,taicpu(hp1).Oper[0]^.reg);
+ allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2,usedregs);
+ end
+ else
+ begin
+ asml.remove(hp2);
+ hp2.free;
+ end
+ end
+ end
+ else
+(* {movl [mem1],reg1
+ movl [mem1],reg2
+ to:
+ movl [mem1],reg1
+ movl reg1,reg2 }
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(p).opsize = taicpu(hp1).opsize) and
+ RefsEqual(TReference(taicpu(p).oper[0]^^),taicpu(hp1).oper[0]^^.ref^) and
+ (taicpu(p).oper[1]^.reg<>taicpu(hp1).oper[0]^^.ref^.base) and
+ (taicpu(p).oper[1]^.reg<>taicpu(hp1).oper[0]^^.ref^.index) then
+ taicpu(hp1).LoadReg(0,taicpu(p).oper[1]^.reg)
+ else*)
+ { movl const1,[mem1]
+ movl [mem1],reg1
+ to:
+ movl const1,reg1
+ movl reg1,[mem1] }
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ = top_ref) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(p).opsize = taicpu(hp1).opsize) and
+ RefsEqual(taicpu(hp1).oper[0]^.ref^,taicpu(p).oper[1]^.ref^) then
+ begin
+ allocregbetween(asml,taicpu(hp1).oper[1]^.reg,p,hp1,usedregs);
+ taicpu(hp1).LoadReg(0,taicpu(hp1).oper[1]^.reg);
+ taicpu(hp1).LoadRef(1,taicpu(p).oper[1]^.ref^);
+ taicpu(p).LoadReg(1,taicpu(hp1).oper[0]^.reg);
+ end
+ end;
+ end;
+ A_MOVZX:
+ begin
+ {removes superfluous And's after movzx's}
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ case taicpu(p).opsize Of
+ S_BL, S_BW:
+ if (taicpu(hp1).oper[0]^.val = $ff) then
+ begin
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ S_WL:
+ if (taicpu(hp1).oper[0]^.val = $ffff) then
+ begin
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ {changes some movzx constructs to faster synonims (all examples
+ are given with eax/ax, but are also valid for other registers)}
+ if (taicpu(p).oper[1]^.typ = top_reg) then
+ if (taicpu(p).oper[0]^.typ = top_reg) then
+ case taicpu(p).opsize of
+ S_BW:
+ begin
+ if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
+ not(CS_LittleSize in aktglobalswitches) then
+ {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
+ begin
+ taicpu(p).opcode := A_AND;
+ taicpu(p).changeopsize(S_W);
+ taicpu(p).LoadConst(0,$ff);
+ end
+ else if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ {Change "movzbw %reg1, %reg2; andw $const, %reg2"
+ to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
+ begin
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_W);
+ setsubreg(taicpu(p).oper[0]^.reg,R_SUBW);
+ taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ff);
+ end;
+ end;
+ S_BL:
+ begin
+ if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
+ not(CS_LittleSize in aktglobalswitches) then
+ {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
+ begin
+ taicpu(p).opcode := A_AND;
+ taicpu(p).changeopsize(S_L);
+ taicpu(p).loadconst(0,$ff)
+ end
+ else if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ {Change "movzbl %reg1, %reg2; andl $const, %reg2"
+ to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
+ begin
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_L);
+ setsubreg(taicpu(p).oper[0]^.reg,R_SUBWHOLE);
+ taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ff);
+ end
+ end;
+ S_WL:
+ begin
+ if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
+ not(CS_LittleSize in aktglobalswitches) then
+ {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
+ begin
+ taicpu(p).opcode := A_AND;
+ taicpu(p).changeopsize(S_L);
+ taicpu(p).LoadConst(0,$ffff);
+ end
+ else if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ {Change "movzwl %reg1, %reg2; andl $const, %reg2"
+ to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
+ begin
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_L);
+ setsubreg(taicpu(p).oper[0]^.reg,R_SUBWHOLE);
+ taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
+ end;
+ end;
+ end
+ else if (taicpu(p).oper[0]^.typ = top_ref) then
+ begin
+ if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = Top_Const) and
+ (taicpu(hp1).oper[1]^.typ = Top_Reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ taicpu(p).opcode := A_MOV;
+ case taicpu(p).opsize Of
+ S_BL:
+ begin
+ taicpu(p).changeopsize(S_L);
+ taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ff);
+ end;
+ S_WL:
+ begin
+ taicpu(p).changeopsize(S_L);
+ taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
+ end;
+ S_BW:
+ begin
+ taicpu(p).changeopsize(S_W);
+ taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ff);
+ end;
+ end;
+ end;
+ end;
+ end;
+(* should not be generated anymore by the current code generator
+ A_POP:
+ begin
+ if target_info.system=system_i386_go32v2 then
+ begin
+ { Transform a series of pop/pop/pop/push/push/push to }
+ { 'movl x(%esp),%reg' for go32v2 (not for the rest, }
+ { because I'm not sure whether they can cope with }
+ { 'movl x(%esp),%reg' with x > 0, I believe we had }
+ { such a problem when using esp as frame pointer (JM) }
+ if (taicpu(p).oper[0]^.typ = top_reg) then
+ begin
+ hp1 := p;
+ hp2 := p;
+ l := 0;
+ while getNextInstruction(hp1,hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_POP) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) do
+ begin
+ hp2 := hp1;
+ inc(l,4);
+ end;
+ getLastInstruction(p,hp3);
+ l1 := 0;
+ while (hp2 <> hp3) and
+ assigned(hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_PUSH) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg.enum = taicpu(hp2).oper[0]^.reg.enum) do
+ begin
+ { change it to a two op operation }
+ taicpu(hp2).oper[1]^.typ:=top_none;
+ taicpu(hp2).ops:=2;
+ taicpu(hp2).opcode := A_MOV;
+ taicpu(hp2).Loadoper(1,taicpu(hp1).oper[0]^);
+ reference_reset(tmpref);
+ tmpRef.base.enum:=R_INTREGISTER;
+ tmpRef.base.number:=NR_STACK_POINTER_REG;
+ convert_register_to_enum(tmpref.base);
+ tmpRef.offset := l;
+ taicpu(hp2).loadRef(0,tmpRef);
+ hp4 := hp1;
+ getNextInstruction(hp1,hp1);
+ asml.remove(hp4);
+ hp4.free;
+ getLastInstruction(hp2,hp2);
+ dec(l,4);
+ inc(l1);
+ end;
+ if l <> -4 then
+ begin
+ inc(l,4);
+ for l1 := l1 downto 1 do
+ begin
+ getNextInstruction(hp2,hp2);
+ dec(taicpu(hp2).oper[0]^.ref^.offset,l);
+ end
+ end
+ end
+ end
+ else
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ=ait_instruction) and
+ (taicpu(hp1).opcode=A_PUSH) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg.enum=taicpu(p).oper[0]^.reg.enum) then
+ begin
+ { change it to a two op operation }
+ taicpu(p).oper[1]^.typ:=top_none;
+ taicpu(p).ops:=2;
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).Loadoper(1,taicpu(p).oper[0]^);
+ reference_reset(tmpref);
+ TmpRef.base.enum := R_ESP;
+ taicpu(p).LoadRef(0,TmpRef);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ end;
+*)
+ A_PUSH:
+ begin
+ if (taicpu(p).opsize = S_W) and
+ (taicpu(p).oper[0]^.typ = Top_Const) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_PUSH) and
+ (taicpu(hp1).oper[0]^.typ = Top_Const) and
+ (taicpu(hp1).opsize = S_W) then
+ begin
+ taicpu(p).changeopsize(S_L);
+ taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val shl 16 + word(taicpu(hp1).oper[0]^.val));
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ A_SHL, A_SAL:
+ begin
+ if (taicpu(p).oper[0]^.typ = Top_Const) and
+ (taicpu(p).oper[1]^.typ = Top_Reg) and
+ (taicpu(p).opsize = S_L) and
+ (taicpu(p).oper[0]^.val <= 3) then
+ {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
+ begin
+ TmpBool1 := True; {should we check the next instruction?}
+ TmpBool2 := False; {have we found an add/sub which could be
+ integrated in the lea?}
+ reference_reset(tmpref);
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.scalefactor := 1 shl taicpu(p).oper[0]^.val;
+ while TmpBool1 and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ ((((taicpu(hp1).opcode = A_ADD) or
+ (taicpu(hp1).opcode = A_SUB)) and
+ (taicpu(hp1).oper[1]^.typ = Top_Reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg)) or
+ (((taicpu(hp1).opcode = A_INC) or
+ (taicpu(hp1).opcode = A_DEC)) and
+ (taicpu(hp1).oper[0]^.typ = Top_Reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg))) Do
+ begin
+ TmpBool1 := False;
+ if (taicpu(hp1).oper[0]^.typ = Top_Const) then
+ begin
+ TmpBool1 := True;
+ TmpBool2 := True;
+ case taicpu(hp1).opcode of
+ A_ADD:
+ inc(TmpRef.offset, longint(taicpu(hp1).oper[0]^.val));
+ A_SUB:
+ dec(TmpRef.offset, longint(taicpu(hp1).oper[0]^.val));
+ end;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else
+ if (taicpu(hp1).oper[0]^.typ = Top_Reg) and
+ (((taicpu(hp1).opcode = A_ADD) and
+ (TmpRef.base = NR_NO)) or
+ (taicpu(hp1).opcode = A_INC) or
+ (taicpu(hp1).opcode = A_DEC)) then
+ begin
+ TmpBool1 := True;
+ TmpBool2 := True;
+ case taicpu(hp1).opcode of
+ A_ADD:
+ TmpRef.base := taicpu(hp1).oper[0]^.reg;
+ A_INC:
+ inc(TmpRef.offset);
+ A_DEC:
+ dec(TmpRef.offset);
+ end;
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ if TmpBool2 or
+ ((aktoptprocessor < ClassPentium2) and
+ (taicpu(p).oper[0]^.val <= 3) and
+ not(CS_LittleSize in aktglobalswitches)) then
+ begin
+ if not(TmpBool2) and
+ (taicpu(p).oper[0]^.val = 1) then
+ begin
+ hp1 := taicpu.Op_reg_reg(A_ADD,taicpu(p).opsize,
+ taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg)
+ end
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef,
+ taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end;
+ end
+ else
+ if (aktoptprocessor < ClassPentium2) and
+ (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ = top_reg) then
+ if (taicpu(p).oper[0]^.val = 1) then
+ {changes "shl $1, %reg" to "add %reg, %reg", which is the same on a 386,
+ but faster on a 486, and Tairable in both U and V pipes on the Pentium
+ (unlike shl, which is only Tairable in the U pipe)}
+ begin
+ hp1 := taicpu.Op_reg_reg(A_ADD,taicpu(p).opsize,
+ taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end
+ else if (taicpu(p).opsize = S_L) and
+ (taicpu(p).oper[0]^.val<= 3) then
+ {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
+ "shl $3, %reg" to "lea (,%reg,8), %reg}
+ begin
+ reference_reset(tmpref);
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.scalefactor := 1 shl taicpu(p).oper[0]^.val;
+ hp1 := taicpu.Op_ref_reg(A_LEA,S_L,TmpRef, taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end
+ end;
+ A_SETcc :
+ { changes
+ setcc (funcres) setcc reg
+ movb (funcres), reg to leave/ret
+ leave/ret }
+ begin
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ GetNextInstruction(p, hp1) and
+ GetNextInstruction(hp1, hp2) and
+ (hp2.typ = ait_instruction) and
+ ((taicpu(hp2).opcode = A_LEAVE) or
+ (taicpu(hp2).opcode = A_RET)) and
+ (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
+ (taicpu(p).oper[0]^.ref^.index = NR_NO) and
+ not(assigned(current_procinfo.procdef.funcretsym) and
+ (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_MOV) and
+ (taicpu(hp1).opsize = S_B) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ RefsEqual(taicpu(hp1).oper[0]^.ref^, taicpu(p).oper[0]^.ref^) then
+ begin
+ taicpu(p).LoadReg(0,taicpu(hp1).oper[1]^.reg);
+ asml.remove(hp1);
+ hp1.free;
+ end
+ end;
+ A_SUB:
+ { * change "subl $2, %esp; pushw x" to "pushl x"}
+ { * change "sub/add const1, reg" or "dec reg" followed by
+ "sub const2, reg" to one "sub ..., reg" }
+ begin
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ = top_reg) then
+ if (taicpu(p).oper[0]^.val = 2) and
+ (taicpu(p).oper[1]^.reg = NR_ESP) and
+ { Don't do the sub/push optimization if the sub }
+ { comes from setting up the stack frame (JM) }
+ (not getLastInstruction(p,hp1) or
+ (hp1.typ <> ait_instruction) or
+ (taicpu(hp1).opcode <> A_MOV) or
+ (taicpu(hp1).oper[0]^.typ <> top_reg) or
+ (taicpu(hp1).oper[0]^.reg <> NR_ESP) or
+ (taicpu(hp1).oper[1]^.typ <> top_reg) or
+ (taicpu(hp1).oper[1]^.reg <> NR_EBP)) then
+ begin
+ hp1 := tai(p.next);
+ while Assigned(hp1) and
+ (tai(hp1).typ in [ait_instruction]+SkipInstr) and
+ not regReadByInstruction(RS_ESP,hp1) and
+ not regModifiedByInstruction(RS_ESP,hp1) do
+ hp1 := tai(hp1.next);
+ if Assigned(hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_PUSH) and
+ (taicpu(hp1).opsize = S_W) then
+ begin
+ taicpu(hp1).changeopsize(S_L);
+ if taicpu(hp1).oper[0]^.typ=top_reg then
+ setsubreg(taicpu(hp1).oper[0]^.reg,R_SUBWHOLE);
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue
+ end;
+ if DoSubAddOpt(p) then
+ continue;
+ end
+ else if DoSubAddOpt(p) then
+ continue
+ end;
+ end;
+ end; { if is_jmp }
+ end;
+ end;
+ updateUsedRegs(UsedRegs,p);
+ p:=tai(p.next);
+ end;
+end;
+
+
+function isFoldableArithOp(hp1: taicpu; reg: tregister): boolean;
+begin
+ isFoldableArithOp := False;
+ case hp1.opcode of
+ A_ADD,A_SUB,A_OR,A_XOR,A_AND,A_SHL,A_SHR,A_SAR:
+ isFoldableArithOp :=
+ ((taicpu(hp1).oper[0]^.typ = top_const) or
+ ((taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg <> reg))) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = reg);
+ A_INC,A_DEC:
+ isFoldableArithOp :=
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = reg);
+ end;
+end;
+
+
+procedure PeepHoleOptPass2(asml: taasmoutput; BlockStart, BlockEnd: tai);
+
+{$ifdef USECMOV}
+ function CanBeCMOV(p : tai) : boolean;
+ begin
+ CanBeCMOV:=assigned(p) and (p.typ=ait_instruction) and
+ (taicpu(p).opcode=A_MOV) and
+ (taicpu(p).opsize in [S_L,S_W]) and
+ ((taicpu(p).oper[0]^.typ = top_reg)
+ { we can't use cmov ref,reg because
+ ref could be nil and cmov still throws an exception
+ if ref=nil but the mov isn't done (FK)
+ or ((taicpu(p).oper[0]^.typ = top_ref) and
+ (taicpu(p).oper[0]^.ref^.refaddr = addr_no))
+ }
+ ) and
+ (taicpu(p).oper[1]^.typ in [top_reg]);
+ end;
+{$endif USECMOV}
+
+var
+ p,hp1,hp2: tai;
+{$ifdef USECMOV}
+ l : longint;
+ condition : tasmcond;
+ hp3: tai;
+{$endif USECMOV}
+ UsedRegs, TmpUsedRegs: TRegSet;
+
+begin
+ p := BlockStart;
+ UsedRegs := [];
+ while (p <> BlockEnd) Do
+ begin
+ UpdateUsedRegs(UsedRegs, tai(p.next));
+ case p.Typ Of
+ Ait_Instruction:
+ begin
+ case taicpu(p).opcode Of
+{$ifdef USECMOV}
+ A_Jcc:
+ if (aktspecificoptprocessor>=ClassPentium2) then
+ begin
+ { check for
+ jCC xxx
+ <several movs>
+ xxx:
+ }
+ l:=0;
+ GetNextInstruction(p, hp1);
+ while assigned(hp1) and
+ CanBeCMOV(hp1) and
+ { stop on labels }
+ not(hp1.typ=ait_label) do
+ begin
+ inc(l);
+ GetNextInstruction(hp1,hp1);
+ end;
+ if assigned(hp1) then
+ begin
+ if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+ begin
+ if (l<=4) and (l>0) then
+ begin
+ condition:=inverse_cond(taicpu(p).condition);
+ hp2:=p;
+ GetNextInstruction(p,hp1);
+ p:=hp1;
+ repeat
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCMOV(hp1));
+ { wait with removing else GetNextInstruction could
+ ignore the label if it was the only usage in the
+ jump moved away }
+ tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp2);
+ hp2.free;
+ continue;
+ end;
+ end
+ else
+ begin
+ { check further for
+ jCC xxx
+ <several movs 1>
+ jmp yyy
+ xxx:
+ <several movs 2>
+ yyy:
+ }
+ { hp2 points to jmp yyy }
+ hp2:=hp1;
+ { skip hp1 to xxx }
+ GetNextInstruction(hp1, hp1);
+ if assigned(hp2) and
+ assigned(hp1) and
+ (l<=3) and
+ (hp2.typ=ait_instruction) and
+ (taicpu(hp2).is_jmp) and
+ (taicpu(hp2).condition=C_None) and
+ { real label and jump, no further references to the
+ label are allowed }
+ (tasmlabel(taicpu(p).oper[0]^.ref^.symbol).getrefs=2) and
+ FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+ begin
+ l:=0;
+ { skip hp1 to <several moves 2> }
+ GetNextInstruction(hp1, hp1);
+ while assigned(hp1) and
+ CanBeCMOV(hp1) do
+ begin
+ inc(l);
+ GetNextInstruction(hp1, hp1);
+ end;
+ { hp1 points to yyy: }
+ if assigned(hp1) and
+ FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
+ begin
+ condition:=inverse_cond(taicpu(p).condition);
+ GetNextInstruction(p,hp1);
+ hp3:=p;
+ p:=hp1;
+ repeat
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCMOV(hp1));
+ { hp2 is still at jmp yyy }
+ GetNextInstruction(hp2,hp1);
+ { hp2 is now at xxx: }
+ condition:=inverse_cond(condition);
+ GetNextInstruction(hp1,hp1);
+ { hp1 is now at <several movs 2> }
+ repeat
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCMOV(hp1));
+ {
+ asml.remove(hp1.next)
+ hp1.next.free;
+ asml.remove(hp1);
+ hp1.free;
+ }
+ { remove jCC }
+ tasmlabel(taicpu(hp3).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp3);
+ hp3.free;
+ { remove jmp }
+ tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp2);
+ hp2.free;
+ continue;
+ end;
+ end;
+ end;
+ end;
+ end;
+{$endif USECMOV}
+ A_FSTP,A_FISTP:
+ if doFpuLoadStoreOpt(asmL,p) then
+ continue;
+ A_IMUL:
+ begin
+ if (taicpu(p).ops >= 2) and
+ ((taicpu(p).oper[0]^.typ = top_const) or
+ ((taicpu(p).oper[0]^.typ = top_ref) and (taicpu(p).oper[0]^.ref^.refaddr=addr_full))) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ ((taicpu(p).ops = 2) or
+ ((taicpu(p).oper[2]^.typ = top_reg) and
+ (taicpu(p).oper[2]^.reg = taicpu(p).oper[1]^.reg))) and
+ getLastInstruction(p,hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_MOV) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ { change "mov reg1,reg2; imul y,reg2" to "imul y,reg1,reg2" }
+ begin
+ taicpu(p).ops := 3;
+ taicpu(p).loadreg(1,taicpu(hp1).oper[0]^.reg);
+ taicpu(p).loadreg(2,taicpu(hp1).oper[1]^.reg);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ A_MOV:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = ait_Instruction) and
+ ((taicpu(hp1).opcode = A_MOV) or
+ (taicpu(hp1).opcode = A_MOVZX) or
+ (taicpu(hp1).opcode = A_MOVSX)) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ ((taicpu(hp1).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) or
+ (taicpu(hp1).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg)) and
+ (getsupreg(taicpu(hp1).oper[1]^.reg) = getsupreg(taicpu(p).oper[1]^.reg)) then
+ {mov reg1, reg2
+ mov/zx/sx (reg2, ..), reg2 to mov/zx/sx (reg1, ..), reg2}
+ begin
+ if (taicpu(hp1).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) then
+ taicpu(hp1).oper[0]^.ref^.base := taicpu(p).oper[0]^.reg;
+ if (taicpu(hp1).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) then
+ taicpu(hp1).oper[0]^.ref^.index := taicpu(p).oper[0]^.reg;
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue;
+ end
+ else if (taicpu(p).oper[0]^.typ = top_ref) and
+ GetNextInstruction(p,hp1) and
+ (hp1.typ = ait_instruction) and
+ IsFoldableArithOp(taicpu(hp1),taicpu(p).oper[1]^.reg) and
+ GetNextInstruction(hp1,hp2) and
+ (hp2.typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_MOV) and
+ (taicpu(hp2).oper[0]^.typ = top_reg) and
+ (taicpu(hp2).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
+ (taicpu(hp2).oper[1]^.typ = top_ref) then
+ begin
+ TmpUsedRegs := UsedRegs;
+ UpdateUsedRegs(TmpUsedRegs,tai(hp1.next));
+ if (RefsEqual(taicpu(hp2).oper[1]^.ref^, taicpu(p).oper[0]^.ref^) and
+ not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,
+ hp2, TmpUsedRegs))) then
+ { change mov (ref), reg }
+ { add/sub/or/... reg2/$const, reg }
+ { mov reg, (ref) }
+ { # release reg }
+ { to add/sub/or/... reg2/$const, (ref) }
+ begin
+ case taicpu(hp1).opcode of
+ A_INC,A_DEC:
+ taicpu(hp1).LoadRef(0,taicpu(p).oper[0]^.ref^)
+ else
+ taicpu(hp1).LoadRef(1,taicpu(p).oper[0]^.ref^);
+ end;
+ asml.remove(p);
+ asml.remove(hp2);
+ p.free;
+ hp2.free;
+ p := hp1
+ end;
+ end
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next)
+ end;
+end;
+
+
+procedure PostPeepHoleOpts(asml: taasmoutput; BlockStart, BlockEnd: tai);
+var
+ p,hp1,hp2: tai;
+begin
+ p := BlockStart;
+ while (p <> BlockEnd) Do
+ begin
+ case p.Typ Of
+ Ait_Instruction:
+ begin
+ case taicpu(p).opcode Of
+ A_CALL:
+ if (AktOptProcessor < ClassPentium2) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_JMP) and
+ ((taicpu(hp1).oper[0]^.typ=top_ref) and (taicpu(hp1).oper[0]^.ref^.refaddr=addr_full)) then
+ begin
+ hp2 := taicpu.Op_sym(A_PUSH,S_L,taicpu(hp1).oper[0]^.ref^.symbol);
+ InsertLLItem(asml, p.previous, p, hp2);
+ taicpu(p).opcode := A_JMP;
+ taicpu(p).is_jmp := true;
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ A_CMP:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[0]^.val = 0) and
+ (taicpu(p).oper[1]^.typ = top_reg) then
+ {change "cmp $0, %reg" to "test %reg, %reg"}
+ begin
+ taicpu(p).opcode := A_TEST;
+ taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
+ continue;
+ end;
+ end;
+(*
+Optimization is not safe; xor clears the carry flag.
+See test/tgadint64 in the test suite.
+ A_MOV:
+ if (taicpu(p).oper[0]^.typ = Top_Const) and
+ (taicpu(p).oper[0]^.val = 0) and
+ (taicpu(p).oper[1]^.typ = Top_Reg) then
+ { change "mov $0, %reg" into "xor %reg, %reg" }
+ begin
+ taicpu(p).opcode := A_XOR;
+ taicpu(p).LoadReg(0,taicpu(p).oper[1]^.reg);
+ end;
+*)
+ A_MOVZX:
+ { if register vars are on, it's possible there is code like }
+ { "cmpl $3,%eax; movzbl 8(%ebp),%ebx; je .Lxxx" }
+ { so we can't safely replace the movzx then with xor/mov, }
+ { since that would change the flags (JM) }
+ if not(cs_regvars in aktglobalswitches) then
+ begin
+ if (taicpu(p).oper[1]^.typ = top_reg) then
+ if (taicpu(p).oper[0]^.typ = top_reg)
+ then
+ case taicpu(p).opsize of
+ S_BL:
+ begin
+ if IsGP32Reg(getsupreg(taicpu(p).oper[1]^.reg)) and
+ not(CS_LittleSize in aktglobalswitches) and
+ (aktoptprocessor = ClassPentium) then
+ {Change "movzbl %reg1, %reg2" to
+ "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
+ PentiumMMX}
+ begin
+ hp1 := taicpu.op_reg_reg(A_XOR, S_L,
+ taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p, hp1);
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_B);
+ setsubreg(taicpu(p).oper[1]^.reg,R_SUBL);
+ end;
+ end;
+ end
+ else if (taicpu(p).oper[0]^.typ = top_ref) and
+ (taicpu(p).oper[0]^.ref^.base <> taicpu(p).oper[1]^.reg) and
+ (taicpu(p).oper[0]^.ref^.index <> taicpu(p).oper[1]^.reg) and
+ not(CS_LittleSize in aktglobalswitches) and
+ IsGP32Reg(getsupreg(taicpu(p).oper[1]^.reg)) and
+ (aktoptprocessor = ClassPentium) and
+ (taicpu(p).opsize = S_BL) then
+ {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
+ Pentium and PentiumMMX}
+ begin
+ hp1 := taicpu.Op_reg_reg(A_XOR, S_L, taicpu(p).oper[1]^.reg,
+ taicpu(p).oper[1]^.reg);
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_B);
+ setsubreg(taicpu(p).oper[1]^.reg,R_SUBL);
+ InsertLLItem(asml,p.previous, p, hp1);
+ end;
+ end;
+ A_TEST, A_OR:
+ {removes the line marked with (x) from the sequence
+ and/or/xor/add/sub/... $x, %y
+ test/or %y, %y (x)
+ j(n)z _Label
+ as the first instruction already adjusts the ZF}
+ begin
+ if OpsEqual(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then
+ if GetLastInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) then
+ case taicpu(hp1).opcode Of
+ A_ADD, A_SUB, A_OR, A_XOR, A_AND{, A_SHL, A_SHR}:
+ begin
+ if OpsEqual(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) then
+ begin
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ p := tai(hp1);
+ continue
+ end;
+ end;
+ A_DEC, A_INC, A_NEG:
+ begin
+ if OpsEqual(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) then
+ begin
+ case taicpu(hp1).opcode Of
+ A_DEC, A_INC:
+ {replace inc/dec with add/sub 1, because inc/dec doesn't set the carry flag}
+ begin
+ case taicpu(hp1).opcode Of
+ A_DEC: taicpu(hp1).opcode := A_SUB;
+ A_INC: taicpu(hp1).opcode := A_ADD;
+ end;
+ taicpu(hp1).Loadoper(1,taicpu(hp1).oper[0]^);
+ taicpu(hp1).LoadConst(0,1);
+ taicpu(hp1).ops:=2;
+ end
+ end;
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ p := tai(hp1);
+ continue
+ end;
+ end
+ end
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next)
+ end;
+end;
+
+
+
+end.
diff --git a/compiler/i386/r386ari.inc b/compiler/i386/r386ari.inc
new file mode 100644
index 0000000000..bcab45d02a
--- /dev/null
+++ b/compiler/i386/r386ari.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+2,
+1,
+3,
+14,
+13,
+21,
+15,
+6,
+5,
+38,
+39,
+40,
+41,
+26,
+7,
+10,
+19,
+9,
+32,
+33,
+34,
+35,
+36,
+37,
+27,
+11,
+4,
+22,
+16,
+8,
+20,
+12,
+28,
+18,
+24,
+30,
+31,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+17,
+23,
+29,
+55,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+42,
+43,
+44,
+45,
+46,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+25,
+0
diff --git a/compiler/i386/r386att.inc b/compiler/i386/r386att.inc
new file mode 100644
index 0000000000..8c2a8e2004
--- /dev/null
+++ b/compiler/i386/r386att.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'%al',
+'%ah',
+'%ax',
+'%eax',
+'%cl',
+'%ch',
+'%cx',
+'%ecx',
+'%dl',
+'%dh',
+'%dx',
+'%edx',
+'%bl',
+'%bh',
+'%bx',
+'%ebx',
+'%si',
+'%esi',
+'%di',
+'%edi',
+'%bp',
+'%ebp',
+'%sp',
+'%esp',
+'EIP',
+'%cs',
+'%ds',
+'%es',
+'%ss',
+'%fs',
+'%gs',
+'%dr0',
+'%dr1',
+'%dr2',
+'%dr3',
+'%dr6',
+'%dr7',
+'%cr0',
+'%cr2',
+'%cr3',
+'%cr4',
+'%tr3',
+'%tr4',
+'%tr5',
+'%tr6',
+'%tr7',
+'%st(0)',
+'%st(1)',
+'%st(2)',
+'%st(3)',
+'%st(4)',
+'%st(5)',
+'%st(6)',
+'%st(7)',
+'%st',
+'%mm0',
+'%mm1',
+'%mm2',
+'%mm3',
+'%mm4',
+'%mm5',
+'%mm6',
+'%mm7',
+'%xmm0',
+'%xmm1',
+'%xmm2',
+'%xmm3',
+'%xmm4',
+'%xmm5',
+'%xmm6',
+'%xmm7'
diff --git a/compiler/i386/r386con.inc b/compiler/i386/r386con.inc
new file mode 100644
index 0000000000..eb1f3d0a78
--- /dev/null
+++ b/compiler/i386/r386con.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+NR_NO = tregister($00000000);
+NR_AL = tregister($01010000);
+NR_AH = tregister($01020000);
+NR_AX = tregister($01030000);
+NR_EAX = tregister($01040000);
+NR_CL = tregister($01010001);
+NR_CH = tregister($01020001);
+NR_CX = tregister($01030001);
+NR_ECX = tregister($01040001);
+NR_DL = tregister($01010002);
+NR_DH = tregister($01020002);
+NR_DX = tregister($01030002);
+NR_EDX = tregister($01040002);
+NR_BL = tregister($01010003);
+NR_BH = tregister($01020003);
+NR_BX = tregister($01030003);
+NR_EBX = tregister($01040003);
+NR_SI = tregister($01030004);
+NR_ESI = tregister($01040004);
+NR_DI = tregister($01030005);
+NR_EDI = tregister($01040005);
+NR_BP = tregister($01030006);
+NR_EBP = tregister($01040006);
+NR_SP = tregister($01030007);
+NR_ESP = tregister($01040007);
+NR_EIP = tregister($05000000);
+NR_CS = tregister($05000001);
+NR_DS = tregister($05000002);
+NR_ES = tregister($05000003);
+NR_SS = tregister($05000004);
+NR_FS = tregister($05000005);
+NR_GS = tregister($05000006);
+NR_DR0 = tregister($05000007);
+NR_DR1 = tregister($05000008);
+NR_DR2 = tregister($05000009);
+NR_DR3 = tregister($0500000a);
+NR_DR6 = tregister($0500000b);
+NR_DR7 = tregister($0500000c);
+NR_CR0 = tregister($0500000d);
+NR_CR2 = tregister($0500000e);
+NR_CR3 = tregister($0500000f);
+NR_CR4 = tregister($05000010);
+NR_TR3 = tregister($05000011);
+NR_TR4 = tregister($05000012);
+NR_TR5 = tregister($05000013);
+NR_TR6 = tregister($05000014);
+NR_TR7 = tregister($05000015);
+NR_ST0 = tregister($02000000);
+NR_ST1 = tregister($02000001);
+NR_ST2 = tregister($02000002);
+NR_ST3 = tregister($02000003);
+NR_ST4 = tregister($02000004);
+NR_ST5 = tregister($02000005);
+NR_ST6 = tregister($02000006);
+NR_ST7 = tregister($02000007);
+NR_ST = tregister($02000008);
+NR_MM0 = tregister($03000000);
+NR_MM1 = tregister($03000001);
+NR_MM2 = tregister($03000002);
+NR_MM3 = tregister($03000003);
+NR_MM4 = tregister($03000004);
+NR_MM5 = tregister($03000005);
+NR_MM6 = tregister($03000006);
+NR_MM7 = tregister($03000007);
+NR_XMM0 = tregister($04000000);
+NR_XMM1 = tregister($04000001);
+NR_XMM2 = tregister($04000002);
+NR_XMM3 = tregister($04000003);
+NR_XMM4 = tregister($04000004);
+NR_XMM5 = tregister($04000005);
+NR_XMM6 = tregister($04000006);
+NR_XMM7 = tregister($04000007);
diff --git a/compiler/i386/r386dwrf.inc b/compiler/i386/r386dwrf.inc
new file mode 100644
index 0000000000..79d6522842
--- /dev/null
+++ b/compiler/i386/r386dwrf.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+-1,
+0,
+0,
+0,
+0,
+1,
+1,
+1,
+1,
+2,
+2,
+2,
+2,
+3,
+3,
+3,
+3,
+6,
+6,
+7,
+7,
+5,
+5,
+4,
+4,
+8,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+11,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28
diff --git a/compiler/i386/r386int.inc b/compiler/i386/r386int.inc
new file mode 100644
index 0000000000..1bdcd93fc9
--- /dev/null
+++ b/compiler/i386/r386int.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'dl',
+'dh',
+'dx',
+'edx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'si',
+'esi',
+'di',
+'edi',
+'bp',
+'ebp',
+'sp',
+'esp',
+'EIP',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st(0)',
+'st(1)',
+'st(2)',
+'st(3)',
+'st(4)',
+'st(5)',
+'st(6)',
+'st(7)',
+'st',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7'
diff --git a/compiler/i386/r386iri.inc b/compiler/i386/r386iri.inc
new file mode 100644
index 0000000000..a713142cef
--- /dev/null
+++ b/compiler/i386/r386iri.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+25,
+0,
+2,
+1,
+3,
+14,
+13,
+21,
+15,
+6,
+5,
+38,
+39,
+40,
+41,
+26,
+7,
+10,
+19,
+9,
+32,
+33,
+34,
+35,
+36,
+37,
+27,
+11,
+4,
+22,
+16,
+8,
+20,
+12,
+28,
+18,
+24,
+30,
+31,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+17,
+23,
+29,
+55,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+42,
+43,
+44,
+45,
+46,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71
diff --git a/compiler/i386/r386nasm.inc b/compiler/i386/r386nasm.inc
new file mode 100644
index 0000000000..9ceb0c1799
--- /dev/null
+++ b/compiler/i386/r386nasm.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'dl',
+'dh',
+'dx',
+'edx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'si',
+'esi',
+'di',
+'edi',
+'bp',
+'ebp',
+'sp',
+'esp',
+'EIP',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st0',
+'st1',
+'st2',
+'st3',
+'st4',
+'st5',
+'st6',
+'st7',
+'st0',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7'
diff --git a/compiler/i386/r386nor.inc b/compiler/i386/r386nor.inc
new file mode 100644
index 0000000000..2e66b09488
--- /dev/null
+++ b/compiler/i386/r386nor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from x86reg.dat }
+72
diff --git a/compiler/i386/r386nri.inc b/compiler/i386/r386nri.inc
new file mode 100644
index 0000000000..a713142cef
--- /dev/null
+++ b/compiler/i386/r386nri.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+25,
+0,
+2,
+1,
+3,
+14,
+13,
+21,
+15,
+6,
+5,
+38,
+39,
+40,
+41,
+26,
+7,
+10,
+19,
+9,
+32,
+33,
+34,
+35,
+36,
+37,
+27,
+11,
+4,
+22,
+16,
+8,
+20,
+12,
+28,
+18,
+24,
+30,
+31,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+17,
+23,
+29,
+55,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+42,
+43,
+44,
+45,
+46,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71
diff --git a/compiler/i386/r386num.inc b/compiler/i386/r386num.inc
new file mode 100644
index 0000000000..5762785a18
--- /dev/null
+++ b/compiler/i386/r386num.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+tregister($00000000),
+tregister($01010000),
+tregister($01020000),
+tregister($01030000),
+tregister($01040000),
+tregister($01010001),
+tregister($01020001),
+tregister($01030001),
+tregister($01040001),
+tregister($01010002),
+tregister($01020002),
+tregister($01030002),
+tregister($01040002),
+tregister($01010003),
+tregister($01020003),
+tregister($01030003),
+tregister($01040003),
+tregister($01030004),
+tregister($01040004),
+tregister($01030005),
+tregister($01040005),
+tregister($01030006),
+tregister($01040006),
+tregister($01030007),
+tregister($01040007),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c),
+tregister($0500000d),
+tregister($0500000e),
+tregister($0500000f),
+tregister($05000010),
+tregister($05000011),
+tregister($05000012),
+tregister($05000013),
+tregister($05000014),
+tregister($05000015),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($04000000),
+tregister($04000001),
+tregister($04000002),
+tregister($04000003),
+tregister($04000004),
+tregister($04000005),
+tregister($04000006),
+tregister($04000007)
diff --git a/compiler/i386/r386op.inc b/compiler/i386/r386op.inc
new file mode 100644
index 0000000000..c9df7fabcb
--- /dev/null
+++ b/compiler/i386/r386op.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+0,
+4,
+0,
+0,
+1,
+5,
+1,
+1,
+2,
+6,
+2,
+2,
+3,
+7,
+3,
+3,
+6,
+6,
+7,
+7,
+5,
+5,
+4,
+4,
+0,
+1,
+3,
+0,
+2,
+4,
+5,
+0,
+1,
+2,
+3,
+6,
+7,
+0,
+2,
+3,
+4,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7
diff --git a/compiler/i386/r386ot.inc b/compiler/i386/r386ot.inc
new file mode 100644
index 0000000000..d30c918dc7
--- /dev/null
+++ b/compiler/i386/r386ot.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+OT_NONE,
+OT_REG_AL,
+OT_REG8,
+OT_REG_AX,
+OT_REG_EAX,
+OT_REG_CL,
+OT_REG8,
+OT_REG_CX,
+OT_REG_ECX,
+OT_REG8,
+OT_REG8,
+OT_REG_DX,
+OT_REG32,
+OT_REG8,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG16,
+OT_REG32,
+OT_REG16,
+OT_REG32,
+OT_REG16,
+OT_REG32,
+OT_REG16,
+OT_REG32,
+OT_NONE,
+OT_REG_CS,
+OT_REG_DESS,
+OT_REG_DESS,
+OT_REG_DESS,
+OT_REG_FSGS,
+OT_REG_FSGS,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_CREG,
+OT_REG_CREG,
+OT_REG_CREG,
+OT_REG_CR4,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_FPU0,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPU0,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG
diff --git a/compiler/i386/r386rni.inc b/compiler/i386/r386rni.inc
new file mode 100644
index 0000000000..294022d5e2
--- /dev/null
+++ b/compiler/i386/r386rni.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+1,
+5,
+9,
+13,
+2,
+6,
+10,
+14,
+3,
+7,
+11,
+15,
+17,
+19,
+21,
+23,
+4,
+8,
+12,
+16,
+18,
+20,
+22,
+24,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46
diff --git a/compiler/i386/r386sri.inc b/compiler/i386/r386sri.inc
new file mode 100644
index 0000000000..a713142cef
--- /dev/null
+++ b/compiler/i386/r386sri.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+25,
+0,
+2,
+1,
+3,
+14,
+13,
+21,
+15,
+6,
+5,
+38,
+39,
+40,
+41,
+26,
+7,
+10,
+19,
+9,
+32,
+33,
+34,
+35,
+36,
+37,
+27,
+11,
+4,
+22,
+16,
+8,
+20,
+12,
+28,
+18,
+24,
+30,
+31,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+17,
+23,
+29,
+55,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+42,
+43,
+44,
+45,
+46,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71
diff --git a/compiler/i386/r386stab.inc b/compiler/i386/r386stab.inc
new file mode 100644
index 0000000000..d2fbf4d7e5
--- /dev/null
+++ b/compiler/i386/r386stab.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+-1,
+0,
+0,
+0,
+0,
+1,
+1,
+1,
+1,
+2,
+2,
+2,
+2,
+3,
+3,
+3,
+3,
+6,
+6,
+7,
+7,
+5,
+5,
+4,
+4,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+12,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28
diff --git a/compiler/i386/r386std.inc b/compiler/i386/r386std.inc
new file mode 100644
index 0000000000..1bdcd93fc9
--- /dev/null
+++ b/compiler/i386/r386std.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'dl',
+'dh',
+'dx',
+'edx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'si',
+'esi',
+'di',
+'edi',
+'bp',
+'ebp',
+'sp',
+'esp',
+'EIP',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st(0)',
+'st(1)',
+'st(2)',
+'st(3)',
+'st(4)',
+'st(5)',
+'st(6)',
+'st(7)',
+'st',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7'
diff --git a/compiler/i386/ra386att.pas b/compiler/i386/ra386att.pas
new file mode 100644
index 0000000000..4e1185e905
--- /dev/null
+++ b/compiler/i386/ra386att.pas
@@ -0,0 +1,59 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the i386 GNU AS styled inline assembler.
+
+ 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 ra386att;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ rax86att;
+
+ type
+ ti386attreader = class(tx86attreader)
+ end;
+
+
+ implementation
+
+ uses
+ rabase,systems;
+
+const
+ asmmode_i386_att_info : tasmmodeinfo =
+ (
+ id : asmmode_i386_att;
+ idtxt : 'ATT';
+ casmreader : ti386attreader;
+ );
+
+ asmmode_i386_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : ti386attreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_i386_att_info);
+ RegisterAsmMode(asmmode_i386_standard_info);
+end.
diff --git a/compiler/i386/ra386int.pas b/compiler/i386/ra386int.pas
new file mode 100644
index 0000000000..15f2ba6e21
--- /dev/null
+++ b/compiler/i386/ra386int.pas
@@ -0,0 +1,2107 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing process for the intel styled inline assembler.
+
+ 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 Ra386int;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ cpubase,
+ globtype,
+ aasmbase,
+ rasm,
+ rax86;
+
+ type
+ tasmtoken = (
+ AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
+ AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
+ AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
+ AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,
+ {------------------ Assembler directives --------------------}
+ AS_ALIGN,AS_DB,AS_DW,AS_DD,AS_END,
+ {------------------ Assembler Operators --------------------}
+ AS_BYTE,AS_WORD,AS_DWORD,AS_QWORD,AS_TBYTE,AS_DQWORD,AS_NEAR,AS_FAR,
+ AS_HIGH,AS_LOW,AS_OFFSET,AS_SIZEOF,AS_SEG,AS_TYPE,AS_PTR,AS_MOD,AS_SHL,AS_SHR,AS_NOT,
+ AS_AND,AS_OR,AS_XOR);
+
+ type
+ ti386intreader = class(tasmreader)
+ actasmtoken : tasmtoken;
+ prevasmtoken : tasmtoken;
+ ActOpsize : topsize;
+ constructor create;override;
+ function is_asmopcode(const s: string):boolean;
+ function is_asmoperator(const s: string):boolean;
+ function is_asmdirective(const s: string):boolean;
+ function is_register(const s:string):boolean;
+ function is_locallabel(const s:string):boolean;
+ function Assemble: tlinkedlist;override;
+ procedure GetToken;
+ function consume(t : tasmtoken):boolean;
+ procedure RecoverConsume(allowcomma:boolean);
+ procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint);
+ procedure BuildConstSymbolExpression(needofs,isref:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
+ function BuildConstExpression:aint;
+ function BuildRefConstExpression:aint;
+ procedure BuildReference(oper : tx86operand);
+ procedure BuildOperand(oper: tx86operand;istypecast:boolean);
+ procedure BuildConstantOperand(oper: tx86operand);
+ procedure BuildOpCode(instr : tx86instruction);
+ procedure BuildConstant(constsize: byte);
+ end;
+
+
+ implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globals,verbose,
+ systems,
+ { aasm }
+ aasmtai,aasmcpu,
+ { symtable }
+ symconst,symbase,symtype,symsym,symdef,symtable,
+ { parser }
+ scanner,
+ { register allocator }
+ rabase,rautils,itx86int,
+ { codegen }
+ cgbase,cgobj,procinfo
+ ;
+
+ type
+ tasmkeyword = string[6];
+
+
+ const
+ { These tokens should be modified accordingly to the modifications }
+ { in the different enumerations. }
+ firstdirective = AS_ALIGN;
+ lastdirective = AS_END;
+ firstoperator = AS_BYTE;
+ lastoperator = AS_XOR;
+
+ _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
+ _count_asmoperators = longint(lastoperator)-longint(firstoperator);
+
+ _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
+ ('ALIGN','DB','DW','DD','END');
+
+ { problems with shl,shr,not,and,or and xor, they are }
+ { context sensitive. }
+ _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
+ 'BYTE','WORD','DWORD','QWORD','TBYTE','DQWORD','NEAR','FAR','HIGH',
+ 'LOW','OFFSET','SIZEOF','SEG','TYPE','PTR','MOD','SHL','SHR','NOT','AND',
+ 'OR','XOR');
+
+ token2str : array[tasmtoken] of string[10] = (
+ '','Label','LLabel','String','Integer',
+ ',','[',']','(',
+ ')',':','.','+','-','*',
+ ';','identifier','register','opcode','/',
+ '','','','','END',
+ '','','','','','','','','',
+ '','','sizeof','','type','ptr','mod','shl','shr','not',
+ 'and','or','xor'
+ );
+
+ var
+ inexpression : boolean;
+
+ constructor ti386intreader.create;
+ var
+ i : tasmop;
+ str2opentry: tstr2opentry;
+ Begin
+ inherited create;
+ { opcodes }
+ { creates uppercased symbol tables for speed access }
+ iasmops:=tdictionary.create;
+ iasmops.delete_doubles:=true;
+ for i:=firstop to lastop do
+ begin
+ str2opentry:=tstr2opentry.createname(upper(std_op2str[i]));
+ str2opentry.op:=i;
+ iasmops.insert(str2opentry);
+ end;
+ end;
+
+
+{---------------------------------------------------------------------}
+{ Routines for the tokenizing }
+{---------------------------------------------------------------------}
+
+
+ function ti386intreader.is_asmopcode(const s: string):boolean;
+ var
+ str2opentry: tstr2opentry;
+ cond : string[4];
+ cnd : tasmcond;
+ j: longint;
+ Begin
+ is_asmopcode:=FALSE;
+
+ actopcode:=A_None;
+ actcondition:=C_None;
+ actopsize:=S_NO;
+
+ str2opentry:=tstr2opentry(iasmops.search(s));
+ if assigned(str2opentry) then
+ begin
+ actopcode:=str2opentry.op;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=TRUE;
+ exit;
+ end;
+ { not found yet, check condition opcodes }
+ j:=0;
+ while (j<CondAsmOps) do
+ begin
+ if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
+ begin
+ cond:=Copy(s,Length(CondAsmOpStr[j])+1,255);
+ if cond<>'' then
+ begin
+ for cnd:=low(TasmCond) to high(TasmCond) do
+ if Cond=Upper(cond2str[cnd]) then
+ begin
+ actopcode:=CondASmOp[j];
+ actcondition:=cnd;
+ is_asmopcode:=TRUE;
+ actasmtoken:=AS_OPCODE;
+ exit
+ end;
+ end;
+ end;
+ inc(j);
+ end;
+ end;
+
+
+ function ti386intreader.is_asmoperator(const s: string):boolean;
+ var
+ i : longint;
+ Begin
+ for i:=0 to _count_asmoperators do
+ if s=_asmoperators[i] then
+ begin
+ actasmtoken:=tasmtoken(longint(firstoperator)+i);
+ is_asmoperator:=true;
+ exit;
+ end;
+ is_asmoperator:=false;
+ end;
+
+
+ Function ti386intreader.is_asmdirective(const s: string):boolean;
+ var
+ i : longint;
+ Begin
+ for i:=0 to _count_asmdirectives do
+ if s=_asmdirectives[i] then
+ begin
+ actasmtoken:=tasmtoken(longint(firstdirective)+i);
+ is_asmdirective:=true;
+ exit;
+ end;
+ is_asmdirective:=false;
+ end;
+
+
+ function ti386intreader.is_register(const s:string):boolean;
+ begin
+ is_register:=false;
+ actasmregister:=masm_regnum_search(lower(s));
+ if actasmregister<>NR_NO then
+ begin
+ is_register:=true;
+ actasmtoken:=AS_REGISTER;
+ end;
+ end;
+
+
+ function ti386intreader.is_locallabel(const s:string):boolean;
+ begin
+ is_locallabel:=(length(s)>1) and (s[1]='@');
+ end;
+
+
+ Procedure ti386intreader.GetToken;
+ var
+ len : longint;
+ forcelabel : boolean;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ { save old token and reset new token }
+ prevasmtoken:=actasmtoken;
+ actasmtoken:=AS_NONE;
+ { reset }
+ forcelabel:=FALSE;
+ actasmpattern:='';
+ { while space and tab , continue scan... }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ { get token pos }
+ if not (c in [#10,#13,'{',';']) then
+ current_scanner.gettokenpos;
+ { Local Label, Label, Directive, Prefix or Opcode }
+ if firsttoken and not (c in [#10,#13,'{',';']) then
+ begin
+ firsttoken:=FALSE;
+ len:=0;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
+ begin
+ { if there is an at_sign, then this must absolutely be a label }
+ if c = '@' then
+ forcelabel:=TRUE;
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ uppervar(actasmpattern);
+ { allow spaces }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ { label ? }
+ if c = ':' then
+ begin
+ if actasmpattern[1]='@' then
+ actasmtoken:=AS_LLABEL
+ else
+ actasmtoken:=AS_LABEL;
+ { let us point to the next character }
+ c:=current_scanner.asmgetchar;
+ firsttoken:=true;
+ exit;
+ end;
+ { Are we trying to create an identifier with }
+ { an at-sign...? }
+ if forcelabel then
+ Message(asmr_e_none_label_contain_at);
+ { opcode ? }
+ If is_asmopcode(actasmpattern) then
+ Begin
+ { check if we are in an expression }
+ { then continue with asm directives }
+ if not inexpression then
+ exit;
+ end;
+ if is_asmdirective(actasmpattern) then
+ exit;
+ message1(asmr_e_unknown_opcode,actasmpattern);
+ actasmtoken:=AS_NONE;
+ exit;
+ end
+ else { else firsttoken }
+ begin
+ case c of
+ '@' : { possiblities : - local label reference , such as in jmp @local1 }
+ { - @Result, @Code or @Data special variables. }
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ 'A'..'Z','a'..'z','_': { identifier, register, opcode, prefix or directive }
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+ { after prefix we allow also a new opcode }
+ If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
+ Begin
+ { if we are not in a constant }
+ { expression than this is an }
+ { opcode. }
+ if not inexpression then
+ exit;
+ end;
+ { support st(X) for fpu registers }
+ if (actasmpattern = 'ST') and (c='(') then
+ Begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ { allow spaces }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ if c in ['0'..'7'] then
+ actasmpattern:=actasmpattern + c
+ else
+ Message(asmr_e_invalid_fpu_register);
+ c:=current_scanner.asmgetchar;
+ { allow spaces }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ if c <> ')' then
+ Message(asmr_e_invalid_fpu_register)
+ else
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ if is_register(actasmpattern) then
+ exit;
+ if is_asmdirective(actasmpattern) then
+ exit;
+ if is_asmoperator(actasmpattern) then
+ exit;
+ { allow spaces }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ { if next is a '.' and this is a unitsym then we also need to
+ parse the identifier }
+ if (c='.') then
+ begin
+ searchsym(actasmpattern,srsym,srsymtable);
+ if assigned(srsym) and
+ (srsym.typ=unitsym) and
+ (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
+ srsym.owner.iscurrentunit then
+ begin
+ { Add . to create System.Identifier }
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ { Delphi allows System.@Halt, just ignore the @ }
+ if c='@' then
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ actasmpattern:=actasmpattern + upcase(c);
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ end;
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ '''' : { string or character }
+ begin
+ actasmpattern:='';
+ current_scanner.in_asm_string:=true;
+ repeat
+ if c = '''' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ repeat
+ if c='''' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c='''' then
+ begin
+ actasmpattern:=actasmpattern+'''';
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ end
+ else
+ break;
+ end
+ else
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break
+ end;
+ end;
+ until false; { end repeat }
+ end
+ else
+ break; { end if }
+ until false;
+ current_scanner.in_asm_string:=false;
+ actasmtoken:=AS_STRING;
+ exit;
+ end;
+
+ '"' : { string or character }
+ begin
+ current_scanner.in_asm_string:=true;
+ actasmpattern:='';
+ repeat
+ if c = '"' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ repeat
+ if c='"' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c='"' then
+ begin
+ actasmpattern:=actasmpattern+'"';
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ end
+ else
+ break;
+ end
+ else
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break
+ end;
+ end;
+ until false; { end repeat }
+ end
+ else
+ break; { end if }
+ until false;
+ current_scanner.in_asm_string:=false;
+ actasmtoken:=AS_STRING;
+ exit;
+ end;
+
+ '$' :
+ begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern:=tostr(ParseVal(actasmpattern,16));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+
+ ',' :
+ begin
+ actasmtoken:=AS_COMMA;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '[' :
+ begin
+ actasmtoken:=AS_LBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ']' :
+ begin
+ actasmtoken:=AS_RBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '(' :
+ begin
+ actasmtoken:=AS_LPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ')' :
+ begin
+ actasmtoken:=AS_RPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ':' :
+ begin
+ actasmtoken:=AS_COLON;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '.' :
+ begin
+ actasmtoken:=AS_DOT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '+' :
+ begin
+ actasmtoken:=AS_PLUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '-' :
+ begin
+ actasmtoken:=AS_MINUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '*' :
+ begin
+ actasmtoken:=AS_STAR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '/' :
+ begin
+ actasmtoken:=AS_SLASH;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '0'..'9':
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ { Get the possible characters }
+ while c in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ { Get ending character }
+ uppervar(actasmpattern);
+ c:=upcase(c);
+ { possibly a binary number. }
+ if (actasmpattern[length(actasmpattern)] = 'B') and (c <> 'H') then
+ Begin
+ { Delete the last binary specifier }
+ delete(actasmpattern,length(actasmpattern),1);
+ actasmpattern:=tostr(ParseVal(actasmpattern,2));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end
+ else
+ Begin
+ case c of
+ 'O' :
+ Begin
+ actasmpattern:=tostr(ParseVal(actasmpattern,8));
+ actasmtoken:=AS_INTNUM;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ 'H' :
+ Begin
+ actasmpattern:=tostr(ParseVal(actasmpattern,16));
+ actasmtoken:=AS_INTNUM;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ else { must be an integer number }
+ begin
+ actasmpattern:=tostr(ParseVal(actasmpattern,10));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ ';','{',#13,#10 :
+ begin
+ c:=current_scanner.asmgetchar;
+ firsttoken:=TRUE;
+ actasmtoken:=AS_SEPARATOR;
+ exit;
+ end;
+
+ else
+ current_scanner.illegal_char(c);
+ end;
+ end;
+ end;
+
+
+ function ti386intreader.consume(t : tasmtoken):boolean;
+ begin
+ Consume:=true;
+ if t<>actasmtoken then
+ begin
+ Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
+ Consume:=false;
+ end;
+ repeat
+ gettoken;
+ until actasmtoken<>AS_NONE;
+ end;
+
+
+ procedure ti386intreader.RecoverConsume(allowcomma:boolean);
+ begin
+ While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
+ begin
+ if allowcomma and (actasmtoken=AS_COMMA) then
+ break;
+ Consume(actasmtoken);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Parsing Helpers
+*****************************************************************************}
+
+ { This routine builds up a record offset after a AS_DOT
+ token is encountered.
+ On entry actasmtoken should be equal to AS_DOT }
+ Procedure ti386intreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint);
+ var
+ s : string;
+ Begin
+ offset:=0;
+ size:=0;
+ s:=expr;
+ while (actasmtoken=AS_DOT) do
+ begin
+ Consume(AS_DOT);
+ if actasmtoken in [AS_BYTE,AS_ID,AS_WORD,AS_DWORD,AS_QWORD] then
+ begin
+ s:=s+'.'+actasmpattern;
+ consume(actasmtoken);
+ end
+ else
+ begin
+ Consume(AS_ID);
+ RecoverConsume(true);
+ break;
+ end;
+ end;
+ if not GetRecordOffsetSize(s,offset,size) then
+ Message(asmr_e_building_record_offset);
+ end;
+
+
+ Procedure ti386intreader.BuildConstSymbolExpression(needofs,isref:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
+ var
+ tempstr,expr,hs : string;
+ parenlevel : longint;
+ l,k : aint;
+ hasparen,
+ errorflag : boolean;
+ prevtok : tasmtoken;
+ hl : tasmlabel;
+ hssymtyp : Tasmsymtype;
+ def : tdef;
+ sym : tsym;
+ srsymtable : tsymtable;
+ Begin
+ { reset }
+ value:=0;
+ asmsym:='';
+ asmsymtyp:=AT_DATA;
+ errorflag:=FALSE;
+ tempstr:='';
+ expr:='';
+ inexpression:=TRUE;
+ parenlevel:=0;
+ Repeat
+ { Support ugly delphi constructs like: [ECX].1+2[EDX] }
+ if isref and (actasmtoken=AS_LBRACKET) then
+ break;
+ Case actasmtoken of
+ AS_LPAREN:
+ Begin
+ Consume(AS_LPAREN);
+ expr:=expr + '(';
+ inc(parenlevel);
+ end;
+ AS_RPAREN:
+ Begin
+ { Keep the AS_PAREN in actasmtoken, it is maybe a typecast }
+ if parenlevel=0 then
+ break;
+ Consume(AS_RPAREN);
+ expr:=expr + ')';
+ dec(parenlevel);
+ end;
+ AS_SHL:
+ Begin
+ Consume(AS_SHL);
+ expr:=expr + '<';
+ end;
+ AS_SHR:
+ Begin
+ Consume(AS_SHR);
+ expr:=expr + '>';
+ end;
+ AS_SLASH:
+ Begin
+ Consume(AS_SLASH);
+ expr:=expr + '/';
+ end;
+ AS_MOD:
+ Begin
+ Consume(AS_MOD);
+ expr:=expr + '%';
+ end;
+ AS_STAR:
+ Begin
+ Consume(AS_STAR);
+ if isref and (actasmtoken=AS_REGISTER) then
+ break;
+ expr:=expr + '*';
+ end;
+ AS_PLUS:
+ Begin
+ Consume(AS_PLUS);
+ if isref and (actasmtoken=AS_REGISTER) then
+ break;
+ expr:=expr + '+';
+ end;
+ AS_MINUS:
+ Begin
+ Consume(AS_MINUS);
+ expr:=expr + '-';
+ end;
+ AS_AND:
+ Begin
+ Consume(AS_AND);
+ expr:=expr + '&';
+ end;
+ AS_NOT:
+ Begin
+ Consume(AS_NOT);
+ expr:=expr + '~';
+ end;
+ AS_XOR:
+ Begin
+ Consume(AS_XOR);
+ expr:=expr + '^';
+ end;
+ AS_OR:
+ Begin
+ Consume(AS_OR);
+ expr:=expr + '|';
+ end;
+ AS_INTNUM:
+ Begin
+ expr:=expr + actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_OFFSET:
+ begin
+ Consume(AS_OFFSET);
+ needofs:=true;
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_offset_without_identifier);
+ end;
+ AS_SIZEOF,
+ AS_TYPE:
+ begin
+ l:=0;
+ hasparen:=false;
+ Consume(actasmtoken);
+ if actasmtoken=AS_LPAREN then
+ begin
+ hasparen:=true;
+ Consume(AS_LPAREN);
+ end;
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_type_without_identifier)
+ else
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ if actasmtoken=AS_DOT then
+ BuildRecordOffsetSize(tempstr,k,l)
+ else
+ begin
+ searchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ l:=tabstractvarsym(sym).getsize;
+ typedconstsym :
+ l:=ttypedconstsym(sym).getsize;
+ typesym :
+ l:=ttypesym(sym).restype.def.size;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ end;
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ if hasparen then
+ Consume(AS_RPAREN);
+ end;
+ AS_PTR :
+ begin
+ { Support ugly delphi constructs like <constant> PTR [ref] }
+ break;
+ end;
+ AS_STRING:
+ begin
+ l:=0;
+ case Length(actasmpattern) of
+ 1 :
+ l:=ord(actasmpattern[1]);
+ 2 :
+ l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
+ 3 :
+ l:=ord(actasmpattern[3]) +
+ Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
+ 4 :
+ l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
+ Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
+ else
+ Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
+ end;
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ Consume(AS_STRING);
+ end;
+ AS_ID:
+ begin
+ hs:='';
+ hssymtyp:=AT_DATA;
+ def:=nil;
+ tempstr:=actasmpattern;
+ prevtok:=prevasmtoken;
+ consume(AS_ID);
+ if SearchIConstant(tempstr,l) then
+ begin
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end
+ else
+ begin
+ if is_locallabel(tempstr) then
+ begin
+ CreateLocalLabel(tempstr,hl,false);
+ hs:=hl.name;
+ hssymtyp:=AT_FUNCTION;
+ end
+ else
+ if SearchLabel(tempstr,hl,false) then
+ begin
+ hs:=hl.name;
+ hssymtyp:=AT_FUNCTION;
+ end
+ else
+ begin
+ searchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ globalvarsym :
+ begin
+ hs:=tglobalvarsym(sym).mangledname;
+ def:=tglobalvarsym(sym).vartype.def;
+ end;
+ localvarsym,
+ paravarsym :
+ begin
+ Message(asmr_e_no_local_or_para_allowed);
+ end;
+ typedconstsym :
+ begin
+ hs:=ttypedconstsym(sym).mangledname;
+ def:=ttypedconstsym(sym).typedconsttype.def;
+ end;
+ procsym :
+ begin
+ if Tprocsym(sym).procdef_count>1 then
+ Message(asmr_w_calling_overload_func);
+ hs:=tprocsym(sym).first_procdef.mangledname;
+ hssymtyp:=AT_FUNCTION;
+ end;
+ typesym :
+ begin
+ if not(ttypesym(sym).restype.def.deftype in [recorddef,objectdef]) then
+ Message(asmr_e_wrong_sym_type);
+ end;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ { symbol found? }
+ if hs<>'' then
+ begin
+ if asmsym='' then
+ begin
+ asmsym:=hs;
+ asmsymtyp:=hssymtyp;
+ end
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ if (expr='') or (expr[length(expr)]='+') then
+ begin
+ { don't remove the + if there could be a record field }
+ if actasmtoken<>AS_DOT then
+ delete(expr,length(expr),1);
+ end
+ else
+ if needofs then
+ begin
+ if (prevtok<>AS_OFFSET) then
+ Message(asmr_e_need_offset);
+ end
+ else
+ Message(asmr_e_only_add_relocatable_symbol);
+ end;
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k);
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end
+ else
+ begin
+ if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
+ delete(expr,length(expr),1);
+ end;
+ if (actasmtoken=AS_LBRACKET) and
+ assigned(def) and
+ (def.deftype=arraydef) then
+ begin
+ consume(AS_LBRACKET);
+ l:=BuildConstExpression;
+ if l<tarraydef(def).lowrange then
+ begin
+ Message(asmr_e_constant_out_of_bounds);
+ l:=0;
+ end
+ else
+ l:=(l-tarraydef(def).lowrange)*tarraydef(def).elesize;
+ str(l, tempstr);
+ expr:=expr + '+' + tempstr;
+ consume(AS_RBRACKET);
+ end;
+ end;
+ { check if there are wrong operator used like / or mod etc. }
+ if (hs<>'') and not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,AS_END,AS_RBRACKET]) then
+ Message(asmr_e_only_add_relocatable_symbol);
+ end;
+ AS_END,
+ AS_RBRACKET,
+ AS_SEPARATOR,
+ AS_COMMA,
+ AS_COLON:
+ break;
+ else
+ begin
+ { write error only once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag:=TRUE;
+ end;
+ end;
+ Until false;
+ { calculate expression }
+ if not ErrorFlag then
+ value:=CalculateExpression(expr)
+ else
+ value:=0;
+ { no longer in an expression }
+ inexpression:=FALSE;
+ end;
+
+
+ Function ti386intreader.BuildConstExpression:aint;
+ var
+ l : aint;
+ hs : string;
+ hssymtyp : TAsmsymtype;
+ begin
+ BuildConstSymbolExpression(false,false,l,hs,hssymtyp);
+ if hs<>'' then
+ Message(asmr_e_relocatable_symbol_not_allowed);
+ BuildConstExpression:=l;
+ end;
+
+
+ Function ti386intreader.BuildRefConstExpression:aint;
+ var
+ l : aint;
+ hs : string;
+ hssymtyp : TAsmsymtype;
+ begin
+ BuildConstSymbolExpression(false,true,l,hs,hssymtyp);
+ if hs<>'' then
+ Message(asmr_e_relocatable_symbol_not_allowed);
+ BuildRefConstExpression:=l;
+ end;
+
+
+ procedure ti386intreader.BuildReference(oper : tx86operand);
+ var
+ scale : byte;
+ k,l : aint;
+ tempstr,hs : string;
+ tempsymtyp : tasmsymtype;
+ code : integer;
+ hreg : tregister;
+ GotStar,GotOffset,HadVar,
+ GotPlus,Negative : boolean;
+ hl : tasmlabel;
+ Begin
+ Consume(AS_LBRACKET);
+ if not(oper.opr.typ in [OPR_LOCAL,OPR_REFERENCE]) then
+ oper.InitRef;
+ GotStar:=false;
+ GotPlus:=true;
+ GotOffset:=false;
+ Negative:=false;
+ Scale:=0;
+ repeat
+ if GotOffset and (actasmtoken<>AS_ID) then
+ Message(asmr_e_invalid_reference_syntax);
+
+ Case actasmtoken of
+
+ AS_ID: { Constant reference expression OR variable reference expression }
+ Begin
+ if not GotPlus then
+ Message(asmr_e_invalid_reference_syntax);
+ GotStar:=false;
+ GotPlus:=false;
+ if SearchIConstant(actasmpattern,l) or
+ SearchRecordType(actasmpattern) then
+ begin
+ l:=BuildRefConstExpression;
+ GotPlus:=(prevasmtoken=AS_PLUS);
+ GotStar:=(prevasmtoken=AS_STAR);
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ if GotStar then
+ Message(asmr_e_invalid_reference_syntax);
+ if negative then
+ Dec(oper.opr.localsymofs,l)
+ else
+ Inc(oper.opr.localsymofs,l);
+ end;
+ OPR_REFERENCE :
+ begin
+ if GotStar then
+ oper.opr.ref.scalefactor:=l
+ else
+ begin
+ if negative then
+ Dec(oper.opr.ref.offset,l)
+ else
+ Inc(oper.opr.ref.offset,l);
+ end;
+ end;
+ end;
+ end
+ else
+ Begin
+ if oper.hasvar and not GotOffset then
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ HadVar:=oper.hasvar and GotOffset;
+ if negative then
+ Message(asmr_e_only_add_relocatable_symbol);
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,l) then
+ begin
+ oper.hastype:=true;
+ oper.typesize:=l;
+ Consume(AS_LPAREN);
+ BuildOperand(oper,true);
+ Consume(AS_RPAREN);
+ end
+ else
+ if is_locallabel(tempstr) then
+ begin
+ CreateLocalLabel(tempstr,hl,false);
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ oper.hasvar:=true;
+ end
+ else
+ if oper.SetupVar(tempstr,GotOffset) then
+ begin
+ { force OPR_LOCAL to be a reference }
+ if oper.opr.typ=OPR_LOCAL then
+ oper.opr.localforceref:=true;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k);
+ case oper.opr.typ of
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+ if GotOffset then
+ begin
+ if oper.hasvar and (oper.opr.ref.base=current_procinfo.framepointer) then
+ begin
+ if (oper.opr.typ=OPR_REFERENCE) then
+ oper.opr.ref.base:=NR_NO;
+ oper.hasvar:=hadvar;
+ end
+ else
+ begin
+ if oper.hasvar and hadvar then
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ { should we allow ?? }
+ end;
+ end;
+ end;
+ GotOffset:=false;
+ end;
+
+ AS_PLUS :
+ Begin
+ Consume(AS_PLUS);
+ Negative:=false;
+ GotPlus:=true;
+ GotStar:=false;
+ Scale:=0;
+ end;
+
+ AS_MINUS :
+ begin
+ Consume(AS_MINUS);
+ Negative:=true;
+ GotPlus:=true;
+ GotStar:=false;
+ Scale:=0;
+ end;
+
+ AS_STAR : { Scaling, with eax*4 order }
+ begin
+ Consume(AS_STAR);
+ hs:='';
+ l:=0;
+ case actasmtoken of
+ AS_LPAREN :
+ l:=BuildConstExpression;
+ AS_INTNUM:
+ Begin
+ hs:=actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_REGISTER :
+ begin
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ begin
+ if oper.opr.ref.scalefactor=0 then
+ begin
+ if scale<>0 then
+ begin
+ oper.opr.ref.scalefactor:=scale;
+ scale:=0;
+ end
+ else
+ Message(asmr_e_wrong_scale_factor);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ OPR_LOCAL :
+ begin
+ if oper.opr.localscale=0 then
+ begin
+ if scale<>0 then
+ begin
+ oper.opr.localscale:=scale;
+ scale:=0;
+ end
+ else
+ Message(asmr_e_wrong_scale_factor);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end;
+ end;
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ if actasmtoken<>AS_REGISTER then
+ begin
+ if hs<>'' then
+ val(hs,l,code);
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ oper.opr.ref.scalefactor:=l;
+ OPR_LOCAL :
+ oper.opr.localscale:=l;
+ end;
+ if l>9 then
+ Message(asmr_e_wrong_scale_factor);
+ end;
+ GotPlus:=false;
+ GotStar:=false;
+ end;
+
+ AS_REGISTER :
+ begin
+ if not((GotPlus and (not Negative)) or
+ GotStar) then
+ Message(asmr_e_invalid_reference_syntax);
+ hreg:=actasmregister;
+ Consume(AS_REGISTER);
+ { this register will be the index:
+ 1. just read a *
+ 2. next token is a *
+ 3. base register is already used }
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ if (oper.opr.localindexreg<>NR_NO) then
+ Message(asmr_e_multiple_index);
+ oper.opr.localindexreg:=hreg;
+ if scale<>0 then
+ begin
+ oper.opr.localscale:=scale;
+ scale:=0;
+ end;
+ end;
+ OPR_REFERENCE :
+ begin
+ if (GotStar) or
+ (actasmtoken=AS_STAR) or
+ (oper.opr.ref.base<>NR_NO) then
+ begin
+ if (oper.opr.ref.index<>NR_NO) then
+ Message(asmr_e_multiple_index);
+ oper.opr.ref.index:=hreg;
+ if scale<>0 then
+ begin
+ oper.opr.ref.scalefactor:=scale;
+ scale:=0;
+ end;
+ end
+ else
+ oper.opr.ref.base:=hreg;
+ end;
+ end;
+ GotPlus:=false;
+ GotStar:=false;
+ end;
+
+ AS_OFFSET :
+ begin
+ Consume(AS_OFFSET);
+ GotOffset:=true;
+ end;
+
+ AS_TYPE,
+ AS_NOT,
+ AS_STRING,
+ AS_INTNUM,
+ AS_LPAREN : { Constant reference expression }
+ begin
+ if not GotPlus and not GotStar then
+ Message(asmr_e_invalid_reference_syntax);
+ BuildConstSymbolExpression(true,true,l,tempstr,tempsymtyp);
+
+ if tempstr<>'' then
+ begin
+ if GotStar then
+ Message(asmr_e_only_add_relocatable_symbol);
+ if not assigned(oper.opr.ref.symbol) then
+ oper.opr.ref.symbol:=objectlibrary.newasmsymbol(tempstr,AB_EXTERNAL,tempsymtyp)
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ end;
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ begin
+ if GotStar then
+ oper.opr.ref.scalefactor:=l
+ else if (prevasmtoken = AS_STAR) then
+ begin
+ if scale<>0 then
+ scale:=l*scale
+ else
+ scale:=l;
+ end
+ else
+ begin
+ if negative then
+ Dec(oper.opr.ref.offset,l)
+ else
+ Inc(oper.opr.ref.offset,l);
+ end;
+ end;
+ OPR_LOCAL :
+ begin
+ if GotStar then
+ oper.opr.localscale:=l
+ else if (prevasmtoken = AS_STAR) then
+ begin
+ if scale<>0 then
+ scale:=l*scale
+ else
+ scale:=l;
+ end
+ else
+ begin
+ if negative then
+ Dec(oper.opr.localsymofs,l)
+ else
+ Inc(oper.opr.localsymofs,l);
+ end;
+ end;
+ end;
+ GotPlus:=(prevasmtoken=AS_PLUS) or
+ (prevasmtoken=AS_MINUS);
+ if GotPlus then
+ negative := prevasmtoken = AS_MINUS;
+ GotStar:=(prevasmtoken=AS_STAR);
+ end;
+
+ AS_RBRACKET :
+ begin
+ if GotPlus or GotStar then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_RBRACKET);
+ break;
+ end;
+
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ break;
+ end;
+ end;
+ until false;
+ end;
+
+
+ Procedure ti386intreader.BuildConstantOperand(oper: tx86operand);
+ var
+ l : aint;
+ tempstr : string;
+ tempsymtyp : tasmsymtype;
+ begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstSymbolExpression(true,false,l,tempstr,tempsymtyp);
+ if tempstr<>'' then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symofs:=l;
+ oper.opr.symbol:=objectlibrary.newasmsymbol(tempstr,AB_EXTERNAL,tempsymtyp);
+ end
+ else
+ if oper.opr.typ=OPR_NONE then
+ begin
+ oper.opr.typ:=OPR_CONSTANT;
+ oper.opr.val:=l;
+ end
+ else
+ inc(oper.opr.val,l);
+ end;
+
+
+ Procedure ti386intreader.BuildOperand(oper: tx86operand;istypecast:boolean);
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if (oper.opr.typ=OPR_NONE) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+ var
+ expr : string;
+ tempreg : tregister;
+ l : aint;
+ hl : tasmlabel;
+ toffset,
+ tsize : aint;
+ begin
+ expr:='';
+ repeat
+ if actasmtoken=AS_DOT then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize);
+ oper.SetSize(tsize,true);
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, becuase that
+ will generate buggy code. Allow it only for explicit typecasting
+ and when the parameter is in a register (delphi compatible) }
+ if (not oper.hastype) and
+ (oper.opr.localsym.owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,toffset)
+ end;
+ OPR_CONSTANT :
+ inc(oper.opr.val,toffset);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,toffset);
+ OPR_NONE :
+ begin
+ oper.opr.typ:=OPR_CONSTANT;
+ oper.opr.val:=toffset;
+ end;
+ else
+ internalerror(200309222);
+ end;
+ expr:='';
+ end
+ else
+ begin
+ { See it as a separator }
+ Consume(AS_DOT);
+ end;
+ end;
+
+ case actasmtoken of
+ AS_OFFSET,
+ AS_SIZEOF,
+ AS_TYPE,
+ AS_NOT,
+ AS_STRING,
+ AS_PLUS,
+ AS_MINUS,
+ AS_LPAREN,
+ AS_INTNUM :
+ begin
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,BuildRefConstExpression);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,BuildConstExpression);
+ OPR_NONE,
+ OPR_CONSTANT :
+ BuildConstantOperand(oper);
+ else
+ Message(asmr_e_invalid_operand_type);
+ end;
+ end;
+
+ AS_PTR :
+ begin
+ if not oper.hastype then
+ begin
+ if (oper.opr.typ=OPR_CONSTANT) then
+ begin
+ oper.typesize:=oper.opr.val;
+ { reset constant value of operand }
+ oper.opr.typ:=OPR_NONE;
+ oper.opr.val:=0;
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ Consume(AS_PTR);
+ oper.InitRef;
+ BuildOperand(oper,false);
+ end;
+
+ AS_ID : { A constant expression, or a Variable ref. }
+ Begin
+ { Label or Special symbol reference? }
+ if actasmpattern[1] = '@' then
+ Begin
+ if actasmpattern = '@RESULT' then
+ Begin
+ oper.SetupResult;
+ Consume(AS_ID);
+ end
+ else
+ if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
+ begin
+ Message(asmr_w_CODE_and_DATA_not_supported);
+ Consume(AS_ID);
+ end
+ else
+ { Local Label }
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end;
+ end
+ else
+ { support result for delphi modes }
+ if (m_objpas in aktmodeswitches) and (actasmpattern='RESULT') then
+ begin
+ oper.SetUpResult;
+ Consume(AS_ID);
+ end
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ else
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,BuildRefConstExpression);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,BuildRefConstExpression);
+ OPR_NONE,
+ OPR_CONSTANT :
+ BuildConstantOperand(oper);
+ else
+ Message(asmr_e_invalid_operand_type);
+ end;
+ end
+ else
+ { Check for pascal label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { is it a normal variable ? }
+ Begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if SearchType(expr,l) then
+ begin
+ oper.hastype:=true;
+ oper.typesize:=l;
+ case actasmtoken of
+ AS_LPAREN :
+ begin
+ { Support Type([Reference]) }
+ Consume(AS_LPAREN);
+ BuildOperand(oper,true);
+ Consume(AS_RPAREN);
+ end;
+ AS_LBRACKET :
+ begin
+ { Support Var.Type[Index] }
+ { Convert @label.Byte[1] to reference }
+ if oper.opr.typ=OPR_SYMBOL then
+ oper.initref;
+ end;
+ end;
+ end
+ else
+ begin
+ if not oper.SetupVar(expr,false) then
+ Begin
+ { not a variable, check special variables.. }
+ if expr = 'SELF' then
+ oper.SetupSelf
+ else
+ Message1(sym_e_unknown_id,expr);
+ expr:='';
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ AS_REGISTER : { Register, a variable reference or a constant reference }
+ begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if actasmtoken = AS_COLON then
+ Begin
+ Consume(AS_COLON);
+ oper.InitRef;
+ oper.opr.ref.segment:=tempreg;
+ BuildReference(oper);
+ end
+ else
+ { Simple register }
+ begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ oper.SetSize(tcgsize2size[reg_cgsize(oper.opr.reg)],true);
+ end;
+ end;
+
+ AS_LBRACKET: { a variable reference, register ref. or a constant reference }
+ Begin
+ BuildReference(oper);
+ end;
+
+ AS_SEG :
+ Begin
+ Message(asmr_e_seg_not_supported);
+ Consume(actasmtoken);
+ end;
+
+ AS_DWORD,
+ AS_BYTE,
+ AS_WORD,
+ AS_TBYTE,
+ AS_DQWORD,
+ AS_QWORD :
+ begin
+ { Type specifier }
+ oper.hastype:=true;
+ oper.typesize:=0;
+ case actasmtoken of
+ AS_DWORD : oper.typesize:=4;
+ AS_WORD : oper.typesize:=2;
+ AS_BYTE : oper.typesize:=1;
+ AS_QWORD : oper.typesize:=8;
+ AS_DQWORD : oper.typesize:=16;
+ AS_TBYTE : oper.typesize:=10;
+ end;
+ Consume(actasmtoken);
+ if (actasmtoken=AS_LPAREN) then
+ begin
+ { Support Type([Reference]) }
+ Consume(AS_LPAREN);
+ BuildOperand(oper,true);
+ Consume(AS_RPAREN);
+ end;
+ end;
+
+ AS_SEPARATOR,
+ AS_END,
+ AS_COMMA,
+ AS_COLON:
+ begin
+ break;
+ end;
+
+ AS_RPAREN:
+ begin
+ if not istypecast then
+ begin
+ Message(asmr_e_syn_operand);
+ Consume(AS_RPAREN);
+ end
+ else
+ break;
+ end;
+
+ else
+ begin
+ Message(asmr_e_syn_operand);
+ RecoverConsume(true);
+ break;
+ end;
+ end;
+ until false;
+ { End of operand, update size if a typecast is forced }
+ if (oper.typesize<>0) and
+ (oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL]) then
+ oper.SetSize(oper.typesize,true);
+ end;
+
+
+ Procedure ti386intreader.BuildOpCode(instr : tx86instruction);
+ var
+ PrefixOp,OverrideOp: tasmop;
+ operandnum : longint;
+ is_far_const:boolean;
+ i:byte;
+ begin
+ PrefixOp:=A_None;
+ OverrideOp:=A_None;
+ is_far_const:=false;
+ { prefix seg opcode / prefix opcode }
+ repeat
+ if is_prefix(actopcode) then
+ with instr do
+ begin
+ OpOrder:=op_intel;
+ PrefixOp:=ActOpcode;
+ opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ ConcatInstruction(curlist);
+ consume(AS_OPCODE);
+ end
+ else
+ if is_override(actopcode) then
+ with instr do
+ begin
+ OpOrder:=op_intel;
+ OverrideOp:=ActOpcode;
+ opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ ConcatInstruction(curlist);
+ consume(AS_OPCODE);
+ end
+ else
+ break;
+ { allow for newline after prefix or override }
+ while actasmtoken=AS_SEPARATOR do
+ consume(AS_SEPARATOR);
+ until (actasmtoken<>AS_OPCODE);
+ { opcode }
+ if (actasmtoken <> AS_OPCODE) then
+ begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(false);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ OpOrder:=op_intel;
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+
+ { Valid combination of prefix/override and instruction ? }
+ if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
+ Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
+ if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
+ Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
+ end;
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ is_far_const:=false;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read Operands }
+ repeat
+ case actasmtoken of
+ { End of asm operands for this opcode }
+ AS_END,
+ AS_SEPARATOR :
+ break;
+
+ { Operand delimiter }
+ AS_COMMA :
+ begin
+ if operandnum > Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+
+ {Far constant, i.e. jmp $0000:$11111111.}
+ AS_COLON:
+ begin
+ is_far_const:=true;
+ if operandnum>1 then
+ message(asmr_e_too_many_operands)
+ else
+ inc(operandnum);
+ consume(AS_COLON);
+ end;
+
+ { Type specifier }
+ AS_NEAR,
+ AS_FAR :
+ begin
+ if actasmtoken = AS_NEAR then
+ begin
+ Message(asmr_w_near_ignored);
+ instr.opsize:=S_NEAR;
+ end
+ else
+ begin
+ Message(asmr_w_far_ignored);
+ instr.opsize:=S_FAR;
+ end;
+ Consume(actasmtoken);
+ if actasmtoken=AS_PTR then
+ begin
+ Consume(AS_PTR);
+ instr.Operands[operandnum].InitRef;
+ end;
+ BuildOperand(instr.Operands[operandnum] as tx86operand,false);
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tx86operand,false);
+ end; { end case }
+ until false;
+ instr.ops:=operandnum;
+ { Check operands }
+ for i:=1 to operandnum do
+ begin
+ if is_far_const and
+ (instr.operands[i].opr.typ<>OPR_CONSTANT) then
+ message(asmr_e_expr_illegal)
+ else
+ if instr.operands[i].opr.typ=OPR_NONE then
+ Message(asmr_e_syntax_error);
+ end;
+ end;
+
+
+ Procedure ti386intreader.BuildConstant(constsize: byte);
+ var
+ asmsymtyp : tasmsymtype;
+ asmsym,
+ expr: string;
+ value : aint;
+ Begin
+ Repeat
+ Case actasmtoken of
+ AS_STRING:
+ Begin
+ { DD and DW cases }
+ if constsize <> 1 then
+ Begin
+ if Not PadZero(actasmpattern,constsize) then
+ Message(scan_f_string_exceeds_line);
+ end;
+ expr:=actasmpattern;
+ Consume(AS_STRING);
+ Case actasmtoken of
+ AS_COMMA:
+ Consume(AS_COMMA);
+ AS_END,
+ AS_SEPARATOR: ;
+ else
+ Message(asmr_e_invalid_string_expression);
+ end;
+ ConcatString(curlist,expr);
+ end;
+ AS_PLUS,
+ AS_MINUS,
+ AS_LPAREN,
+ AS_NOT,
+ AS_INTNUM,
+ AS_ID :
+ Begin
+ BuildConstSymbolExpression(false,false,value,asmsym,asmsymtyp);
+ if asmsym<>'' then
+ begin
+ if constsize<>sizeof(aint) then
+ Message1(asmr_w_const32bit_for_address,asmsym);
+ ConcatConstSymbol(curlist,asmsym,asmsymtyp,value)
+ end
+ else
+ ConcatConstant(curlist,value,constsize);
+ end;
+ AS_COMMA:
+ Consume(AS_COMMA);
+ AS_END,
+ AS_SEPARATOR:
+ break;
+ else
+ begin
+ Message(asmr_e_syn_constant);
+ RecoverConsume(false);
+ end
+ end;
+ Until false;
+ end;
+
+
+ function ti386intreader.Assemble: tlinkedlist;
+ Var
+ hl : tasmlabel;
+ instr : Tx86Instruction;
+ Begin
+ Message1(asmr_d_start_reading,'intel');
+ inexpression:=FALSE;
+ firsttoken:=TRUE;
+ { sets up all opcode and register tables in uppercase
+ done in the construtor now
+ if not _asmsorted then
+ Begin
+ SetupTables;
+ _asmsorted:=TRUE;
+ end;
+ }
+ curlist:=TAAsmoutput.Create;
+ { setup label linked list }
+ LocalLabelList:=TLocalLabelList.Create;
+ { start tokenizer }
+ c:=current_scanner.asmgetcharstart;
+ gettoken;
+ { main loop }
+ repeat
+ case actasmtoken of
+ AS_LLABEL:
+ Begin
+ if CreateLocalLabel(actasmpattern,hl,true) then
+ ConcatLabel(curlist,hl);
+ Consume(AS_LLABEL);
+ end;
+
+ AS_LABEL:
+ Begin
+ if SearchLabel(upper(actasmpattern),hl,true) then
+ ConcatLabel(curlist,hl)
+ else
+ Message1(asmr_e_unknown_label_identifier,actasmpattern);
+ Consume(AS_LABEL);
+ end;
+
+ AS_DW :
+ Begin
+ inexpression:=true;
+ Consume(AS_DW);
+ BuildConstant(2);
+ inexpression:=false;
+ end;
+
+ AS_DB :
+ Begin
+ inexpression:=true;
+ Consume(AS_DB);
+ BuildConstant(1);
+ inexpression:=false;
+ end;
+
+ AS_DD :
+ Begin
+ inexpression:=true;
+ Consume(AS_DD);
+ BuildConstant(4);
+ inexpression:=false;
+ end;
+
+ AS_ALIGN:
+ Begin
+ Consume(AS_ALIGN);
+ ConcatAlign(curlist,BuildConstExpression);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_OPCODE :
+ Begin
+ instr:=Tx86Instruction.Create(Tx86Operand);
+ BuildOpcode(instr);
+ with instr do
+ begin
+ { We need AT&T style operands }
+ Swapoperands;
+ { Must be done with args in ATT order }
+ CheckNonCommutativeOpcodes;
+ AddReferenceSizes;
+ SetInstructionOpsize;
+ CheckOperandSizes;
+ ConcatInstruction(curlist);
+ end;
+ instr.Free;
+ end;
+
+ AS_SEPARATOR :
+ Begin
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_END :
+ break; { end assembly block }
+
+ else
+ Begin
+ Message(asmr_e_syntax_error);
+ RecoverConsume(false);
+ end;
+ end; { end case }
+ until false;
+ { Check LocalLabelList }
+ LocalLabelList.CheckEmitted;
+ LocalLabelList.Free;
+ { Return the list in an asmnode }
+ assemble:=curlist;
+ Message1(asmr_d_finish_reading,'intel');
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_i386_intel_info : tasmmodeinfo =
+ (
+ id : asmmode_i386_intel;
+ idtxt : 'INTEL';
+ casmreader : ti386intreader;
+ );
+
+begin
+ RegisterAsmMode(asmmode_i386_intel_info);
+end.
diff --git a/compiler/i386/rgcpu.pas b/compiler/i386/rgcpu.pas
new file mode 100644
index 0000000000..10d9d58d34
--- /dev/null
+++ b/compiler/i386/rgcpu.pas
@@ -0,0 +1,71 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the i386 specific class for the register
+ allocator
+
+ 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 rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ cpuinfo,
+ aasmbase,aasmtai,
+ cclasses,globtype,cgbase,rgobj,rgx86;
+
+ type
+ trgcpu = class(trgx86)
+ procedure add_constraints(reg:Tregister);override;
+ end;
+
+implementation
+
+ uses
+ systems,
+ verbose;
+
+ const
+ { This value is used in tsaved. If the array value is equal
+ to this, then this means that this register is not used.}
+ reg_not_saved = $7fffffff;
+
+{************************************************************************
+ trgcpu
+*************************************************************************}
+
+ procedure trgcpu.add_constraints(reg:Tregister);
+ var
+ supreg : tsuperregister;
+ begin
+ if getsubreg(reg) in [R_SUBL,R_SUBH] then
+ begin
+ { Some registers have no 8-bit subregister }
+ supreg:=getsupreg(reg);
+ add_edge(supreg,RS_ESI);
+ add_edge(supreg,RS_EDI);
+ add_edge(supreg,RS_EBP);
+ end;
+ end;
+
+
+end.
diff --git a/compiler/i386/rropt386.pas b/compiler/i386/rropt386.pas
new file mode 100644
index 0000000000..d32165cf89
--- /dev/null
+++ b/compiler/i386/rropt386.pas
@@ -0,0 +1,364 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ development team
+
+ This unit contains register renaming functionality
+
+ 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 rropt386;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses aasmbase,aasmtai,aasmcpu;
+
+procedure doRenaming(asml: taasmoutput; first, last: tai);
+
+implementation
+
+uses
+ {$ifdef replaceregdebug}cutils,{$endif}
+ verbose,globals,cpubase,daopt386,csopt386,rgobj,
+ cgbase,cgutils,cgobj;
+
+function canBeFirstSwitch(p: taicpu; supreg: tsuperregister): boolean;
+{ checks whether an operation on reg can be switched to another reg without an }
+{ additional mov, e.g. "addl $4,%reg1" can be changed to "leal 4(%reg1),%reg2" }
+begin
+ canBeFirstSwitch := false;
+ case p.opcode of
+ A_MOV,A_MOVZX,A_MOVSX,A_LEA:
+ canBeFirstSwitch :=
+ (p.oper[1]^.typ = top_reg) and
+ (getsupreg(p.oper[1]^.reg) = supreg);
+ A_IMUL:
+ canBeFirstSwitch :=
+ (p.ops >= 2) and
+ (p.oper[0]^.typ = top_const) and
+ (getsupreg(p.oper[p.ops-1]^.reg) = supreg) and
+ (not pTaiprop(p.optinfo)^.FlagsUsed);
+ A_INC,A_DEC:
+ canBeFirstSwitch :=
+ (p.oper[0]^.typ = top_reg) and
+ (p.opsize = S_L) and
+ (not pTaiprop(p.optinfo)^.FlagsUsed);
+ A_SUB,A_ADD:
+ canBeFirstSwitch :=
+ (p.oper[1]^.typ = top_reg) and
+ (p.opsize = S_L) and
+ (getsupreg(p.oper[1]^.reg) = supreg) and
+ (p.oper[0]^.typ <> top_ref) and
+ ((p.opcode <> A_SUB) or
+ (p.oper[0]^.typ = top_const)) and
+ (not pTaiprop(p.optinfo)^.FlagsUsed);
+ A_SHL:
+ canBeFirstSwitch :=
+ (p.opsize = S_L) and
+ (p.oper[1]^.typ = top_reg) and
+ (getsupreg(p.oper[1]^.reg) = supreg) and
+ (p.oper[0]^.typ = top_const) and
+ (p.oper[0]^.val in [1,2,3]) and
+ (not pTaiprop(p.optinfo)^.FlagsUsed);
+ end;
+end;
+
+
+procedure switchReg(var reg: tregister; reg1, reg2: tsuperregister);
+var
+ supreg: tsuperregister;
+begin
+ if (reg = NR_NO) or
+ (getregtype(reg) <> R_INTREGISTER) then
+ exit;
+ supreg := getsupreg(reg);
+ if (supreg = reg1) then
+ setsupreg(reg,reg2)
+ else if (supreg = reg2) then
+ setsupreg(reg,reg1);
+end;
+
+
+procedure switchOp(var op: toper; reg1, reg2: tsuperregister);
+begin
+ case op.typ of
+ top_reg:
+ switchReg(op.reg,reg1,reg2);
+ top_ref:
+ begin
+ switchReg(op.ref^.base,reg1,reg2);
+ switchReg(op.ref^.index,reg1,reg2);
+ end;
+ end;
+end;
+
+
+procedure doSwitchReg(hp: taicpu; reg1,reg2: tsuperregister);
+var
+ opCount: longint;
+begin
+ for opCount := 0 to hp.ops-1 do
+ switchOp(hp.oper[opCount]^,reg1,reg2);
+end;
+
+
+procedure doFirstSwitch(p: taicpu; reg1, reg2: tsuperregister);
+var
+ tmpRef: treference;
+begin
+ case p.opcode of
+ A_MOV,A_MOVZX,A_MOVSX,A_LEA:
+ begin
+ changeOp(p.oper[1]^,reg1,reg2);
+ changeOp(p.oper[0]^,reg2,reg1);
+ end;
+ A_IMUL:
+ begin
+ p.ops := 3;
+ p.loadreg(2,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
+ changeOp(p.oper[1]^,reg2,reg1);
+ end;
+ A_INC,A_DEC:
+ begin
+ reference_reset(tmpref);
+ tmpref.base := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
+ case p.opcode of
+ A_INC:
+ tmpref.offset := 1;
+ A_DEC:
+ tmpref.offset := -1;
+ end;
+ p.ops := 2;
+ p.opcode := A_LEA;
+ p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
+ p.loadref(0,tmpref);
+ end;
+ A_SUB,A_ADD:
+ begin
+ reference_reset(tmpref);
+ tmpref.base := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
+ case p.oper[0]^.typ of
+ top_const:
+ begin
+ tmpref.offset := longint(p.oper[0]^.val);
+ if p.opcode = A_SUB then
+ tmpref.offset := - tmpRef.offset;
+ end;
+ top_ref:
+ if (p.oper[0]^.ref^.refaddr=addr_full) then
+ tmpref.symbol := p.oper[0]^.ref^.symbol
+ else
+ internalerror(200402263);
+ top_reg:
+ begin
+ tmpref.index := p.oper[0]^.reg;
+ tmpref.scalefactor := 1;
+ end;
+ else internalerror(200010031);
+ end;
+ p.opcode := A_LEA;
+ p.loadref(0,tmpref);
+ p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
+ end;
+ A_SHL:
+ begin
+ reference_reset(tmpref);
+ tmpref.index := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
+ tmpref.scalefactor := 1 shl p.oper[0]^.val;
+ p.opcode := A_LEA;
+ p.loadref(0,tmpref);
+ p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
+ end;
+ else internalerror(200010032);
+ end;
+end;
+
+
+function switchRegs(asml: taasmoutput; reg1, reg2: tsuperregister; start: tai): Boolean;
+{ change movl %reg1,%reg2 ... bla ... to ... bla with reg1 and reg2 switched }
+var
+ endP, hp, lastreg1,lastreg2: tai;
+ switchDone, switchLast, tmpResult, sequenceEnd, reg1Modified, reg2Modified: boolean;
+ reg1StillUsed, reg2StillUsed, isInstruction: boolean;
+begin
+ switchRegs := false;
+ tmpResult := true;
+ sequenceEnd := false;
+ reg1Modified := false;
+ reg2Modified := false;
+ endP := start;
+ while tmpResult and not sequenceEnd do
+ begin
+ tmpResult :=
+ getNextInstruction(endP,endP);
+ If tmpResult and
+ not pTaiprop(endp.optinfo)^.canBeRemoved then
+ begin
+ { if the newReg gets stored back to the oldReg, we can change }
+ { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
+ { %oldReg" to "<operations on %oldReg>" }
+ switchLast := storeBack(start,endP,reg1,reg2);
+ reg1StillUsed := reg1 in pTaiprop(endp.optinfo)^.usedregs;
+ reg2StillUsed := reg2 in pTaiprop(endp.optinfo)^.usedregs;
+ isInstruction := endp.typ = ait_instruction;
+ sequenceEnd :=
+ switchLast or
+ { if both registers are released right before an instruction }
+ { that contains hardcoded regs, it's ok too }
+ (not reg1StillUsed and not reg2StillUsed) or
+ { no support for (i)div, mul and imul with hardcoded operands }
+ (((not isInstruction) or
+ noHardCodedRegs(taicpu(endP),reg1,reg2)) and
+ (not reg1StillUsed or
+ (isInstruction and findRegDealloc(reg1,endP) and
+ regLoadedWithNewValue(reg1,false,taicpu(endP)))) and
+ (not reg2StillUsed or
+ (isInstruction and findRegDealloc(reg2,endP) and
+ regLoadedWithNewValue(reg2,false,taicpu(endP)))));
+
+ { we can't switch reg1 and reg2 in something like }
+ { movl %reg1,%reg2 }
+ { movl (%reg2),%reg2 }
+ { movl 4(%reg1),%reg1 }
+ if reg2Modified and not(reg1Modified) and
+ regReadByInstruction(reg1,endP) then
+ begin
+ tmpResult := false;
+ break
+ end;
+
+ if not reg1Modified then
+ begin
+ reg1Modified := regModifiedByInstruction(reg1,endP);
+ if reg1Modified and not canBeFirstSwitch(taicpu(endP),reg1) then
+ begin
+ tmpResult := false;
+ break;
+ end;
+ end;
+ if not reg2Modified then
+ reg2Modified := regModifiedByInstruction(reg2,endP);
+
+ tmpResult :=
+ ((not isInstruction) or
+ (NoHardCodedRegs(taicpu(endP),reg1,reg2) and
+ RegSizesOk(reg1,reg2,taicpu(endP))));
+
+ if sequenceEnd then
+ break;
+
+ tmpResult :=
+ tmpresult and
+ (endp.typ <> ait_label) and
+ ((not isInstruction) or
+ (not taicpu(endp).is_jmp));
+ end;
+ end;
+
+ if tmpResult and sequenceEnd then
+ begin
+ switchRegs := true;
+ reg1Modified := false;
+ reg2Modified := false;
+ lastreg1 := start;
+ lastreg2 := start;
+ getNextInstruction(start,hp);
+ while hp <> endP do
+ begin
+ if (not pTaiprop(hp.optinfo)^.canberemoved) and
+ (hp.typ = ait_instruction) then
+ begin
+ switchDone := false;
+ if not reg1Modified then
+ begin
+ reg1Modified := regModifiedByInstruction(reg1,hp);
+ if reg1Modified then
+ begin
+ doFirstSwitch(taicpu(hp),reg1,reg2);
+ switchDone := true;
+ end;
+ end;
+ if not switchDone then
+ if reg1Modified then
+ doSwitchReg(taicpu(hp),reg1,reg2)
+ else
+ doReplaceReg(taicpu(hp),reg2,reg1);
+ end;
+ if regininstruction(reg1,hp) then
+ lastreg1 := hp;
+ if regininstruction(reg2,hp) then
+ lastreg2 := hp;
+ getNextInstruction(hp,hp);
+ end;
+ if switchLast then
+ begin
+ { this is in case of a storeback, make sure the same size of register }
+ { contents as the initial move is transfered }
+ doSwitchReg(taicpu(hp),reg1,reg2);
+ if taicpu(hp).opsize <> taicpu(start).opsize then
+ begin
+ taicpu(hp).opsize := taicpu(start).opsize;
+ taicpu(hp).oper[0]^.reg := taicpu(start).oper[0]^.reg;
+ taicpu(hp).oper[1]^.reg := taicpu(start).oper[1]^.reg;
+ end;
+ end
+ else
+ getLastInstruction(hp,hp);
+ allocRegBetween(asmL,newreg(R_INTREGISTER,reg1,R_SUBWHOLE),start,lastreg1,
+ ptaiprop(start.optinfo)^.usedregs);
+ allocRegBetween(asmL,newreg(R_INTREGISTER,reg2,R_SUBWHOLE),start,lastreg2,
+ ptaiprop(start.optinfo)^.usedregs);
+ end;
+end;
+
+
+procedure doRenaming(asml: taasmoutput; first, last: tai);
+var
+ p: tai;
+begin
+ p := First;
+ SkipHead(p);
+ while p <> last do
+ begin
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_MOV:
+ begin
+ if not(pTaiprop(p.optinfo)^.canBeRemoved) and
+ (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(p).opsize = S_L) and
+ (getsupreg(taicpu(p).oper[0]^.reg) in ([RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI])) and
+ (getsupreg(taicpu(p).oper[1]^.reg) in ([RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI])) then
+ if switchRegs(asml,getsupreg(taicpu(p).oper[0]^.reg),
+ getsupreg(taicpu(p).oper[1]^.reg),p) then
+ begin
+ pTaiprop(p.optinfo)^.canBeRemoved := true;
+ end;
+ end;
+ end;
+ end;
+ end;
+ getNextInstruction(p,p);
+ end;
+end;
+
+
+End.
diff --git a/compiler/ia64/cpuasm.pas b/compiler/ia64/cpuasm.pas
new file mode 100644
index 0000000000..4acab4d226
--- /dev/null
+++ b/compiler/ia64/cpuasm.pas
@@ -0,0 +1,296 @@
+{
+ Copyright (c) 2000 by Florian Klaempfl
+
+ Contains the assembler object for the ia64
+
+ 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 cpuasm;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cobjects,
+ aasm,globals,verbose,
+ cpubase;
+
+
+type
+ pairegalloc = ^tairegalloc;
+ tairegalloc = class(tai)
+ allocation : boolean;
+ reg : tregister;
+ constructor alloc(r : tregister);
+ constructor dealloc(r : tregister);
+ end;
+
+ { Types of operand }
+ toptype=(top_none,top_reg,top_ref,top_const,top_symbol,top_qp);
+
+ toper=record
+ case typ : toptype of
+ top_none : ();
+ top_reg : (reg:tregister);
+ top_qp : (qp : tqp);
+ top_ref : (ref:preference);
+ top_const : (val:int64);
+ top_symbol : (sym:pasmsymbol;symofs:longint);
+ end;
+
+ paicpu = ^taicpu;
+ taicpu = class(tai)
+ is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
+ opcode : tasmop;
+ ops : array[0..4] of longint;
+ oper : longint;
+ qp : tqp;
+ ldsttype : tldsttype;
+ hint : thint;
+ { ALU instructions }
+ { A1,A9: integer ALU }
+ constructor op_reg_reg_reg(op : tasmop;const r1,r2,r3 : tregister);
+ { A2,A10: shift left and add }
+ constructor op_reg_reg_const_reg(_qp : tqp;op : tasmop;
+ const r1,r2 : tregister;i : byte;const r3 : tregister);
+ { A3,A4,A5: integer ALU - imm.,register }
+ constructor op_reg_const_reg(_qp : tqp;op : tasmop;
+ const r1 : tregister;i : longint;const r3 : tregister);
+ { A6,A7: integer compare - register,register }
+ constructor op_preg_preg_reg_reg(_qp : tqp;op : tasmop;
+ cond : tasmcond;p1,p2 : tqp;const r2,r3 : tregister);
+ { A8: integer compare - imm.,register }
+ constructor op_preg_preg_const_reg(_qp : tqp;op : tasmop;
+ cond : tasmcond;p1,p2 : tqp;i : longint;const r3 : tregister);
+{!!!!!!!
+ { multimedia shift and multiply }
+ constructor op_reg_reg_reg_const(_qp : tqp;
+ { multimedia mux }
+ constructor op_reg_reg_mbtype(_qp : tqp;
+ { multimedia shift fixed }
+ constructor op_reg_reg_const(_qp : tqp;
+ { div. }
+ constructor op_reg_reg(_qp : tqp;
+ { mm extract }
+ constructor op_reg_reg_const_const(_qp : tqp;
+ { zero and deposit imm }
+ constructor op_reg_const_const_const(_qp : tqp;
+ { deposit imm }
+ constructor op_reg_const_reg_const_const(_qp : tqp;
+ { deposit }
+ constructor op_reg_reg_reg_const_const(_qp : tqp;
+ { test bit }
+ { !!!! here we need also to take care of the postfix }
+ constructor op_preg_preg_reg_const(_qp : tqp;
+ { test NaT }
+ { !!!! here we need also to take care of the postfix }
+ constructor op_preg_preg_reg(_qp : tqp;
+
+ { -------- here are some missed ----------- }
+}
+
+ { M1: integer load }
+ { M4: integer store }
+ { M6: floating-point load }
+ { M9: floating-point store }
+ constructor op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;ref : preference);
+
+ { M2: integer load incremented by register }
+ { M7: floating-point load incremented by register }
+ constructor op_reg_ref_reg(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;const ref : treference;
+ const r2 : tregister);
+
+ { M3: integer load increment by imm. }
+ { M5: integer store increment by imm. }
+ { M8: floating-point load increment by imm. }
+ { M10: floating-point store increment by imm. }
+ constructor op_reg_ref_const(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;ref : preference;i : longint);
+
+ { M11: floating-point load pair}
+ constructor op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1,r2 : tregister;ref : preference);
+
+ { M12: floating-point load pair increment by imm. }
+ constructor op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1,r2 : tregister;ref : preference;i : longint);
+
+ { X1: break/nop }
+ constructor op_const62(_qp : tqp;op : tasmop;i : int64);
+ { X2: move imm64 }
+ constructor op_reg_const64(_qp : tqp;op : tasmop;const r1 : tregister;
+ i : int64);
+ end;
+
+ { the following objects are special for the ia64 }
+ { they decribe a stop and the bundles }
+ paistop = ^taistop;
+ taistop = class(tai)
+ constructor init;
+ end;
+
+ { a second underscro indicates a stop }
+ tbundletemplate = (but_none,but_mii,but_mii_,
+ but_mi_i,but_mi_i_,but_mlx,but_mlx_,
+ but_mmi,but_mmi_,but_m_mi,but_m_mi_,
+ but_mfi,but_mfi_,but_mmf,but_mmf_,
+ but_mif,but_mib_,but_mbb,but_mbb_,
+ but_bbb,but_bbb_,but_mmb,but_mmb_,
+ but_mfb,but_mfb_);
+
+ paibundle = ^taibundle;
+ taibundle = class(tai)
+ template : tbundletemplate;
+ instructions : array[0..1] of paicpu;
+ end;
+
+implementation
+
+
+{*****************************************************************************
+ TaiStop
+*****************************************************************************}
+
+ constructor taistop.init;
+
+ begin
+ inherited create;
+ typ:=ait_stop;
+ end;
+
+
+{*****************************************************************************
+ TaiRegAlloc
+*****************************************************************************}
+
+ constructor tairegalloc.alloc(r : tregister);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ allocation:=true;
+ reg:=r;
+ end;
+
+
+ constructor tairegalloc.dealloc(r : tregister);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ allocation:=false;
+ reg:=r;
+ end;
+
+
+{*****************************************************************************
+ Taicpu
+*****************************************************************************}
+
+ { ALU instructions }
+ { A1,A9: integer ALU }
+ constructor taicpu.op_reg_reg_reg(op : tasmop;const r1,r2,r3 : tregister);
+
+ begin
+ end;
+
+ { A2,A10: shift left and add }
+ constructor taicpu.op_reg_reg_const_reg(_qp : tqp;op : tasmop;
+ const r1,r2 : tregister;i : byte;const r3 : tregister);
+
+ begin
+ end;
+
+ { A3,A4,A5: integer ALU - imm.,register }
+ constructor taicpu.op_reg_const_reg(_qp : tqp;op : tasmop;
+ const r1 : tregister;i : longint;const r3 : tregister);
+
+ begin
+ end;
+
+ { A6,A7: integer compare - register,register }
+ constructor taicpu.op_preg_preg_reg_reg(_qp : tqp;op : tasmop;
+ cond : tasmcond;p1,p2 : tqp;const r2,r3 : tregister);
+
+ begin
+ end;
+
+ { A8: integer compare - imm.,register }
+ constructor taicpu.op_preg_preg_const_reg(_qp : tqp;op : tasmop;
+ cond : tasmcond;p1,p2 : tqp;i : longint;const r3 : tregister);
+
+ begin
+ end;
+
+ { M1: integer load }
+ { M4: integer store }
+ { M6: floating-point load }
+ { M9: floating-point store }
+ constructor taicpu.op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;ref : preference);
+
+ begin
+ end;
+
+ { M2: integer load incremented by register }
+ { M7: floating-point load incremented by register }
+ constructor taicpu.op_reg_ref_reg(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;const ref : treference;
+ const r2 : tregister);
+
+ begin
+ end;
+
+ { M3: integer load increment by imm. }
+ { M5: integer store increment by imm. }
+ { M8: floating-point load increment by imm. }
+ { M10: floating-point store increment by imm. }
+ constructor taicpu.op_reg_ref_const(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;ref : preference;i : longint);
+
+ begin
+ end;
+
+ { M11: floating-point load pair}
+ constructor taicpu.op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1,r2 : tregister;ref : preference);
+
+ begin
+ end;
+
+ { M12: floating-point load pair increment by imm. }
+ constructor taicpu.op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1,r2 : tregister;ref : preference;i : longint);
+
+ begin
+ end;
+
+ { X1: break/nop }
+ constructor taicpu.op_const62(_qp : tqp;op : tasmop;i : int64);
+ { X2: move imm64 }
+
+ begin
+ end;
+
+ constructor taicpu.op_reg_const64(_qp : tqp;op : tasmop;const r1 : tregister;
+ i : int64);
+
+ begin
+ end;
+
+end.
diff --git a/compiler/ia64/cpubase.pas b/compiler/ia64/cpubase.pas
new file mode 100644
index 0000000000..ee705d9bc1
--- /dev/null
+++ b/compiler/ia64/cpubase.pas
@@ -0,0 +1,282 @@
+{
+ Copyright (C) 2000 by Florian Klaempfl
+
+ this unit implements an asmlistitem class for the iA-64 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 cpubase;
+
+ interface
+
+ uses
+ cutils,strings,systems,cobjects,globals,aasm,cpuinfo;
+
+type
+ tasmop = (A_ADD,A_SUB,A_ADDP4,A_AND,A_ANDCM,A_OR,A_XOR,A_SHLADD,
+ A_SHLADDP4,A_ADDS,A_ADDL,A_CMP,A_CMP4,A_PADD1,A_PADD2,
+ A_PADD4,A_PSUB1,A_PSUB2,A_PSUB4,A_PAVG1,A_PAVG2,A_PAVGSUB1,
+ A_PAVGSUB2,A_PCMP1,A_PCMP2,A_PCMP4,A_PSHLADD2,A_PSHRADD2,
+ A_PMPY2,A_MIX1,A_MIX2,A_MIX4,A_PACK2,A_PACK4,A_UNPACK2,
+ A_UNPACK4,A_PMIN1,A_PMAX1,A_PMIN2,A_PMAX2,A_PSAD1,A_MUX1,
+ A_MUX2,A_PSHR2,A_PSHR4,A_SHR,A_PSHL2,A_SHL4,A_SHL,
+ A_POPCNT,A_SHRP,A_EXTR,A_DEP,A_TBIT,A_TNAT,A_BREAK,
+ A_NOP,A_CHK,A_MOV,A_ZX1,A_ZX2,A_ZXT4,A_SXT1,A_SXT2,A_SXT4,
+ A_CXZ1,A_CZX2,A_LD1,A_LD2,A_LD4,A_LD8,A_ST1,A_ST2,A_ST4,
+ A_ST8,A_LDFS,A_LDFD,A_LDF8,A_LDFE,A_LDF,A_STFS,A_STFD,A_STF8,
+ A_STFE,A_STF,A_LDFPS,A_LDFPD,A_LDFP8,A_LFETCH,A_CMPXCHG1,
+ A_CMPXCHG2,A_CMPXHG4,A_CMPXCHG8,A_XCHG1,A_XCHG2,A_XCHG4,
+ A_XCHG8,A_FETCHADD4,A_FETCHADD8,A_SETF,A_GETF,
+ A_INVALA,A_MF,A_SRLZ,A_SYNC,A_FLUSHRS,A_FC,A_ALLOC,A_SUM,
+ A_RUM,A_BR,A_CLRRRB,A_FMA,A_FPMA,A_FMS,A_FPMS,A_FNMA,A_FPNMA,
+ A_XMA,A_FSELECT,A_FCLASS,A_FRCPA,A_FPRCPA,A_FRSQRTA,
+ A_FPRSQRTA,A_FMIN,A_FMAX,A_FAMIN,A_FAMAX,A_FPMIN,A_FPMAX,
+ A_FPAMIN,A_FPAMAX,A_FPCMP,A_FMERGE,A_FMIX,A_FSXT,A_FPACK,
+ A_FSWAP,A_FAND,A_FANDCM,A_FOR,A_FXOR,A_FPMERGE,A_FCVT,
+ A_FPCVT,A_FSETC,A_FCLRT,A_FCHKF,A_MOVL);
+
+Const
+ firstop = low(tasmop);
+ lastop = high(tasmop);
+
+type
+ TAsmCond = (C_NONE,C_LT,C_LTU,C_EQ,C_LT_UNC,C_LTU_UNC,C_EQ_UNC,
+ C_EQ_AND,C_EQ_OR,C_EQ_OR_ANDCM,C_NE_AND,C_NE_OR);
+
+ THint = (H_NONE,H_NT1,H_NT2,H_NTA);
+ TLdStType = (LST_NONE,LST_S,LST_A,LSR_SA,LST_BIAS,LST_ACQ,LST_C_CLR,
+ LST_FILL,LST_C_NC,LST_C_CLR_ACQ,LST_REL,
+ LST_SPILL);
+
+Type
+ TRegister = (R_NO, { R_NO is Mandatory, signifies no register }
+ R_0,R_1,R_2,R_3,R_4,R_5,R_6,R_7,R_8,R_9,
+ R_10,R_11,R_12,R_13,R_14,R_15,R_16,R_17,R_18,R_19,
+ R_20,R_21,R_22,R_23,R_24,R_25,R_26,R_27,R_28,R_29,
+ R_30,R_31,
+ R_F0,R_F1,R_F2,R_F3,R_F4,R_F5,R_F6,R_F7,R_F8,R_F9,
+ R_F10,R_F11,R_F12,R_F13,R_F14,R_F15,R_F16,R_F17,R_F18,R_F19,
+ R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,
+ R_F30,R_F31);
+
+ TRegisterset = Set of TRegister;
+
+ { -1 indicates no qualifying prediction }
+ tqp = -1..63;
+
+const
+ qp_none : tqp = -1;
+
+{ Constants describing the registers }
+
+Const
+ Firstreg = R_0;
+ LastReg = R_F31;
+
+ stack_pointer_reg = R_30;
+ frame_pointer_reg = R_15;
+ self_pointer_reg = R_16;
+ accumulator = R_0;
+ {the return_result_reg, is used inside the called function to store its return
+ value when that is a scalar value otherwise a pointer to the address of the
+ result is placed inside it}
+ return_result_reg = accumulator;
+
+ {the function_result_reg contains the function result after a call to a scalar
+ function othewise it contains a pointer to the returned result}
+ function_result_reg = accumulator;
+ global_pointer = R_29;
+ return_pointer = R_26;
+
+ max_scratch_regs = 2;
+ scratch_regs : array[1..max_scratch_regs] of tregister = (R_1,R_2);
+
+{ low and high of the available maximum width integer general purpose }
+{ registers }
+ LoGPReg = R_0;
+ HiGPReg = R_31;
+
+ { sizes }
+ sizeof(aint) = 8;
+ extended_size = 16;
+
+ general_registers = [R_0..R_31];
+
+ intregs = [R_0..R_31];
+ fpuregs = [R_F0..R_F31];
+ mmregs = [];
+
+ availabletempregsint = [R_0..R_14,R_16..R_25,R_28];
+ availabletempregsfpu = [R_F0..R_F30];
+ availabletempregsmm = [];
+
+ c_countusableregsint = 26;
+ c_countusableregsfpu = 31;
+ c_countusableregsmm = 0;
+
+ maxfpuvarregs = 128;
+ maxvarregs = 128;
+
+ max_operands = 4;
+
+ varregs : Array [1..6] of Tregister =
+ (R_9,R_10,R_11,R_12,R_13,R_14);
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ std_saved_registers = [R_9..R_14,R_F2..R_F9];
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = ???;
+
+
+Type
+ TReference = record
+ offset : aword;
+ symbol : pasmsymbol;
+ base : tregister;
+ is_immediate : boolean;
+ offsetfixup : word; {needed for inline}
+ { the boundary to which the reference is surely aligned }
+ alignment : byte;
+ end;
+ PReference = ^TReference;
+
+ tloc = (LOC_INVALID,
+ LOC_REGISTER,
+ LOC_FPU,
+ LOC_MEM,
+ LOC_REFERENCE,
+ LOC_JUMP,
+ { the alpha doesn't have flags, but this }
+ { avoid some conditional compiling }
+ { DON'T USE for the alpha }
+ LOC_FLAGS,
+ LOC_CREGISTER,
+ LOC_CFPUREGISTER,
+ LOC_CONST);
+
+ tlocation = record
+ case loc : tloc of
+ LOC_REFERENCE,LOC_MEM : (reference : treference);
+ LOC_CREGISTER,
+ LOC_REGISTER : (register : tregister);
+ LOC_FLAGS : (qp : tqp);
+ LOC_JUMP : ();
+ end;
+
+{*****************************************************************************
+ Opcode propeties (needed for optimizer)
+*****************************************************************************}
+
+{$ifndef NOOPT}
+Type
+{What an instruction can change}
+ TInsChange = (Ch_None);
+{$endif}
+
+
+ { resets all values of ref to defaults }
+ procedure reset_reference(var ref : treference);
+ { set mostly used values of a new reference }
+ function new_reference(base : tregister;offset : longint) : preference;
+ function newreference(const r : treference) : preference;
+ procedure disposereference(var r : preference);
+
+ procedure set_location(var destloc : tlocation;const sourceloc : tlocation);
+
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure InitCpu;
+ procedure DoneCpu;
+
+implementation
+
+ uses
+ verbose;
+
+
+ procedure reset_reference(var ref : treference);
+ begin
+ FillChar(ref,sizeof(treference),0);
+ end;
+
+
+ function new_reference(base : tregister;offset : longint) : preference;
+ var
+ r : preference;
+ begin
+ new(r);
+ FillChar(r^,sizeof(treference),0);
+ r^.offset:=offset;
+ r^.alignment:=8;
+ new_reference:=r;
+ end;
+
+ function newreference(const r : treference) : preference;
+
+ var
+ p : preference;
+ begin
+ new(p);
+ p^:=r;
+ newreference:=p;
+ end;
+
+ procedure disposereference(var r : preference);
+
+ begin
+ dispose(r);
+ r:=Nil;
+ end;
+
+ procedure set_location(var destloc : tlocation;const sourceloc : tlocation);
+
+ begin
+ destloc:=sourceloc;
+ end;
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure InitCpu;
+ begin
+ end;
+
+ procedure DoneCpu;
+ begin
+ end;
+
+end.
diff --git a/compiler/ia64/cpuinfo.pas b/compiler/ia64/cpuinfo.pas
new file mode 100644
index 0000000000..9bdc53d3ab
--- /dev/null
+++ b/compiler/ia64/cpuinfo.pas
@@ -0,0 +1,60 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ Basic Processor information
+
+ 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 CPUInfo;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Type
+ AWord = QWord;
+
+ { this must be an ordinal type with the same size as a pointer }
+ { to allow some dirty type casts for example when using }
+ { tconstsym.value }
+ TPointerOrd = longint;
+
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ { on the ia64 comp will be mapped to int64 }
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+
+Const
+ { Size of native extended type }
+ extended_size = 10;
+
+ c_countusableregsint = 95;
+ c_countusableregsfpu = 95;
+ c_countusableregsmm = 0;
+ c_countusableregsqp = 48;
+
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'ia64';
+
+Implementation
+
+end.
diff --git a/compiler/impdef.pas b/compiler/impdef.pas
new file mode 100644
index 0000000000..9206c5f8fc
--- /dev/null
+++ b/compiler/impdef.pas
@@ -0,0 +1,483 @@
+{
+ Copyright (c) 1998-2002 by Pavel
+
+ This unit finds the export defs from PE files
+
+ C source code of DEWIN Windows disassembler (written by A. Milukov) was
+ partially used
+
+ 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 impdef;
+
+{$ifndef STANDALONE}
+ {$i fpcdefs.inc}
+{$endif}
+
+interface
+
+ uses
+ {$IFDEF USE_SYSUTILS}
+ SysUtils,
+ {$ELSE USE_SYSUTILS}
+ Dos;
+ {$ENDIF USE_SYSUTILS}
+
+ var
+ as_name,
+ ar_name : string;
+
+ function makedef(const binname,
+{$IFDEF STANDALONE}
+ textname,
+{$ENDIF}
+ libname:string):longbool;
+
+
+implementation
+
+{$IFDEF STANDALONE}
+var
+ __textname : string;
+const
+ kind : array[longbool] of pchar=('',' DATA');
+{$ENDIF}
+
+var
+ f:file;
+{$IFDEF STANDALONE}
+ t:text;
+ FileCreated:longbool;
+{$ENDIF}
+ lname:string;
+ impname:string;
+ TheWord:array[0..1]of char;
+ PEoffset:cardinal;
+ loaded:longint;
+
+function DOSstubOK(var x:cardinal):longbool;
+begin
+ blockread(f,TheWord,2,loaded);
+ if loaded<>2 then
+ DOSstubOK:=false
+ else
+ begin
+ DOSstubOK:=TheWord='MZ';
+ seek(f,$3C);
+ blockread(f,x,4,loaded);
+ if(loaded<>4)or(x>filesize(f))then
+ DOSstubOK:=false;
+ end;
+end;
+
+
+function isPE(x:longint):longbool;
+begin
+ seek(f,x);
+ blockread(f,TheWord,2,loaded);
+ isPE:=(loaded=2)and(TheWord='PE');
+end;
+
+
+var
+ cstring : array[0..127]of char;
+function GetEdata(PE:cardinal):longbool;
+type
+ TObjInfo=packed record
+ ObjName:array[0..7]of char;
+ VirtSize,
+ VirtAddr,
+ RawSize,
+ RawOffset,
+ Reloc,
+ LineNum:cardinal;
+ RelCount,
+ LineCount:word;
+ flags:cardinal;
+ end;
+var
+ i:cardinal;
+ ObjOfs:cardinal;
+ Obj:TObjInfo;
+ APE_obj,APE_Optsize:word;
+ ExportRVA:cardinal;
+ delta:cardinal;
+const
+ IMAGE_SCN_CNT_CODE=$00000020;
+ const
+{$ifdef unix}
+ DirSep = '/';
+{$else}
+ {$ifdef amiga}
+ DirSep = '/';
+ {$else}
+ DirSep = '\';
+ {$endif}
+{$endif}
+var
+ path:string;
+ _d:dirstr;
+ _n:namestr;
+ _e:extstr;
+ common_created:longbool;
+procedure cleardir(const s,ext:string);
+ var
+ ff:file;
+ dir:searchrec;
+ attr:word;
+ begin
+ findfirst(s+dirsep+ext,anyfile,dir);
+ while (doserror=0) do
+ begin
+ assign(ff,s+dirsep+dir.name);
+ GetFattr(ff,attr);
+ if not((DOSError<>0)or(Attr and Directory<>0))then
+ Erase(ff);
+ findnext(dir);
+ end;
+ findclose(dir);
+ end;
+procedure CreateTempDir(const s:string);
+ var
+ attr:word;
+ ff:file;
+ begin
+ assign(ff,s);
+ GetFattr(ff,attr);
+ if DosError=0 then
+ begin
+ cleardir(s,'*.sw');
+ cleardir(s,'*.swo');
+ end
+ else
+ begin
+ {$I-}
+ mkdir(s);
+ {$I+}
+ if ioresult<>0 then;
+ end;
+ end;
+procedure call_as(const name:string);
+ begin
+{$IFDEF USE_SYSUTILS}
+ ExecuteProcess(as_name,'-o '+name+'o '+name);
+{$ELSE USE_SYSUTILS}
+ exec(as_name,'-o '+name+'o '+name);
+{$ENDIF USE_SYSUTILS}
+ end;
+procedure call_ar;
+ var
+ f:file;
+ attr:word;
+ begin
+{$IFDEF STANDALONE}
+ if impname='' then
+ exit;
+{$ENDIF}
+ assign(f,impname);
+ GetFAttr(f,attr);
+ If DOSError=0 then
+ erase(f);
+{$IFDEF USE_SYSUTILS}
+ ExecuteProcess(ar_name,'rs '+impname+' '+path+dirsep+'*.swo');
+{$ELSE USE_SYSUTILS}
+ exec(ar_name,'rs '+impname+' '+path+dirsep+'*.swo');
+{$ENDIF USE_SYSUTILS}
+ cleardir(path,'*.sw');
+ cleardir(path,'*.swo');
+ {$i-}
+ RmDir(path);
+ {$i+}
+ if ioresult<>0 then;
+ end;
+procedure makeasm(index:cardinal;name:pchar;isData:longbool);
+ type
+ tt=array[1..1]of pchar;
+ pt=^tt;
+ const
+ fn_template:array[1..24]of pchar=(
+ '.section .idata$2',
+ '.rva .L4',
+ '.long 0,0',
+ '.rva ',
+ '.rva .L5',
+ '.section .idata$4',
+ '.L4:',
+ '.rva .L6',
+ '.long 0',
+ '.section .idata$5',
+ '.L5:',
+ '.text',
+ '.globl ',
+ ':',
+ 'jmp *.L7',
+ '.balign 4,144',
+ '.section .idata$5',
+ '.L7:',
+ '.rva .L6',
+ '.long 0',
+ '.section .idata$6',
+ '.L6:',
+ '.short 0',
+ '.ascii "\000"'
+ );
+ var_template:array[1..19]of pchar=(
+ '.section .idata$2',
+ '.rva .L7',
+ '.long 0,0',
+ '.rva ',
+ '.rva .L8',
+ '.section .idata$4',
+ '.L7:',
+ '.rva .L9',
+ '.long 0',
+ '.section .idata$5',
+ '.L8:',
+ '.globl ',
+ ':',
+ '.rva .L9',
+ '.long 0',
+ '.section .idata$6',
+ '.L9:',
+ '.short 0',
+ '.ascii "\000"'
+ );
+ __template:array[longbool]of pointer=(@fn_template,@var_template);
+ common_part:array[1..5]of pchar=(
+ '.balign 2,0',
+ '.section .idata$7',
+ '.globl ',
+ ':',
+ '.ascii "\000"'
+ );
+ posit:array[longbool,1..4]of longint=((4,13,14,24),(4,12,13,19));
+ var
+ template:array[longbool]of pt absolute __template;
+ f:text;
+ s:string;
+ i:longint;
+ n:string;
+ common_name,asmout:string;
+ __d:dirstr;
+ __n:namestr;
+ __x:extstr;
+ begin
+ if not common_created then
+ begin
+ common_name:='_$'+_n+'@common';
+ asmout:=path+dirsep+'0.sw';
+ assign(f,asmout);
+ rewrite(f);
+ for i:=1 to 5 do
+ begin
+ s:=StrPas(Common_part[i]);
+ case i of
+ 3:
+ s:=s+common_name;
+ 4:
+ s:=common_name+s;
+ 5:
+ begin
+ fsplit(lname,__d,__n,__x);
+ insert(__n+__x,s,9);
+ end;
+ end;
+ writeln(f,s);
+ end;
+ close(f);
+ call_as(asmout);
+ common_created:=true;
+ end;
+ n:=strpas(name);
+ str(succ(index):0,s);
+ asmout:=path+dirsep+s+'.sw';
+ assign(f,asmout);
+ rewrite(f);
+ for i:=1 to posit[isData,4]do
+ begin
+ s:=StrPas(template[isData]^[i]);
+ if i=posit[isData,1]then
+ s:=s+common_name
+ else if i=posit[isData,2]then
+ s:=s+n
+ else if i=posit[isData,3]then
+ s:=n+s
+ else if i=posit[isData,4]then
+ insert(n,s,9);
+ writeln(f,s);
+ end;
+ close(f);
+ call_as(asmout);
+ end;
+procedure ProcessEdata;
+ type
+ a8=array[0..7]of char;
+ function GetSectionName(rva:cardinal;var Flags:cardinal):a8;
+ var
+ i:cardinal;
+ LocObjOfs:cardinal;
+ LocObj:TObjInfo;
+ begin
+ GetSectionName:='';
+ Flags:=0;
+ LocObjOfs:=APE_OptSize+PEoffset+24;
+ for i:=1 to APE_obj do
+ begin
+ seek(f,LocObjOfs);
+ blockread(f,LocObj,sizeof(LocObj));
+ if(rva>=LocObj.VirtAddr)and(rva<=LocObj.VirtAddr+LocObj.RawSize)then
+ begin
+ GetSectionName:=a8(LocObj.ObjName);
+ Flags:=LocObj.flags;
+ end;
+ end;
+ end;
+ var
+ j,Fl:cardinal;
+ ulongval,procEntry:cardinal;
+ Ordinal:word;
+ isData:longbool;
+ ExpDir:packed record
+ flag,
+ stamp:cardinal;
+ Major,
+ Minor:word;
+ Name,
+ Base,
+ NumFuncs,
+ NumNames,
+ AddrFuncs,
+ AddrNames,
+ AddrOrds:cardinal;
+ end;
+ begin
+ with Obj do
+ begin
+ seek(f,RawOffset+delta);
+ blockread(f,ExpDir,sizeof(ExpDir));
+ fsplit(impname,_d,_n,_e);
+ path:=_d+_n+'.ils';
+{$IFDEF STANDALONE}
+ if impname<>'' then
+{$ENDIF}
+ CreateTempDir(path);
+ Common_created:=false;
+ for j:=0 to pred(ExpDir.NumNames)do
+ begin
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrOrds+j*2);
+ blockread(f,Ordinal,2);
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrFuncs+Cardinal(Ordinal*4));
+ blockread(f,ProcEntry,4);
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrNames+j*4);
+ blockread(f,ulongval,4);
+ seek(f,RawOffset-VirtAddr+ulongval);
+ blockread(f,cstring,sizeof(cstring));
+{$IFDEF STANDALONE}
+ if not FileCreated then
+ begin
+ FileCreated:=true;
+ if(__textname<>'')or(impname='')then
+ begin
+ rewrite(t);
+ writeln(t,'EXPORTS');
+ end;
+ end;
+{$ENDIF}
+ isData:=GetSectionName(procentry,Fl)='';
+ if not isData then
+ isData:=Fl and IMAGE_SCN_CNT_CODE<>IMAGE_SCN_CNT_CODE;
+{$IFDEF STANDALONE}
+ if(__textname<>'')or(impname='')then
+ writeln(t,cstring,' @',succ(ordinal):0,' ',kind[isData]);
+ if impname<>''then
+{$ENDIF}
+ makeasm(j,cstring,isData);
+ end;
+ call_ar;
+ end;
+ end;
+
+begin
+ GetEdata:=false;
+{$IFDEF STANDALONE}
+ FileCreated:=false;
+{$ENDIF}
+ seek(f,PE+120);
+ blockread(f,ExportRVA,4);
+ seek(f,PE+6);
+ blockread(f,APE_Obj,2);
+ seek(f,PE+20);
+ blockread(f,APE_OptSize,2);
+ ObjOfs:=APE_OptSize+PEoffset+24;
+ for i:=1 to APE_obj do
+ begin
+ seek(f,ObjOfs);
+ blockread(f,Obj,sizeof(Obj));
+ inc(ObjOfs,sizeof(Obj));
+ with Obj do
+ if(VirtAddr<=ExportRva)and(ExportRva<VirtAddr+VirtSize)then
+ begin
+ delta:=ExportRva-VirtAddr;
+ ProcessEdata;
+ GetEdata:=true;
+ end;
+ end;
+end;
+
+
+function makedef(const binname,
+{$IFDEF STANDALONE}
+ textname,
+{$ENDIF}
+ libname:string):longbool;
+var
+ OldFileMode:longint;
+begin
+ assign(f,binname);
+{$IFDEF STANDALONE}
+ FileCreated:=false;
+ assign(t,textname);
+ __textname:=textname;
+{$ENDIF}
+ impname:=libname;
+ lname:=binname;
+ OldFileMode:=filemode;
+ {$I-}
+ filemode:=0;
+ reset(f,1);
+ filemode:=OldFileMode;
+ {$I+}
+ if IOResult<>0 then
+ begin
+ makedef:=false;
+ exit;
+ end;
+ if not DOSstubOK(PEoffset)then
+ makedef:=false
+ else if not IsPE(PEoffset)then
+ makedef:=false
+ else
+ makedef:=GetEdata(PEoffset);
+ close(f);
+{$IFDEF STANDALONE}
+ if FileCreated then
+ if(textname<>'')or(impname='')then
+ close(t);
+{$ENDIF}
+end;
+
+end.
diff --git a/compiler/import.pas b/compiler/import.pas
new file mode 100644
index 0000000000..f096a6bfef
--- /dev/null
+++ b/compiler/import.pas
@@ -0,0 +1,237 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements an uniform import object
+
+ 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 import;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cutils,cclasses,
+ systems,
+ aasmbase,
+ symdef,symsym;
+
+type
+ timported_item = class(TLinkedListItem)
+ ordnr : word;
+ name,
+ func : pstring;
+ lab : tasmlabel;
+ is_var : boolean;
+ constructor Create(const n,s : string;o : word);
+ constructor Create_var(const n,s : string);
+ destructor Destroy;override;
+ end;
+
+ timportlist = class(TLinkedListItem)
+ dllname : pstring;
+ imported_items : tlinkedlist;
+ constructor Create(const n : string);
+ destructor Destroy;Override;
+ end;
+
+ timportlib=class
+ private
+ notsupmsg : boolean;
+ procedure NotSupported;
+ public
+ constructor Create;virtual;
+ destructor Destroy;override;
+ procedure preparelib(const s:string);virtual;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);virtual;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);virtual;
+ procedure generatelib;virtual;
+ procedure generatesmartlib;virtual;
+ end;
+
+ TDLLScanner=class
+ public
+ f:file;
+ impname:string;
+ TheWord:array[0..1]of char;
+ HeaderOffset:cardinal;
+ loaded:integer;
+ function isSuitableFileType(x:cardinal):longbool;virtual;abstract;
+ function GetEdata(HeaderEntry:cardinal):longbool;virtual;abstract;
+ function Scan(const binname:string):longbool;virtual;abstract;
+ end;
+
+ TImportLibClass=class of TImportLib;
+ TDLLScannerClass=class of TDLLScanner;
+
+var
+ CImportLib : array[tsystem] of TImportLibClass;
+ CDLLScanner : array[tsystem] of TDLLScannerClass;
+ ImportLib : TImportLib;
+
+procedure RegisterImport(t:tsystem;c:TImportLibClass);
+procedure RegisterDLLScanner(t:tsystem;c:TDLLScannerClass);
+procedure InitImport;
+procedure DoneImport;
+
+
+implementation
+
+uses
+ verbose,globals;
+
+{****************************************************************************
+ Timported_item
+****************************************************************************}
+
+constructor timported_item.Create(const n,s : string;o : word);
+begin
+ inherited Create;
+ func:=stringdup(n);
+ name:=stringdup(s);
+ ordnr:=o;
+ lab:=nil;
+ is_var:=false;
+end;
+
+
+constructor timported_item.create_var(const n,s : string);
+begin
+ inherited Create;
+ func:=stringdup(n);
+ name:=stringdup(s);
+ ordnr:=0;
+ lab:=nil;
+ is_var:=true;
+end;
+
+
+destructor timported_item.destroy;
+begin
+ stringdispose(name);
+ stringdispose(func);
+ inherited destroy;
+end;
+
+
+{****************************************************************************
+ TImportlist
+****************************************************************************}
+
+constructor timportlist.Create(const n : string);
+begin
+ inherited Create;
+ dllname:=stringdup(n);
+ imported_items:=Tlinkedlist.Create;
+end;
+
+
+destructor timportlist.destroy;
+begin
+ imported_items.free;
+ stringdispose(dllname);
+end;
+
+
+{****************************************************************************
+ TImportLib
+****************************************************************************}
+
+constructor timportlib.Create;
+begin
+ notsupmsg:=false;
+end;
+
+
+destructor timportlib.Destroy;
+begin
+end;
+
+
+procedure timportlib.NotSupported;
+begin
+ { show the message only once }
+ if not notsupmsg then
+ begin
+ Message(exec_e_dll_not_supported);
+ notsupmsg:=true;
+ end;
+end;
+
+
+procedure timportlib.preparelib(const s:string);
+begin
+ NotSupported;
+end;
+
+
+procedure timportlib.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+begin
+ NotSupported;
+end;
+
+
+procedure timportlib.importvariable(vs:tglobalvarsym;const name,module:string);
+begin
+ NotSupported;
+end;
+
+
+procedure timportlib.generatelib;
+begin
+ NotSupported;
+end;
+
+
+procedure timportlib.generatesmartlib;
+begin
+ NotSupported;
+end;
+
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+procedure RegisterImport(t:tsystem;c:TImportLibClass);
+begin
+ CImportLib[t]:=c;
+end;
+
+
+procedure RegisterDLLScanner(t:tsystem;c:TDLLScannerClass);
+begin
+ CDLLScanner[t]:=c;
+end;
+
+
+procedure InitImport;
+begin
+ if assigned(CImportLib[target_info.system]) then
+ importlib:=CImportLib[target_info.system].Create
+ else
+ importlib:=TImportLib.Create;
+end;
+
+
+procedure DoneImport;
+begin
+ if assigned(importlib) then
+ importlib.free;
+end;
+
+end.
diff --git a/compiler/link.pas b/compiler/link.pas
new file mode 100644
index 0000000000..b12f3e7248
--- /dev/null
+++ b/compiler/link.pas
@@ -0,0 +1,705 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit handles the linker and binder calls for programs and
+ libraries
+
+ 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 link;
+
+{$i fpcdefs.inc}
+
+interface
+uses
+ cclasses,
+ systems,
+ fmodule,
+ globtype;
+
+Type
+ TLinkerInfo=record
+ ExeCmd,
+ DllCmd : array[1..3] of string;
+ ResName : string[100];
+ ScriptName : string[100];
+ ExtraOptions : string;
+ DynamicLinker : string[100];
+ end;
+
+ TLinker = class(TAbstractLinker)
+ public
+ ObjectFiles,
+ SharedLibFiles,
+ StaticLibFiles : TStringList;
+ Constructor Create;virtual;
+ Destructor Destroy;override;
+ procedure AddModuleFiles(hp:tmodule);
+ Procedure AddObject(const S,unitpath : String;isunit:boolean);
+ Procedure AddStaticLibrary(const S : String);
+ Procedure AddSharedLibrary(S : String);
+ Procedure AddStaticCLibrary(const S : String);
+ Procedure AddSharedCLibrary(S : String);
+ Function MakeExecutable:boolean;virtual;
+ Function MakeSharedLibrary:boolean;virtual;
+ Function MakeStaticLibrary:boolean;virtual;
+ end;
+
+ TExternalLinker = class(TLinker)
+ public
+ Info : TLinkerInfo;
+ Constructor Create;override;
+ Destructor Destroy;override;
+ Function FindUtil(const s:string):String;
+ Function DoExec(const command:string; para:TCmdStr;showinfo,useshell:boolean):boolean;
+ procedure SetDefaultInfo;virtual;
+ Function MakeStaticLibrary:boolean;override;
+ end;
+
+ TInternalLinker = class(TLinker)
+ private
+ procedure readobj(const fn:string);
+ public
+ Constructor Create;override;
+ Destructor Destroy;override;
+ Function MakeExecutable:boolean;override;
+ end;
+
+
+var
+ Linker : TLinker;
+
+function FindObjectFile(s : string;const unitpath:string;isunit:boolean) : string;
+function FindLibraryFile(s:string;const prefix,ext:string;var foundfile : string) : boolean;
+
+procedure InitLinker;
+procedure DoneLinker;
+
+
+Implementation
+
+uses
+{$IFDEF USE_SYSUTILS}
+ SysUtils,
+{$ELSE USE_SYSUTILS}
+ dos,
+{$ENDIF USE_SYSUTILS}
+ cutils,
+ script,globals,verbose,ppu,
+ aasmbase,aasmtai,aasmcpu,
+ ogbase,ogmap;
+
+type
+ TLinkerClass = class of Tlinker;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+{ searches an object file }
+function FindObjectFile(s:string;const unitpath:string;isunit:boolean) : string;
+var
+ found : boolean;
+ foundfile : string;
+begin
+ findobjectfile:='';
+ if s='' then
+ exit;
+
+ {When linking on target, the units has not been assembled yet,
+ so there is no object files to look for at
+ the host. Look for the corresponding assembler file instead,
+ because it will be assembled to object file on the target.}
+ if isunit and (cs_link_on_target in aktglobalswitches) then
+ s:= ForceExtension(s,target_info.asmext);
+
+ { when it does not belong to the unit then check if
+ the specified file exists without searching any paths }
+ if not isunit then
+ begin
+ if FileExists(FixFileName(s)) then
+ begin
+ foundfile:=ScriptFixFileName(s);
+ found:=true;
+ end;
+ end;
+ if pos('.',s)=0 then
+ s:=s+target_info.objext;
+ { find object file
+ 1. output unit path
+ 2. output exe path
+ 3. specified unit path (if specified)
+ 4. cwd
+ 5. unit search path
+ 6. local object path
+ 7. global object path
+ 8. exepath (not when linking on target) }
+ found:=false;
+ if isunit and (OutputUnitDir<>'') then
+ found:=FindFile(s,OutPutUnitDir,foundfile)
+ else
+ if OutputExeDir<>'' then
+ found:=FindFile(s,OutPutExeDir,foundfile);
+ if (not found) and (unitpath<>'') then
+ found:=FindFile(s,unitpath,foundfile);
+ if (not found) then
+ found:=FindFile(s, CurDirRelPath(source_info), foundfile);
+ if (not found) then
+ found:=UnitSearchPath.FindFile(s,foundfile);
+ if (not found) then
+ found:=current_module.localobjectsearchpath.FindFile(s,foundfile);
+ if (not found) then
+ found:=objectsearchpath.FindFile(s,foundfile);
+ if not(cs_link_on_target in aktglobalswitches) and (not found) then
+ found:=FindFile(s,exepath,foundfile);
+ if not(cs_link_extern in aktglobalswitches) and (not found) then
+ Message1(exec_w_objfile_not_found,s);
+
+ {Restore file extension}
+ if isunit and (cs_link_on_target in aktglobalswitches) then
+ foundfile:= ForceExtension(foundfile,target_info.objext);
+
+ findobjectfile:=ScriptFixFileName(foundfile);
+end;
+
+
+{ searches an library file }
+function FindLibraryFile(s:string;const prefix,ext:string;var foundfile : string) : boolean;
+var
+ found : boolean;
+ paths : string;
+begin
+ findlibraryfile:=false;
+ foundfile:=s;
+ if s='' then
+ exit;
+ { split path from filename }
+ paths:=SplitPath(s);
+ s:=SplitFileName(s);
+ { add prefix 'lib' }
+ if (prefix<>'') and (Copy(s,1,length(prefix))<>prefix) then
+ s:=prefix+s;
+ { add extension }
+ if (ext<>'') and (Copy(s,length(s)-length(ext)+1,length(ext))<>ext) then
+ s:=s+ext;
+ { readd the split path }
+ s:=paths+s;
+ if FileExists(s) then
+ begin
+ foundfile:=ScriptFixFileName(s);
+ FindLibraryFile:=true;
+ exit;
+ end;
+ { find libary
+ 1. cwd
+ 2. local libary dir
+ 3. global libary dir
+ 4. exe path of the compiler (not when linking on target) }
+ found:=FindFile(s, CurDirRelPath(source_info), foundfile);
+ if (not found) and (current_module.outputpath^<>'') then
+ found:=FindFile(s,current_module.outputpath^,foundfile);
+ if (not found) then
+ found:=current_module.locallibrarysearchpath.FindFile(s,foundfile);
+ if (not found) then
+ found:=librarysearchpath.FindFile(s,foundfile);
+ if not(cs_link_on_target in aktglobalswitches) and (not found) then
+ found:=FindFile(s,exepath,foundfile);
+ foundfile:=ScriptFixFileName(foundfile);
+ findlibraryfile:=found;
+end;
+
+
+{*****************************************************************************
+ TLINKER
+*****************************************************************************}
+
+Constructor TLinker.Create;
+begin
+ Inherited Create;
+ ObjectFiles:=TStringList.Create_no_double;
+ SharedLibFiles:=TStringList.Create_no_double;
+ StaticLibFiles:=TStringList.Create_no_double;
+end;
+
+
+Destructor TLinker.Destroy;
+begin
+ ObjectFiles.Free;
+ SharedLibFiles.Free;
+ StaticLibFiles.Free;
+end;
+
+
+procedure TLinker.AddModuleFiles(hp:tmodule);
+var
+ mask : longint;
+begin
+ with hp do
+ begin
+ { link unit files }
+ if (flags and uf_no_link)=0 then
+ begin
+ { create mask which unit files need linking }
+ mask:=link_allways;
+ { static linking ? }
+ if (cs_link_static in aktglobalswitches) then
+ begin
+ if (flags and uf_static_linked)=0 then
+ begin
+ { if smart not avail then try static linking }
+ if (flags and uf_smart_linked)<>0 then
+ begin
+ Message1(exec_t_unit_not_static_linkable_switch_to_smart,modulename^);
+ mask:=mask or link_smart;
+ end
+ else
+ Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
+ end
+ else
+ mask:=mask or link_static;
+ end;
+ { smart linking ? }
+ if (cs_link_smart in aktglobalswitches) then
+ begin
+ if (flags and uf_smart_linked)=0 then
+ begin
+ { if smart not avail then try static linking }
+ if (flags and uf_static_linked)<>0 then
+ begin
+ Message1(exec_t_unit_not_smart_linkable_switch_to_static,modulename^);
+ mask:=mask or link_static;
+ end
+ else
+ Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
+ end
+ else
+ mask:=mask or link_smart;
+ end;
+ { shared linking }
+ if (cs_link_shared in aktglobalswitches) then
+ begin
+ if (flags and uf_shared_linked)=0 then
+ begin
+ { if shared not avail then try static linking }
+ if (flags and uf_static_linked)<>0 then
+ begin
+ Message1(exec_t_unit_not_shared_linkable_switch_to_static,modulename^);
+ mask:=mask or link_static;
+ end
+ else
+ Message1(exec_e_unit_not_shared_or_static_linkable,modulename^);
+ end
+ else
+ mask:=mask or link_shared;
+ end;
+ { unit files }
+ while not linkunitofiles.empty do
+ begin
+ AddObject(linkunitofiles.getusemask(mask),path^,true);
+ end;
+ while not linkunitstaticlibs.empty do
+ AddStaticLibrary(linkunitstaticlibs.getusemask(mask));
+ while not linkunitsharedlibs.empty do
+ AddSharedLibrary(linkunitsharedlibs.getusemask(mask));
+ end;
+ { Other needed .o and libs, specified using $L,$LINKLIB,external }
+ mask:=link_allways;
+ while not linkotherofiles.empty do
+ AddObject(linkotherofiles.Getusemask(mask),path^,false);
+ while not linkotherstaticlibs.empty do
+ AddStaticCLibrary(linkotherstaticlibs.Getusemask(mask));
+ while not linkothersharedlibs.empty do
+ AddSharedCLibrary(linkothersharedlibs.Getusemask(mask));
+ end;
+end;
+
+
+Procedure TLinker.AddObject(const S,unitpath : String;isunit:boolean);
+begin
+ ObjectFiles.Concat(FindObjectFile(s,unitpath,isunit));
+end;
+
+
+Procedure TLinker.AddSharedLibrary(S:String);
+begin
+ if s='' then
+ exit;
+{ remove prefix 'lib' }
+ if Copy(s,1,length(target_info.sharedlibprefix))=target_info.sharedlibprefix then
+ Delete(s,1,length(target_info.sharedlibprefix));
+{ remove extension if any }
+ if Copy(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext))=target_info.sharedlibext then
+ Delete(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext)+1);
+{ ready to be added }
+ SharedLibFiles.Concat(S);
+end;
+
+
+Procedure TLinker.AddStaticLibrary(const S:String);
+var
+ ns : string;
+ found : boolean;
+begin
+ if s='' then
+ exit;
+ found:=FindLibraryFile(s,target_info.staticlibprefix,target_info.staticlibext,ns);
+ if not(cs_link_extern in aktglobalswitches) and (not found) then
+ Message1(exec_w_libfile_not_found,s);
+ StaticLibFiles.Concat(ns);
+end;
+
+
+Procedure TLinker.AddSharedCLibrary(S:String);
+begin
+ if s='' then
+ exit;
+{ remove prefix 'lib' }
+ if Copy(s,1,length(target_info.sharedclibprefix))=target_info.sharedclibprefix then
+ Delete(s,1,length(target_info.sharedclibprefix));
+{ remove extension if any }
+ if Copy(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext))=target_info.sharedclibext then
+ Delete(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext)+1);
+{ ready to be added }
+ SharedLibFiles.Concat(S);
+end;
+
+
+Procedure TLinker.AddStaticCLibrary(const S:String);
+var
+ ns : string;
+ found : boolean;
+begin
+ if s='' then
+ exit;
+ found:=FindLibraryFile(s,target_info.staticclibprefix,target_info.staticclibext,ns);
+ if not(cs_link_extern in aktglobalswitches) and (not found) then
+ Message1(exec_w_libfile_not_found,s);
+ StaticLibFiles.Concat(ns);
+end;
+
+
+function TLinker.MakeExecutable:boolean;
+begin
+ MakeExecutable:=false;
+ Message(exec_e_exe_not_supported);
+end;
+
+
+Function TLinker.MakeSharedLibrary:boolean;
+begin
+ MakeSharedLibrary:=false;
+ Message(exec_e_dll_not_supported);
+end;
+
+
+Function TLinker.MakeStaticLibrary:boolean;
+begin
+ MakeStaticLibrary:=false;
+ Message(exec_e_dll_not_supported);
+end;
+
+
+{*****************************************************************************
+ TEXTERNALLINKER
+*****************************************************************************}
+
+Constructor TExternalLinker.Create;
+begin
+ inherited Create;
+ { set generic defaults }
+ FillChar(Info,sizeof(Info),0);
+ if cs_link_on_target in aktglobalswitches then
+ begin
+ Info.ResName:=outputexedir+inputfile+'_link.res';
+ Info.ScriptName:=outputexedir+inputfile+'_script.res';
+ end
+ else
+ begin
+ Info.ResName:='link.res';
+ Info.ScriptName:='script.res';
+ end;
+ { set the linker specific defaults }
+ SetDefaultInfo;
+ { Allow Parameter overrides for linker info }
+ with Info do
+ begin
+ if ParaLinkOptions<>'' then
+ ExtraOptions:=ParaLinkOptions;
+ if ParaDynamicLinker<>'' then
+ DynamicLinker:=ParaDynamicLinker;
+ end;
+end;
+
+
+Destructor TExternalLinker.Destroy;
+begin
+ inherited destroy;
+end;
+
+
+Procedure TExternalLinker.SetDefaultInfo;
+begin
+end;
+
+
+Function TExternalLinker.FindUtil(const s:string):string;
+var
+ Found : boolean;
+ FoundBin : string;
+ UtilExe : string;
+begin
+ if cs_link_on_target in aktglobalswitches then
+ begin
+ { If linking on target, don't add any path PM }
+ FindUtil:=AddExtension(s,target_info.exeext);
+ exit;
+ end;
+ UtilExe:=AddExtension(s,source_info.exeext);
+ FoundBin:='';
+ Found:=false;
+ if utilsdirectory<>'' then
+ Found:=FindFile(utilexe,utilsdirectory,Foundbin);
+ if (not Found) then
+ Found:=FindExe(utilexe,Foundbin);
+ if (not Found) and not(cs_link_extern in aktglobalswitches) then
+ begin
+ Message1(exec_e_util_not_found,utilexe);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ end;
+ if (FoundBin<>'') then
+ Message1(exec_t_using_util,FoundBin);
+ FindUtil:=FoundBin;
+end;
+
+
+Function TExternalLinker.DoExec(const command:string; para:TCmdStr;showinfo,useshell:boolean):boolean;
+var
+ exitcode: longint;
+begin
+ DoExec:=true;
+ if not(cs_link_extern in aktglobalswitches) then
+ begin
+ if useshell then
+ exitcode := shell(maybequoted(command)+' '+para)
+ else
+{$IFDEF USE_SYSUTILS}
+ try
+ if ExecuteProcess(command,para) <> 0
+ then begin
+ Message(exec_e_error_while_linking);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ DoExec:=false;
+ end;
+ except on E:EOSError do
+ begin
+ Message(exec_e_cant_call_linker);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ DoExec:=false;
+ end;
+ end
+ end;
+{$ELSE USE_SYSUTILS}
+ begin
+ swapvectors;
+ exec(command,para);
+ swapvectors;
+ exitcode := dosexitcode;
+ end;
+ if (doserror<>0) then
+ begin
+ Message(exec_e_cant_call_linker);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ DoExec:=false;
+ end
+ else
+ if (exitcode<>0) then
+ begin
+ Message(exec_e_error_while_linking);
+ aktglobalswitches:=aktglobalswitches+[cs_link_extern];
+ DoExec:=false;
+ end;
+ end;
+{$ENDIF USE_SYSUTILS}
+{ Update asmres when externmode is set }
+ if cs_link_extern in aktglobalswitches then
+ begin
+ if showinfo then
+ begin
+ if DLLsource then
+ AsmRes.AddLinkCommand(Command,Para,current_module.sharedlibfilename^)
+ else
+ AsmRes.AddLinkCommand(Command,Para,current_module.exefilename^);
+ end
+ else
+ AsmRes.AddLinkCommand(Command,Para,'');
+ end;
+end;
+
+
+Function TExternalLinker.MakeStaticLibrary:boolean;
+var
+ smartpath,
+ cmdstr : TCmdStr;
+ binstr : string;
+ success : boolean;
+begin
+ MakeStaticLibrary:=false;
+{ remove the library, to be sure that it is rewritten }
+ RemoveFile(current_module.staticlibfilename^);
+{ Call AR }
+ smartpath:=current_module.outputpath^+FixPath(lower(current_module.modulename^)+target_info.smartext,false);
+ SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
+ Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
+ Replace(cmdstr,'$FILES',FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
+ success:=DoExec(FindUtil(binstr),cmdstr,false,true);
+{ Clean up }
+ if not(cs_asm_leave in aktglobalswitches) then
+ if not(cs_link_extern in aktglobalswitches) then
+ begin
+ while not SmartLinkOFiles.Empty do
+ RemoveFile(SmartLinkOFiles.GetFirst);
+ RemoveDir(smartpath);
+ end
+ else
+ begin
+ AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
+ AsmRes.Add('rmdir '+smartpath);
+ end;
+ MakeStaticLibrary:=success;
+end;
+
+
+{*****************************************************************************
+ TINTERNALLINKER
+*****************************************************************************}
+
+Constructor TInternalLinker.Create;
+begin
+ inherited Create;
+ exemap:=nil;
+ exeoutput:=nil;
+end;
+
+
+Destructor TInternalLinker.Destroy;
+begin
+ exeoutput.free;
+ exeoutput:=nil;
+ inherited destroy;
+end;
+
+
+procedure TInternalLinker.readobj(const fn:string);
+var
+ objdata : TAsmObjectData;
+ objinput : tobjectinput;
+begin
+ Comment(V_Info,'Reading object '+fn);
+ objinput:=exeoutput.newobjectinput;
+ objdata:=objinput.newobjectdata(fn);
+ if objinput.readobjectfile(fn,objdata) then
+ exeoutput.addobjdata(objdata);
+ { release input object }
+ objinput.free;
+end;
+
+
+function TInternalLinker.MakeExecutable:boolean;
+var
+ s : string;
+begin
+ MakeExecutable:=false;
+
+ { no support yet for libraries }
+ if (not StaticLibFiles.Empty) or
+ (not SharedLibFiles.Empty) then
+ internalerror(123456789);
+
+ if (cs_link_map in aktglobalswitches) then
+ exemap:=texemap.create(current_module.mapfilename^);
+
+ { read objects }
+ readobj(FindObjectFile('prt0','',false));
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ readobj(s);
+ end;
+
+ { generate executable }
+ exeoutput.GenerateExecutable(current_module.exefilename^);
+
+ { close map }
+ if assigned(exemap) then
+ begin
+ exemap.free;
+ exemap:=nil;
+ end;
+
+ MakeExecutable:=true;
+end;
+
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+procedure InitLinker;
+var
+ lk : TlinkerClass;
+begin
+ if (cs_link_internal in aktglobalswitches) and
+ assigned(target_info.link) then
+ begin
+ lk:=TLinkerClass(target_info.link);
+ linker:=lk.Create;
+ end
+ else if assigned(target_info.linkextern) then
+ begin
+ lk:=TlinkerClass(target_info.linkextern);
+ linker:=lk.Create;
+ end
+ else
+ begin
+ linker:=Tlinker.Create;
+ end;
+end;
+
+
+procedure DoneLinker;
+begin
+ if assigned(linker) then
+ Linker.Free;
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ ar_gnu_ar_info : tarinfo =
+ (
+ id : ar_gnu_ar;
+ arcmd : 'ar rs $LIB $FILES'
+ );
+
+initialization
+ RegisterAr(ar_gnu_ar_info);
+
+end.
diff --git a/compiler/m68k/aasmcpu.pas b/compiler/m68k/aasmcpu.pas
new file mode 100644
index 0000000000..924b089d83
--- /dev/null
+++ b/compiler/m68k/aasmcpu.pas
@@ -0,0 +1,539 @@
+{
+ Copyright (c) 1998-2001 by Florian Klaempfl and Pierre Muller
+
+ m68k family assembler instructions
+
+ 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;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,aasmtai,
+ aasmbase,globals,verbose,symtype,
+ cpubase,cpuinfo,cgbase,cgutils;
+
+
+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)
+ opsize : topsize;
+ constructor op_none(op : tasmop);
+ constructor op_none(op : tasmop;_size : topsize);
+
+ constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
+ constructor op_ref(op : tasmop;_size : topsize;_op1 : treference);
+
+ constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
+ constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
+
+ constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+ constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
+ constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
+
+ constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
+ { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
+ constructor op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : treference);
+
+ constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
+ constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
+ constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference;_op3 : tregister);
+ constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : treference);
+ constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : treference);
+
+ constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2: tcpuregisterset);
+ constructor op_regset_reg(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: tregister);
+
+ constructor op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2: tcpuregisterset);
+ constructor op_regset_ref(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: 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);
+ { for DBxx opcodes }
+ constructor op_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
+ constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+
+ constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
+ constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+
+ function is_same_reg_move(regtype: Tregistertype):boolean;override;
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+
+ private
+ procedure loadregset(opidx:longint;const s:tcpuregisterset);
+ procedure init(_size : topsize); { this need to be called by all constructor }
+ end;
+
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+ function spilling_create_load(const ref:treference;r:tregister): tai;
+ function spilling_create_store(r:tregister; const ref:treference): tai;
+
+ implementation
+
+ uses
+ globtype;
+
+
+{*****************************************************************************
+ Taicpu Constructors
+*****************************************************************************}
+
+
+
+ procedure taicpu.loadregset(opidx:longint;const s:tcpuregisterset);
+ var
+ i : byte;
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_regset then
+ clearop(opidx);
+ new(regset);
+ regset^:=s;
+ typ:=top_regset;
+ for i:=RS_D0 to RS_D7 do
+ begin
+ if assigned(add_reg_instruction_hook) and (i in regset^) then
+ add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,R_SUBWHOLE));
+ end;
+ for i:=RS_A0 to RS_SP do
+ begin
+ if assigned(add_reg_instruction_hook) and (i in regset^) then
+ add_reg_instruction_hook(self,newreg(R_ADDRESSREGISTER,i,R_SUBWHOLE));
+ end;
+ end;
+ end;
+
+
+ procedure taicpu.init(_size : topsize);
+ begin
+ typ:=ait_instruction;
+ is_jmp:=false;
+ opsize:=_size;
+ ops:=0;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ init(S_NO);
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop;_size : topsize);
+ begin
+ inherited create(op);
+ init(_size);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadconst(0,aword(_op1));
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_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; _size: topsize; _op1: tregister; _op2: longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,aword(_op2));
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadconst(1,aword(_op2));
+ end;
+
+
+ constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_ref(op : tasmop;_size : topsize;_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;_size : topsize;_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_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,aword(_op1));
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;_op3 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_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 : longint;_op2 : tregister;_op3 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,aword(_op1));
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2: tcpuregisterset);
+ Begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadregset(1,_op2);
+ end;
+
+ constructor taicpu.op_regset_ref(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: treference);
+ Begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadregset(0,_op1);
+ loadref(1,_op2);
+ End;
+
+
+
+ constructor taicpu.op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2: tcpuregisterset);
+ Begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadregset(1,_op2);
+ end;
+
+
+ constructor taicpu.op_regset_reg(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: tregister);
+ Begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadregset(0,_op1);
+ loadreg(1,_op2);
+ 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_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadsymbol(1,_op2,0);
+ 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;
+
+
+ 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;
+ if ((op >= A_DBCC) and (op <= A_DBF))
+ or ((op >= A_FDBEQ) and (op <= A_FDBNGLE)) then
+ begin
+ loadreg(0,_op2);
+ loadsymbol(1,_op1,_op1ofs);
+ end
+ else
+ begin
+ loadsymbol(0,_op1,_op1ofs);
+ loadreg(1,_op2);
+ end;
+ 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;
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ result:=(((opcode=A_MOVE) or (opcode=A_EXG)) and
+ (regtype = R_INTREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ ) or
+ ((opcode=A_FMOVE) and
+ (regtype = R_FPUREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ );
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ case opcode of
+ A_MOVE, A_MOVEQ, A_ADD, A_ADDQ, A_SUB, A_SUBQ:
+ if opnr=0 then begin
+// writeln('move/etc write');
+ result:=operand_write;
+ end else begin
+// writeln('move/etc read');
+ result:=operand_read;
+ end;
+ else
+ writeln('other opcode: ',dword(opcode),' (faked value returned)',opnr);
+ result:=operand_write;
+ end;
+ // fake
+
+// internalerror(200404091);
+ end;
+
+ function spilling_create_load(const ref:treference;r:tregister): tai;
+ begin
+// writeln('spilling_create_load');
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_ref_reg(A_MOVE,S_L,ref,r);
+ R_FPUREGISTER : begin end;
+ end;
+{
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_ref_reg(A_LD,ref,r);
+ R_FPUREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFS :
+ result:=taicpu.op_ref_reg(A_LDF,ref,r);
+ R_SUBFD :
+ result:=taicpu.op_ref_reg(A_LDD,ref,r);
+ else
+ internalerror(200401042);
+ end;
+ end
+ else
+ internalerror(200401041);
+ end;
+ }
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference): tai;
+ begin
+// writeln('spilling_create_store');
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
+ R_FPUREGISTER :
+ begin
+// result:=taicpu.op_reg_ref(A_FMOVE,R_SUBFS,r,ref);
+ end;
+ end;
+ {case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_reg_ref(A_ST,r,ref);
+ R_FPUREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFS :
+ result:=taicpu.op_reg_ref(A_STF,r,ref);
+ R_SUBFD :
+ result:=taicpu.op_reg_ref(A_STD,r,ref);
+ else
+ internalerror(200401042);
+ end;
+ end
+ else
+ internalerror(200401041);
+ end;}
+ end;
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+end.
diff --git a/compiler/m68k/agcpugas.pas b/compiler/m68k/agcpugas.pas
new file mode 100644
index 0000000000..f6ab696ca3
--- /dev/null
+++ b/compiler/m68k/agcpugas.pas
@@ -0,0 +1,354 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for m68k GAS 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.
+
+ ****************************************************************************
+}
+{ This unit implements an asmoutput class for i386 AT&T syntax
+}
+unit agcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,cpubase,
+ globals,
+ aasmbase,aasmtai,aasmcpu,assemble,aggas;
+
+ type
+ TM68kAssembler=class(TGNUassembler)
+ public
+ procedure WriteInstruction(hp: tai);override;
+ end;
+
+ const
+ gas_op2str:op2strtable=
+ { warning: CPU32 opcodes are not fully compatible with the MC68020. }
+ { 68000 only opcodes }
+ ('abcd',
+ 'add','adda','addi','addq','addx','and','andi',
+ 'asl','asr','bcc','bcs','beq','bge','bgt','bhi',
+ 'ble','bls','blt','bmi','bne','bpl','bvc','bvs',
+ 'bchg','bclr','bra','bset','bsr','btst','chk',
+ 'clr','cmp','cmpa','cmpi','cmpm','dbcc','dbcs','dbeq','dbge',
+ 'dbgt','dbhi','dble','dbls','dblt','dbmi','dbne','dbra',
+ 'dbpl','dbt','dbvc','dbvs','dbf','divs','divu',
+ 'eor','eori','exg','illegal','ext','jmp','jsr',
+ 'lea','link','lsl','lsr','move','movea','movei','moveq',
+ 'movem','movep','muls','mulu','nbcd','neg','negx',
+ 'nop','not','or','ori','pea','rol','ror','roxl',
+ 'roxr','rtr','rts','sbcd','scc','scs','seq','sge',
+ 'sgt','shi','sle','sls','slt','smi','sne',
+ 'spl','st','svc','svs','sf','sub','suba','subi','subq',
+ 'subx','swap','tas','trap','trapv','tst','unlk',
+ 'rte','reset','stop',
+ { mc68010 instructions }
+ 'bkpt','movec','moves','rtd',
+ { mc68020 instructions }
+ 'bfchg','bfclr','bfexts','bfextu','bfffo',
+ 'bfins','bfset','bftst','callm','cas','cas2',
+ 'chk2','cmp2','divsl','divul','extb','pack','rtm',
+ 'trapcc','tracs','trapeq','trapf','trapge','trapgt',
+ 'traphi','traple','trapls','traplt','trapmi','trapne',
+ 'trappl','trapt','trapvc','trapvs','unpk',
+ { fpu processor instructions - directly supported only. }
+ { ieee aware and misc. condition codes not supported }
+ 'fabs','fadd',
+ 'fbeq','fbne','fbngt','fbgt','fbge','fbnge',
+ 'fblt','fbnlt','fble','fbgl','fbngl','fbgle','fbngle',
+ 'fdbeq','fdbne','fdbgt','fdbngt','fdbge','fdbnge',
+ 'fdblt','fdbnlt','fdble','fdbgl','fdbngl','fdbgle','fdbngle',
+ 'fseq','fsne','fsgt','fsngt','fsge','fsnge',
+ 'fslt','fsnlt','fsle','fsgl','fsngl','fsgle','fsngle',
+ 'fcmp','fdiv','fmove','fmovem',
+ 'fmul','fneg','fnop','fsqrt','fsub','fsgldiv',
+ 'fsflmul','ftst',
+ 'ftrapeq','ftrapne','ftrapgt','ftrapngt','ftrapge','ftrapnge',
+ 'ftraplt','ftrapnlt','ftraple','ftrapgl','ftrapngl','ftrapgle','ftrapngle',
+ { protected instructions }
+ 'cprestore','cpsave',
+ { fpu unit protected instructions }
+ { and 68030/68851 common mmu instructions }
+ { (this may include 68040 mmu instructions) }
+ 'frestore','fsave','pflush','pflusha','pload','pmove','ptest',
+ { useful for assembly language output }
+ 'label','none','db','s','b','fb');
+
+
+ gas_opsize2str : array[topsize] of string[2] =
+ ('','.b','.w','.l','.s','.d','.x',''
+ );
+{
+ gas_reg2str : treg2strtable =
+ ('', '%d0','%d1','%d2','%d3','%d4','%d5','%d6','%d7',
+ '%a0','%a1','%a2','%a3','%a4','%a5','%a6','%sp',
+ '-(%sp)','(%sp)+',
+ '%ccr','%fp0','%fp1','%fp2','%fp3','%fp4','%fp5',
+ '%fp6','%fp7','%fpcr','%sr','%ssp','%dfc',
+ '%sfc','%vbr','%fpsr');
+}
+
+ implementation
+
+ uses
+ cutils,systems,
+ cgbase,cgutils,
+ verbose,itcpugas;
+
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s,basestr,indexstr : string;
+
+ begin
+ s:='';
+ with ref do
+ begin
+ basestr:=gas_regname(base);
+ indexstr:=gas_regname(index);
+ if assigned(symbol) then
+ s:=s+symbol.name;
+
+ if offset<0 then s:=s+tostr(offset)
+ else if (offset>0) then
+ begin
+ if (symbol=nil) then s:=tostr(offset)
+ else s:=s+'+'+tostr(offset);
+ end
+ else if (index=NR_NO) and (base=NR_NO) and not assigned(symbol) then
+ s:=s+'0';
+
+ if (index<>NR_NO) and (base=NR_NO) and (direction=dir_none) then
+ begin
+ if (scalefactor = 1) or (scalefactor = 0) then
+ s:=s+'(,'+indexstr+'.l)'
+ else
+ s:=s+'(,'+indexstr+'.l*'+tostr(scalefactor)+')'
+ end
+ else if (index=NR_NO) and (base<>NR_NO) and (direction=dir_inc) then
+ begin
+ if (scalefactor = 1) or (scalefactor = 0) then
+ s:=s+'('+basestr+')+'
+ else
+ InternalError(10002);
+ end
+ else if (index=NR_NO) and (base<>NR_NO) and (direction=dir_dec) then
+ begin
+ if (scalefactor = 1) or (scalefactor = 0) then
+ s:=s+'-('+basestr+')'
+ else
+ InternalError(10003);
+ end
+ else if (index=NR_NO) and (base<>NR_NO) and (direction=dir_none) then
+ begin
+ s:=s+'('+basestr+')'
+ end
+ else if (index<>NR_NO) and (base<>NR_NO) and (direction=dir_none) then
+ begin
+ if (scalefactor = 1) or (scalefactor = 0) then
+ s:=s+'('+basestr+','+indexstr+'.l)'
+ else
+ s:=s+'('+basestr+','+indexstr+'.l*'+tostr(scalefactor)+')';
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ i : tsuperregister;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ if assigned(o.ref^.symbol) then
+ hs:='#'+o.ref^.symbol.name
+ else
+ hs:='#';
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset)
+ else
+ if not(assigned(o.ref^.symbol)) then
+ hs:=hs+'0';
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(o.ref^);
+ top_regset:
+ begin
+ hs:='';
+ for i:=RS_D0 to RS_D7 do
+ begin
+ if i in o.regset^ then
+ hs:=hs+gas_regname(newreg(R_INTREGISTER,i,R_SUBWHOLE))+'/';
+ end;
+ for i:=RS_A0 to RS_SP do
+ begin
+ if i in o.regset^ then
+ hs:=hs+gas_regname(newreg(R_INTREGISTER,i,R_SUBWHOLE))+'/';
+ end;
+ delete(hs,length(hs),1);
+ getopstr := hs;
+ end;
+ top_const:
+ getopstr:='#'+tostr(longint(o.val));
+ else internalerror(200405021);
+ end;
+ end;
+
+
+ function getopstr_jmp(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr_jmp:=gas_regname(o.reg);
+ top_ref:
+ if o.ref^.refaddr=addr_no then
+ getopstr_jmp:=getreferencestring(o.ref^)
+ else
+ begin
+ if assigned(o.ref^.symbol) then
+ hs:=o.ref^.symbol.name
+ else
+ hs:='';
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset)
+ else
+ if not(assigned(o.ref^.symbol)) then
+ hs:=hs+'0';
+ getopstr_jmp:=hs;
+ end;
+ top_const:
+ getopstr_jmp:=tostr(o.val);
+ else internalerror(200405022);
+ end;
+ end;
+
+{****************************************************************************
+ TM68kASMOUTPUT
+ ****************************************************************************}
+
+ { returns the opcode string }
+ function getopcodestring(hp : tai) : string;
+ var
+ op : tasmop;
+ s : string;
+ begin
+ op:=taicpu(hp).opcode;
+ { old versions of GAS don't like PEA.L and LEA.L }
+ if (op in [
+ A_LEA,A_PEA,A_ABCD,A_BCHG,A_BCLR,A_BSET,A_BTST,
+ A_EXG,A_NBCD,A_SBCD,A_SWAP,A_TAS,A_SCC,A_SCS,
+ A_SEQ,A_SGE,A_SGT,A_SHI,A_SLE,A_SLS,A_SLT,A_SMI,
+ A_SNE,A_SPL,A_ST,A_SVC,A_SVS,A_SF]) then
+ s:=gas_op2str[op]
+ else
+ if op = A_SXX then
+ s:=gas_op2str[op]+cond2str[taicpu(hp).condition]
+ else
+ if op in [a_dbxx,a_bxx,a_fbxx] then
+ s:=gas_op2str[op]+cond2str[taicpu(hp).condition]+gas_opsize2str[taicpu(hp).opsize]
+ else
+ s:=gas_op2str[op]+gas_opsize2str[taicpu(hp).opsize];
+ getopcodestring:=s;
+ end;
+
+
+ procedure TM68kAssembler.WriteInstruction(hp: tai);
+ var
+ op : tasmop;
+ s : string;
+ sep : char;
+ calljmp : boolean;
+ i : integer;
+ begin
+ if hp.typ <> ait_instruction then exit;
+ op:=taicpu(hp).opcode;
+ calljmp:=is_calljmp(op);
+ { call maybe not translated to call }
+ s:=#9+getopcodestring(hp);
+ { process operands }
+ if taicpu(hp).ops<>0 then
+ begin
+ { call and jmp need an extra handling }
+ { this code is only called if jmp isn't a labeled instruction }
+ { quick hack to overcome a problem with manglednames=255 chars }
+ if calljmp then
+ begin
+ AsmWrite(s+#9);
+ s:=getopstr_jmp(taicpu(hp).oper[0]^);
+ end
+ else
+ begin
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ if i=0 then
+ sep:=#9
+ else
+ if ((op = A_DIVSL) or
+ (op = A_DIVUL) or
+ (op = A_MULU) or
+ (op = A_MULS) or
+ (op = A_DIVS) or
+ (op = A_DIVU)) and (i=1) then
+ sep:=':'
+ else
+ sep:=',';
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^)
+ end;
+ end;
+ end;
+ AsmWriteLn(s);
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_m68k_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+initialization
+ RegisterAssembler(as_m68k_as_info,TM68kAssembler);
+end.
diff --git a/compiler/m68k/aoptcpu.pas b/compiler/m68k/aoptcpu.pas
new file mode 100644
index 0000000000..cb656af36e
--- /dev/null
+++ b/compiler/m68k/aoptcpu.pas
@@ -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.
diff --git a/compiler/m68k/aoptcpub.pas b/compiler/m68k/aoptcpub.pas
new file mode 100644
index 0000000000..bf1ab48cb8
--- /dev/null
+++ b/compiler/m68k/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the sparc 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_JMP;
+ aopt_condjmp = A_Bxx;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/compiler/m68k/aoptcpud.pas b/compiler/m68k/aoptcpud.pas
new file mode 100644
index 0000000000..cb8c5d319f
--- /dev/null
+++ b/compiler/m68k/aoptcpud.pas
@@ -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.
diff --git a/compiler/m68k/cgcpu.pas b/compiler/m68k/cgcpu.pas
new file mode 100644
index 0000000000..8142c3cb9e
--- /dev/null
+++ b/compiler/m68k/cgcpu.pas
@@ -0,0 +1,1321 @@
+{
+ Copyright (c) 1998-2002 by the FPC team
+
+ This unit implements the code generator for the 680x0
+
+ 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.
+
+ ****************************************************************************
+}
+{$WARNINGS OFF}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase,cgobj,globtype,
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,cpuinfo,
+ parabase,cpupara,
+ node,symconst,symtype,
+ cgutils,cg64f32;
+
+ type
+ tcg68k = class(tcg)
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+ procedure a_call_name(list : taasmoutput;const s : string);override;
+ procedure a_call_reg(list : taasmoutput;reg : tregister);override;
+ procedure a_load_const_reg(list : taasmoutput;size : tcgsize;a : aint;register : tregister);override;
+ procedure a_load_reg_ref(list : taasmoutput;fromsize,tosize : tcgsize;register : tregister;const ref : treference);override;
+ procedure a_load_reg_reg(list : taasmoutput;fromsize,tosize : tcgsize;reg1,reg2 : tregister);override;
+ procedure a_load_ref_reg(list : taasmoutput;fromsize,tosize : tcgsize;const ref : treference;register : tregister);override;
+ procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
+ procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
+ procedure a_loadmm_reg_reg(list: taasmoutput;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_ref_reg(list: taasmoutput;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_reg_ref(list: taasmoutput;fromsize,tosize : tcgsize; reg: tregister; const ref: treference;shuffle : pmmshuffle); override;
+ procedure a_parammm_reg(list: taasmoutput; size: tcgsize; reg: tregister;const locpara : TCGPara;shuffle : pmmshuffle); override;
+ procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: tcgsize; a: aint; reg: TRegister); override;
+ procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister); override;
+ procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+ procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
+ procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
+ procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister); override;
+
+ procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);override;
+ { generates overflow checking code for a node }
+ procedure g_overflowcheck(list: taasmoutput; const l:tlocation; def:tdef); override;
+ procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);override;
+
+ procedure g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);override;
+
+// procedure g_restore_frame_pointer(list : taasmoutput);override;
+// procedure g_return_from_proc(list : taasmoutput;parasize : aint);override;
+ procedure g_restore_standard_registers(list:Taasmoutput);override;
+ procedure g_save_standard_registers(list:Taasmoutput);override;
+
+// procedure g_save_all_registers(list : taasmoutput);override;
+// procedure g_restore_all_registers(list : taasmoutput;const funcretparaloc:TCGPara);override;
+ protected
+ function fixref(list: taasmoutput; var ref: treference): boolean;
+ private
+ { # Sign or zero extend the register to a full 32-bit value.
+ The new value is left in the same register.
+ }
+ procedure sign_extend(list: taasmoutput;_oldsize : tcgsize; reg: tregister);
+ procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
+
+ end;
+
+ tcg64f68k = class(tcg64f32)
+ procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG; size: tcgsize; regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : taasmoutput;op:TOpCG; size: tcgsize; value : int64;regdst : tregister64);override;
+ end;
+
+ { This function returns true if the reference+offset is valid.
+ Otherwise extra code must be generated to solve the reference.
+
+ On the m68k, this verifies that the reference is valid
+ (e.g : if index register is used, then the max displacement
+ is 256 bytes, if only base is used, then max displacement
+ is 32K
+ }
+ function isvalidrefoffset(const ref: treference): boolean;
+
+ const
+ TCGSize2OpSize: Array[tcgsize] of topsize =
+ (S_NO,S_B,S_W,S_L,S_L,S_NO,S_B,S_W,S_L,S_L,S_NO,
+ S_FS,S_FD,S_FX,S_NO,S_NO,
+ S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
+
+
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ symdef,symsym,defutil,paramgr,procinfo,
+ rgobj,tgobj,rgcpu;
+
+
+ const
+ { opcode table lookup }
+ topcg2tasmop: Array[topcg] of tasmop =
+ (
+ A_NONE,
+ A_ADD,
+ A_AND,
+ A_DIVU,
+ A_DIVS,
+ A_MULS,
+ A_MULU,
+ A_NEG,
+ A_NOT,
+ A_OR,
+ A_ASR,
+ A_LSL,
+ A_LSR,
+ A_SUB,
+ A_EOR
+ );
+
+
+ TOpCmp2AsmCond: Array[topcmp] of TAsmCond =
+ (
+ C_NONE,
+ C_EQ,
+ C_GT,
+ C_LT,
+ C_GE,
+ C_LE,
+ C_NE,
+ C_LS,
+ C_CS,
+ C_CC,
+ C_HI
+ );
+
+
+ function isvalidrefoffset(const ref: treference): boolean;
+ begin
+ isvalidrefoffset := true;
+ if ref.index <> NR_NO then
+ begin
+ if ref.base <> NR_NO then
+ internalerror(20020814);
+ if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
+ isvalidrefoffset := false
+ end
+ else
+ begin
+ if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
+ isvalidrefoffset := false;
+ end;
+ end;
+
+
+{****************************************************************************}
+{ TCG68K }
+{****************************************************************************}
+ procedure tcg68k.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_D0,RS_D1,RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7],
+ first_int_imreg,[]);
+ rg[R_ADDRESSREGISTER]:=trgcpu.create(R_ADDRESSREGISTER,R_SUBWHOLE,
+ [RS_A0,RS_A1,RS_A2,RS_A3,RS_A4,RS_A5,RS_A6],
+ first_addr_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_FP0,RS_FP1,RS_FP2,RS_FP3,RS_FP4,RS_FP5,RS_FP6,RS_FP7],
+ first_fpu_imreg,[]);
+ end;
+
+
+ procedure tcg68k.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_ADDRESSREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ function tcg68k.fixref(list: taasmoutput; var ref: treference): boolean;
+
+ begin
+ result:=false;
+ { The Coldfire and MC68020+ have extended
+ addressing capabilities with a 32-bit
+ displacement.
+ }
+ if (aktoptprocessor<>MC68000) then
+ exit;
+ if (ref.base<>NR_NO) then
+ begin
+ if (ref.index <> NR_NO) and assigned(ref.symbol) then
+ internalerror(20020814);
+ { base + reg }
+ if ref.index <> NR_NO then
+ begin
+ { base + reg + offset }
+ if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
+ begin
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,ref.base));
+ fixref := true;
+ ref.offset := 0;
+ exit;
+ end;
+ end
+ else
+ { base + offset }
+ if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
+ begin
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,ref.base));
+ fixref := true;
+ ref.offset := 0;
+ exit;
+ end;
+ end;
+ end;
+
+
+
+ procedure tcg68k.a_call_name(list : taasmoutput;const s : string);
+
+ begin
+ list.concat(taicpu.op_sym(A_JSR,S_NO,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
+ end;
+
+
+ procedure tcg68k.a_call_reg(list : taasmoutput;reg : tregister);
+ var
+ href : treference;
+ begin
+ reference_reset_base(href, reg, 0);
+ //!!! a_call_ref(list,href);
+ end;
+
+
+
+ procedure tcg68k.a_load_const_reg(list : taasmoutput;size : tcgsize;a : aint;register : tregister);
+ begin
+ if getregtype(register)=R_ADDRESSREGISTER then
+ begin
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
+ end
+ else
+ if a = 0 then
+ list.concat(taicpu.op_reg(A_CLR,S_L,register))
+ else
+ begin
+ if (longint(a) >= low(shortint)) and (longint(a) <= high(shortint)) then
+ list.concat(taicpu.op_const_reg(A_MOVEQ,S_L,longint(a),register))
+ else
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
+ end;
+ end;
+
+
+ procedure tcg68k.a_load_reg_ref(list : taasmoutput;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
+ var
+ href : treference;
+ begin
+ href := ref;
+ fixref(list,href);
+ { move to destination reference }
+ list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[fromsize],register,href));
+ end;
+
+
+ procedure tcg68k.a_load_reg_reg(list : taasmoutput;fromsize,tosize : tcgsize;reg1,reg2 : tregister);
+ begin
+ { move to destination register }
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2));
+ { zero/sign extend register to 32-bit }
+ sign_extend(list, fromsize, reg2);
+ end;
+
+
+ procedure tcg68k.a_load_ref_reg(list : taasmoutput;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
+ var
+ href : treference;
+ begin
+ href := ref;
+ fixref(list,href);
+ list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],href,register));
+ { extend the value in the register }
+ sign_extend(list, tosize, register);
+ end;
+
+
+ procedure tcg68k.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
+ var
+ href : treference;
+ begin
+ if getregtype(r)=R_ADDRESSREGISTER then
+ begin
+ internalerror(2002072901);
+ end;
+ href:=ref;
+ fixref(list, href);
+ list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,r));
+ end;
+
+
+ procedure tcg68k.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
+ begin
+ { in emulation mode, only 32-bit single is supported }
+ if cs_fp_emulation in aktmoduleswitches then
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2))
+ else
+ list.concat(taicpu.op_reg_reg(A_FMOVE,S_FD,reg1,reg2));
+ end;
+
+
+ procedure tcg68k.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
+ var
+ opsize : topsize;
+ href : treference;
+ begin
+ opsize := tcgsize2opsize[size];
+ { extended is not supported, since it is not available on Coldfire }
+ if opsize = S_FX then
+ internalerror(20020729);
+ href := ref;
+ fixref(list,href);
+ { in emulation mode, only 32-bit single is supported }
+ if cs_fp_emulation in aktmoduleswitches then
+ list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
+ else
+ list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
+ end;
+
+ procedure tcg68k.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
+ var
+ opsize : topsize;
+ begin
+ opsize := tcgsize2opsize[size];
+ { extended is not supported, since it is not available on Coldfire }
+ if opsize = S_FX then
+ internalerror(20020729);
+ { in emulation mode, only 32-bit single is supported }
+ if cs_fp_emulation in aktmoduleswitches then
+ list.concat(taicpu.op_reg_ref(A_MOVE,S_L,reg, ref))
+ else
+ list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
+ end;
+
+
+ procedure tcg68k.a_loadmm_reg_reg(list: taasmoutput;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle);
+ begin
+ internalerror(20020729);
+ end;
+
+
+ procedure tcg68k.a_loadmm_ref_reg(list: taasmoutput;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle);
+ begin
+ internalerror(20020729);
+ end;
+
+
+ procedure tcg68k.a_loadmm_reg_ref(list: taasmoutput;fromsize,tosize : tcgsize; reg: tregister; const ref: treference;shuffle : pmmshuffle);
+ begin
+ internalerror(20020729);
+ end;
+
+
+ procedure tcg68k.a_parammm_reg(list: taasmoutput; size: tcgsize; reg: tregister;const locpara : TCGPara;shuffle : pmmshuffle);
+ begin
+ internalerror(20020729);
+ end;
+
+
+ procedure tcg68k.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: tcgsize; a: aint; reg: TRegister);
+ var
+ scratch_reg : tregister;
+ scratch_reg2: tregister;
+ opcode : tasmop;
+ r,r2 : Tregister;
+ begin
+ { need to emit opcode? }
+ if optimize_op_const_reg(list, op, a, reg) then
+ exit;
+ opcode := topcg2tasmop[op];
+ case op of
+ OP_ADD :
+ Begin
+ if (a >= 1) and (a <= 8) then
+ list.concat(taicpu.op_const_reg(A_ADDQ,S_L,a, reg))
+ else
+ begin
+ { all others, including coldfire }
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,a, reg));
+ end;
+ end;
+ OP_AND,
+ OP_OR:
+ Begin
+ list.concat(taicpu.op_const_reg(topcg2tasmop[op],S_L,longint(a), reg));
+ end;
+ OP_DIV :
+ Begin
+ internalerror(20020816);
+ end;
+ OP_IDIV :
+ Begin
+ internalerror(20020816);
+ end;
+ OP_IMUL :
+ Begin
+ if aktoptprocessor = MC68000 then
+ begin
+ r:=NR_D0;
+ r2:=NR_D1;
+ cg.getcpuregister(list,NR_D0);
+ cg.getcpuregister(list,NR_D1);
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, r));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, r2));
+ cg.a_call_name(list,'FPC_MUL_LONGINT');
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg));
+ cg.ungetcpuregister(list,r);
+ cg.ungetcpuregister(list,r2);
+
+ end
+ else
+ begin
+ if (isaddressregister(reg)) then
+ begin
+ scratch_reg := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
+ list.concat(taicpu.op_const_reg(A_MULS,S_L,a,scratch_reg));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
+ cg.ungetcpuregister(list,scratch_reg);
+ end
+ else
+ list.concat(taicpu.op_const_reg(A_MULS,S_L,a,reg));
+ end;
+ end;
+ OP_MUL :
+ Begin
+ if aktoptprocessor = MC68000 then
+ begin
+ r:=NR_D0;
+ r2:=NR_D1;
+ cg.getcpuregister(list,NR_D0);
+ cg.getcpuregister(list,NR_D1);
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, r));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, r2));
+ cg.a_call_name(list,'FPC_MUL_LONGWORD');
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg));
+ cg.ungetcpuregister(list,r);
+ cg.ungetcpuregister(list,r2);
+ end
+ else
+ begin
+ if (isaddressregister(reg)) then
+ begin
+ scratch_reg := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
+ list.concat(taicpu.op_const_reg(A_MULU,S_L,a,scratch_reg));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
+ cg.ungetcpuregister(list,scratch_reg);
+ end
+ else
+ list.concat(taicpu.op_const_reg(A_MULU,S_L,a,reg));
+ end;
+ end;
+ OP_SAR,
+ OP_SHL,
+ OP_SHR :
+ Begin
+ if (a >= 1) and (a <= 8) then
+ begin
+ { now allowed to shift an address register }
+ if (isaddressregister(reg)) then
+ begin
+ scratch_reg := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
+ list.concat(taicpu.op_const_reg(opcode,S_L,a, scratch_reg));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
+ cg.ungetcpuregister(list,scratch_reg);
+ end
+ else
+ list.concat(taicpu.op_const_reg(opcode,S_L,a, reg));
+ end
+ else
+ begin
+ { we must load the data into a register ... :() }
+ scratch_reg := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, scratch_reg));
+ { again... since shifting with address register is not allowed }
+ if (isaddressregister(reg)) then
+ begin
+ scratch_reg2 := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg2));
+ list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, scratch_reg2));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg2,reg));
+ cg.ungetcpuregister(list,scratch_reg2);
+ end
+ else
+ list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, reg));
+ cg.ungetcpuregister(list,scratch_reg);
+ end;
+ end;
+ OP_SUB :
+ Begin
+ if (a >= 1) and (a <= 8) then
+ list.concat(taicpu.op_const_reg(A_SUBQ,S_L,a,reg))
+ else
+ begin
+ { all others, including coldfire }
+ list.concat(taicpu.op_const_reg(A_SUB,S_L,a, reg));
+ end;
+ end;
+ OP_XOR :
+ Begin
+ list.concat(taicpu.op_const_reg(A_EORI,S_L,a, reg));
+ end;
+ else
+ internalerror(20020729);
+ end;
+ end;
+
+
+ procedure tcg68k.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister);
+ var
+ hreg1,hreg2,r,r2: tregister;
+ begin
+ case op of
+ OP_ADD :
+ Begin
+ if aktoptprocessor = ColdFire then
+ begin
+ { operation only allowed only a longword }
+ sign_extend(list, size, reg1);
+ sign_extend(list, size, reg2);
+ list.concat(taicpu.op_reg_reg(A_ADD,S_L,reg1, reg2));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,TCGSize2OpSize[size],reg1, reg2));
+ end;
+ end;
+ OP_AND,OP_OR,
+ OP_SAR,OP_SHL,
+ OP_SHR,OP_SUB,OP_XOR :
+ Begin
+ { load to data registers }
+ if (isaddressregister(reg1)) then
+ begin
+ hreg1 := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
+ end
+ else
+ hreg1 := reg1;
+
+ if (isaddressregister(reg2)) then
+ begin
+ hreg2:= cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
+ end
+ else
+ hreg2 := reg2;
+
+ if aktoptprocessor = ColdFire then
+ begin
+ { operation only allowed only a longword }
+ {!***************************************
+ in the case of shifts, the value to
+ shift by, should already be valid, so
+ no need to sign extend the value
+ !
+ }
+ if op in [OP_AND,OP_OR,OP_SUB,OP_XOR] then
+ sign_extend(list, size, hreg1);
+ sign_extend(list, size, hreg2);
+ list.concat(taicpu.op_reg_reg(topcg2tasmop[op],S_L,hreg1, hreg2));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg1, hreg2));
+ end;
+
+ if reg1 <> hreg1 then
+ cg.ungetcpuregister(list,hreg1);
+ { move back result into destination register }
+ if reg2 <> hreg2 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
+ cg.ungetcpuregister(list,hreg2);
+ end;
+ end;
+ OP_DIV :
+ Begin
+ internalerror(20020816);
+ end;
+ OP_IDIV :
+ Begin
+ internalerror(20020816);
+ end;
+ OP_IMUL :
+ Begin
+ sign_extend(list, size,reg1);
+ sign_extend(list, size,reg2);
+ if aktoptprocessor = MC68000 then
+ begin
+ r:=NR_D0;
+ r2:=NR_D1;
+ cg.getcpuregister(list,NR_D0);
+ cg.getcpuregister(list,NR_D1);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, r));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, r2));
+ cg.a_call_name(list,'FPC_MUL_LONGINT');
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg2));
+ cg.ungetcpuregister(list,r);
+ cg.ungetcpuregister(list,r2);
+ end
+ else
+ begin
+ if (isaddressregister(reg1)) then
+ hreg1 := cg.getintregister(list,OS_INT)
+ else
+ hreg1 := reg1;
+ if (isaddressregister(reg2)) then
+ hreg2:= cg.getintregister(list,OS_INT)
+ else
+ hreg2 := reg2;
+
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
+
+ list.concat(taicpu.op_reg_reg(A_MULS,S_L,reg1,reg2));
+
+ if reg1 <> hreg1 then
+ cg.ungetcpuregister(list,hreg1);
+ { move back result into destination register }
+ if reg2 <> hreg2 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
+ cg.ungetcpuregister(list,hreg2);
+ end;
+ end;
+ end;
+ OP_MUL :
+ Begin
+ sign_extend(list, size,reg1);
+ sign_extend(list, size,reg2);
+ if aktoptprocessor = MC68000 then
+ begin
+ r:=NR_D0;
+ r2:=NR_D1;
+ cg.getcpuregister(list,NR_D0);
+ cg.getcpuregister(list,NR_D1);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, r));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, r2));
+ cg.a_call_name(list,'FPC_MUL_LONGWORD');
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg2));
+ cg.ungetcpuregister(list,r);
+ cg.ungetcpuregister(list,r2);
+ end
+ else
+ begin
+ if (isaddressregister(reg1)) then
+ begin
+ hreg1 := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
+ end
+ else
+ hreg1 := reg1;
+
+ if (isaddressregister(reg2)) then
+ begin
+ hreg2:= cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
+ end
+ else
+ hreg2 := reg2;
+
+
+ list.concat(taicpu.op_reg_reg(A_MULU,S_L,reg1,reg2));
+
+ if reg1<>hreg1 then
+ cg.ungetcpuregister(list,hreg1);
+ { move back result into destination register }
+ if reg2<>hreg2 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
+ cg.ungetcpuregister(list,hreg2);
+ end;
+ end;
+ end;
+ OP_NEG,
+ OP_NOT :
+ Begin
+ { if there are two operands, move the register,
+ since the operation will only be done on the result
+ register.
+ }
+ if reg1 <> NR_NO then
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,reg1,reg2);
+
+ if (isaddressregister(reg2)) then
+ begin
+ hreg2 := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
+ end
+ else
+ hreg2 := reg2;
+
+ { coldfire only supports long version }
+ if aktoptprocessor = ColdFire then
+ begin
+ sign_extend(list, size,hreg2);
+ list.concat(taicpu.op_reg(topcg2tasmop[op],S_L,hreg2));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg2));
+ end;
+
+ if reg2 <> hreg2 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
+ cg.ungetcpuregister(list,hreg2);
+ end;
+
+ end;
+ else
+ internalerror(20020729);
+ end;
+ end;
+
+
+
+ procedure tcg68k.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);
+ var
+ hregister : tregister;
+ begin
+ if a = 0 then
+ begin
+ list.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[size],reg));
+ end
+ else
+ begin
+ if (aktoptprocessor = ColdFire) then
+ begin
+ {
+ only longword comparison is supported,
+ and only on data registers.
+ }
+ hregister := cg.getintregister(list,OS_INT);
+ { always move to a data register }
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg,hregister));
+ { sign/zero extend the register }
+ sign_extend(list, size,hregister);
+ list.concat(taicpu.op_const_reg(A_CMPI,S_L,a,hregister));
+ cg.ungetcpuregister(list,hregister);
+ end
+ else
+ begin
+ list.concat(taicpu.op_const_reg(A_CMPI,TCGSize2OpSize[size],a,reg));
+ end;
+ end;
+ { emit the actual jump to the label }
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+ procedure tcg68k.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+ begin
+ list.concat(taicpu.op_reg_reg(A_CMP,tcgsize2opsize[size],reg1,reg2));
+ { emit the actual jump to the label }
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+ procedure tcg68k.a_jmp_always(list : taasmoutput;l: tasmlabel);
+ var
+ ai: taicpu;
+ begin
+ ai := Taicpu.op_sym(A_JMP,S_NO,l);
+ ai.is_jmp := true;
+ list.concat(ai);
+ end;
+
+ procedure tcg68k.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai := Taicpu.op_sym(A_BXX,S_NO,l);
+ ai.SetCondition(flags_to_cond(f));
+ ai.is_jmp := true;
+ list.concat(ai);
+ end;
+
+ procedure tcg68k.g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister);
+ var
+ ai : taicpu;
+ hreg : tregister;
+ begin
+ { move to a Dx register? }
+ if (isaddressregister(reg)) then
+ begin
+ hreg := getintregister(list,OS_INT);
+ a_load_const_reg(list,size,0,hreg);
+ ai:=Taicpu.Op_reg(A_Sxx,S_B,hreg);
+ ai.SetCondition(flags_to_cond(f));
+ list.concat(ai);
+
+ if (aktoptprocessor = ColdFire) then
+ begin
+ { neg.b does not exist on the Coldfire
+ so we need to sign extend the value
+ before doing a neg.l
+ }
+ list.concat(taicpu.op_reg(A_EXTB,S_L,hreg));
+ list.concat(taicpu.op_reg(A_NEG,S_L,hreg));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg(A_NEG,S_B,hreg));
+ end;
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg,reg));
+ cg.ungetcpuregister(list,hreg);
+ end
+ else
+ begin
+ a_load_const_reg(list,size,0,reg);
+ ai:=Taicpu.Op_reg(A_Sxx,S_B,reg);
+ ai.SetCondition(flags_to_cond(f));
+ list.concat(ai);
+
+ if (aktoptprocessor = ColdFire) then
+ begin
+ { neg.b does not exist on the Coldfire
+ so we need to sign extend the value
+ before doing a neg.l
+ }
+ list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
+ list.concat(taicpu.op_reg(A_NEG,S_L,reg));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg(A_NEG,S_B,reg));
+ end;
+ end;
+ end;
+
+
+
+ procedure tcg68k.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);
+
+ var
+ helpsize : longint;
+ i : byte;
+ reg8,reg32 : tregister;
+ swap : boolean;
+ hregister : tregister;
+ iregister : tregister;
+ jregister : tregister;
+ hp1 : treference;
+ hp2 : treference;
+ hl : tasmlabel;
+ hl2: tasmlabel;
+ popaddress : boolean;
+ srcref,dstref : treference;
+
+ begin
+ popaddress := false;
+
+// writeln('concatcopy:',len);
+
+ { this should never occur }
+ if len > 65535 then
+ internalerror(0);
+
+ hregister := getintregister(list,OS_INT);
+// if delsource then
+// reference_release(list,source);
+
+ { from 12 bytes movs is being used }
+ if {(not loadref) and} ((len<=8) or (not(cs_littlesize in aktglobalswitches) and (len<=12))) then
+ begin
+ srcref := source;
+ dstref := dest;
+ helpsize:=len div 4;
+ { move a dword x times }
+ for i:=1 to helpsize do
+ begin
+ a_load_ref_reg(list,OS_INT,OS_INT,srcref,hregister);
+ a_load_reg_ref(list,OS_INT,OS_INT,hregister,dstref);
+ inc(srcref.offset,4);
+ inc(dstref.offset,4);
+ dec(len,4);
+ end;
+ { move a word }
+ if len>1 then
+ begin
+ a_load_ref_reg(list,OS_16,OS_16,srcref,hregister);
+ a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
+ inc(srcref.offset,2);
+ inc(dstref.offset,2);
+ dec(len,2);
+ end;
+ { move a single byte }
+ if len>0 then
+ begin
+ a_load_ref_reg(list,OS_8,OS_8,srcref,hregister);
+ a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
+ end
+ end
+ else
+ begin
+ iregister:=getaddressregister(list);
+ jregister:=getaddressregister(list);
+ { reference for move (An)+,(An)+ }
+ reference_reset(hp1);
+ hp1.base := iregister; { source register }
+ hp1.direction := dir_inc;
+ reference_reset(hp2);
+ hp2.base := jregister;
+ hp2.direction := dir_inc;
+ { iregister = source }
+ { jregister = destination }
+
+{ if loadref then
+ cg.a_load_ref_reg(list,OS_INT,OS_INT,source,iregister)
+ else}
+ a_loadaddr_ref_reg(list,source,iregister);
+
+ a_loadaddr_ref_reg(list,dest,jregister);
+
+ { double word move only on 68020+ machines }
+ { because of possible alignment problems }
+ { use fast loop mode }
+ if (aktoptprocessor=MC68020) then
+ begin
+ helpsize := len - len mod 4;
+ len := len mod 4;
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize div 4,hregister));
+ objectlibrary.getjumplabel(hl2);
+ a_jmp_always(list,hl2);
+ objectlibrary.getjumplabel(hl);
+ a_label(list,hl);
+ list.concat(taicpu.op_ref_ref(A_MOVE,S_L,hp1,hp2));
+ a_label(list,hl2);
+ list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
+ if len > 1 then
+ begin
+ dec(len,2);
+ list.concat(taicpu.op_ref_ref(A_MOVE,S_W,hp1,hp2));
+ end;
+ if len = 1 then
+ list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
+ end
+ else
+ begin
+ { Fast 68010 loop mode with no possible alignment problems }
+ helpsize := len;
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize,hregister));
+ objectlibrary.getjumplabel(hl2);
+ a_jmp_always(list,hl2);
+ objectlibrary.getjumplabel(hl);
+ a_label(list,hl);
+ list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
+ a_label(list,hl2);
+ list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
+ end;
+
+ { restore the registers that we have just used olny if they are used! }
+ ungetcpuregister(list, iregister);
+ ungetcpuregister(list, jregister);
+ if jregister = NR_A1 then
+ hp2.base := NR_NO;
+ if iregister = NR_A0 then
+ hp1.base := NR_NO;
+// reference_release(list,hp1);
+// reference_release(list,hp2);
+ end;
+
+// if delsource then
+// tg.ungetiftemp(list,source);
+
+// Not needed? (KB)
+// ungetcpuregister(list,hregister);
+ end;
+
+ procedure tcg68k.g_overflowcheck(list: taasmoutput; const l:tlocation; def:tdef);
+ begin
+ end;
+
+ procedure tcg68k.g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);
+ begin
+ end;
+
+
+ procedure tcg68k.g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);
+ var
+ r,rsp:Tregister;
+ ref : treference;
+ begin
+ r:=NR_FRAME_POINTER_REG;
+ rsp:=NR_STACK_POINTER_REG;
+ if localsize<>0 then
+ begin
+ { Not to complicate the code generator too much, and since some }
+ { of the systems only support this format, the localsize cannot }
+ { exceed 32K in size. }
+ if (localsize < low(smallint)) or (localsize > high(smallint)) then
+ CGMessage(cg_e_localsize_too_big);
+ list.concat(taicpu.op_reg_const(A_LINK,S_W,r,-localsize));
+ end { endif localsize <> 0 }
+ else
+ begin
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_dec;
+ list.concat(taicpu.op_reg_ref(A_MOVE,S_L,r,ref));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,rsp,r));
+ end;
+ end;
+
+
+{ procedure tcg68k.g_restore_frame_pointer(list : taasmoutput);
+ var
+ r:Tregister;
+ begin
+ r:=NR_FRAME_POINTER_REG;
+ list.concat(taicpu.op_reg(A_UNLK,S_NO,r));
+ end;
+}
+
+ procedure tcg68k.g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);
+ var
+ r,hregister : tregister;
+ ref : treference;
+ begin
+ { Routines with the poclearstack flag set use only a ret.
+ also routines with parasize=0 }
+ if current_procinfo.procdef.proccalloption in clearstack_pocalls then
+ begin
+ { complex return values are removed from stack in C code PM }
+ if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption) then
+ list.concat(taicpu.op_const(A_RTD,S_NO,4))
+ else
+ list.concat(taicpu.op_none(A_RTS,S_NO));
+ end
+ else if (parasize=0) then
+ begin
+ list.concat(taicpu.op_none(A_RTS,S_NO));
+ end
+ else
+ begin
+ { return with immediate size possible here
+ signed!
+ RTD is not supported on the coldfire }
+ if (aktoptprocessor=MC68020) and (parasize<$7FFF) then
+ list.concat(taicpu.op_const(A_RTD,S_NO,parasize))
+ { manually restore the stack }
+ else
+ begin
+ { We must pull the PC Counter from the stack, before }
+ { restoring the stack pointer, otherwise the PC would }
+ { point to nowhere! }
+
+ { save the PC counter (pop it from the stack) }
+ hregister:=NR_A3;
+ cg.a_reg_alloc(list,hregister);
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_inc;
+ list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister));
+ { can we do a quick addition ... }
+ r:=NR_SP;
+ if (parasize > 0) and (parasize < 9) then
+ list.concat(taicpu.op_const_reg(A_ADDQ,S_L,parasize,r))
+ else { nope ... }
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,parasize,r));
+
+ { restore the PC counter (push it on the stack) }
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_dec;
+ cg.a_reg_alloc(list,hregister);
+ list.concat(taicpu.op_reg_ref(A_MOVE,S_L,hregister,ref));
+ list.concat(taicpu.op_none(A_RTS,S_NO));
+ end;
+ end;
+ end;
+
+
+ procedure Tcg68k.g_save_standard_registers(list:Taasmoutput);
+ var
+ tosave : tcpuregisterset;
+ ref : treference;
+ begin
+ {!!!!!
+ tosave:=std_saved_registers;
+ { only save the registers which are not used and must be saved }
+ tosave:=tosave*(rg[R_INTREGISTER].used_in_proc+rg[R_ADDRESSREGISTER].used_in_proc);
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_dec;
+ if tosave<>[] then
+ list.concat(taicpu.op_regset_ref(A_MOVEM,S_L,tosave,ref));
+ }
+ end;
+
+
+ procedure Tcg68k.g_restore_standard_registers(list:Taasmoutput);
+ var
+ torestore : tcpuregisterset;
+ r:Tregister;
+ ref : treference;
+ begin
+ {!!!!!!!!
+ torestore:=std_saved_registers;
+ { should be intersected with used regs, no ? }
+ torestore:=torestore*(rg[R_INTREGISTER].used_in_proc+rg[R_ADDRESSREGISTER].used_in_proc);
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_inc;
+ if torestore<>[] then
+ list.concat(taicpu.op_ref_regset(A_MOVEM,S_L,ref,torestore));
+ }
+ end;
+
+{
+ procedure tcg68k.g_save_all_registers(list : taasmoutput);
+ begin
+ end;
+
+ procedure tcg68k.g_restore_all_registers(list : taasmoutput;const funcretparaloc:TCGPara);
+ begin
+ end;
+}
+ procedure tcg68k.sign_extend(list: taasmoutput;_oldsize : tcgsize; reg: tregister);
+ begin
+ case _oldsize of
+ { sign extend }
+ OS_S8:
+ begin
+ if (isaddressregister(reg)) then
+ internalerror(20020729);
+ if (aktoptprocessor = MC68000) then
+ begin
+ list.concat(taicpu.op_reg(A_EXT,S_W,reg));
+ list.concat(taicpu.op_reg(A_EXT,S_L,reg));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
+ end;
+ end;
+ OS_S16:
+ begin
+ if (isaddressregister(reg)) then
+ internalerror(20020729);
+ list.concat(taicpu.op_reg(A_EXT,S_L,reg));
+ end;
+ { zero extend }
+ OS_8:
+ begin
+ list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg));
+ end;
+ OS_16:
+ begin
+ list.concat(taicpu.op_const_reg(A_AND,S_L,$FFFF,reg));
+ end;
+ end; { otherwise the size is already correct }
+ end;
+
+ procedure tcg68k.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
+
+ var
+ ai : taicpu;
+
+ begin
+ if cond=OC_None then
+ ai := Taicpu.Op_sym(A_JMP,S_NO,l)
+ else
+ begin
+ ai:=Taicpu.Op_sym(A_Bxx,S_NO,l);
+ ai.SetCondition(TOpCmp2AsmCond[cond]);
+ end;
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+{****************************************************************************}
+{ TCG64F68K }
+{****************************************************************************}
+ procedure tcg64f68k.a_op64_reg_reg(list : taasmoutput;op:TOpCG;size: tcgsize; regsrc,regdst : tregister64);
+ var
+ hreg1, hreg2 : tregister;
+ opcode : tasmop;
+ begin
+ opcode := topcg2tasmop[op];
+ case op of
+ OP_ADD :
+ begin
+ { if one of these three registers is an address
+ register, we'll really get into problems!
+ }
+ if isaddressregister(regdst.reglo) or
+ isaddressregister(regdst.reghi) or
+ isaddressregister(regsrc.reghi) then
+ internalerror(20020817);
+ list.concat(taicpu.op_reg_reg(A_ADD,S_L,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(A_ADDX,S_L,regsrc.reghi,regdst.reghi));
+ end;
+ OP_AND,OP_OR :
+ begin
+ { at least one of the registers must be a data register }
+ if (isaddressregister(regdst.reglo) and
+ isaddressregister(regsrc.reglo)) or
+ (isaddressregister(regsrc.reghi) and
+ isaddressregister(regdst.reghi))
+ then
+ internalerror(20020817);
+ cg.a_op_reg_reg(list,op,OS_32,regsrc.reglo,regdst.reglo);
+ cg.a_op_reg_reg(list,op,OS_32,regsrc.reghi,regdst.reghi);
+ end;
+ { this is handled in 1st pass for 32-bit cpu's (helper call) }
+ OP_IDIV,OP_DIV,
+ OP_IMUL,OP_MUL: internalerror(2002081701);
+ { this is also handled in 1st pass for 32-bit cpu's (helper call) }
+ OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
+ OP_SUB:
+ begin
+ { if one of these three registers is an address
+ register, we'll really get into problems!
+ }
+ if isaddressregister(regdst.reglo) or
+ isaddressregister(regdst.reghi) or
+ isaddressregister(regsrc.reghi) then
+ internalerror(20020817);
+ list.concat(taicpu.op_reg_reg(A_SUB,S_L,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(A_SUBX,S_L,regsrc.reghi,regdst.reghi));
+ end;
+ OP_XOR:
+ begin
+ if isaddressregister(regdst.reglo) or
+ isaddressregister(regsrc.reglo) or
+ isaddressregister(regsrc.reghi) or
+ isaddressregister(regdst.reghi) then
+ internalerror(20020817);
+ list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reghi,regdst.reghi));
+ end;
+ end; { end case }
+ end;
+
+
+ procedure tcg64f68k.a_op64_const_reg(list : taasmoutput;op:TOpCG;size: tcgsize; value : int64;regdst : tregister64);
+ var
+ lowvalue : cardinal;
+ highvalue : cardinal;
+ begin
+ { is it optimized out ? }
+// if cg.optimize64_op_const_reg(list,op,value,reg) then
+// exit;
+
+ lowvalue := cardinal(value);
+ highvalue:= value shr 32;
+
+ { the destination registers must be data registers }
+ if isaddressregister(regdst.reglo) or
+ isaddressregister(regdst.reghi) then
+ internalerror(20020817);
+ case op of
+ OP_ADD :
+ begin
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,lowvalue,regdst.reglo));
+ list.concat(taicpu.op_const_reg(A_ADDX,S_L,highvalue,regdst.reglo));
+ end;
+ OP_AND :
+ begin
+ { should already be optimized out }
+ internalerror(2002081801);
+ end;
+ OP_OR :
+ begin
+ { should already be optimized out }
+ internalerror(2002081802);
+ end;
+ { this is handled in 1st pass for 32-bit cpu's (helper call) }
+ OP_IDIV,OP_DIV,
+ OP_IMUL,OP_MUL: internalerror(2002081701);
+ { this is also handled in 1st pass for 32-bit cpu's (helper call) }
+ OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
+ OP_SUB:
+ begin
+ list.concat(taicpu.op_const_reg(A_SUB,S_L,lowvalue,regdst.reglo));
+ list.concat(taicpu.op_const_reg(A_SUBX,S_L,highvalue,regdst.reglo));
+ end;
+ OP_XOR:
+ begin
+ list.concat(taicpu.op_const_reg(A_EOR,S_L,lowvalue,regdst.reglo));
+ list.concat(taicpu.op_const_reg(A_EOR,S_L,highvalue,regdst.reglo));
+ end;
+ end; { end case }
+ end;
+
+begin
+ cg := tcg68k.create;
+ cg64 :=tcg64f68k.create;
+end.
diff --git a/compiler/m68k/cpuasm.pas b/compiler/m68k/cpuasm.pas
new file mode 100644
index 0000000000..b19eb527df
--- /dev/null
+++ b/compiler/m68k/cpuasm.pas
@@ -0,0 +1,26 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ 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 cpuasm;
+
+ interface
+
+ implementation
+
+end.
diff --git a/compiler/m68k/cpubase.pas b/compiler/m68k/cpubase.pas
new file mode 100644
index 0000000000..c378fdb086
--- /dev/null
+++ b/compiler/m68k/cpubase.pas
@@ -0,0 +1,464 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the m68k
+
+ 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 contains the base types for the m68k
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ strings,cutils,cclasses,aasmbase,cpuinfo,cgbase;
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ { warning: CPU32 opcodes are not fully compatible with the MC68020. }
+ { 68000 only opcodes }
+ tasmop = (a_abcd,
+ a_add,a_adda,a_addi,a_addq,a_addx,a_and,a_andi,
+ a_asl,a_asr,a_bcc,a_bcs,a_beq,a_bge,a_bgt,a_bhi,
+ a_ble,a_bls,a_blt,a_bmi,a_bne,a_bpl,a_bvc,a_bvs,
+ a_bchg,a_bclr,a_bra,a_bset,a_bsr,a_btst,a_chk,
+ a_clr,a_cmp,a_cmpa,a_cmpi,a_cmpm,a_dbcc,a_dbcs,a_dbeq,a_dbge,
+ a_dbgt,a_dbhi,a_dble,a_dbls,a_dblt,a_dbmi,a_dbne,a_dbra,
+ a_dbpl,a_dbt,a_dbvc,a_dbvs,a_dbf,a_divs,a_divu,
+ a_eor,a_eori,a_exg,a_illegal,a_ext,a_jmp,a_jsr,
+ a_lea,a_link,a_lsl,a_lsr,a_move,a_movea,a_movei,a_moveq,
+ a_movem,a_movep,a_muls,a_mulu,a_nbcd,a_neg,a_negx,
+ a_nop,a_not,a_or,a_ori,a_pea,a_rol,a_ror,a_roxl,
+ a_roxr,a_rtr,a_rts,a_sbcd,a_scc,a_scs,a_seq,a_sge,
+ a_sgt,a_shi,a_sle,a_sls,a_slt,a_smi,a_sne,
+ a_spl,a_st,a_svc,a_svs,a_sf,a_sub,a_suba,a_subi,a_subq,
+ a_subx,a_swap,a_tas,a_trap,a_trapv,a_tst,a_unlk,
+ a_rte,a_reset,a_stop,
+ { mc68010 instructions }
+ a_bkpt,a_movec,a_moves,a_rtd,
+ { mc68020 instructions }
+ a_bfchg,a_bfclr,a_bfexts,a_bfextu,a_bfffo,
+ a_bfins,a_bfset,a_bftst,a_callm,a_cas,a_cas2,
+ a_chk2,a_cmp2,a_divsl,a_divul,a_extb,a_pack,a_rtm,
+ a_trapcc,a_tracs,a_trapeq,a_trapf,a_trapge,a_trapgt,
+ a_traphi,a_traple,a_trapls,a_traplt,a_trapmi,a_trapne,
+ a_trappl,a_trapt,a_trapvc,a_trapvs,a_unpk,
+ { fpu processor instructions - directly supported only. }
+ { ieee aware and misc. condition codes not supported }
+ a_fabs,a_fadd,
+ a_fbeq,a_fbne,a_fbngt,a_fbgt,a_fbge,a_fbnge,
+ a_fblt,a_fbnlt,a_fble,a_fbgl,a_fbngl,a_fbgle,a_fbngle,
+ a_fdbeq,a_fdbne,a_fdbgt,a_fdbngt,a_fdbge,a_fdbnge,
+ a_fdblt,a_fdbnlt,a_fdble,a_fdbgl,a_fdbngl,a_fdbgle,a_fdbngle,
+ a_fseq,a_fsne,a_fsgt,a_fsngt,a_fsge,a_fsnge,
+ a_fslt,a_fsnlt,a_fsle,a_fsgl,a_fsngl,a_fsgle,a_fsngle,
+ a_fcmp,a_fdiv,a_fmove,a_fmovem,
+ a_fmul,a_fneg,a_fnop,a_fsqrt,a_fsub,a_fsgldiv,
+ a_fsflmul,a_ftst,
+ a_ftrapeq,a_ftrapne,a_ftrapgt,a_ftrapngt,a_ftrapge,a_ftrapnge,
+ a_ftraplt,a_ftrapnlt,a_ftraple,a_ftrapgl,a_ftrapngl,a_ftrapgle,a_ftrapngle,
+ { protected instructions }
+ a_cprestore,a_cpsave,
+ { fpu unit protected instructions }
+ { and 68030/68851 common mmu instructions }
+ { (this may include 68040 mmu instructions) }
+ a_frestore,a_fsave,a_pflush,a_pflusha,a_pload,a_pmove,a_ptest,
+ { useful for assembly language output }
+ a_label,a_none,a_dbxx,a_sxx,a_bxx,a_fbxx);
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i r68knor.inc}-1;
+
+ const
+ { Available Superregisters }
+ {$i r68ksup.inc}
+
+ { ? whatever... }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+ {$i r68kcon.inc}
+
+ { Integer Super registers first and last }
+ first_int_imreg = RS_D7+1;
+
+ { Float Super register first and last }
+ first_fpu_imreg = RS_FP7+1;
+
+ { Integer Super registers first and last }
+ first_addr_imreg = RS_SP+1;
+
+ { MM Super register first and last }
+ first_mm_supreg = 0;
+ first_mm_imreg = 0;
+
+{$WARNING TODO FIX BSSTART}
+ regnumber_count_bsstart = 16;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i r68knum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i r68ksta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+{$warning TODO reused stabs values!}
+ {$i r68ksta.inc}
+ );
+
+ { registers which may be destroyed by calls }
+ VOLATILE_INTREGISTERS = [];
+ VOLATILE_FPUREGISTERS = [];
+
+ type
+ totherregisterset = set of tregisterindex;
+
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_CC,C_LS,C_CS,C_LT,C_EQ,C_MI,C_F,C_NE,
+ C_GE,C_PL,C_GT,C_T,C_HI,C_VC,C_LE,C_VS
+ );
+
+
+ const
+ cond2str:array[TAsmCond] of string[3]=('',
+ 'cc','ls','cs','lt','eq','mi','f','ne',
+ 'ge','pl','gt','t','hi','vc','le','vs'
+ );
+
+ inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
+{$warning TODO, this is just a copy!}
+ C_CC,C_LS,C_CS,C_LT,C_EQ,C_MI,C_F,C_NE,
+ C_GE,C_PL,C_GT,C_T,C_HI,C_VC,C_LE,C_VS
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (
+ F_E,F_NE,
+ F_G,F_L,F_GE,F_LE,F_C,F_NC,F_A,F_AE,F_B,F_BE);
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+ type
+ { direction of address register : }
+ { (An) (An)+ -(An) }
+ tdirection = (dir_none,dir_inc,dir_dec);
+
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ { S_NO = No Size of operand }
+ { S_B = 8-bit size operand }
+ { S_W = 16-bit size operand }
+ { S_L = 32-bit size operand }
+ { Floating point types }
+ { S_FS = single type (32 bit) }
+ { S_FD = double/64bit integer }
+ { S_FX = Extended type }
+ topsize = (S_NO,S_B,S_W,S_L,S_FS,S_FD,S_FX,S_IQ);
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ {# maximum number of operands in assembler instruction }
+ max_operands = 4;
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from m68kelf.h (DBX_REGISTER_NUMBER)
+ from GCC 3.x source code.
+
+ This is not compatible with the m68k-sun
+ implementation.
+ }
+ stab_regindex : array[tregisterindex] of shortint =
+ (
+ {$i r68ksta.inc}
+ );
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_SP;
+ RS_STACK_POINTER_REG = RS_SP;
+ {# Frame pointer register }
+{$warning FIX ME!!! frame pointer is A5 on Amiga, but A6 on unixes?}
+ NR_FRAME_POINTER_REG = NR_A5;
+ RS_FRAME_POINTER_REG = RS_A5;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+{$warning FIX ME!!! pic offset reg conflicts with frame pointer?}
+ NR_PIC_OFFSET_REG = NR_A5;
+ { Return address for DWARF }
+{$warning TODO just a guess!}
+ NR_RETURN_ADDRESS_REG = NR_A0;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_D0;
+ RS_FUNCTION_RETURN_REG = RS_D0;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_D0;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_D0;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_D1;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_D1;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ {# Floating point results will be placed into this register }
+ NR_FPU_RESULT_REG = NR_FP0;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..5] of tsuperregister = (RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7);
+ saved_standard_address_registers : array[0..3] of tsuperregister = (RS_A2,RS_A3,RS_A4,RS_A5);
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+
+ procedure inverse_flags(var r : TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ function reg_cgsize(const reg: tregister): tcgsize;
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ function isaddressregister(reg : tregister) : boolean;
+
+implementation
+
+ uses
+ verbose,
+ rgbase;
+
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i r68kstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i r68krni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r68ksri.inc}
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ is_calljmp := false;
+ if o in [A_BXX,A_FBXX,A_DBXX,A_BCC..A_BVS,A_DBCC..A_DBVS,A_FBEQ..A_FSNGLE,
+ A_JSR,A_BSR,A_JMP] then
+ is_calljmp := true;
+ end;
+
+
+ procedure inverse_flags(var r: TResFlags);
+ const flagsinvers : array[F_E..F_BE] of tresflags =
+ (F_NE,F_E,
+ F_LE,F_GE,
+ F_L,F_G,
+ F_NC,F_C,
+ F_BE,F_B,
+ F_AE,F_A);
+ begin
+ r:=flagsinvers[r];
+ end;
+
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const flags2cond: array[tresflags] of tasmcond = (
+ C_EQ,{F_E equal}
+ C_NE,{F_NE not equal}
+ C_GT,{F_G gt signed}
+ C_LT,{F_L lt signed}
+ C_GE,{F_GE ge signed}
+ C_LE,{F_LE le signed}
+ C_CS,{F_C carry set}
+ C_CC,{F_NC carry clear}
+ C_HI,{F_A gt unsigned}
+ C_CC,{F_AE ge unsigned}
+ C_CS,{F_B lt unsigned}
+ C_LS);{F_BE le unsigned}
+ begin
+ flags_to_cond := flags2cond[f];
+ end;
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ begin
+ case s of
+ OS_8,OS_S8:
+ cgsize2subreg:=R_SUBWHOLE;
+ OS_16,OS_S16:
+ cgsize2subreg:=R_SUBWHOLE;
+ OS_32,OS_S32:
+ cgsize2subreg:=R_SUBWHOLE;
+ else
+ internalerror(200301231);
+ end;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_ADDRESSREGISTER,
+ R_INTREGISTER :
+ result:=OS_32;
+ R_FPUREGISTER :
+ result:=OS_F32;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function isaddressregister(reg : tregister) : boolean;
+ begin
+ result:=getregtype(reg)=R_ADDRESSREGISTER;
+ end;
+
+
+end.
diff --git a/compiler/m68k/cpuinfo.pas b/compiler/m68k/cpuinfo.pas
new file mode 100644
index 0000000000..178a0fa28e
--- /dev/null
+++ b/compiler/m68k/cpuinfo.pas
@@ -0,0 +1,74 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the PowerPC
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = real;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = extended;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors =
+ (no_processor,
+ MC68000,
+ MC68020,
+ Coldfire
+ );
+
+ tfputype =
+ (no_fpuprocessor,
+ fpu_soft,
+ fpu_libgcc,
+ fpu_68881
+ );
+
+Const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { the difference to stdcall is only the name mangling }
+ pocall_cdecl,
+ { the difference to stdcall is only the name mangling }
+ pocall_cppdecl,
+ { this used by the PalmOS port only }
+ pocall_syscall
+ ];
+
+ processorsstr : array[tprocessors] of string[5] = ('',
+ '68000',
+ '68020',
+ 'COLDFIRE'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'SOFT',
+ 'LIBGCC',
+ '68881'
+ );
+
+Implementation
+
+end.
diff --git a/compiler/m68k/cpunode.pas b/compiler/m68k/cpunode.pas
new file mode 100644
index 0000000000..17f4460650
--- /dev/null
+++ b/compiler/m68k/cpunode.pas
@@ -0,0 +1,52 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the 680x0/Coldfire 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
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgmat,ncgadd,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ ncpuadd,
+// nppccal,
+// nppccon,
+// nppcflw,
+// nppcmem,
+// nppcset,
+// nppcinl,
+// nppcopt,
+ { this not really a node }
+// nppcobj,
+// nppcmat,
+ n68kmat,
+ n68kcnv
+ ;
+
+end.
diff --git a/compiler/m68k/cpupara.pas b/compiler/m68k/cpupara.pas
new file mode 100644
index 0000000000..579009fdde
--- /dev/null
+++ b/compiler/m68k/cpupara.pas
@@ -0,0 +1,477 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generates the argument location information for 680x0
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published bymethodpointer
+ 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.
+
+ ****************************************************************************
+}
+{ Generates the argument location information for 680x0.
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cpubase,
+ symconst,symtype,symdef,symsym,
+ parabase,paramgr,cgbase;
+
+ type
+ { Returns the location for the nr-st 32 Bit int parameter
+ if every parameter before is an 32 Bit int parameter as well
+ and if the calling conventions for the helper routines of the
+ rtl are used.
+ }
+ tm68kparamanager = class(tparamanager)
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ private
+ procedure init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword):longint;
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,
+ globals,
+ systems,
+ cpuinfo,cgutils,
+ defutil;
+
+ procedure tm68kparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ internalerror(2002070801);
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.alignment:=std_param_align;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ { warning : THIS ONLY WORKS WITH INTERNAL ROUTINES,
+ WHICH MUST ALWAYS PASS 4-BYTE PARAMETERS!!
+ }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=target_info.first_parm_offset+nr*4;
+ end;
+ end;
+
+ function getparaloc(p : tdef) : tcgloc;
+
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.deftype of
+ orddef:
+ result:=LOC_REGISTER;
+ floatdef:
+ result:=LOC_FPUREGISTER;
+ enumdef:
+ result:=LOC_REGISTER;
+ pointerdef:
+ result:=LOC_REGISTER;
+ formaldef:
+ result:=LOC_REGISTER;
+ classrefdef:
+ result:=LOC_REGISTER;
+ recorddef:
+ if (target_info.abi<>abi_powerpc_aix) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ objectdef:
+ if is_object(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ procvardef:
+ if (po_methodpointer in tprocvardef(p).procoptions) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ filedef:
+ result:=LOC_REGISTER;
+ arraydef:
+ result:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ result:=LOC_REGISTER
+ else
+ result:=LOC_REFERENCE;
+ variantdef:
+ result:=LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ result:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+
+{$warning copied from ppc cg, needs work}
+ function tm68kparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out always require address }
+ if varspez in [vs_var,vs_out] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.deftype of
+ variantdef,
+ formaldef :
+ result:=true;
+ recorddef:
+ result:=true;
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef :
+ result:=is_object(def);
+ setdef :
+ result:=(tsetdef(def).settype<>smallset);
+ stringdef :
+ result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
+ procvardef :
+ result:=po_methodpointer in tprocvardef(def).procoptions;
+ end;
+ end;
+
+ procedure tm68kparamanager.init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ cur_stack_offset:=8;
+ curintreg:=RS_D0;
+ curfloatreg:=RS_FP0;
+ end;
+
+ procedure tm68kparamanager.create_funcretloc_info(p: tabstractprocdef; side: tcallercallee);
+ var
+ retcgsize: tcgsize;
+ begin
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ retcgsize:=OS_ADDR
+ else
+ retcgsize:=def_cgsize(p.rettype.def);
+
+ location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
+ { void has no location }
+ if is_void(p.rettype.def) then
+ begin
+ location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
+ exit;
+ end;
+ { Return in FPU register? }
+ if p.rettype.def.deftype=floatdef then
+ begin
+ p.funcretloc[side].loc:=LOC_FPUREGISTER;
+ p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+ p.funcretloc[side].size:=retcgsize;
+ end
+ else
+ { Return in register? }
+ if not ret_in_param(p.rettype.def,p.proccalloption) then
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { low 32bits }
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].size:=OS_64;
+ if side=callerside then
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+ { high 32bits }
+ if side=calleeside then
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].size:=retcgsize;
+ if side=callerside then
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+ else
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+ end;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REFERENCE;
+ p.funcretloc[side].size:=retcgsize;
+ end;
+ end;
+
+ function tm68kparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,cur_stack_offset);
+
+ create_funcretloc_info(p,side);
+ end;
+
+ function tm68kparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword):longint;
+ var
+ paraloc : pcgparalocation;
+ hp : tparavarsym;
+ paracgsize : tcgsize;
+ paralen : aint;
+ parasize : longint;
+ paradef : tdef;
+ i : longint;
+ loc : tcgloc;
+ nextintreg,
+ nextfloatreg : tsuperregister;
+ stack_offset : longint;
+
+ begin
+ result:=0;
+ nextintreg:=curintreg;
+ nextfloatreg:=curfloatreg;
+ stack_offset:=cur_stack_offset;
+
+ parasize:=0;
+
+ for i:=0 to p.paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paradef:=hp.vartype.def;
+
+ { syscall for AmigaOS can have already a paraloc set }
+ if (vo_has_explicit_paraloc in hp.varoptions) then
+ begin
+ if not(vo_is_syscall_lib in hp.varoptions) then
+ internalerror(200506051);
+ continue;
+ end;
+ hp.paraloc[side].reset;
+
+ { currently only support C-style array of const }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(paradef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_D0;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if (hp.varspez in [vs_var,vs_out]) or
+ push_addr_param(hp.varspez,paradef,p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then
+ begin
+ paradef:=voidpointertype.def;
+ loc:=LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end
+ else
+ begin
+ if not is_special_array(paradef) then
+ paralen:=paradef.size
+ else
+ paralen:=tcgsize2size[def_cgsize(paradef)];
+
+ loc:=getparaloc(paradef);
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end;
+ hp.paraloc[side].alignment:=std_param_align;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+
+ if (paralen = 0) then
+ if (paradef.deftype = recorddef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc := LOC_VOID;
+ end
+ else
+ internalerror(200506052);
+ { can become < 0 for e.g. 3-byte records }
+ while (paralen > 0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ if (loc = LOC_REGISTER) and
+ (nextintreg <= RS_D7) then
+ begin
+ //writeln('loc register');
+ paraloc^.loc := loc;
+ { make sure we don't lose whether or not the type is signed }
+ if (paradef.deftype <> orddef) then
+ paracgsize := int_cgsize(paralen);
+ if (paracgsize in [OS_NO,OS_64,OS_S64]) then
+ paraloc^.size := OS_INT
+ else
+ paraloc^.size := paracgsize;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
+ inc(nextintreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end
+ else if (loc = LOC_FPUREGISTER) and
+ (nextfloatreg <= RS_FP7) then
+ begin
+ writeln('loc fpuregister');
+ paraloc^.loc:=loc;
+ paraloc^.size := paracgsize;
+ paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
+ inc(nextfloatreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end
+ else { LOC_REFERENCE }
+ begin
+ writeln('loc reference');
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=int_cgsize(paralen);
+ if (side = callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen := 0;
+ end;
+ end;
+ end;
+ result:=stack_offset;
+// writeln('stack offset:',stack_offset);
+ end;
+
+
+{
+
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ paracgsize:=OS_ADDR
+ else
+ begin
+ paracgsize:=def_cgsize(paradef);
+ if paracgsize=OS_NO then
+ paracgsize:=OS_ADDR;
+ end;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].Alignment:=std_param_align;
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.size:=paracgsize;
+ paraloc^.loc:=LOC_REFERENCE;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
+ end;
+ create_funcretloc_info(p,side);
+ result:=parasize;
+ end;
+}
+
+ function tm68kparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
+ var
+ paraloc : pcgparalocation;
+ begin
+ result:=false;
+ case target_info.system of
+ system_m68k_amiga:
+ begin
+ p.paraloc[callerside].alignment:=4;
+ paraloc:=p.paraloc[callerside].add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=def_cgsize(p.vartype.def);
+ { pattern is always uppercase'd }
+ if s='D0' then
+ paraloc^.register:=NR_D0
+ else if s='D1' then
+ paraloc^.register:=NR_D1
+ else if s='D2' then
+ paraloc^.register:=NR_D2
+ else if s='D3' then
+ paraloc^.register:=NR_D3
+ else if s='D4' then
+ paraloc^.register:=NR_D4
+ else if s='D5' then
+ paraloc^.register:=NR_D5
+ else if s='D6' then
+ paraloc^.register:=NR_D6
+ else if s='D7' then
+ paraloc^.register:=NR_D7
+ else if s='A0' then
+ paraloc^.register:=NR_A0
+ else if s='A1' then
+ paraloc^.register:=NR_A1
+ else if s='A2' then
+ paraloc^.register:=NR_A2
+ else if s='A3' then
+ paraloc^.register:=NR_A3
+ else if s='A4' then
+ paraloc^.register:=NR_A4
+ else if s='A5' then
+ paraloc^.register:=NR_A5
+ { 'A6' is problematic, since it's the frame pointer in fpc,
+ so it should be saved before a call! }
+ else if s='A6' then
+ paraloc^.register:=NR_A6
+ { 'A7' is the stack pointer on 68k, can't be overwritten by API calls }
+ else
+ exit;
+
+ { copy to callee side }
+ p.paraloc[calleeside].add_location^:=paraloc^;
+ end;
+ else
+ internalerror(200405092);
+ end;
+ result:=true;
+ end;
+
+begin
+ paramanager:=tm68kparamanager.create;
+end.
diff --git a/compiler/m68k/cpupi.pas b/compiler/m68k/cpupi.pas
new file mode 100644
index 0000000000..2ed0f87dae
--- /dev/null
+++ b/compiler/m68k/cpupi.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ 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 contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ procinfo,cgbase,psub;
+
+ type
+ tm68kprocinfo = class(tcgprocinfo)
+ end;
+
+ implementation
+
+begin
+ cprocinfo:=tm68kprocinfo;
+end.
diff --git a/compiler/m68k/cpuswtch.pas b/compiler/m68k/cpuswtch.pas
new file mode 100644
index 0000000000..1472f17e76
--- /dev/null
+++ b/compiler/m68k/cpuswtch.pas
@@ -0,0 +1,106 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ interprets the commandline options which are 680x0 specific
+
+ 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 cpuswtch;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ options;
+
+type
+ toptionm68k=class(toption)
+ procedure interpret_proc_specific_options(const opt:string);override;
+ end;
+
+implementation
+
+uses
+ cutils,globtype,systems,globals,cpuinfo;
+
+procedure toptionm68k.interpret_proc_specific_options(const opt:string);
+var
+ j : longint;
+ More : string;
+begin
+ More:=Upper(copy(opt,3,length(opt)-2));
+ case opt[2] of
+ 'O' : Begin
+ j := 3;
+ While (j <= Length(Opt)) Do
+ Begin
+ case opt[j] of
+ '-' :
+ begin
+ initglobalswitches:=initglobalswitches-[cs_optimize,cs_fastoptimize,cs_slowoptimize,cs_littlesize,
+ cs_regvars,cs_uncertainopts];
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+ end;
+ 'a' :
+ begin
+ UpdateAlignmentStr(Copy(Opt,j+1,255),ParaAlignment);
+ j:=length(Opt);
+ end;
+ 'g' : initglobalswitches:=initglobalswitches+[cs_littlesize];
+ 'G' : initglobalswitches:=initglobalswitches-[cs_littlesize];
+ 'r' :
+ begin
+ initglobalswitches:=initglobalswitches+[cs_regvars];
+ Simplify_ppu:=false;
+ end;
+ 'u' : initglobalswitches:=initglobalswitches+[cs_uncertainopts];
+ '1' : initglobalswitches:=initglobalswitches-[cs_fastoptimize,cs_slowoptimize]+[cs_optimize];
+ '2' : initglobalswitches:=initglobalswitches-[cs_slowoptimize]+[cs_optimize,cs_fastoptimize];
+ '3' : initglobalswitches:=initglobalswitches+[cs_optimize,cs_fastoptimize,cs_slowoptimize];
+ 'p' :
+ Begin
+ If j < Length(Opt) Then
+ Begin
+ Case opt[j+1] Of
+ '2': initoptprocessor := MC68020;
+ Else IllegalPara(Opt)
+ End;
+ Inc(j);
+ End
+ Else IllegalPara(opt)
+ End;
+ else IllegalPara(opt);
+ End;
+ Inc(j)
+ end;
+ end;
+ 'R' : begin
+ if More='GAS' then
+ initasmmode:=asmmode_standard
+ else
+ IllegalPara(opt);
+ end;
+ else
+ IllegalPara(opt);
+ end;
+end;
+
+
+initialization
+ coption:=toptionm68k;
+end.
diff --git a/compiler/m68k/cputarg.pas b/compiler/m68k/cputarg.pas
new file mode 100644
index 0000000000..e337035a95
--- /dev/null
+++ b/compiler/m68k/cputarg.pas
@@ -0,0 +1,56 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the m68k dependent target units
+
+ 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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ ,t_amiga
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ ,ra68kmot
+
+{**************************************
+ Assemblers
+**************************************}
+
+ ,agcpugas
+ ;
+
+end.
diff --git a/compiler/m68k/itcpugas.pas b/compiler/m68k/itcpugas.pas
new file mode 100644
index 0000000000..12372bfed5
--- /dev/null
+++ b/compiler/m68k/itcpugas.pas
@@ -0,0 +1,138 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the m68k GAS instruction tables
+
+ 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 itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+ const
+ gas_op2str : op2strtable=
+ { warning: CPU32 opcodes are not fully compatible with the MC68020. }
+ { 68000 only opcodes }
+ ('abcd',
+ 'add','adda','addi','addq','addx','and','andi',
+ 'asl','asr','bcc','bcs','beq','bge','bgt','bhi',
+ 'ble','bls','blt','bmi','bne','bpl','bvc','bvs',
+ 'bchg','bclr','bra','bset','bsr','btst','chk',
+ 'clr','cmp','cmpa','cmpi','cmpm','dbcc','dbcs','dbeq','dbge',
+ 'dbgt','dbhi','dble','dbls','dblt','dbmi','dbne','dbra',
+ 'dbpl','dbt','dbvc','dbvs','dbf','divs','divu',
+ 'eor','eori','exg','illegal','ext','jmp','jsr',
+ 'lea','link','lsl','lsr','move','movea','movei','moveq',
+ 'movem','movep','muls','mulu','nbcd','neg','negx',
+ 'nop','not','or','ori','pea','rol','ror','roxl',
+ 'roxr','rtr','rts','sbcd','scc','scs','seq','sge',
+ 'sgt','shi','sle','sls','slt','smi','sne',
+ 'spl','st','svc','svs','sf','sub','suba','subi','subq',
+ 'subx','swap','tas','trap','trapv','tst','unlk',
+ 'rte','reset','stop',
+ { mc68010 instructions }
+ 'bkpt','movec','moves','rtd',
+ { mc68020 instructions }
+ 'bfchg','bfclr','bfexts','bfextu','bfffo',
+ 'bfins','bfset','bftst','callm','cas','cas2',
+ 'chk2','cmp2','divsl','divul','extb','pack','rtm',
+ 'trapcc','tracs','trapeq','trapf','trapge','trapgt',
+ 'traphi','traple','trapls','traplt','trapmi','trapne',
+ 'trappl','trapt','trapvc','trapvs','unpk',
+ { fpu processor instructions - directly supported only. }
+ { ieee aware and misc. condition codes not supported }
+ 'fabs','fadd',
+ 'fbeq','fbne','fbngt','fbgt','fbge','fbnge',
+ 'fblt','fbnlt','fble','fbgl','fbngl','fbgle','fbngle',
+ 'fdbeq','fdbne','fdbgt','fdbngt','fdbge','fdbnge',
+ 'fdblt','fdbnlt','fdble','fdbgl','fdbngl','fdbgle','fdbngle',
+ 'fseq','fsne','fsgt','fsngt','fsge','fsnge',
+ 'fslt','fsnlt','fsle','fsgl','fsngl','fsgle','fsngle',
+ 'fcmp','fdiv','fmove','fmovem',
+ 'fmul','fneg','fnop','fsqrt','fsub','fsgldiv',
+ 'fsflmul','ftst',
+ 'ftrapeq','ftrapne','ftrapgt','ftrapngt','ftrapge','ftrapnge',
+ 'ftraplt','ftrapnlt','ftraple','ftrapgl','ftrapngl','ftrapgle','ftrapngle',
+ { protected instructions }
+ 'cprestore','cpsave',
+ { fpu unit protected instructions }
+ { and 68030/68851 common mmu instructions }
+ { (this may include 68040 mmu instructions) }
+ 'frestore','fsave','pflush','pflusha','pload','pmove','ptest',
+ { useful for assembly language output }
+ 'label','none','db','s','b','fb');
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+ implementation
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {r386att.inc contains the AT&T name of each register.}
+ {$i r68kgas.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {r386ari.inc contains an index which sorts att_regname_table by
+ ATT name.}
+ {$i r68kgri.inc}
+ );
+
+
+ function findreg_by_gasname(const s:string):byte;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:='%'+generic_regname(r);
+ end;
+
+end.
diff --git a/compiler/m68k/m68kreg.dat b/compiler/m68k/m68kreg.dat
new file mode 100644
index 0000000000..9ff2289155
--- /dev/null
+++ b/compiler/m68k/m68kreg.dat
@@ -0,0 +1,44 @@
+;
+; Motorola 680x0 registers
+;
+; layout
+; <name>,<type>,<value>,<stdname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,-1
+
+D0,$01,$00,d0,%d0,0
+D1,$01,$01,d1,%d1,1
+D2,$01,$02,d2,%d2,2
+D3,$01,$03,d3,%d3,3
+D4,$01,$04,d4,%d4,4
+D5,$01,$05,d5,%d5,5
+D6,$01,$06,d6,%d6,6
+D7,$01,$07,d7,%d7,7
+
+FP0,$02,$00,fp0,%fp0,16
+FP1,$02,$01,fp1,%fp1,17
+FP2,$02,$02,fp2,%fp2,18
+FP3,$02,$03,fp3,%fp3,19
+FP4,$02,$04,fp4,%fp4,20
+FP5,$02,$05,fp5,%fp5,21
+FP6,$02,$06,fp6,%fp6,22
+FP7,$02,$07,fp7,%fp7,23
+
+PC,$05,$00,pc,%pc,24
+CCR,$05,$01,ccr,%ccr,0
+FPCR,$05,$02,fpcr,%fpcr,0
+SR,$05,$03,sr,%sr,0
+SSP,$05,$04,ssp,%ssp,0
+DFC,$05,$05,dfc,%dfc,0
+SFC,$05,$06,sfc,%sfc,0
+VBR,$05,$07,vbr,%vbr,0
+FPSR,$05,$08,fpsr,%fpsr,0
+
+A0,$06,$00,a0,%a0,8
+A1,$06,$01,a1,%a1,9
+A2,$06,$02,a2,%a2,10
+A3,$06,$03,a3,%a3,11
+A4,$06,$04,a4,%a4,12
+A5,$06,$05,a5,%a5,13
+A6,$06,$06,a6,%a6,14
+SP,$06,$07,sp,%sp,15
diff --git a/compiler/m68k/n68kcnv.pas b/compiler/m68k/n68kcnv.pas
new file mode 100644
index 0000000000..3fa1bc9f53
--- /dev/null
+++ b/compiler/m68k/n68kcnv.pas
@@ -0,0 +1,239 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate m68k assembler for type converting 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 n68kcnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,defcmp;
+
+ type
+ tm68ktypeconvnode = class(tcgtypeconvnode)
+ protected
+ function first_int_to_real: tnode; override;
+ procedure second_int_to_real;override;
+ procedure second_int_to_bool;override;
+ procedure pass_2;override;
+ end;
+
+implementation
+
+ uses
+ verbose,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,
+ defutil,
+ cgbase,pass_1,pass_2,
+ ncon,ncal,
+ ncgutil,
+ cpubase,aasmcpu,
+ rgobj,tgobj,cgobj,cgutils,globtype,cgcpu;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function tm68ktypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[19];
+ begin
+ { In case we are in emulation mode, we must
+ always call the helpers
+ }
+ if (cs_fp_emulation in aktmoduleswitches) then
+ begin
+ result := inherited first_int_to_real;
+ exit;
+ end
+ else
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resulttype.def) then
+ begin
+ if is_signed(left.resulttype.def) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resulttype.def) then
+ inserttypeconv(left,s32inttype)
+ else
+ { the fpu always considers 32-bit values as signed
+ therefore we need to call the helper in case of
+ a cardinal value.
+ }
+ begin
+ fname := 'fpc_longword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end;
+ firstpass(left);
+ end;
+ result := nil;
+ if registersfpu<1 then
+ registersfpu:=1;
+ location.loc:=LOC_FPUREGISTER;
+ end;
+
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+
+
+ procedure tm68ktypeconvnode.second_int_to_real;
+
+ var
+ tempconst: trealconstnode;
+ ref: treference;
+ valuereg, tempreg, leftreg, tmpfpureg: tregister;
+ signed : boolean;
+ scratch_used : boolean;
+ opsize : tcgsize;
+ begin
+ scratch_used := false;
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ signed := is_signed(left.resulttype.def);
+ opsize := def_cgsize(left.resulttype.def);
+ { has to be handled by a helper }
+ if is_64bitint(left.resulttype.def) then
+ internalerror(200110011);
+ { has to be handled by a helper }
+ if not signed then
+ internalerror(20020814);
+
+ location.register:=cg.getfpuregister(exprasmlist,opsize);
+ case left.location.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ begin
+ leftreg := left.location.register;
+ exprasmlist.concat(taicpu.op_reg_reg(A_FMOVE,TCGSize2OpSize[opsize],leftreg,
+ location.register));
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ exprasmlist.concat(taicpu.op_ref_reg(A_FMOVE,TCGSize2OpSize[opsize],
+ left.location.reference,location.register));
+ end
+ else
+ internalerror(200110012);
+ end;
+ end;
+
+
+ procedure tm68ktypeconvnode.second_int_to_bool;
+ var
+ hreg1,
+ hreg2 : tregister;
+ resflags : tresflags;
+ opsize : tcgsize;
+ begin
+ { byte(boolean) or word(wordbool) or longint(longbool) must }
+ { be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resulttype.def.size=resulttype.def.size) and
+ (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ begin
+ location_copy(location,left.location);
+ exit;
+ end;
+ location_reset(location,LOC_REGISTER,def_cgsize(left.resulttype.def));
+ opsize := def_cgsize(left.resulttype.def);
+ case left.location.loc of
+ LOC_CREFERENCE,LOC_REFERENCE :
+ begin
+ { can we optimize it, or do we need to fix the ref. ? }
+ if isvalidrefoffset(left.location.reference) then
+ begin
+ exprasmlist.concat(taicpu.op_ref(A_TST,TCGSize2OpSize[opsize],
+ left.location.reference));
+ end
+ else
+ begin
+ hreg2:=cg.getintregister(exprasmlist,opsize);
+ cg.a_load_ref_reg(exprasmlist,opsize,opsize,
+ left.location.reference,hreg2);
+ exprasmlist.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[opsize],hreg2));
+ cg.ungetcpuregister(exprasmlist,hreg2);
+ end;
+// reference_release(exprasmlist,left.location.reference);
+ resflags:=F_NE;
+ hreg1:=cg.getintregister(exprasmlist,opsize);
+ end;
+ LOC_REGISTER,LOC_CREGISTER :
+ begin
+ hreg2:=left.location.register;
+ exprasmlist.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[opsize],hreg2));
+ cg.ungetcpuregister(exprasmlist,hreg2);
+ hreg1:=cg.getintregister(exprasmlist,opsize);
+ resflags:=F_NE;
+ end;
+ LOC_FLAGS :
+ begin
+ hreg1:=cg.getintregister(exprasmlist,opsize);
+ resflags:=left.location.resflags;
+ end;
+ else
+ internalerror(10062);
+ end;
+ cg.g_flags2reg(exprasmlist,location.size,resflags,hreg1);
+ location.register := hreg1;
+ end;
+
+
+ procedure tm68ktypeconvnode.pass_2;
+{$ifdef TESTOBJEXT2}
+ var
+ r : preference;
+ nillabel : plabel;
+{$endif TESTOBJEXT2}
+ begin
+ { this isn't good coding, I think tc_bool_2_int, shouldn't be }
+ { type conversion (FK) }
+
+ if not(convtype in [tc_bool_2_int,tc_bool_2_bool]) then
+ begin
+ secondpass(left);
+ location_copy(location,left.location);
+ if codegenerror then
+ exit;
+ end;
+ second_call_helper(convtype);
+ end;
+
+
+begin
+ ctypeconvnode:=tm68ktypeconvnode;
+end.
diff --git a/compiler/m68k/n68kmat.pas b/compiler/m68k/n68kmat.pas
new file mode 100644
index 0000000000..f1bf8a4248
--- /dev/null
+++ b/compiler/m68k/n68kmat.pas
@@ -0,0 +1,248 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate 680x0 assembler for math 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 n68kmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat,cpubase,cgbase;
+
+ type
+
+
+ tm68knotnode = class(tnotnode)
+ procedure pass_2;override;
+ end;
+
+ tm68kmoddivnode = class(tcgmoddivnode)
+ procedure emit_div_reg_reg(signed: boolean;denum,num : tregister);override;
+ procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);override;
+ end;
+
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,aasmbase,aasmtai,aasmcpu,
+ pass_1,pass_2,
+ ncon,
+ cpuinfo,paramgr,defutil,parabase,
+ tgobj,ncgutil,cgobj,cgutils,rgobj,rgcpu,cgcpu,cg64f32;
+
+
+
+
+{*****************************************************************************
+ TM68KNOTNODE
+*****************************************************************************}
+
+ procedure tm68knotnode.pass_2;
+ var
+ hl : tasmlabel;
+ opsize : tcgsize;
+ begin
+ opsize:=def_cgsize(resulttype.def);
+ if is_boolean(resulttype.def) then
+ begin
+ { the second pass could change the location of left }
+ { if it is a register variable, so we've to do }
+ { this before the case statement }
+ if left.location.loc<>LOC_JUMP then
+ secondpass(left);
+
+ case left.location.loc of
+ LOC_JUMP :
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ end;
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+// location_release(exprasmlist,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_CONSTANT,
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location_force_reg(exprasmlist,left.location,def_cgsize(resulttype.def),true);
+ exprasmlist.concat(taicpu.op_reg(A_TST,tcgsize2opsize[opsize],left.location.register));
+// location_release(exprasmlist,left.location);
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_E;
+ end;
+ else
+ internalerror(200203224);
+ end;
+ end
+ else if is_64bitint(left.resulttype.def) then
+ begin
+ secondpass(left);
+ location_copy(location,left.location);
+ location_force_reg(exprasmlist,location,OS_64,false);
+ cg64.a_op64_loc_reg(exprasmlist,OP_NOT,OS_64,location,
+ joinreg64(location.register64.reglo,location.register64.reghi));
+ end
+ else
+ begin
+ secondpass(left);
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
+ location_copy(location,left.location);
+ if location.loc=LOC_CREGISTER then
+ location.register := cg.getintregister(exprasmlist,opsize);
+ { perform the NOT operation }
+ cg.a_op_reg_reg(exprasmlist,OP_NOT,opsize,location.register,left.location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TM68KMODDIVNODE
+*****************************************************************************}
+ procedure tm68kmoddivnode.emit_div_reg_reg(signed: boolean;denum,num : tregister);
+ var
+ continuelabel : tasmlabel;
+ reg_d0,reg_d1 : tregister;
+ paraloc1 : tcgpara;
+ begin
+ { no RTL call, so inline a zero denominator verification }
+ if aktoptprocessor <> MC68000 then
+ begin
+ { verify if denominator is zero }
+ objectlibrary.getjumplabel(continuelabel);
+ { compare against zero, if not zero continue }
+ cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_NE,0,denum,continuelabel);
+// paraloc1.init;
+// cg.a_param_const(exprasmlist,OS_S32,200,paramanager.getintparaloc(pocall_default,1,paraloc1));
+
+ cg.a_call_name(exprasmlist,'FPC_HANDLEERROR');
+ cg.a_label(exprasmlist, continuelabel);
+ if signed then
+ exprasmlist.concat(taicpu.op_reg_reg(A_DIVS,S_L,denum,num))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(A_DIVU,S_L,denum,num));
+ { result should be in denuminator }
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,denum);
+ end
+ else
+ begin
+ { On MC68000/68010 mw must pass through RTL routines }
+ reg_d0:=NR_D0;
+ cg.getcpuregister(exprasmlist,NR_D0);
+ reg_d1:=NR_D1;
+ cg.getcpuregister(exprasmlist,NR_D1);
+ { put numerator in d0 }
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,reg_d0);
+ { put denum in D1 }
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,denum,reg_d1);
+ if signed then
+ cg.a_call_name(exprasmlist,'FPC_DIV_LONGINT')
+ else
+ cg.a_call_name(exprasmlist,'FPC_DIV_CARDINAL');
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,reg_d0,denum);
+ cg.ungetcpuregister(exprasmlist,reg_d0);
+ cg.ungetcpuregister(exprasmlist,reg_d1);
+ end;
+ end;
+
+ procedure tm68kmoddivnode.emit_mod_reg_reg(signed: boolean;denum,num : tregister);
+ var tmpreg : tregister;
+ continuelabel : tasmlabel;
+ signlabel : tasmlabel;
+ reg_d0,reg_d1 : tregister;
+ begin
+ { no RTL call, so inline a zero denominator verification }
+ if aktoptprocessor <> MC68000 then
+ begin
+ { verify if denominator is zero }
+ objectlibrary.getjumplabel(continuelabel);
+ { compare against zero, if not zero continue }
+ cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_NE,0,denum,continuelabel);
+// cg.a_param_const(exprasmlist, OS_S32,200,paramanager.getintparaloc(pocall_default,1));
+ cg.a_call_name(exprasmlist,'FPC_HANDLEERROR');
+ cg.a_label(exprasmlist, continuelabel);
+
+ tmpreg:=cg.getintregister(exprasmlist,OS_INT);
+
+ { we have to prepare the high register with the }
+ { correct sign. i.e we clear it, check if the low dword reg }
+ { which will participate in the division is signed, if so we}
+ { we extend the sign to the high doword register by inverting }
+ { all the bits. }
+ exprasmlist.concat(taicpu.op_reg(A_CLR,S_L,tmpreg));
+ objectlibrary.getjumplabel(signlabel);
+ exprasmlist.concat(taicpu.op_reg(A_TST,S_L,tmpreg));
+ cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_A,0,tmpreg,signlabel);
+ { its a negative value, therefore change sign }
+ cg.a_label(exprasmlist,signlabel);
+ { tmpreg:num / denum }
+
+ if signed then
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_DIVSL,S_L,denum,tmpreg,num))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_DIVUL,S_L,denum,tmpreg,num));
+ { remainder in tmpreg }
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,tmpreg,denum);
+ cg.ungetcpuregister(exprasmlist,tmpreg);
+ end
+ else
+ begin
+ { On MC68000/68010 mw must pass through RTL routines }
+ Reg_d0:=NR_D0;
+ cg.getcpuregister(exprasmlist,NR_D0);
+ Reg_d1:=NR_D1;
+ cg.getcpuregister(exprasmlist,NR_D1);
+ { put numerator in d0 }
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,num,Reg_D0);
+ { put denum in D1 }
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,denum,Reg_D1);
+ if signed then
+ cg.a_call_name(exprasmlist,'FPC_MOD_LONGINT')
+ else
+ cg.a_call_name(exprasmlist,'FPC_MOD_CARDINAL');
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,Reg_D0,denum);
+ cg.ungetcpuregister(exprasmlist,Reg_D0);
+ cg.ungetcpuregister(exprasmlist,Reg_D1);
+ end;
+ end;
+
+
+
+begin
+ cnotnode:=tm68knotnode;
+ cmoddivnode:=tm68kmoddivnode;
+end.
diff --git a/compiler/m68k/ncpuadd.pas b/compiler/m68k/ncpuadd.pas
new file mode 100644
index 0000000000..695f623128
--- /dev/null
+++ b/compiler/m68k/ncpuadd.pas
@@ -0,0 +1,424 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the Motorola 680x0 family
+
+ 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,nadd,ncgadd,cpubase;
+
+
+ type
+ t68kaddnode = class(tcgaddnode)
+ procedure second_cmpordinal;override;
+ procedure second_cmpsmallset;override;
+ procedure second_cmp64bit;override;
+ procedure second_cmpboolean;override;
+ private
+ function getresflags(unsigned: boolean) : tresflags;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmcpu,defutil,htypechk,
+ cgbase,cpuinfo,pass_1,pass_2,regvars,
+ cpupara,cgutils,
+ ncon,nset,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+
+ function t68kaddnode.getresflags(unsigned : boolean) : tresflags;
+ begin
+ case nodetype of
+ equaln : getresflags:=F_E;
+ unequaln : getresflags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swaped in flags then
+ case nodetype of
+ ltn : getresflags:=F_G;
+ lten : getresflags:=F_GE;
+ gtn : getresflags:=F_L;
+ gten : getresflags:=F_LE;
+ end
+ else
+ case nodetype of
+ ltn : getresflags:=F_L;
+ lten : getresflags:=F_LE;
+ gtn : getresflags:=F_G;
+ gten : getresflags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swaped in flags then
+ case nodetype of
+ ltn : getresflags:=F_A;
+ lten : getresflags:=F_AE;
+ gtn : getresflags:=F_B;
+ gten : getresflags:=F_BE;
+ end
+ else
+ case nodetype of
+ ltn : getresflags:=F_B;
+ lten : getresflags:=F_BE;
+ gtn : getresflags:=F_A;
+ gten : getresflags:=F_AE;
+ end;
+ end;
+ end;
+ end;
+
+{*****************************************************************************
+ Smallsets
+*****************************************************************************}
+
+ procedure t68kaddnode.second_cmpsmallset;
+ var
+ tmpreg : tregister;
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ case nodetype of
+ equaln,
+ unequaln :
+ begin
+ {emit_compare(true);}
+ end;
+ lten,gten:
+ begin
+ If (not(nf_swaped in flags) and
+ (nodetype = lten)) or
+ ((nf_swaped in flags) and
+ (nodetype = gten)) then
+ swapleftright;
+ // now we have to check whether left >= right
+ tmpreg := cg.getintregister(exprasmlist,OS_INT);
+ if left.location.loc = LOC_CONSTANT then
+ begin
+ cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
+ not(left.location.value),right.location.register,tmpreg);
+ exprasmlist.concat(taicpu.op_reg(A_TST,S_L,tmpreg));
+ // the two instructions above should be folded together by
+ // the peepholeoptimizer
+ end
+ else
+ begin
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ cg.a_load_const_reg(exprasmlist,OS_INT,
+ aword(right.location.value),tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg(A_AND,S_L,
+ tmpreg,left.location.register));
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(A_AND,S_L,
+ right.location.register,left.location.register));
+ end;
+ cg.ungetcpuregister(exprasmlist,tmpreg);
+ location.resflags := getresflags(true);
+ end;
+ else
+ internalerror(2002072701);
+ end;
+
+
+ end;
+
+
+{*****************************************************************************
+ Ordinals
+*****************************************************************************}
+
+ procedure t68kaddnode.second_cmpordinal;
+ var
+ unsigned : boolean;
+ useconst : boolean;
+ tmpreg : tregister;
+ op : tasmop;
+ begin
+ { set result location }
+ location_reset(location,LOC_JUMP,OS_NO);
+
+ { load values into registers (except constants) }
+ force_reg_left_right(true, false);
+
+ { determine if the comparison will be unsigned }
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+
+ // get the constant on the right if there is one
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ // can we use an immediate, or do we have to load the
+ // constant in a register first?
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+{$ifdef extdebug}
+ if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.value64)<>0) and ((hi(right.location.value64)<>-1) or unsigned) then
+ internalerror(2002080301);
+{$endif extdebug}
+ if (nodetype in [equaln,unequaln]) then
+ if (unsigned and
+ (right.location.value > high(word))) or
+ (not unsigned and
+ (longint(right.location.value) < low(smallint)) or
+ (longint(right.location.value) > high(smallint))) then
+ { we can then maybe use a constant in the 'othersigned' case
+ (the sign doesn't matter for // equal/unequal)}
+ unsigned := not unsigned;
+
+ if (unsigned and
+ ((right.location.value) <= high(word))) or
+ (not(unsigned) and
+ (longint(right.location.value) >= low(smallint)) and
+ (longint(right.location.value) <= high(smallint))) then
+ useconst := true
+ else
+ begin
+ useconst := false;
+ tmpreg := cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_const_reg(exprasmlist,OS_INT,
+ aword(right.location.value),tmpreg);
+ end
+ end
+ else
+ useconst := false;
+ location.loc := LOC_FLAGS;
+ location.resflags := getresflags(unsigned);
+ op := A_CMP;
+ if (right.location.loc = LOC_CONSTANT) then
+ if useconst then
+ exprasmlist.concat(taicpu.op_reg_const(op,S_L,
+ left.location.register,longint(right.location.value)))
+ else
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg(op,S_L,
+ left.location.register,tmpreg));
+ cg.ungetcpuregister(exprasmlist,tmpreg);
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(op,S_L,
+ left.location.register,right.location.register));
+ end;
+
+{*****************************************************************************
+ Boolean
+*****************************************************************************}
+
+ procedure t68kaddnode.second_cmpboolean;
+ var
+ cgop : TOpCg;
+ cgsize : TCgSize;
+ isjump : boolean;
+ otl,ofl : tasmlabel;
+ begin
+ if (torddef(left.resulttype.def).typ=bool8bit) or
+ (torddef(right.resulttype.def).typ=bool8bit) then
+ cgsize:=OS_8
+ else
+ if (torddef(left.resulttype.def).typ=bool16bit) or
+ (torddef(right.resulttype.def).typ=bool16bit) then
+ cgsize:=OS_16
+ else
+ cgsize:=OS_32;
+
+ if (cs_full_boolean_eval in aktlocalswitches) or
+ (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ swapleftright;
+
+ isjump:=(left.location.loc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(left);
+ if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(exprasmlist,left.location,cgsize,false);
+ if isjump then
+ begin
+ truelabel:=otl;
+ falselabel:=ofl;
+ end;
+
+ isjump:=(right.location.loc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(right);
+ if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(exprasmlist,right.location,cgsize,false);
+ if isjump then
+ begin
+ truelabel:=otl;
+ falselabel:=ofl;
+ end;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ force_reg_left_right(true,false);
+
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+
+ if (right.location.loc <> LOC_CONSTANT) then
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,S_L,
+ left.location.register,right.location.register))
+ else
+ exprasmlist.concat(taicpu.op_const_reg(A_CMP,S_L,
+ longint(right.location.value),left.location.register));
+ location.resflags := getresflags(true);
+ end;
+
+ //release_reg_left_right;
+ end;
+
+
+{*****************************************************************************
+ 64-bit
+*****************************************************************************}
+
+ procedure t68kaddnode.second_cmp64bit;
+ begin
+(* load_left_right(true,false);
+
+ case nodetype of
+ ltn,lten,
+ gtn,gten:
+ begin
+ emit_cmp64_hi;
+ firstjmp64bitcmp;
+ emit_cmp64_lo;
+ secondjmp64bitcmp;
+ end;
+ equaln,unequaln:
+ begin
+ // instead of doing a complicated compare, do
+ // (left.hi xor right.hi) or (left.lo xor right.lo)
+ // (somewhate optimized so that no superfluous 'mr's are
+ // generated)
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if left.location.loc = LOC_REGISTER then
+ begin
+ tempreg64.reglo := left.location.register64.reglo;
+ tempreg64.reghi := left.location.register64.reghi;
+ end
+ else
+ begin
+ if (aword(right.location.valueqword) <> 0) then
+ tempreg64.reglo := cg.getintregister(exprasmlist)
+ else
+ tempreg64.reglo := left.location.register64.reglo;
+ if ((right.location.valueqword shr 32) <> 0) then
+ tempreg64.reghi := cg.getintregister(exprasmlist)
+ else
+ tempreg64.reghi := left.location.register64.reghi;
+ end;
+
+ if (aword(right.location.valueqword) <> 0) then
+ { negative values can be handled using SUB, }
+ { positive values < 65535 using XOR. }
+ if (longint(right.location.valueqword) >= -32767) and
+ (longint(right.location.valueqword) < 0) then
+ cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
+ aword(right.location.valueqword),
+ left.location.register64.reglo,tempreg64.reglo)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
+ aword(right.location.valueqword),
+ left.location.register64.reglo,tempreg64.reglo);
+
+ if ((right.location.valueqword shr 32) <> 0) then
+ if (longint(right.location.valueqword shr 32) >= -32767) and
+ (longint(right.location.valueqword shr 32) < 0) then
+ cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
+ aword(right.location.valueqword shr 32),
+ left.location.register64.reghi,tempreg64.reghi)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
+ aword(right.location.valueqword shr 32),
+ left.location.register64.reghi,tempreg64.reghi);
+ end
+ else
+ begin
+ tempreg64.reglo := cg.getintregister(exprasmlist);
+ tempreg64.reghi := cg.getintregister(exprasmlist);
+ cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
+ left.location.register64,right.location.register64,
+ tempreg64);
+ end;
+
+ cg.a_reg_alloc(exprasmlist,R_0);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,R_0,
+ tempreg64.reglo,tempreg64.reghi));
+ cg.a_reg_dealloc(exprasmlist,R_0);
+ if (tempreg64.reglo <> left.location.register64.reglo) then
+ cg.ungetregister(exprasmlist,tempreg64.reglo);
+ if (tempreg64.reghi <> left.location.register64.reghi) then
+ cg.ungetregister(exprasmlist,tempreg64.reghi);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags := getresflags;
+ end;
+ else
+ internalerror(2002072803);
+ end;
+
+
+ { set result location }
+ { (emit_compare sets it to LOC_FLAGS for compares, so set the }
+ { real location only now) (JM) }
+ if cmpop and
+ not(nodetype in [equaln,unequaln]) then
+ location_reset(location,LOC_JUMP,OS_NO);
+*)
+ location_reset(location,LOC_JUMP,OS_NO);
+ end;
+
+
+begin
+ caddnode:=t68kaddnode;
+end.
diff --git a/compiler/m68k/r68kcon.inc b/compiler/m68k/r68kcon.inc
new file mode 100644
index 0000000000..2e8f8716fb
--- /dev/null
+++ b/compiler/m68k/r68kcon.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+NR_NO = tregister($00000000);
+NR_D0 = tregister($01000000);
+NR_D1 = tregister($01000001);
+NR_D2 = tregister($01000002);
+NR_D3 = tregister($01000003);
+NR_D4 = tregister($01000004);
+NR_D5 = tregister($01000005);
+NR_D6 = tregister($01000006);
+NR_D7 = tregister($01000007);
+NR_FP0 = tregister($02000000);
+NR_FP1 = tregister($02000001);
+NR_FP2 = tregister($02000002);
+NR_FP3 = tregister($02000003);
+NR_FP4 = tregister($02000004);
+NR_FP5 = tregister($02000005);
+NR_FP6 = tregister($02000006);
+NR_FP7 = tregister($02000007);
+NR_PC = tregister($05000000);
+NR_CCR = tregister($05000001);
+NR_FPCR = tregister($05000002);
+NR_SR = tregister($05000003);
+NR_SSP = tregister($05000004);
+NR_DFC = tregister($05000005);
+NR_SFC = tregister($05000006);
+NR_VBR = tregister($05000007);
+NR_FPSR = tregister($05000008);
+NR_A0 = tregister($06000000);
+NR_A1 = tregister($06000001);
+NR_A2 = tregister($06000002);
+NR_A3 = tregister($06000003);
+NR_A4 = tregister($06000004);
+NR_A5 = tregister($06000005);
+NR_A6 = tregister($06000006);
+NR_SP = tregister($06000007);
diff --git a/compiler/m68k/r68kgas.inc b/compiler/m68k/r68kgas.inc
new file mode 100644
index 0000000000..ee47e9ad64
--- /dev/null
+++ b/compiler/m68k/r68kgas.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+'INVALID',
+'%d0',
+'%d1',
+'%d2',
+'%d3',
+'%d4',
+'%d5',
+'%d6',
+'%d7',
+'%fp0',
+'%fp1',
+'%fp2',
+'%fp3',
+'%fp4',
+'%fp5',
+'%fp6',
+'%fp7',
+'%pc',
+'%ccr',
+'%fpcr',
+'%sr',
+'%ssp',
+'%dfc',
+'%sfc',
+'%vbr',
+'%fpsr',
+'%a0',
+'%a1',
+'%a2',
+'%a3',
+'%a4',
+'%a5',
+'%a6',
+'%sp'
diff --git a/compiler/m68k/r68kgri.inc b/compiler/m68k/r68kgri.inc
new file mode 100644
index 0000000000..17ba5dc3a9
--- /dev/null
+++ b/compiler/m68k/r68kgri.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+18,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+22,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+19,
+25,
+17,
+23,
+33,
+20,
+21,
+24,
+0
diff --git a/compiler/m68k/r68knor.inc b/compiler/m68k/r68knor.inc
new file mode 100644
index 0000000000..c1e8cc2f30
--- /dev/null
+++ b/compiler/m68k/r68knor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from m68kreg.dat }
+34
diff --git a/compiler/m68k/r68knum.inc b/compiler/m68k/r68knum.inc
new file mode 100644
index 0000000000..0dc71ce16f
--- /dev/null
+++ b/compiler/m68k/r68knum.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($06000000),
+tregister($06000001),
+tregister($06000002),
+tregister($06000003),
+tregister($06000004),
+tregister($06000005),
+tregister($06000006),
+tregister($06000007)
diff --git a/compiler/m68k/r68krni.inc b/compiler/m68k/r68krni.inc
new file mode 100644
index 0000000000..d6364bb31a
--- /dev/null
+++ b/compiler/m68k/r68krni.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33
diff --git a/compiler/m68k/r68ksri.inc b/compiler/m68k/r68ksri.inc
new file mode 100644
index 0000000000..44010ba66a
--- /dev/null
+++ b/compiler/m68k/r68ksri.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+0,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+18,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+22,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+19,
+25,
+17,
+23,
+33,
+20,
+21,
+24
diff --git a/compiler/m68k/r68ksta.inc b/compiler/m68k/r68ksta.inc
new file mode 100644
index 0000000000..ed8d142fe4
--- /dev/null
+++ b/compiler/m68k/r68ksta.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15
diff --git a/compiler/m68k/r68kstd.inc b/compiler/m68k/r68kstd.inc
new file mode 100644
index 0000000000..3719f1f96b
--- /dev/null
+++ b/compiler/m68k/r68kstd.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+'INVALID',
+'d0',
+'d1',
+'d2',
+'d3',
+'d4',
+'d5',
+'d6',
+'d7',
+'fp0',
+'fp1',
+'fp2',
+'fp3',
+'fp4',
+'fp5',
+'fp6',
+'fp7',
+'pc',
+'ccr',
+'fpcr',
+'sr',
+'ssp',
+'dfc',
+'sfc',
+'vbr',
+'fpsr',
+'a0',
+'a1',
+'a2',
+'a3',
+'a4',
+'a5',
+'a6',
+'sp'
diff --git a/compiler/m68k/r68ksup.inc b/compiler/m68k/r68ksup.inc
new file mode 100644
index 0000000000..8677c2a633
--- /dev/null
+++ b/compiler/m68k/r68ksup.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+RS_NO = $00;
+RS_D0 = $00;
+RS_D1 = $01;
+RS_D2 = $02;
+RS_D3 = $03;
+RS_D4 = $04;
+RS_D5 = $05;
+RS_D6 = $06;
+RS_D7 = $07;
+RS_FP0 = $00;
+RS_FP1 = $01;
+RS_FP2 = $02;
+RS_FP3 = $03;
+RS_FP4 = $04;
+RS_FP5 = $05;
+RS_FP6 = $06;
+RS_FP7 = $07;
+RS_PC = $00;
+RS_CCR = $01;
+RS_FPCR = $02;
+RS_SR = $03;
+RS_SSP = $04;
+RS_DFC = $05;
+RS_SFC = $06;
+RS_VBR = $07;
+RS_FPSR = $08;
+RS_A0 = $00;
+RS_A1 = $01;
+RS_A2 = $02;
+RS_A3 = $03;
+RS_A4 = $04;
+RS_A5 = $05;
+RS_A6 = $06;
+RS_SP = $07;
diff --git a/compiler/m68k/ra68k.pas b/compiler/m68k/ra68k.pas
new file mode 100755
index 0000000000..3b7c24dc8d
--- /dev/null
+++ b/compiler/m68k/ra68k.pas
@@ -0,0 +1,363 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common 68k assembler reader routines
+
+ 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 ra68k;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,rautils,cclasses;
+
+ type
+ Tm68kOperand=class(TOperand)
+ end;
+
+ Tm68kInstruction=class(TInstruction)
+ opsize : topsize;
+ function ConcatInstruction(p : taasmoutput):tai;override;
+ function ConcatLabeledInstr(p : taasmoutput):tai;
+ end;
+
+ implementation
+
+ uses
+ verbose,cgbase;
+
+{*****************************************************************************
+ TM68kInstruction
+*****************************************************************************}
+
+ function TM68kInstruction.ConcatInstruction(p : taasmoutput):tai;
+ var
+ fits : boolean;
+ begin
+ result:=nil;
+ fits := FALSE;
+ { setup specific opcodetions for first pass }
+
+ { Setup special operands }
+ { Convert to general form as to conform to the m68k opcode table }
+ if (opcode = A_ADDA) or (opcode = A_ADDI)
+ then opcode := A_ADD
+ else
+ { CMPM excluded because of GAS v1.34 BUG }
+ if (opcode = A_CMPA) or
+ (opcode = A_CMPI) then
+ opcode := A_CMP
+ else
+ if opcode = A_EORI then
+ opcode := A_EOR
+ else
+ if opcode = A_MOVEA then
+ opcode := A_MOVE
+ else
+ if opcode = A_ORI then
+ opcode := A_OR
+ else
+ if (opcode = A_SUBA) or (opcode = A_SUBI) then
+ opcode := A_SUB;
+
+ { Setup operand types }
+
+(*
+ in opcode <> A_MOVEM then
+ begin
+
+ while not(fits) do
+ begin
+ { set the opcodetion cache, if the opcodetion }
+ { occurs the first time }
+ if (it[i].i=opcode) and (ins_cache[opcode]=-1) then
+ ins_cache[opcode]:=i;
+
+ if (it[i].i=opcode) and (instr.ops=it[i].ops) then
+ begin
+ { first fit }
+ case instr.ops of
+ 0 : begin
+ fits:=true;
+ break;
+ end;
+ 1 :
+ begin
+ if (optyp1 and it[i].o1)<>0 then
+ begin
+ fits:=true;
+ break;
+ end;
+ end;
+ 2 : if ((optyp1 and it[i].o1)<>0) and
+ ((optyp2 and it[i].o2)<>0) then
+ begin
+ fits:=true;
+ break;
+ end
+ 3 : if ((optyp1 and it[i].o1)<>0) and
+ ((optyp2 and it[i].o2)<>0) and
+ ((optyp3 and it[i].o3)<>0) then
+ begin
+ fits:=true;
+ break;
+ end;
+ end; { end case }
+ end; { endif }
+ if it[i].i=A_NONE then
+ begin
+ { NO MATCH! }
+ Message(asmr_e_invalid_combination_opcode_and_operand);
+ exit;
+ end;
+ inc(i);
+ end; { end while }
+ *)
+ fits:=TRUE;
+
+ { We add the opcode to the opcode linked list }
+ if fits then
+ begin
+ case ops of
+ 0:
+ if opsize <> S_NO then
+ result:=(taicpu.op_none(opcode,opsize))
+ else
+ result:=(taicpu.op_none(opcode,S_NO));
+ 1: begin
+ case operands[1].opr.typ of
+ OPR_SYMBOL:
+ begin
+ result:=(taicpu.op_sym_ofs(opcode,
+ opsize, operands[1].opr.symbol,operands[1].opr.symofs));
+ end;
+ OPR_CONSTANT:
+ begin
+ result:=(taicpu.op_const(opcode,
+ opsize, operands[1].opr.val));
+ end;
+ OPR_REGISTER:
+ result:=(taicpu.op_reg(opcode,opsize,operands[1].opr.reg));
+ OPR_REFERENCE:
+ if opsize <> S_NO then
+ begin
+ result:=(taicpu.op_ref(opcode,
+ opsize,operands[1].opr.ref));
+ end
+ else
+ begin
+ { special jmp and call case with }
+ { symbolic references. }
+ if opcode in [A_BSR,A_JMP,A_JSR,A_BRA,A_PEA] then
+ begin
+ result:=(taicpu.op_ref(opcode,
+ S_NO,operands[1].opr.ref));
+ end
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ OPR_NONE:
+ Message(asmr_e_invalid_opcode_and_operand);
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end;
+ end;
+ 2: begin
+ { source }
+ case operands[1].opr.typ of
+ { reg,reg }
+ { reg,ref }
+ OPR_REGISTER:
+ begin
+ case operands[2].opr.typ of
+ OPR_REGISTER:
+ begin
+ result:=(taicpu.op_reg_reg(opcode,
+ opsize,operands[1].opr.reg,operands[2].opr.reg));
+ end;
+ OPR_REFERENCE:
+ result:=(taicpu.op_reg_ref(opcode,
+ opsize,operands[1].opr.reg,operands[2].opr.ref));
+ else { else case }
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_REGISTER }
+ end;
+ { regset, ref }
+ OPR_regset:
+ begin
+ case operands[2].opr.typ of
+ OPR_REFERENCE :
+ result:=(taicpu.op_regset_ref(opcode,
+ opsize,operands[1].opr.regset,operands[2].opr.ref));
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_regset }
+ end;
+
+ { const,reg }
+ { const,const }
+ { const,ref }
+ OPR_CONSTANT:
+ case operands[2].opr.typ of
+ { constant, constant does not have a specific size. }
+ OPR_CONSTANT:
+ result:=(taicpu.op_const_const(opcode,
+ S_NO,operands[1].opr.val,operands[2].opr.val));
+ OPR_REFERENCE:
+ begin
+ result:=(taicpu.op_const_ref(opcode,
+ opsize,operands[1].opr.val,
+ operands[2].opr.ref))
+ end;
+ OPR_REGISTER:
+ begin
+ result:=(taicpu.op_const_reg(opcode,
+ opsize,operands[1].opr.val,
+ operands[2].opr.reg))
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_CONSTANT }
+ { ref,reg }
+ { ref,ref }
+ OPR_REFERENCE:
+ case operands[2].opr.typ of
+ OPR_REGISTER:
+ begin
+ result:=(taicpu.op_ref_reg(opcode,
+ opsize,operands[1].opr.ref,
+ operands[2].opr.reg));
+ end;
+ OPR_regset:
+ begin
+ result:=(taicpu.op_ref_regset(opcode,
+ opsize,operands[1].opr.ref,
+ operands[2].opr.regset));
+ end;
+ OPR_REFERENCE: { special opcodes }
+ result:=(taicpu.op_ref_ref(opcode,
+ opsize,operands[1].opr.ref,
+ operands[2].opr.ref));
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_REFERENCE }
+ OPR_SYMBOL: case operands[2].opr.typ of
+ OPR_REFERENCE:
+ begin
+ result:=(taicpu.op_sym_ofs_ref(opcode,
+ opsize,operands[1].opr.symbol,operands[1].opr.symofs,
+ operands[2].opr.ref))
+ end;
+ OPR_REGISTER:
+ begin
+ result:=(taicpu.op_sym_ofs_reg(opcode,
+ opsize,operands[1].opr.symbol,operands[1].opr.symofs,
+ operands[2].opr.reg))
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_SYMBOL }
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end first operand case }
+ end;
+ 3: begin
+ if (opcode = A_DIVSL) or (opcode = A_DIVUL) or (opcode = A_MULU)
+ or (opcode = A_MULS) or (opcode = A_DIVS) or (opcode = A_DIVU) then
+ begin
+ if (operands[1].opr.typ <> OPR_REGISTER)
+ or (operands[2].opr.typ <> OPR_REGISTER)
+ or (operands[3].opr.typ <> OPR_REGISTER) then
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end
+ else
+ begin
+ result:=(taicpu. op_reg_reg_reg(opcode,opsize,
+ operands[1].opr.reg,operands[2].opr.reg,operands[3].opr.reg));
+ end;
+ end
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end case }
+ end;
+ if assigned(result) then
+ p.concat(result);
+ end;
+
+
+ function TM68kInstruction.ConcatLabeledInstr(p : taasmoutput):tai;
+ begin
+ if ((opcode >= A_BCC) and (opcode <= A_BVS)) or
+ (opcode = A_BRA) or (opcode = A_BSR) or
+ (opcode = A_JMP) or (opcode = A_JSR) or
+ ((opcode >= A_FBEQ) and (opcode <= A_FBNGLE)) then
+ begin
+ if ops > 2 then
+ Message(asmr_e_invalid_opcode_and_operand)
+ else if operands[1].opr.typ <> OPR_SYMBOL then
+ Message(asmr_e_invalid_opcode_and_operand)
+ else if (operands[1].opr.typ = OPR_SYMBOL) and
+ (ops = 1) then
+ if assigned(operands[1].opr.symbol) and
+ (operands[1].opr.symofs=0) then
+ result:=taicpu.op_sym(opcode,S_NO,
+ operands[1].opr.symbol)
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ end
+ else if ((opcode >= A_DBCC) and (opcode <= A_DBF))
+ or ((opcode >= A_FDBEQ) and (opcode <= A_FDBNGLE)) then
+ begin
+ if (ops<>2) or
+ (operands[1].opr.typ <> OPR_REGISTER) or
+ (operands[2].opr.typ <> OPR_SYMBOL) or
+ (operands[2].opr.symofs <> 0) then
+ Message(asmr_e_invalid_opcode_and_operand)
+ else
+ result:=taicpu.op_reg_sym(opcode,opsize,operands[1].opr.reg,
+ operands[2].opr.symbol);
+ end
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ if assigned(result) then
+ p.concat(result);
+ end;
+
+
+
+
+end.
diff --git a/compiler/m68k/ra68kmot.pas b/compiler/m68k/ra68kmot.pas
new file mode 100644
index 0000000000..11f8442c46
--- /dev/null
+++ b/compiler/m68k/ra68kmot.pas
@@ -0,0 +1,1790 @@
+{
+ Copyright (c) 1998-2000 by Carl Eric Codere
+
+ This unit does the parsing process for the motorola inline assembler
+
+ 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 ra68kmot;
+
+{$i fpcdefs.inc}
+
+{**********************************************************************}
+{ WARNING }
+{**********************************************************************}
+{ Any modification in the order or removal of terms in the tables }
+{ in m68k.pas and asmo68k.pas will BREAK the code in this unit, }
+{ unless the appropriate changes are made to this unit. Addition }
+{ of terms though, will not change the code herein. }
+{**********************************************************************}
+
+{---------------------------------------------------------------------------}
+{ LEFT TO DO }
+{---------------------------------------------------------------------------}
+{ o Add support for sized indexing such as in d0.l }
+{ presently only (an,dn) is supported for indexing -- }
+{ size defaults to LONG. }
+{ o Add support for MC68020 opcodes. }
+{ o Add support for MC68020 adressing modes. }
+{ o Add operand checking with m68k opcode table in ConcatOpCode }
+{ o Add Floating point support }
+{---------------------------------------------------------------------------}
+
+ interface
+
+
+ uses
+ cutils,
+ globtype,cclasses,cpubase,
+ symconst,
+ aasmbase,
+ rabase,rasm,ra68k,rautils;
+
+ type
+ tasmtoken = (
+ AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_HEXNUM,AS_OCTALNUM,
+ AS_BINNUM,AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
+ AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,AS_INTNUM,
+ AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_APPT,AS_REALNUM,
+ AS_ALIGN,
+ {------------------ Assembler directives --------------------}
+ AS_DB,AS_DW,AS_DD,AS_XDEF,AS_END,
+ {------------------ Assembler Operators --------------------}
+ AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR);
+
+ tasmkeyword = string[10];
+
+ tm68kmotreader = class(tasmreader)
+ actasmtoken : tasmtoken;
+ prevasmtoken : tasmtoken;
+ procedure SetupTables;
+ function Assemble: tlinkedlist;override;
+ function is_asmopcode(const s: string) : boolean;
+ Function is_asmdirective(const s: string):boolean;
+ function is_register(const s:string):boolean;
+ procedure GetToken;
+ function consume(t : tasmtoken):boolean;
+ function findopcode(s: string; var opsize: topsize): tasmop;
+ Function BuildExpression(allow_symbol : boolean; asmsym : pstring) : longint;
+ Procedure BuildConstant(maxvalue: longint);
+ Procedure BuildRealConstant(typ : tfloattype);
+ Procedure BuildScaling(const oper:tm68koperand);
+ Function BuildRefExpression: longint;
+ procedure BuildReference(const oper:tm68koperand);
+ Procedure BuildOperand(const oper:tm68koperand);
+ Procedure BuildStringConstant(asciiz: boolean);
+ Procedure BuildOpCode(instr:Tm68kinstruction);
+ end;
+
+
+Implementation
+
+ uses
+ { global }
+ globals,verbose,
+ systems,
+ { aasm }
+ cpuinfo,aasmtai,aasmcpu,
+ cgbase,
+ { symtable }
+ symbase,symtype,symsym,symtable,
+ { pass 1 }
+ nbas,
+ { parser }
+ scanner,agcpugas,
+ itcpugas
+ ;
+
+const
+ firstdirective = AS_DB;
+ lastdirective = AS_END;
+ firstoperator = AS_MOD;
+ lastoperator = AS_XOR;
+
+ _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
+ _count_asmoperators = longint(lastoperator)-longint(firstoperator);
+
+ _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
+ ('DC.B','DC.W','DC.L','XDEF','END');
+
+ { problems with shl,shr,not,and,or and xor, they are }
+ { context sensitive. }
+ _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
+ 'MOD','SHL','SHR','NOT','AND','OR','XOR');
+
+ token2str : array[tasmtoken] of tasmkeyword=(
+ 'NONE','LABEL','LLABEL','STRING','HEXNUM','OCTALNUM',
+ 'BINNUM',',','[',']','(',
+ ')',':','.','+','-','*','INTNUM',
+ 'SEPARATOR','ID','REGISTER','OPCODE','/','APPT','REALNUM',
+ 'ALIGN',
+ {------------------ Assembler directives --------------------}
+ 'DB','DW','DD','XDEF','END',
+ {------------------ Assembler Operators --------------------}
+ 'MOD','SHL','SHR','NOT','AND','OR','XOR');
+
+const
+ firsttoken : boolean = TRUE;
+ operandnum : byte = 0;
+
+ procedure tm68kmotreader.SetupTables;
+ { creates uppercased symbol tables for speed access }
+ var
+ i : tasmop;
+ str2opentry: tstr2opentry;
+ Begin
+ { opcodes }
+ iasmops:=TDictionary.Create;
+ iasmops.delete_doubles:=true;
+ for i:=firstop to lastop do
+ begin
+ str2opentry:=tstr2opentry.createname(upper(gas_op2str[i]));
+ str2opentry.op:=i;
+ iasmops.insert(str2opentry);
+ end;
+ end;
+
+
+ {---------------------------------------------------------------------}
+ { Routines for the tokenizing }
+ {---------------------------------------------------------------------}
+
+ function tm68kmotreader.is_asmopcode(const s: string):boolean;
+ var
+ str2opentry: tstr2opentry;
+ hs : string;
+ j : byte;
+ Begin
+ is_asmopcode:=false;
+ { first of all we remove the suffix }
+ j:=pos('.',s);
+ if j>0 then
+ hs:=copy(s,3,255)
+ else
+ hs:=s;
+
+ str2opentry:=tstr2opentry(iasmops.search(hs));
+ if assigned(str2opentry) then
+ begin
+ actopcode:=str2opentry.op;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ end;
+
+
+
+ Function tm68kmotreader.is_asmdirective(const s: string):boolean;
+ var
+ i:byte;
+ begin
+ result:=false;
+ for i:=0 to _count_asmdirectives do
+ begin
+ if s=_asmdirectives[i] then
+ begin
+ actasmtoken := tasmtoken(longint(firstdirective)+i);
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+
+
+ function tm68kmotreader.is_register(const s:string):boolean;
+ begin
+ is_register:=false;
+ actasmregister:=gas_regnum_search(lower(s));
+ if actasmregister<>NR_NO then
+ begin
+ is_register:=true;
+ actasmtoken:=AS_REGISTER;
+ end;
+ end;
+
+
+ Procedure tm68kmotreader.GetToken;
+ {*********************************************************************}
+ { FUNCTION GetToken: tinteltoken; }
+ { Description: This routine returns intel assembler tokens and }
+ { does some minor syntax error checking. }
+ {*********************************************************************}
+ var
+ token: tasmtoken;
+ forcelabel: boolean;
+ begin
+ forcelabel := FALSE;
+ actasmpattern :='';
+ {* INIT TOKEN TO NOTHING *}
+ token := AS_NONE;
+ { while space and tab , continue scan... }
+ while c in [' ',#9] do
+ c:=current_scanner.asmgetchar;
+
+ if not (c in [#10,#13,'{',';']) then
+ current_scanner.gettokenpos;
+ { Possiblities for first token in a statement: }
+ { Local Label, Label, Directive, Prefix or Opcode.... }
+ if firsttoken and not (c in [#10,#13,'{',';']) then
+ begin
+
+ firsttoken := FALSE;
+ if c = '@' then
+ begin
+ token := AS_LLABEL; { this is a local label }
+ { Let us point to the next character }
+ c := current_scanner.asmgetchar;
+ end;
+
+
+
+ while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
+ begin
+ { if there is an at_sign, then this must absolutely be a label }
+ if c = '@' then forcelabel:=TRUE;
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+
+ uppervar(actasmpattern);
+
+ if c = ':' then
+ begin
+ case token of
+ AS_NONE: token := AS_LABEL;
+ AS_LLABEL: ; { do nothing }
+ end; { end case }
+ { let us point to the next character }
+ c := current_scanner.asmgetchar;
+ actasmtoken := token;
+ exit;
+ end;
+
+ { Are we trying to create an identifier with }
+ { an at-sign...? }
+ if forcelabel then
+ Message(asmr_e_none_label_contain_at);
+
+ If is_asmopcode(actasmpattern) then
+ exit;
+ if is_asmdirective(actasmpattern) then
+ exit
+ else
+ begin
+ actasmtoken := AS_NONE;
+ Message1(asmr_e_invalid_or_missing_opcode,actasmpattern);
+ end;
+ end
+ else { else firsttoken }
+ { Here we must handle all possible cases }
+ begin
+ case c of
+
+ '@': { possiblities : - local label reference , such as in jmp @local1 }
+ { - @Result, @Code or @Data special variables. }
+ begin
+ actasmpattern := c;
+ c:= current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+ actasmtoken := AS_ID;
+ exit;
+ end;
+ { identifier, register, opcode, prefix or directive }
+ 'A'..'Z','a'..'z','_': begin
+ actasmpattern := c;
+ c:= current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','.'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+
+ If is_asmopcode(actasmpattern) then
+ exit;
+ if is_register(actasmpattern) then
+ exit;
+ if is_asmdirective(actasmpattern) then
+ exit;
+ { this is surely an identifier }
+ actasmtoken := AS_ID;
+ exit;
+ end;
+ { override operator... not supported }
+ '&': begin
+ c:=current_scanner.asmgetchar;
+ actasmtoken := AS_AND;
+ end;
+ { string or character }
+ '''' :
+ begin
+ actasmpattern:='';
+ while true do
+ begin
+ if c = '''' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c=#10 then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ repeat
+ if c=''''then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c='''' then
+ begin
+ actasmpattern:=actasmpattern+'''';
+ c:=current_scanner.asmgetchar;
+ if c=#10 then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ end
+ else break;
+ end
+ else
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ if c=#10 then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break
+ end;
+ end;
+ until false; { end repeat }
+ end
+ else break; { end if }
+ end; { end while }
+ token:=AS_STRING;
+ actasmtoken := token;
+ exit;
+ end;
+ '$' : begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+ actasmtoken := AS_HEXNUM;
+ exit;
+ end;
+ ',' : begin
+ actasmtoken := AS_COMMA;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '(' : begin
+ actasmtoken := AS_LPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ ')' : begin
+ actasmtoken := AS_RPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ ':' : begin
+ actasmtoken := AS_COLON;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+{ '.' : begin
+ actasmtoken := AS_DOT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end; }
+ '+' : begin
+ actasmtoken := AS_PLUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '-' : begin
+ actasmtoken := AS_MINUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '*' : begin
+ actasmtoken := AS_STAR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '/' : begin
+ actasmtoken := AS_SLASH;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '<' : begin
+ c := current_scanner.asmgetchar;
+ { invalid characters }
+ if c <> '<' then
+ Message(asmr_e_invalid_char_smaller);
+ { still assume << }
+ actasmtoken := AS_SHL;
+ c := current_scanner.asmgetchar;
+ exit;
+ end;
+ '>' : begin
+ c := current_scanner.asmgetchar;
+ { invalid characters }
+ if c <> '>' then
+ Message(asmr_e_invalid_char_greater);
+ { still assume << }
+ actasmtoken := AS_SHR;
+ c := current_scanner.asmgetchar;
+ exit;
+ end;
+ '|' : begin
+ actasmtoken := AS_OR;
+ c := current_scanner.asmgetchar;
+ exit;
+ end;
+ '^' : begin
+ actasmtoken := AS_XOR;
+ c := current_scanner.asmgetchar;
+ exit;
+ end;
+ '#' : begin
+ actasmtoken:=AS_APPT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '%' : begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0','1'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+ actasmtoken := AS_BINNUM;
+ exit;
+ end;
+ { integer number }
+ '0'..'9': begin
+ actasmpattern := c;
+ c := current_scanner.asmgetchar;
+ while c in ['0'..'9'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c:= current_scanner.asmgetchar;
+ end;
+ actasmtoken := AS_INTNUM;
+ exit;
+ end;
+ ';' : begin
+ repeat
+ c:=current_scanner.asmgetchar;
+ until c=#10;
+ firsttoken := TRUE;
+ actasmtoken:=AS_SEPARATOR;
+ end;
+
+ '{',#13,#10 : begin
+ c:=current_scanner.asmgetchar;
+ firsttoken := TRUE;
+ actasmtoken:=AS_SEPARATOR;
+ end;
+ else
+ begin
+ Message(scan_f_illegal_char);
+ end;
+
+ end; { end case }
+ end; { end else if }
+ end;
+
+
+ {---------------------------------------------------------------------}
+ { Routines for the parsing }
+ {---------------------------------------------------------------------}
+
+ function tm68kmotreader.consume(t : tasmtoken):boolean;
+ begin
+ Consume:=true;
+ if t<>actasmtoken then
+ begin
+ Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
+ Consume:=false;
+ end;
+ repeat
+ gettoken;
+ until actasmtoken<>AS_NONE;
+ end;
+
+
+ function tm68kmotreader.findopcode(s: string; var opsize: topsize): tasmop;
+ {*********************************************************************}
+ { FUNCTION findopcode(s: string): tasmop; }
+ { Description: Determines if the s string is a valid opcode }
+ { if so returns correct tasmop token. }
+ {*********************************************************************}
+ var
+ j: byte;
+ op_size: string;
+ begin
+ findopcode := A_NONE;
+ j:=pos('.',s);
+ if j<>0 then
+ begin
+ op_size:=copy(s,j+1,1);
+ case op_size[1] of
+ { For the motorola only opsize size is used to }
+ { determine the size of the operands. }
+ 'B': opsize := S_B;
+ 'W': opsize := S_W;
+ 'L': opsize := S_L;
+ 'S': opsize := S_FS;
+ 'D': opsize := S_FD;
+ 'X': opsize := S_FX;
+ else
+ Message1(asmr_e_unknown_opcode,s);
+ end;
+ { delete everything starting from dot }
+ delete(s,j,length(s));
+ end;
+ result:=actopcode;
+ end;
+
+
+
+
+ Function tm68kmotreader.BuildExpression(allow_symbol : boolean; asmsym : pstring) : longint;
+ {*********************************************************************}
+ { FUNCTION BuildExpression: longint }
+ { Description: This routine calculates a constant expression to }
+ { a given value. The return value is the value calculated from }
+ { the expression. }
+ { The following tokens (not strings) are recognized: }
+ { (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
+ {*********************************************************************}
+ { ENTRY: On entry the token should be any valid expression token. }
+ { EXIT: On Exit the token points to either COMMA or SEPARATOR }
+ { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+ { invalid tokens. }
+ {*********************************************************************}
+ var expr: string;
+ hs, tempstr: string;
+ sym : tsym;
+ srsymtable : tsymtable;
+ hl : tasmlabel;
+ l : longint;
+ errorflag: boolean;
+ begin
+ errorflag := FALSE;
+ expr := '';
+ tempstr := '';
+ if allow_symbol then
+ asmsym^:='';
+ Repeat
+ Case actasmtoken of
+ AS_LPAREN: begin
+ Consume(AS_LPAREN);
+ expr := expr + '(';
+ end;
+ AS_RPAREN: begin
+ Consume(AS_RPAREN);
+ expr := expr + ')';
+ end;
+ AS_SHL: begin
+ Consume(AS_SHL);
+ expr := expr + '<';
+ end;
+ AS_SHR: begin
+ Consume(AS_SHR);
+ expr := expr + '>';
+ end;
+ AS_SLASH: begin
+ Consume(AS_SLASH);
+ expr := expr + '/';
+ end;
+ AS_MOD: begin
+ Consume(AS_MOD);
+ expr := expr + '%';
+ end;
+ AS_STAR: begin
+ Consume(AS_STAR);
+ expr := expr + '*';
+ end;
+ AS_PLUS: begin
+ Consume(AS_PLUS);
+ expr := expr + '+';
+ end;
+ AS_MINUS: begin
+ Consume(AS_MINUS);
+ expr := expr + '-';
+ end;
+ AS_AND: begin
+ Consume(AS_AND);
+ expr := expr + '&';
+ end;
+ AS_NOT: begin
+ Consume(AS_NOT);
+ expr := expr + '~';
+ end;
+ AS_XOR: begin
+ Consume(AS_XOR);
+ expr := expr + '^';
+ end;
+ AS_OR: begin
+ Consume(AS_OR);
+ expr := expr + '|';
+ end;
+ AS_ID: begin
+ if SearchIConstant(actasmpattern,l) then
+ begin
+ str(l, tempstr);
+ expr := expr + tempstr;
+ Consume(AS_ID);
+ End else
+ if not allow_symbol then
+ begin
+ Message(asmr_e_syn_constant);
+ l := 0;
+ End else
+ begin
+ hs:='';
+ if (expr[Length(expr)]='+') then
+ Delete(expr,Length(expr),1)
+ else if expr<>'' then
+ begin
+ Message(asmr_e_invalid_constant_expression);
+ break;
+ End;
+ tempstr:=actasmpattern;
+ consume(AS_ID);
+ if (length(tempstr)>1) and (tempstr[1]='@') then
+ begin
+ CreateLocalLabel(tempstr,hl,false);
+ hs:=hl.name
+ end
+ else if SearchLabel(tempstr,hl,false) then
+ hs:=hl.name
+ else
+ begin
+ searchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ paravarsym,
+ localvarsym :
+ begin
+ Message(asmr_e_no_local_or_para_allowed);
+ hs:=tabstractvarsym(sym).mangledname;
+ end;
+ typedconstsym :
+ hs:=ttypedconstsym(sym).mangledname;
+ procsym :
+ begin
+ if tprocsym(sym).procdef_count>1 then
+ Message(asmr_w_calling_overload_func);
+ hs:=tprocsym(sym).first_procdef.mangledname;
+ end;
+ typesym :
+ begin
+ if not(ttypesym(sym).restype.def.deftype in [recorddef,objectdef]) then
+ Message(asmr_e_wrong_sym_type);
+ end;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ { symbol found? }
+ if hs<>'' then
+ begin
+ if asmsym^='' then
+ asmsym^:=hs
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ end;
+ end;
+ end;
+ AS_INTNUM: begin
+ expr := expr + actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_BINNUM: begin
+ tempstr := tostr(ParseVal(actasmpattern,2));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_binary);
+ expr:=expr+tempstr;
+ Consume(AS_BINNUM);
+ end;
+
+ AS_HEXNUM: begin
+ tempstr := tostr(ParseVal(actasmpattern,16));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_hexadecimal);
+ expr:=expr+tempstr;
+ Consume(AS_HEXNUM);
+ end;
+ AS_OCTALNUM: begin
+ tempstr := tostr(ParseVal(actasmpattern,8));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_octal);
+ expr:=expr+tempstr;
+ Consume(AS_OCTALNUM);
+ end;
+ { go to next term }
+ AS_COMMA: begin
+ if not ErrorFlag then
+ BuildExpression := CalculateExpression(expr)
+ else
+ BuildExpression := 0;
+ Exit;
+ end;
+ { go to next symbol }
+ AS_SEPARATOR: begin
+ if not ErrorFlag then
+ BuildExpression := CalculateExpression(expr)
+ else
+ BuildExpression := 0;
+ Exit;
+ end;
+ else
+ begin
+ { only write error once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag := TRUE;
+ End;
+ end;
+ Until false;
+ end;
+
+
+ Procedure tm68kmotreader.BuildRealConstant(typ : tfloattype);
+ {*********************************************************************}
+ { PROCEDURE BuilRealConst }
+ { Description: This routine calculates a constant expression to }
+ { a given value. The return value is the value calculated from }
+ { the expression. }
+ { The following tokens (not strings) are recognized: }
+ { +/-,numbers and real numbers }
+ {*********************************************************************}
+ { ENTRY: On entry the token should be any valid expression token. }
+ { EXIT: On Exit the token points to either COMMA or SEPARATOR }
+ { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+ { invalid tokens. }
+ {*********************************************************************}
+ var expr: string;
+ r : extended;
+ code : word;
+ negativ : boolean;
+ errorflag: boolean;
+ begin
+ errorflag := FALSE;
+ Repeat
+ negativ:=false;
+ expr := '';
+ if actasmtoken=AS_PLUS then Consume(AS_PLUS)
+ else if actasmtoken=AS_MINUS then
+ begin
+ negativ:=true;
+ consume(AS_MINUS);
+ end;
+ Case actasmtoken of
+ AS_INTNUM: begin
+ expr := actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_REALNUM: begin
+ expr := actasmpattern;
+ { in ATT syntax you have 0d in front of the real }
+ { should this be forced ? yes i think so, as to }
+ { conform to gas as much as possible. }
+ if (expr[1]='0') and (upper(expr[2])='D') then
+ expr:=copy(expr,3,255);
+ Consume(AS_REALNUM);
+ end;
+ AS_BINNUM: begin
+ { checking for real constants with this should use }
+ { real DECODING otherwise the compiler will crash! }
+ Message(asmr_e_invalid_float_expr);
+ expr:='0.0';
+ Consume(AS_BINNUM);
+ end;
+
+ AS_HEXNUM: begin
+ { checking for real constants with this should use }
+ { real DECODING otherwise the compiler will crash! }
+ Message(asmr_e_invalid_float_expr);
+ expr:='0.0';
+ Consume(AS_HEXNUM);
+ end;
+ AS_OCTALNUM: begin
+ { checking for real constants with this should use }
+ { real DECODING otherwise the compiler will crash! }
+ { xxxToDec using reals could be a solution, but the }
+ { problem is that these will crash the m68k compiler }
+ { when compiling -- because of lack of good fpu }
+ { support. }
+ Message(asmr_e_invalid_float_expr);
+ expr:='0.0';
+ Consume(AS_OCTALNUM);
+ end;
+ else
+ begin
+ { only write error once. }
+ if not errorflag then
+ Message(asmr_e_invalid_float_expr);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag := TRUE;
+ End;
+
+ end;
+ { go to next term }
+ if (actasmtoken=AS_COMMA) or (actasmtoken=AS_SEPARATOR) then
+ begin
+ if negativ then expr:='-'+expr;
+ val(expr,r,code);
+ if code<>0 then
+ begin
+ r:=0;
+ Message(asmr_e_invalid_float_expr);
+ ConcatRealConstant(curlist,r,typ);
+ End
+ else
+ begin
+ ConcatRealConstant(curlist,r,typ);
+ End;
+ end
+ else
+ Message(asmr_e_invalid_float_expr);
+ Until actasmtoken=AS_SEPARATOR;
+ end;
+
+
+ Procedure tm68kmotreader.BuildConstant(maxvalue: longint);
+ {*********************************************************************}
+ { PROCEDURE BuildConstant }
+ { Description: This routine takes care of parsing a DB,DD,or DW }
+ { line and adding those to the assembler node. Expressions, range- }
+ { checking are fullly taken care of. }
+ { maxvalue: $ff -> indicates that this is a DB node. }
+ { $ffff -> indicates that this is a DW node. }
+ { $ffffffff -> indicates that this is a DD node. }
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
+ {*********************************************************************}
+ var
+ expr: string;
+ value : longint;
+ begin
+ Repeat
+ Case actasmtoken of
+ AS_STRING: begin
+ if maxvalue <> $ff then
+ Message(asmr_e_string_not_allowed_as_const);
+ expr := actasmpattern;
+ if length(expr) > 1 then
+ Message(asmr_e_string_not_allowed_as_const);
+ Consume(AS_STRING);
+ Case actasmtoken of
+ AS_COMMA: Consume(AS_COMMA);
+ AS_SEPARATOR: ;
+ else
+ Message(asmr_e_invalid_string_expression);
+ end; { end case }
+ ConcatString(curlist,expr);
+ end;
+ AS_INTNUM,AS_BINNUM,
+ AS_OCTALNUM,AS_HEXNUM:
+ begin
+ value:=BuildExpression(false,nil);
+ ConcatConstant(curlist,value,maxvalue);
+ end;
+ AS_ID:
+ begin
+ value:=BuildExpression(false,nil);
+ if value > maxvalue then
+ begin
+ Message(asmr_e_constant_out_of_bounds);
+ { assuming a value of maxvalue }
+ value := maxvalue;
+ end;
+ ConcatConstant(curlist,value,maxvalue);
+ end;
+ { These terms can start an assembler expression }
+ AS_PLUS,AS_MINUS,AS_LPAREN,AS_NOT: begin
+ value := BuildExpression(false,nil);
+ ConcatConstant(curlist,value,maxvalue);
+ end;
+ AS_COMMA: begin
+ Consume(AS_COMMA);
+ END;
+ AS_SEPARATOR: ;
+
+ else
+ begin
+ Message(asmr_e_syntax_error);
+ end;
+ end; { end case }
+ Until actasmtoken = AS_SEPARATOR;
+ end;
+
+
+ Procedure TM68kMotreader.BuildScaling(const oper:tm68koperand);
+ {*********************************************************************}
+ { Takes care of parsing expression starting from the scaling value }
+ { up to and including possible field specifiers. }
+ { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR }
+ { or AS_COMMA. On entry should point to the AS_STAR token. }
+ {*********************************************************************}
+ var str:string;
+ l: longint;
+ code: integer;
+ begin
+ Consume(AS_STAR);
+ if (oper.opr.ref.scalefactor <> 0)
+ and (oper.opr.ref.scalefactor <> 1) then
+ Message(asmr_e_wrong_base_index);
+ case actasmtoken of
+ AS_INTNUM: str := actasmpattern;
+ AS_HEXNUM: str := Tostr(ParseVal(actasmpattern,16));
+ AS_BINNUM: str := Tostr(ParseVal(actasmpattern,2));
+ AS_OCTALNUM: str := Tostr(ParseVal(actasmpattern,8));
+ else
+ Message(asmr_e_syntax_error);
+ end;
+ val(str, l, code);
+ if code <> 0 then
+ Message(asmr_e_wrong_scale_factor);
+ if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
+ begin
+ oper.opr.ref.scalefactor := l;
+ end
+ else
+ begin
+ Message(asmr_e_wrong_scale_factor);
+ oper.opr.ref.scalefactor := 0;
+ end;
+ if oper.opr.ref.index = NR_NO then
+ begin
+ Message(asmr_e_wrong_base_index);
+ oper.opr.ref.scalefactor := 0;
+ end;
+ { Consume the scaling number }
+ Consume(actasmtoken);
+ if actasmtoken = AS_RPAREN then
+ Consume(AS_RPAREN)
+ else
+ Message(asmr_e_wrong_scale_factor);
+ { // .Field.Field ... or separator/comma // }
+ if actasmtoken in [AS_COMMA,AS_SEPARATOR] then
+ begin
+ end
+ else
+ Message(asmr_e_syntax_error);
+ end;
+
+
+ Function TM68kMotreader.BuildRefExpression: longint;
+ {*********************************************************************}
+ { FUNCTION BuildRefExpression: longint }
+ { Description: This routine calculates a constant expression to }
+ { a given value. The return value is the value calculated from }
+ { the expression. }
+ { The following tokens (not strings) are recognized: }
+ { SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
+ {*********************************************************************}
+ { ENTRY: On entry the token should be any valid expression token. }
+ { EXIT: On Exit the token points to the LPAREN token. }
+ { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+ { invalid tokens. }
+ {*********************************************************************}
+ var tempstr: string;
+ expr: string;
+ l : longint;
+ errorflag : boolean;
+ begin
+ errorflag := FALSE;
+ tempstr := '';
+ expr := '';
+ Repeat
+ Case actasmtoken of
+ AS_RPAREN: begin
+ Message(asmr_e_syntax_error);
+ Consume(AS_RPAREN);
+ end;
+ AS_SHL: begin
+ Consume(AS_SHL);
+ expr := expr + '<';
+ end;
+ AS_SHR: begin
+ Consume(AS_SHR);
+ expr := expr + '>';
+ end;
+ AS_SLASH: begin
+ Consume(AS_SLASH);
+ expr := expr + '/';
+ end;
+ AS_MOD: begin
+ Consume(AS_MOD);
+ expr := expr + '%';
+ end;
+ AS_STAR: begin
+ Consume(AS_STAR);
+ expr := expr + '*';
+ end;
+ AS_PLUS: begin
+ Consume(AS_PLUS);
+ expr := expr + '+';
+ end;
+ AS_MINUS: begin
+ Consume(AS_MINUS);
+ expr := expr + '-';
+ end;
+ AS_AND: begin
+ Consume(AS_AND);
+ expr := expr + '&';
+ end;
+ AS_NOT: begin
+ Consume(AS_NOT);
+ expr := expr + '~';
+ end;
+ AS_XOR: begin
+ Consume(AS_XOR);
+ expr := expr + '^';
+ end;
+ AS_OR: begin
+ Consume(AS_OR);
+ expr := expr + '|';
+ end;
+ { End of reference }
+ AS_LPAREN: begin
+ if not ErrorFlag then
+ BuildRefExpression := CalculateExpression(expr)
+ else
+ BuildRefExpression := 0;
+ { no longer in an expression }
+ exit;
+ end;
+ AS_ID:
+ begin
+ if NOT SearchIConstant(actasmpattern,l) then
+ begin
+ Message(asmr_e_syn_constant);
+ l := 0;
+ end;
+ str(l, tempstr);
+ expr := expr + tempstr;
+ Consume(AS_ID);
+ end;
+ AS_INTNUM: begin
+ expr := expr + actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_BINNUM: begin
+ tempstr := Tostr(ParseVal(actasmpattern,2));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_binary);
+ expr:=expr+tempstr;
+ Consume(AS_BINNUM);
+ end;
+
+ AS_HEXNUM: begin
+ tempstr := Tostr(ParseVal(actasmpattern,16));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_hexadecimal);
+ expr:=expr+tempstr;
+ Consume(AS_HEXNUM);
+ end;
+ AS_OCTALNUM: begin
+ tempstr := Tostr(ParseVal(actasmpattern,8));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_octal);
+ expr:=expr+tempstr;
+ Consume(AS_OCTALNUM);
+ end;
+ else
+ begin
+ { write error only once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ BuildRefExpression := 0;
+ if actasmtoken in [AS_COMMA,AS_SEPARATOR] then exit;
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag := TRUE;
+ end;
+ end;
+ Until false;
+ end;
+
+
+
+ {*********************************************************************}
+ { PROCEDURE BuildBracketExpression }
+ { Description: This routine builds up an expression after a LPAREN }
+ { token is encountered. }
+ { On entry actasmtoken should be equal to AS_LPAREN }
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to either the }
+ { AS_COMMA or AS_SEPARATOR token. }
+ {*********************************************************************}
+ procedure TM68kMotreader.BuildReference(const oper:tm68koperand);
+ var
+ l:longint;
+ code: integer;
+ str: string;
+ begin
+ Consume(AS_LPAREN);
+ case actasmtoken of
+ { // (reg ... // }
+ AS_REGISTER:
+ begin
+ oper.opr.ref.base := actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { // (reg) // }
+ { // (reg)+ // }
+ if actasmtoken=AS_RPAREN then
+ begin
+ Consume(AS_RPAREN);
+ if actasmtoken = AS_PLUS then
+ begin
+ if (oper.opr.ref.direction <> dir_none) then
+ Message(asmr_e_no_inc_and_dec_together)
+ else
+ oper.opr.ref.direction := dir_inc;
+ Consume(AS_PLUS);
+ end;
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ { error recovery ... }
+ while actasmtoken <> AS_SEPARATOR do
+ Consume(actasmtoken);
+ end;
+ exit;
+ end;
+ { // (reg,reg .. // }
+ Consume(AS_COMMA);
+ if actasmtoken = AS_REGISTER then
+ begin
+ oper.opr.ref.index :=
+ actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ case actasmtoken of
+ AS_RPAREN:
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+ begin
+ { error recovery ... }
+ Message(asmr_e_invalid_reference_syntax);
+ while actasmtoken <> AS_SEPARATOR do
+ Consume(actasmtoken);
+ end;
+ exit;
+ end;
+ AS_STAR:
+ begin
+ BuildScaling(oper);
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ while (actasmtoken <> AS_SEPARATOR) do
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ while (actasmtoken <> AS_SEPARATOR) do
+ Consume(actasmtoken);
+ end;
+ end;
+ AS_HEXNUM,AS_OCTALNUM, { direct address }
+ AS_BINNUM,AS_INTNUM:
+ begin
+ case actasmtoken of
+ AS_INTNUM: str := actasmpattern;
+ AS_HEXNUM: str := Tostr(ParseVal(actasmpattern,16));
+ AS_BINNUM: str := Tostr(ParseVal(actasmpattern,2));
+ AS_OCTALNUM: str := Tostr(ParseVal(actasmpattern,8));
+ else
+ Message(asmr_e_syntax_error);
+ end;
+ Consume(actasmtoken);
+ val(str, l, code);
+ if code <> 0 then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ oper.opr.ref.offset := l;
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+ begin
+ { error recovery ... }
+ Message(asmr_e_invalid_reference_syntax);
+ while actasmtoken <> AS_SEPARATOR do
+ Consume(actasmtoken);
+ end;
+ exit;
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ while (actasmtoken <> AS_SEPARATOR) do
+ Consume(actasmtoken);
+ end;
+ end;
+ end;
+
+
+
+
+ Procedure TM68kMotreader.BuildOperand(const oper:tm68koperand);
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to either the }
+ { AS_COMMA or AS_SEPARATOR token. }
+ {*********************************************************************}
+ var
+ tempstr: string;
+ lab: tasmlabel;
+ l : longint;
+ i: Tsuperregister;
+ r:Tregister;
+ hl: tasmlabel;
+ reg_one, reg_two: tregister;
+ regset: tcpuregisterset;
+ begin
+ regset := [];
+ tempstr := '';
+ case actasmtoken of
+ { // Memory reference // }
+ AS_LPAREN:
+ begin
+ Oper.InitRef;
+ BuildReference(oper);
+ end;
+ { // Constant expression // }
+ AS_APPT: begin
+ Consume(AS_APPT);
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ { identifiers are handled by BuildExpression }
+ oper.opr.typ := OPR_CONSTANT;
+ oper.opr.val :=BuildExpression(true,@tempstr);
+ if tempstr<>'' then
+ begin
+ l:=oper.opr.val;
+ oper.opr.typ := OPR_SYMBOL;
+ oper.opr.symofs := l;
+ oper.opr.symbol := objectlibrary.newasmsymbol(tempstr,AB_EXTERNAL,AT_FUNCTION);
+ end;
+ end;
+ { // Constant memory offset . // }
+ { // This must absolutely be followed by ( // }
+ AS_HEXNUM,AS_INTNUM,
+ AS_BINNUM,AS_OCTALNUM,AS_PLUS:
+ begin
+ Oper.InitRef;
+ oper.opr.ref.offset:=BuildRefExpression;
+ BuildReference(oper);
+ end;
+ { // A constant expression, or a Variable ref. // }
+ AS_ID: begin
+ Oper.InitRef;
+ if actasmpattern[1] = '@' then
+ { // Label or Special symbol reference // }
+ begin
+ if actasmpattern = '@RESULT' then
+ oper.SetUpResult
+ else
+ if actasmpattern = 'SELF' then
+ oper.SetUpSelf
+ else
+ if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
+ Message(asmr_w_CODE_and_DATA_not_supported)
+ else
+ begin
+ delete(actasmpattern,1,1);
+ if actasmpattern = '' then
+ Message(asmr_e_null_label_ref_not_allowed);
+ CreateLocalLabel(actasmpattern,lab,false);
+ oper.opr.typ := OPR_SYMBOL;
+ oper.opr.symbol := lab;
+ oper.opr.symofs := 0;
+// labeled := TRUE;
+ end;
+ Consume(AS_ID);
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ Message(asmr_e_syntax_error);
+ end
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ else
+ begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ begin
+ Oper.InitRef;
+ oper.opr.ref.offset:=BuildRefExpression;
+ BuildReference(oper);
+ end
+ else { is it a label variable ? }
+ begin
+ { // ID[ , ID.Field.Field or simple ID // }
+ { check if this is a label, if so then }
+ { emit it as a label. }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ oper.opr.typ := OPR_SYMBOL;
+ oper.opr.symbol := hl;
+ oper.opr.symofs := 0;
+// labeled := TRUE;
+ Consume(AS_ID);
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ Message(asmr_e_syntax_error);
+ end
+ else
+ Message1(sym_e_unknown_id,actasmpattern);
+
+ Consume(AS_ID);
+ case actasmtoken of
+ AS_LPAREN: { indexing }
+ BuildReference(oper);
+ AS_SEPARATOR,AS_COMMA: ;
+ else
+ Message(asmr_e_syntax_error);
+ end;
+
+ end;
+ end;
+ end;
+ { // Pre-decrement mode reference or constant mem offset. // }
+ AS_MINUS: begin
+ Consume(AS_MINUS);
+ if actasmtoken = AS_LPAREN then
+ begin
+ Oper.InitRef;
+ { indicate pre-decrement mode }
+ oper.opr.ref.direction := dir_dec;
+ BuildReference(oper);
+ end
+ else
+ if actasmtoken in [AS_OCTALNUM,AS_HEXNUM,AS_BINNUM,AS_INTNUM] then
+ begin
+ Oper.InitRef;
+ oper.opr.ref.offset:=BuildRefExpression;
+ { negate because was preceded by a negative sign! }
+ oper.opr.ref.offset:=-oper.opr.ref.offset;
+ BuildReference(oper);
+ end
+ else
+ begin
+ Message(asmr_e_syntax_error);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ end;
+ { // Register, a variable reference or a constant reference // }
+ AS_REGISTER: begin
+ { save the type of register used. }
+ tempstr := actasmpattern;
+ Consume(AS_REGISTER);
+ { // Simple register // }
+ if (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA) then
+ begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ := OPR_REGISTER;
+ oper.opr.reg := actasmregister;
+ end
+ else
+ { HERE WE MUST HANDLE THE SPECIAL CASE OF MOVEM AND FMOVEM }
+ { // Individual register listing // }
+ if (actasmtoken = AS_SLASH) then
+ begin
+ r:=actasmregister;
+ if getregtype(r)<>R_INTREGISTER then
+ internalerror(200302191);
+ include(regset,getsupreg(r));
+ Consume(AS_SLASH);
+ if actasmtoken = AS_REGISTER then
+ begin
+ While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ begin
+ case actasmtoken of
+ AS_REGISTER: begin
+ if getregtype(r)<>R_INTREGISTER then
+ internalerror(200302191);
+ include(regset,getsupreg(r));
+ Consume(AS_REGISTER);
+ end;
+ AS_SLASH: Consume(AS_SLASH);
+ AS_SEPARATOR,AS_COMMA: break;
+ else
+ begin
+ Message(asmr_e_invalid_reg_list_in_movem);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end; { end while }
+ oper.opr.typ:= OPR_regset;
+ oper.opr.regset := regset;
+ end
+ else
+ { error recovery ... }
+ begin
+ Message(asmr_e_invalid_reg_list_in_movem);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ end
+ else
+ { // Range register listing // }
+ if (actasmtoken = AS_MINUS) then
+ begin
+ Consume(AS_MINUS);
+ reg_one:=actasmregister;
+ if actasmtoken <> AS_REGISTER then
+ begin
+ Message(asmr_e_invalid_reg_list_in_movem);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end
+ else
+ begin
+ { determine the register range ... }
+ reg_two:=actasmregister;
+ if getregtype(reg_two)<>R_INTREGISTER then
+ internalerror(200302191);
+ if getsupreg(reg_one) > getsupreg(reg_two) then
+ for i:=getsupreg(reg_two) to getsupreg(reg_one) do
+ include(regset,i)
+ else
+ for i:=getsupreg(reg_one) to getsupreg(reg_two) do
+ include(regset,i);
+ Consume(AS_REGISTER);
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ begin
+ Message(asmr_e_invalid_reg_list_in_movem);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ { set up instruction }
+ oper.opr.typ:= OPR_regset;
+ oper.opr.regset := regset;
+ end;
+ end
+ else
+ { DIVSL/DIVS/MULS/MULU with long for MC68020 only }
+ if (actasmtoken = AS_COLON) then
+ begin
+ if (aktoptprocessor = MC68020) or (cs_compilesystem in aktmoduleswitches) then
+ begin
+ Consume(AS_COLON);
+ if (actasmtoken = AS_REGISTER) then
+ begin
+ { set up old field, since register is valid }
+ oper.opr.typ := OPR_REGISTER;
+ oper.opr.reg := actasmregister;
+ Inc(operandnum);
+ oper.opr.typ := OPR_REGISTER;
+ oper.opr.reg := actasmregister;
+ Consume(AS_REGISTER);
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ begin
+ Message(asmr_e_invalid_reg_list_for_opcode);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ end;
+ end
+ else
+ begin
+ Message1(asmr_e_higher_cpu_mode_required,'68020');
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ begin
+ Message(asmr_e_invalid_reg_list_for_opcode);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ end;
+ end
+ else
+ Message(asmr_e_invalid_register);
+ end;
+ AS_SEPARATOR, AS_COMMA: ;
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+
+ Procedure tm68kmotreader.BuildStringConstant(asciiz: boolean);
+ {*********************************************************************}
+ { PROCEDURE BuildStringConstant }
+ { Description: Takes care of a ASCII, or ASCIIZ directive. }
+ { asciiz: boolean -> if true then string will be null terminated. }
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
+ { On ENTRY: Token should point to AS_STRING }
+ {*********************************************************************}
+ var
+ expr: string;
+ errorflag : boolean;
+ begin
+ errorflag := FALSE;
+ Repeat
+ Case actasmtoken of
+ AS_STRING: begin
+ expr:=actasmpattern;
+ if asciiz then
+ expr:=expr+#0;
+ ConcatPasString(curlist,expr);
+ Consume(AS_STRING);
+ end;
+ AS_COMMA: begin
+ Consume(AS_COMMA);
+ END;
+ AS_SEPARATOR: ;
+ else
+ begin
+ Consume(actasmtoken);
+ if not errorflag then
+ Message(asmr_e_invalid_string_expression);
+ errorflag := TRUE;
+ end;
+ end; { end case }
+ Until actasmtoken = AS_SEPARATOR;
+ end;
+
+
+ Procedure TM68kmotReader.BuildOpCode(instr:Tm68kinstruction);
+ {*********************************************************************}
+ { PROCEDURE BuildOpcode; }
+ { Description: Parses the intel opcode and operands, and writes it }
+ { in the TInstruction object. }
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
+ { On ENTRY: Token should point to AS_OPCODE }
+ {*********************************************************************}
+ var
+ operandnum : longint;
+ begin
+ { // opcode // }
+ { allow for newline as in gas styled syntax }
+ { under DOS you get two AS_SEPARATOR !! }
+ while actasmtoken=AS_SEPARATOR do
+ Consume(AS_SEPARATOR);
+ if (actasmtoken <> AS_OPCODE) then
+ begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ { error recovery }
+ While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ exit;
+ end
+ else
+ begin
+ Instr.opcode := findopcode(actasmpattern,instr.opsize);
+ Consume(AS_OPCODE);
+ { // Zero operand opcode ? // }
+ if actasmtoken = AS_SEPARATOR then
+ exit
+ else
+ operandnum := 1;
+ end;
+
+ While actasmtoken <> AS_SEPARATOR do
+ begin
+ case actasmtoken of
+ { // Operand delimiter // }
+ AS_COMMA: begin
+ if operandnum > Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+ { // End of asm operands for this opcode // }
+ AS_SEPARATOR: ;
+ else
+ BuildOperand(Instr.Operands[operandnum] as tm68koperand);
+ end; { end case }
+ end; { end while }
+ end;
+
+
+
+
+ function tm68kmotreader.Assemble: tlinkedlist;
+ var
+ hl: tasmlabel;
+ instr : TM68kInstruction;
+ begin
+ Message(asmr_d_start_reading);
+ firsttoken := TRUE;
+ operandnum := 0;
+ { sets up all opcode and register tables in uppercase }
+ if not _asmsorted then
+ begin
+ SetupTables;
+ _asmsorted := TRUE;
+ end;
+ curlist:=TAAsmoutput.Create;
+ { setup label linked list }
+ LocalLabelList:=TLocalLabelList.Create;
+ c:=current_scanner.asmgetchar;
+ gettoken;
+ while actasmtoken<>AS_END do
+ begin
+ case actasmtoken of
+ AS_LLABEL:
+ begin
+ if CreateLocalLabel(actasmpattern,hl,true) then
+ ConcatLabel(curlist,hl);
+ Consume(AS_LLABEL);
+ end;
+ AS_LABEL:
+ begin
+ { when looking for Pascal labels, these must }
+ { be in uppercase. }
+ if SearchLabel(upper(actasmpattern),hl,true) then
+ ConcatLabel(curlist,hl)
+ else
+ Message1(asmr_e_unknown_label_identifier,actasmpattern);
+ Consume(AS_LABEL);
+ end;
+ AS_DW:
+ begin
+ Consume(AS_DW);
+ BuildConstant($ffff);
+ end;
+ AS_DB:
+ begin
+ Consume(AS_DB);
+ BuildConstant($ff);
+ end;
+ AS_DD:
+ begin
+ Consume(AS_DD);
+ BuildConstant(longint($ffffffff));
+ end;
+ AS_XDEF:
+ begin
+ Consume(AS_XDEF);
+ if actasmtoken=AS_ID then
+ ConcatPublic(curlist,actasmpattern);
+ Consume(AS_ID);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+ AS_ALIGN:
+ begin
+ Message(asmr_w_align_not_supported);
+ while actasmtoken <> AS_SEPARATOR do
+ Consume(actasmtoken);
+ end;
+ AS_OPCODE:
+ begin
+ instr:=TM68kInstruction.Create(tm68koperand);
+ BuildOpcode(instr);
+{ instr.AddReferenceSizes;}
+{ instr.SetInstructionOpsize;}
+{ instr.CheckOperandSizes;}
+ if instr.labeled then
+ instr.ConcatLabeledInstr(curlist)
+ else
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+{
+ instr.init;
+ BuildOpcode;
+ instr.ops := operandnum;
+ if instr.labeled then
+ ConcatLabeledInstr(instr)
+ else
+ ConcatOpCode(instr);
+ instr.done;}
+ end;
+ AS_SEPARATOR:
+ begin
+ Consume(AS_SEPARATOR);
+ { let us go back to the first operand }
+ operandnum := 0;
+ end;
+ AS_END:
+ { end assembly block }
+ ;
+ else
+ begin
+ Message(asmr_e_syntax_error);
+ { error recovery }
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end; { end while }
+
+ { Check LocalLabelList }
+ LocalLabelList.CheckEmitted;
+ LocalLabelList.Free;
+
+ assemble:=curlist;
+ Message(asmr_d_finish_reading);
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_m68k_mot_info : tasmmodeinfo =
+ (
+ id : asmmode_m68k_mot;
+ idtxt : 'MOTOROLA';
+ casmreader : tm68kmotreader;
+ );
+
+ asmmode_m68k_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : tm68kmotreader;
+ );
+
+begin
+ RegisterAsmMode(asmmode_m68k_mot_info);
+ RegisterAsmMode(asmmode_m68k_standard_info);
+end.
diff --git a/compiler/m68k/rgcpu.pas b/compiler/m68k/rgcpu.pas
new file mode 100644
index 0000000000..4911fca540
--- /dev/null
+++ b/compiler/m68k/rgcpu.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the register allocator for m68k
+
+ 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 rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ end;
+
+ implementation
+
+end.
diff --git a/compiler/make_old.cmd b/compiler/make_old.cmd
new file mode 100644
index 0000000000..3cf59da9ca
--- /dev/null
+++ b/compiler/make_old.cmd
@@ -0,0 +1,65 @@
+@echo off
+rem $id: make.cmd,v $
+rem
+rem ************************Make batchfile for OS/2****************************
+rem * Purpose: The makefile contains a lot of Unix commands. While it is *
+rem * possible to install for example a bash shell under OS/2 *
+rem * a batch file is much easier. *
+rem * *
+rem * Copyright (c) 1998-2000 by Daniel Mantione, developer of Free Pascal *
+rem ***************************************************************************
+
+goto %1
+
+:clean
+pushd
+\pp\rtl\
+del /s *.ppo *.so2 *.oo2 *.ppu *.s *.o *.pp1 *.s1 *.o1>&dev\nul
+popd
+del *.ppo *.so2 *.oo2 *.ppu *.s *.o *.pp1 *.s1 *.o1>&dev\nul
+goto eind
+
+:prtx
+pushd
+\pp\rtl\os2\
+iff not exist prt0.oo2 then
+ as -o prt0.oo2 prt0.as
+endiff
+iff not exist prt1.oo2 then
+ as -o prt1.oo2 prt1.as
+endiff
+iff not exist code2.oo2 then
+ as -o code2.oo2 code2.as
+endiff
+iff not exist code3.oo2 then
+ as -o code3.oo2 code3.as
+endiff
+popd
+goto eind
+
+:compiler
+call make prtx
+iff "%2"=="" then
+ ppos2 pp.pas
+else
+ %2 pp.pas
+endiff
+goto eind
+
+:remake
+call make clean
+call make compiler %2
+goto eind
+
+:cycle
+call make remake %2
+move pp.exe pp1.exe
+call make remake pp1.exe
+move pp.exe pp2.exe
+call make remake pp2.exe
+move pp.exe pp3.exe
+goto eind
+
+$log: make.cmd,v$
+
+:eind
diff --git a/compiler/mdppc386.bat b/compiler/mdppc386.bat
new file mode 100644
index 0000000000..a47a491a3a
--- /dev/null
+++ b/compiler/mdppc386.bat
@@ -0,0 +1,2 @@
+dcc32 -Di386 -DGDB -Ddelphi -CC -Ui386 -Utargets -E. -N. -$O- ppc.dpr %1 %2 %3 %4 %5 %6 %7 %8 %9
+
diff --git a/compiler/mips/aasmcpu.pas b/compiler/mips/aasmcpu.pas
new file mode 100644
index 0000000000..65fdaa2e16
--- /dev/null
+++ b/compiler/mips/aasmcpu.pas
@@ -0,0 +1,339 @@
+{
+ Copyright (c) 2003 by Florian Klaempfl
+
+ Contains the assembler object for MIPS
+
+ 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;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,aasmtai,
+ aasmbase,globtype,globals,verbose,
+ cpubase,cpuinfo,cgbase,cgutils;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 1;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 0;
+
+ type
+ taicpu = class(tai_cpu_abstract)
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : longint);
+
+ 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_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
+
+ 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);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+
+ 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);
+
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+ 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;
+
+
+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_const(op : tasmop;_op1 : longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(0,aint(_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_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_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_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_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_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_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_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.spilling_get_operation_type(opnr: longint): topertype;
+ 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;
+ else
+ internalerror(200403151);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+end.
diff --git a/compiler/mips/cpubase.pas b/compiler/mips/cpubase.pas
new file mode 100644
index 0000000000..fb8177b8a9
--- /dev/null
+++ b/compiler/mips/cpubase.pas
@@ -0,0 +1,491 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Contains the base types for the ARM
+
+ 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.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+ enumerations of registers, opcodes, sizes, and other
+ such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,
+ cpuinfo,
+ aasmbase,
+ cgbase
+ ;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp=(A_ABS_D,A_ABS_S,A_ADD,A_ADD_D,A_ADD_S,A_ADDI,A_ADDIU,A_ADDU,
+ A_AND,A_ANDI,A_BC1F,A_BC1FL,A_BC1T,A_BC1TL,A_BC2F,A_BC2FL,
+ A_BC2T,A_BC2TL,A_BEQ,A_BEQL,A_BGEZ,A_BGEZAL,A_BGEZALL,A_BGEZL,
+ A_BGTZ,A_BGTZL,A_BLEZ,A_BLEZL,A_BLTZ,A_BLTZAL,A_BLTZALL,A_BLTZL,
+ A_BNE,A_BNEL,A_BREAK,A_C_cond_D,A_C_cond_S,A_CACHE,A_CEIL_W_D,A_CEIL_W_S,
+ A_CFC1,A_CFC2,A_CLO,A_CLZ,A_COP2,A_CTC1,A_CTC2,A_CVT_D_S,
+ A_CVT_D_W,A_CVT_S_D,A_CVT_S_W,A_CVT_W_D,A_CVT_W_S,A_DIV,A_DIV_D,A_DIV_S,
+ A_DIVU,A_ERET,A_FLOOR_W_D,A_FLOOR_W_S,A_J,A_JAL,A_JALR,A_JR,
+ A_LB,A_LBU,A_LDC1,A_LDC2,A_LH,A_LHU,A_LL,A_LUI,
+ A_LW,A_LWC1,A_LWC2,A_LWL,A_LWR,A_MADD,A_MADDU,A_MFC0,
+ A_MFC1,A_MFC2,A_MFHI,A_MFLO,A_MOV_D,A_MOV_S,A_MOVF,A_MOVF_D,
+ A_MOVF_S,A_MOVN,A_MOVN_D,A_MOVN_S,A_MOVT,A_MOVT_D,A_MOVT_S,A_MOVZ,
+ A_MOVZ_D,A_MOVZ_S,A_MSUB,A_MSUBU,A_MTC0,A_MTC1,A_MTC2,A_MTHI,
+ A_MTLO,A_MUL,A_MUL_D,A_MUL_S,A_MULT,A_MULTU,A_NEG_D,A_NEG_S,
+ A_NOR,A_OR,A_ORI,A_PREF,A_ROUND_W_D,A_ROUND_W_S,A_SB,A_SC,
+ A_SDC1,A_SDC2,A_SH,A_SLL,A_SLLV,A_SLT,A_SLTI,A_SLTIU,
+ A_SLTU,A_SQRT_D,A_SQRT_S,A_SRA,A_SRAV,A_SRL,A_SRLV,A_SSNOP,
+ A_SUB,A_SUB_D,A_SUB_S,A_SUBU,A_SW,A_SWC1,A_SWC2,A_SWL,
+ A_SWR,A_SYNC,A_SYSCALL,A_TEQ,A_TEQI,A_TGE,A_TGEI,A_TGEIU,
+ A_TGEU,A_TLBP,A_TLBR,A_TLBWI,A_TLBWR,A_TLT,A_TLTI,A_TLTIU,
+ A_TLTU,A_TNE,A_TNEI,A_TRUNC_W_D,A_TRUNC_W_S,A_WAIT,A_XOR,A_XORI
+ );
+
+ { This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ const
+ { First value of opcode enumeration }
+ firstop = low(tasmop);
+ { Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rmipsnor.inc}-1;
+
+ const
+ { Available Superregisters }
+ {$i rmipssup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+ {$i rmipscon.inc}
+
+ { Integer Super registers first and last }
+ first_int_supreg = RS_R0;
+ first_int_imreg = $10;
+
+ { Float Super register first and last }
+ first_fpu_supreg = RS_F0;
+ first_fpu_imreg = $08;
+
+ { MM Super register first and last }
+ first_mm_supreg = RS_NO;
+ first_mm_imreg = RS_NO;
+
+{$warning TODO Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rmipsnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i rmipssta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i rmipsdwf.inc}
+ );
+ { registers which may be destroyed by calls }
+ VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R15];
+ VOLATILE_FPUREGISTERS = [RS_F0..RS_F3];
+
+ type
+ totherregisterset = set of tregisterindex;
+
+{*****************************************************************************
+ Instruction post fixes
+*****************************************************************************}
+ type
+ { ARM instructions load/store and arithmetic instructions
+ can have several instruction post fixes which are collected
+ in this enumeration
+ }
+ TOpPostfix = (PF_None,
+ { update condition flags
+ or floating point single }
+ PF_S,
+ { floating point size }
+ PF_D,PF_E,PF_P,PF_EP,
+ { load/store }
+ PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
+ { multiple load/store address modes }
+ PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA
+ );
+
+ TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
+
+ const
+ cgsize2fpuoppostfix : array[OS_NO..OS_F128] of toppostfix = (
+ PF_E,
+ PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,
+ PF_S,PF_D,PF_E,PF_None,PF_None);
+
+ oppostfix2str : array[TOpPostfix] of string[2] = ('',
+ 's',
+ 'd','e','p','ep',
+ 'b','sb','bt','h','sh','t',
+ 'ia','ib','da','db','fd','fa','ed','ea');
+
+ roundingmode2str : array[TRoundingMode] of string[1] = ('',
+ 'p','m','z');
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+ C_GE,C_LT,C_GT,C_LE,C_AL,C_NV
+ );
+
+ const
+ cond2str : array[TAsmCond] of string[2]=('',
+ 'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls',
+ 'ge','lt','gt','le','al','nv'
+ );
+
+ uppercond2str : array[TAsmCond] of string[2]=('',
+ 'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS',
+ 'GE','LT','GT','LE','AL','NV'
+ );
+
+ inverse_cond : array[TAsmCond] of TAsmCond=(C_None,
+ C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
+ C_LT,C_GE,C_LE,C_GT,C_None,C_None
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
+ F_GE,F_LT,F_GT,F_LE);
+
+{*****************************************************************************
+ Operands
+*****************************************************************************}
+
+ taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
+ tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX);
+
+ tupdatereg = (UR_None,UR_Update);
+
+ pshifterop = ^tshifterop;
+
+ tshifterop = record
+ shiftmode : tshiftmode;
+ rs : tregister;
+ shiftimm : byte;
+ end;
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 4;
+
+ { Constant defining possibly all registers which might require saving }
+ ALL_OTHERREGISTERS = [];
+
+ general_superregisters = [RS_R0..RS_PC];
+
+ { Table of registers which can be allocated by the code generator
+ internally, when generating the code.
+ }
+ { legend: }
+ { xxxregs = set of all possibly used registers of that type in the code }
+ { generator }
+ { usableregsxxx = set of all 32bit components of registers that can be }
+ { possible allocated to a regvar or using getregisterxxx (this }
+ { excludes registers which can be only used for parameter }
+ { passing on ABI's that define this) }
+ { c_countusableregsxxx = amount of registers in the usableregsxxx set }
+
+ maxintregs = 15;
+ { to determine how many registers to use for regvars }
+ maxintscratchregs = 3;
+ usableregsint = [RS_R4..RS_R10];
+ c_countusableregsint = 7;
+
+ maxfpuregs = 8;
+ fpuregs = [RS_F0..RS_F7];
+ usableregsfpu = [RS_F4..RS_F7];
+ c_countusableregsfpu = 4;
+
+ mmregs = [RS_NO..RS_NO];
+ usableregsmm = [RS_NO..RS_NO];
+ c_countusableregsmm = 0;
+
+ maxaddrregs = 0;
+ addrregs = [];
+ usableregsaddr = [];
+ c_countusableregsaddr = 0;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_BW,S_BL,S_WL,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
+ );
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ maxvarregs = 7;
+ varregs : Array [1..maxvarregs] of tsuperregister =
+ (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+
+ maxfpuvarregs = 4;
+ fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
+ (RS_F4,RS_F5,RS_F6,RS_F7);
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ { the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M32;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ { Stack pointer register }
+ NR_STACK_POINTER_REG = NR_R13;
+ RS_STACK_POINTER_REG = RS_R13;
+ { Frame pointer register }
+ RS_FRAME_POINTER_REG = RS_R11;
+ NR_FRAME_POINTER_REG = NR_R11;
+ { Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+ NR_PIC_OFFSET_REG = NR_R9;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R0;
+ RS_FUNCTION_RETURN_REG = RS_R0;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_R0;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_R0;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ NR_FPU_RESULT_REG = NR_F0;
+
+ NR_MM_RESULT_REG = NR_NO;
+
+ NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
+
+ { Offset where the parent framepointer is pushed }
+ PARENT_FRAMEPOINTER_OFFSET = 0;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..8] of tsuperregister =
+ (RS_R16,RS_R17,RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R30);
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ function is_calljmp(o:tasmop):boolean;
+ procedure inverse_flags(var f: TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ procedure shifterop_reset(var so : tshifterop);
+ function is_pc(const r : tregister) : boolean;
+
+ implementation
+
+ uses
+ rgBase,verbose;
+
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i rmipsstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i rmipsrni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rmipssri.inc}
+ );
+
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ begin
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ const subreg2cgsize:array[Tsubregister] of Tcgsize =
+ (OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO,OS_NO);
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ reg_cgsize:=OS_32;
+ R_FPUREGISTER :
+ reg_cgsize:=OS_F80;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
+ To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
+ is_calljmp:= o in [A_J,A_JAL,A_JALR,{ A_JALX, }A_JR,
+ A_BEQ,A_BNE,A_BGEZ,A_BGEZAL,A_BGTZ,A_BLEZ,A_BLTZ,A_BLTZAL,
+ A_BEQL,A_BGEZALL,A_BGEZL,A_BGTZL,A_BLEZL,A_BLTZALL,A_BLTZL,A_BNEL];
+ end;
+
+
+ procedure inverse_flags(var f: TResFlags);
+ const
+ inv_flags: array[TResFlags] of TResFlags =
+ (F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI,
+ F_LT,F_GE,F_LE,F_GT);
+ begin
+ f:=inv_flags[f];
+ end;
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const
+ flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
+ (C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+ C_GE,C_LT,C_GT,C_LE);
+ begin
+ if f>high(flag_2_cond) then
+ internalerror(200112301);
+ result:=flag_2_cond[f];
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ procedure shifterop_reset(var so : tshifterop);
+ begin
+ FillChar(so,sizeof(so),0);
+ end;
+
+
+ function is_pc(const r : tregister) : boolean;
+ begin
+ is_pc:=(r=NR_R15);
+ end;
+
+end.
diff --git a/compiler/mips/cpuinfo.pas b/compiler/mips/cpuinfo.pas
new file mode 100644
index 0000000000..6dc7979f70
--- /dev/null
+++ b/compiler/mips/cpuinfo.pas
@@ -0,0 +1,72 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the ARM
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = type double;
+ ts128real = type double;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors =
+ (no_processor,
+ mips32
+ );
+
+ tfputype =
+ (no_fpuprocessor,
+ fpu_fpu
+ );
+
+Const
+ {# Size of native extended floating point type }
+ extended_size = 8;
+ {# Size of a multimedia register }
+ mmreg_size = 0;
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'mips';
+
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { same as stdcall only different name mangling }
+ pocall_cdecl,
+ { same as stdcall only different name mangling }
+ pocall_cppdecl
+ ];
+
+ processorsstr : array[tprocessors] of string[5] = ('',
+ 'MIPS32'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'FPU'
+ );
+
+
+Implementation
+
+end.
diff --git a/compiler/mips/itcpugas.pas b/compiler/mips/itcpugas.pas
new file mode 100644
index 0000000000..c1fa15d809
--- /dev/null
+++ b/compiler/mips/itcpugas.pas
@@ -0,0 +1,116 @@
+{
+ Copyright (c) 1998-2005 by Florian Klaempfl
+
+ This unit contains the MIPS GAS instruction tables
+
+ 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 itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+
+ const
+ { Standard opcode string table (for each tasmop enumeration). The
+ opcode strings should conform to the names as defined by the
+ processor manufacturer.
+ }
+ gas_op2str : op2strtable = (
+ 'abs_d','abs_s','add','add_d','add_s','addi','addiu','addu',
+ 'and','andi','bc1f','bc1fl','bc1t','bc1tl','bc2f','bc2fl',
+ 'bc2t','bc2tl','beq','beql','bgez','bgezal','bgezall','bgezl',
+ 'bgtz','bgtzl','blez','blezl','bltz','bltzal','bltzall','bltzl',
+ 'bne','bnel','break','c_cond_d','c_cond_s','cache','ceil_w_d','ceil_w_s',
+ 'cfc1','cfc2','clo','clz','cop2','ctc1','ctc2','cvt_d_s',
+ 'cvt_d_w','cvt_s_d','cvt_s_w','cvt_w_d','cvt_w_s','div','div_d','div_s',
+ 'divu','eret','floor_w_d','floor_w_s','j','jal','jalr','jr',
+ 'lb','lbu','ldc1','ldc2','lh','lhu','ll','lui',
+ 'lw','lwc1','lwc2','lwl','lwr','madd','maddu','mfc0',
+ 'mfc1','mfc2','mfhi','mflo','mov_d','mov_s','movf','movf_d',
+ 'movf_s','movn','movn_d','movn_s','movt','movt_d','movt_s','movz',
+ 'movz_d','movz_s','msub','msubu','mtc0','mtc1','mtc2','mthi',
+ 'mtlo','mul','mul_d','mul_s','mult','multu','neg_d','neg_s',
+ 'nor','or','ori','pref','round_w_d','round_w_s','sb','sc',
+ 'sdc1','sdc2','sh','sll','sllv','slt','slti','sltiu',
+ 'sltu','sqrt_d','sqrt_s','sra','srav','srl','srlv','ssnop',
+ 'sub','sub_d','sub_s','subu','sw','swc1','swc2','swl',
+ 'swr','sync','syscall','teq','teqi','tge','tgei','tgeiu',
+ 'tgeu','tlbp','tlbr','tlbwi','tlbwr','tlt','tlti','tltiu',
+ 'tltu','tne','tnei','trunc_w_d','trunc_w_s','wait','xor','xori'
+ );
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose;
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {$i rmipsgas.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rmipssri.inc}
+ );
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/compiler/mips/mipsreg.dat b/compiler/mips/mipsreg.dat
new file mode 100644
index 0000000000..c666d257cf
--- /dev/null
+++ b/compiler/mips/mipsreg.dat
@@ -0,0 +1,83 @@
+;
+; MIPS registers
+;
+; layout
+; <name>,<value>,<stdname>,<gasname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,-1,-1
+
+R0,$01,$00,r0,r0,0,0
+R1,$01,$01,r1,r1,1,1
+R2,$01,$02,r2,r2,2,2
+R3,$01,$03,r3,r3,3,3
+R4,$01,$04,r4,r4,4,4
+R5,$01,$05,r5,r5,5,5
+R6,$01,$06,r6,r6,6,6
+R7,$01,$07,r7,r7,7,7
+R8,$01,$08,r8,r8,8,8
+R9,$01,$09,r9,r9,9,9
+R10,$01,$0a,r10,r10,10,10
+R11,$01,$0b,r11,r11,11,11
+R12,$01,$0c,r12,r12,12,12
+R13,$01,$0d,r13,r13,13,13
+R14,$01,$0e,r14,r14,14,14
+R15,$01,$0f,r15,r15,15,15
+R16,$01,$10,r16,r16,16,16
+R17,$01,$11,r17,r17,17,17
+R18,$01,$12,r18,r18,18,18
+R19,$01,$13,r19,r19,19,19
+R20,$01,$14,r20,r20,20,20
+R21,$01,$15,r21,r21,21,21
+R22,$01,$16,r22,r22,22,22
+R23,$01,$17,r23,r23,23,23
+R24,$01,$18,r24,r24,24,24
+R25,$01,$19,r25,r25,25,25
+R26,$01,$1a,r26,r26,26,26
+R27,$01,$1b,r27,r27,27,27
+R28,$01,$1c,r28,r28,28,28
+R29,$01,$1d,r29,r29,29,29
+R30,$01,$1e,r30,r30,30,30
+R31,$01,$1f,r31,r31,31,31
+
+F0,$02,$00,F0,f0,32,32
+F1,$02,$01,F1,f1,33,33
+F2,$02,$02,F2,f2,34,34
+F3,$02,$03,F3,f3,35,35
+F4,$02,$04,F4,f4,36,36
+F5,$02,$05,F5,f5,37,37
+F6,$02,$06,F6,f6,38,38
+F7,$02,$07,F7,f7,39,39
+F8,$02,$08,F8,f8,40,40
+F9,$02,$09,F9,f9,41,41
+F10,$02,$0a,F10,f10,42,42
+F11,$02,$0b,F11,f11,43,43
+F12,$02,$0c,F12,f12,44,44
+F13,$02,$0d,F13,f13,45,45
+F14,$02,$0e,F14,f14,46,46
+F15,$02,$0f,F15,f15,47,47
+F16,$02,$10,F16,f16,48,48
+F17,$02,$11,F17,f17,49,49
+F18,$02,$12,F18,f18,50,50
+F19,$02,$13,F19,f19,51,51
+F20,$02,$14,F20,f20,52,52
+F21,$02,$15,F21,f21,53,53
+F22,$02,$16,F22,f22,54,54
+F23,$02,$17,F23,f23,55,55
+F24,$02,$18,F24,f24,56,56
+F25,$02,$19,F25,f25,57,57
+F26,$02,$1a,F26,f26,58,58
+F27,$02,$1b,F27,f27,59,59
+F28,$02,$1c,F28,f28,60,60
+F29,$02,$1d,F29,f29,61,61
+F30,$02,$1e,F30,f30,62,62
+F31,$02,$1f,F31,f31,63,63
+
+PC,$05,$00,PC,pc,-1,-1
+HI,$05,$01,HI,hi,68,68
+LO,$05,$02,LO,lo,69,69
+CR,$05,$03,CR,cr,70,70
+FCR0,$05,$04,FCR0,fcr0,71,71
+FCR25,$05,$05,FCR25,fcr25,72,72
+FCR26,$05,$06,FCR26,fcr26,73,73
+FCR28,$05,$07,FCR28,fcr28,74,74
+FCSR,$05,$08,FCSR,fcsr,75,75
diff --git a/compiler/mips/rmipscon.inc b/compiler/mips/rmipscon.inc
new file mode 100644
index 0000000000..e4dedd516e
--- /dev/null
+++ b/compiler/mips/rmipscon.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_R16 = tregister($01000010);
+NR_R17 = tregister($01000011);
+NR_R18 = tregister($01000012);
+NR_R19 = tregister($01000013);
+NR_R20 = tregister($01000014);
+NR_R21 = tregister($01000015);
+NR_R22 = tregister($01000016);
+NR_R23 = tregister($01000017);
+NR_R24 = tregister($01000018);
+NR_R25 = tregister($01000019);
+NR_R26 = tregister($0100001a);
+NR_R27 = tregister($0100001b);
+NR_R28 = tregister($0100001c);
+NR_R29 = tregister($0100001d);
+NR_R30 = tregister($0100001e);
+NR_R31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_PC = tregister($05000000);
+NR_HI = tregister($05000001);
+NR_LO = tregister($05000002);
+NR_CR = tregister($05000003);
+NR_FCR0 = tregister($05000004);
+NR_FCR25 = tregister($05000005);
+NR_FCR26 = tregister($05000006);
+NR_FCR28 = tregister($05000007);
+NR_FCSR = tregister($05000008);
diff --git a/compiler/mips/rmipsdwf.inc b/compiler/mips/rmipsdwf.inc
new file mode 100644
index 0000000000..35598a2ffe
--- /dev/null
+++ b/compiler/mips/rmipsdwf.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75
diff --git a/compiler/mips/rmipsgas.inc b/compiler/mips/rmipsgas.inc
new file mode 100644
index 0000000000..b81050d8c8
--- /dev/null
+++ b/compiler/mips/rmipsgas.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'pc',
+'hi',
+'lo',
+'cr',
+'fcr0',
+'fcr25',
+'fcr26',
+'fcr28',
+'fcsr'
diff --git a/compiler/mips/rmipsgri.inc b/compiler/mips/rmipsgri.inc
new file mode 100644
index 0000000000..a52df4ffa7
--- /dev/null
+++ b/compiler/mips/rmipsgri.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+0,
+68,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+69,
+70,
+71,
+72,
+73,
+66,
+67,
+65,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/compiler/mips/rmipsgss.inc b/compiler/mips/rmipsgss.inc
new file mode 100644
index 0000000000..c618ae3c54
--- /dev/null
+++ b/compiler/mips/rmipsgss.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'pc',
+'hi',
+'lo',
+'cr',
+'fcr0',
+'fcr25',
+'fcr26',
+'fcr28',
+'fcsr'
diff --git a/compiler/mips/rmipsmot.inc b/compiler/mips/rmipsmot.inc
new file mode 100644
index 0000000000..7f44888e61
--- /dev/null
+++ b/compiler/mips/rmipsmot.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'PC',
+'HI',
+'LO',
+'CR',
+'FCR0',
+'FCR25',
+'FCR26',
+'FCR28',
+'FCSR'
diff --git a/compiler/mips/rmipsmri.inc b/compiler/mips/rmipsmri.inc
new file mode 100644
index 0000000000..68f2626c88
--- /dev/null
+++ b/compiler/mips/rmipsmri.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
diff --git a/compiler/mips/rmipsnor.inc b/compiler/mips/rmipsnor.inc
new file mode 100644
index 0000000000..a03cbf0309
--- /dev/null
+++ b/compiler/mips/rmipsnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from mipsreg.dat }
+74
diff --git a/compiler/mips/rmipsnum.inc b/compiler/mips/rmipsnum.inc
new file mode 100644
index 0000000000..ebd3e23c45
--- /dev/null
+++ b/compiler/mips/rmipsnum.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008)
diff --git a/compiler/mips/rmipsrni.inc b/compiler/mips/rmipsrni.inc
new file mode 100644
index 0000000000..18ce2cb19e
--- /dev/null
+++ b/compiler/mips/rmipsrni.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73
diff --git a/compiler/mips/rmipssri.inc b/compiler/mips/rmipssri.inc
new file mode 100644
index 0000000000..5af5c3069c
--- /dev/null
+++ b/compiler/mips/rmipssri.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+68,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+69,
+70,
+71,
+72,
+73,
+66,
+0,
+67,
+65,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/compiler/mips/rmipssta.inc b/compiler/mips/rmipssta.inc
new file mode 100644
index 0000000000..35598a2ffe
--- /dev/null
+++ b/compiler/mips/rmipssta.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75
diff --git a/compiler/mips/rmipsstd.inc b/compiler/mips/rmipsstd.inc
new file mode 100644
index 0000000000..7f44888e61
--- /dev/null
+++ b/compiler/mips/rmipsstd.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'PC',
+'HI',
+'LO',
+'CR',
+'FCR0',
+'FCR25',
+'FCR26',
+'FCR28',
+'FCSR'
diff --git a/compiler/mips/rmipssup.inc b/compiler/mips/rmipssup.inc
new file mode 100644
index 0000000000..9999435836
--- /dev/null
+++ b/compiler/mips/rmipssup.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_R16 = $10;
+RS_R17 = $11;
+RS_R18 = $12;
+RS_R19 = $13;
+RS_R20 = $14;
+RS_R21 = $15;
+RS_R22 = $16;
+RS_R23 = $17;
+RS_R24 = $18;
+RS_R25 = $19;
+RS_R26 = $1a;
+RS_R27 = $1b;
+RS_R28 = $1c;
+RS_R29 = $1d;
+RS_R30 = $1e;
+RS_R31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_PC = $00;
+RS_HI = $01;
+RS_LO = $02;
+RS_CR = $03;
+RS_FCR0 = $04;
+RS_FCR25 = $05;
+RS_FCR26 = $06;
+RS_FCR28 = $07;
+RS_FCSR = $08;
diff --git a/compiler/mppc386.bat b/compiler/mppc386.bat
new file mode 100644
index 0000000000..999996379a
--- /dev/null
+++ b/compiler/mppc386.bat
@@ -0,0 +1,6 @@
+ppc386 -O3p3 -Ch8000000 -FE. -Fui386 -dI386 -dGDB -dBROWSERLOG -Sg pp.pas %1 %2 %3 %4 %5 %6 %7 %8 %9
+if errorlevel 0 goto success
+goto failed
+:success
+copy pp.exe ppc386.exe
+:failed
diff --git a/compiler/mppc68k.bat b/compiler/mppc68k.bat
new file mode 100644
index 0000000000..7d0c8daf3e
--- /dev/null
+++ b/compiler/mppc68k.bat
@@ -0,0 +1,2 @@
+ppc386 -Ch8000000 -uSUPPORT_MMX -ui386 -dm68k -dGDB -a -Sg pp.pas %1 %2 %3 %4 %5 %6 %7 %8 %9
+copy pp.exe ppc68k.exe
diff --git a/compiler/mppcsparc b/compiler/mppcsparc
new file mode 100644
index 0000000000..29fb72502a
--- /dev/null
+++ b/compiler/mppcsparc
@@ -0,0 +1,42 @@
+#!/bin/bash
+cd "`dirname "$0"`/.."
+FPC_SRC_DIR="$PWD"
+COMP_DIR="$FPC_SRC_DIR/compiler"
+RTL_DIR="$FPC_SRC_DIR/rtl"
+SPARC_BINUTILS_DIR="/usr/local/bin/sparc-linux"
+INCLUDE_PATH=`echo -Fi"$RTL_DIR/"{unix,linux,sparc,inc,linux/sparc,objpas/sysutils}`
+UNITS_PATH=`echo -Fu"$RTL_DIR/"{unix,linux,sparc,inc,linux/sparc,objpas,inc}`
+SRC_DIR=`echo "$COMP_DIR/"{,sparc,systems}:`
+TEST_DIR="$FPC_SRC_DIR/tests/test"
+if [[ "$1" == "-V1.0" ]] || [[ "$#" == 0 ]]
+then
+ if [[ "$1" == "-V1.1" ]]
+ then
+ cd "$COMP_DIR"
+ ~/FPC/bin/fpc -XD -gl -oppcsparc -dExtDebug -Fu"sparc;systems" -FE"sparc" -dSPARC -dGDB -dNewRA pp.pas
+ else
+ cd "$COMP_DIR"
+ fpc -XD -gl -oppcsparc -dExtDebug -Fu"sparc;systems" -FE"sparc" -dSPARC -dGDB -dNewRA pp.pas
+ fi
+fi
+if [[ "$#" -gt "0" ]] && ( [[ "$1" != "-B" ]] || [[ "$#" -gt "1" ]] )
+then
+ cd "$TEST_DIR"
+ COMPILE_COMMAND='"$COMP_DIR/sparc/ppcsparc" -g -artl $UNITS_PATH -FD"$SPARC_BINUTILS_DIR" $INCLUDE_PATH "-FE$TEST_DIR" -dSPARC'
+ if [[ "$1" == "-gdb" ]]
+ then
+ shift 1
+ eval gdb -d \"$SRC_DIR\" --args $COMPILE_COMMAND "$@"
+ else
+ FILES_LIST=`ls $1`
+ shift 1
+ for FileName in $FILES_LIST
+ do
+ eval "$COMPILE_COMMAND" "$FileName" "$@"
+ if [[ $? != 0 ]]
+ then
+ break;
+ fi
+ done
+ fi
+fi
diff --git a/compiler/msg/errorct.msg b/compiler/msg/errorct.msg
new file mode 100644
index 0000000000..dacec0b413
--- /dev/null
+++ b/compiler/msg/errorct.msg
@@ -0,0 +1,2356 @@
+# $Id: errorct.msg,v 1.2 2005/04/20 08:13:25 florian Exp $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1993-2005 by the Free Pascal Development team
+#
+# Catalan Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01017 is the last one used
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilador: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SO d'origen: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SO objectiu: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_S'està utilitzant el camí pels executables: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_S'està utilitzant el camí de les unitats: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_S'està utilitzant el camí dels inclosos: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_S'està utilitzant el camí per les biblioteques : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_S'està utilitzant el camí dels objectes: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Línies compilades, $2 seg
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_No hi ha prou memòria disponible
+% The compiler doesn't have enough memory to compile your program.
+% There are several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_S'està escrivint el fitxer de la taula del recurs: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_S'ha produït un error mentre s'escrivia el fitxer de la taula del recurs: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Avís:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Suggeriment:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_El camí "$1" no existeix
+% The specified path does not exist
+general_e_compilation_aborted=01018_E_S'ha avortat la compilació
+% \end{description}
+#
+# Scanner
+#
+# 02066 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_No s'esperava el final del fitxer
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement.
+% This happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_La cadena excedeix la línia
+% There is a missing closing 'in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Caràcter il·legal "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_S'ha trobat un error de sintaxi, s'esperava "$1" però s'ha trobat "$2"
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_S'està començant a llegir el fitxer inclòs $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_S'ha trobat nivell de comentari $1
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_S'ignora el commutador del compilador "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_El commutador del compilador $1 no és vàlid
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise.
+scan_w_switch_is_global=02010_W_Falta el commutador d'efecte global
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program
+scan_e_illegal_char_const=02011_E_Constant de caràcter il·legal
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_No es pot obrir el fitxer "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_No es pot obrir el fitxer inclòs "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Els camps dels Registres només es poden alinear a 1,2,4 o 16 octets
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1,2,4 or 16 are valid in this case.
+scan_w_only_pack_enum=02016_W_Els enumerats només es poden desar en 1,2 o 4 octets
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_S'esperava $ENDIF per $1, s'ha definit $2 en $3 a la línia $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_S'ha trobat un error de sintaxi mentre es processava una expressió de compilació condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setcd
+% compiler directives.
+scan_e_error_in_preproc_expr=02019_E_S'ha produït un error mentre s'avaluava una expressió de compilació condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc
+% compiler directives.
+scan_w_macro_cut_after_255_chars=02020_W_Els continguts de la macro estan limitats a una longitud de 255 caràcters
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sense IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_L'usuari ha definit: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_L'usuari ha definit: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_L'usuari ha definit: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_L'usuari ha definit: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_L'usuari ha definit: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_L'usuari ha definit: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_La paraula clau redefinida com a macro no té efecte
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Una macroinstrucció ha desbordat la memòria intermèdia mentre es llegia o s'expandia
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_L'expansió de les macroinstruccions excedeix una profunditat de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_No es permeten els commutadors del compilador en comentaris de l'estil //
+% Compiler switches should be in normal pascal style comments
+scan_d_handling_switch=02032_DL_Manejant el commutador "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_S'ha trobat ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_S'ha trobat IFDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_S'ha trobat IFOPT $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_S'ha trobat IF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_S'ha trobat IFNDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_S'ha trobat ELSE $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_S'ha omès fins ...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Premeu <retorn> per a continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_No es permet l'ús del commutador "$1"
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_La directiva del compilador "$1" no és vàlida
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_S'està tornant a $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_El tipus de l'aplicació "$1" no és compatible
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE no és compatible amb el SO objectiu
+% The \var{\{\$APPTYPE\}} directive is supported by certain operanting
+% systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION no és compatible amb el SO objectiu
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION no és compatible amb el SO objectiu
+% The \var{\{\$VERSION\}} directive is not supported on this target OS.
+scan_n_only_exe_version=02048_N_VERSION només es pot utilitzar en executables o DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Format erroni de la directiva VERSION "$1"
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_e_unsupported_asmmode_specifier=02050_E_L'estil d'assemblador especificat "$1" no és vàlid
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_No es permet el commutador de lector d'ASM dins d'una declaració ASM, "$1" serà efectiu a continuació
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_El modificador del commutador és erroni, utilitzeu ON/OFF o +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_No es permet l'ús dels fitxers del recurs en aquest destí
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_No s'ha trobat la variable d'entorn "$1"
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_El valor pel límit del registre FPU no és vàlid
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Aquest destí només permet un fitxer d'origen
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_El suport per a macroinstruccions està aturat
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on, compile with
+% -Sm on the commandline or add {\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_S'ha especificat un tipus d'interfície no vàlida. Les interfícies vàlides son : COM, CORBA o DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID només funciona amb el PalmOS
+% The \var{\{\$APPID}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME només funciona amb el PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target
+scan_e_string_exceeds_255_chars=02061_E_Les constants de cadena no poden excedir els 255 caràcters
+% A single string contant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Els fitxers inclosos superen els 16 niats
+% When including include files the files have been nested to a level of 16
+% The compiler will expand no further, since this may be a sign that
+% recursion is used
+scan_e_too_many_push=02063_E_S'han trobat massa nivells de PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas
+scan_e_too_many_pop=02064_E_S'ha trobat POP sense PUSH anterior
+% This error occur only in mode MacPas
+scan_e_error_macro_lacks_value=02065_E_La macroinstrucció o variable del temps de compilació "$1" no te cap valor
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_La posició del commutador és errònia, utilitzeu ON/OFF/DEFAULT o +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Aquí no es permet el commutador de mode "$1"
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT
+scan_e_error_macro_undefined=02068_E_La variable de temps de compilació "$1" no està definida
+% Thus the conditional compile time expression cannot be evaluated.
+% \end{description}
+#
+# Parser
+#
+# 03211 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+% \section{Parser messages}
+parser_e_syntax_error=03000_E_Analitzador - Error de sintaxi
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_El procediment INTERRUPT no pot estar niat
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_S'ignora el tipus de procediment "$1"
+% The specified is ignored fy FPC programs
+parser_e_no_overload_for_all_procs=03006_E_No totes les declaracions de "$1" s'han declarat amb OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_El nom de la funció exportada "$1" està dupllicat
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_L'índex de la funció exportada $1 no pot estar duplicat
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_L'índex de la funció exportada no és vàlid
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_L'informació de la depuració de la biblioteca reassignada o executable $1 no funciona, es deshabilita.
+parser_w_parser_win32_debug_needs_WN=03012_W_Per permetre la depuració pel codi de win32, necessiteu deshabilitar la reassignació amb l'opció -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_El nom del constructor ha de ser INIT
+% You are declaring a constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_El nom del destructor ha de ser DONE
+% You are declaring a constructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_No es permet l'ús del procediment tipus INLINE
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_El constructor ha de ser públic
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_El destructor ha de ser públic
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_La classe només ha de tenir un destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_No es permeten les definicions de les classes locals
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_No es permeten les definicions de classe anònimes
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_E_L'objecte "$1" no té VMT
+% This is a note indicating that the declared object has no
+% virtual method table
+parser_e_illegal_parameter_list=03024_E_La llista dels paràmetres no és vàlida
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_S'ha especificat una quantitat errònia de paràmetres
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_L'identificador sobrecarregat "$1" no és una funció
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Les funcions sobrecarregades tenen la mateixa llista de paràmetres
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_L'encapçalament de la funció no concorda amb la declaració posterior "$1"
+% You declared a function with same parameters but
+% different result type or function specifiers.
+parser_e_header_different_var_names=03030_E_L'encapçalament de la funció "$1" no concorda amb la posterior declaració : el nom de la variable canvia $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Els valors en tipus d'enumerats han de ser ascendents
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_No es pot utilitzar WITH per les variables en un segment diferent
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_El niat de les funcions és superior a 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_S'ha produït un error de comprovació de l'abast mentre s'avaluaven les constants
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_S'ha produït un error de comprovació de l'abast mentre s'avaluaven les constants
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_L'etiqueta de CASE està duplicada
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_El límit superior de CASE és menor que el límit inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_No es permeten les constants amb tipus de les classes
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_No es permeten les funcions variables de les funcions sobrecarregades
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed.
+parser_e_invalid_string_size=03041_E_La longitud d'una cadena ha de ser un valor entre 1 i 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_Utilitzeu la sintaxi estesa de DISPOSE i NEW per les instàncies dels objectes
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object.
+parser_w_no_new_dispose_on_void_pointers=03043_W_L'utilització de NEW o DISPOSE en punters sense tipus no té sentit
+parser_e_no_new_dispose_on_void_pointers=03044_E_L'utilització de NEW o DISPOSE no és possible amb punters sense tipus
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_S'esperava un identificador de classe
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Aquí no es permet l'identificador de tipus
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_S'esperava un identificador del mètode
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_L'encapçalament de la funció no concorda amb cap mètode d'aquesta classe "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_PROCEDURE/FUNCTION $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_La constant de punt flotant no és vàlida
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL només es pot utilitzar en constructors
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Els destructors no poden tenir paràmetres
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Els mètodes de la classe només es poden referir amb referències de classe
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Només els mètodes de la classe poden ser accedits en mètodes de classe
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Els tipus d'una constant i CASE no concorden
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_No es pot exportar el símbol d'una biblioteca
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_ "$1" està amagant un mètode heretat
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_No hi ha un mètode en una classe avantpassada per ser substituït: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_No s'ha subministrat un membre per accedir a la propietat
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_La directiva Stored encara no està implementada
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_El símbol per accedir a la propietat no és vàlid
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Aquí no es pot accedir a un camp protegit d'un objecte
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Aquí no es pot accedir a un camp privat d'un objecte
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Els mètodes sobrecarregats han de retornar el mateix tipus: "$2" està sobrecarregat per "$1", el qual retorna un altre tipus
+% If you declare overriden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Les funcions declarades amb EXPORT no poden estar niades
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Els mètodes no poden ser EXPORTats
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_Les trucades per paràmetres variables tenen que concordar exactament: s'ha obtingut "$1", s'esperava "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_La classe no és un pare de la classe actual
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF només és permet en mètodes
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Els mètodes només poden estar en altres mètodes cridats directament amb l'identificador del tipus de la classe
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Ús no vàlid de ":"
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_S'ha produït un error de comprovació de l'abast en el constructor del conjunt o hi ha element del conjunt duplicat
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_S'esperava un punter a un objecte
+% You specified an illegal type in a \var{New} statement.
+% The extended syntax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_L'expressió ha de ser una trucada al constructor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_L'expressió ha de ser una trucada al destructor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_L'ordre dels elements del registre no és correcte
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_El tipus de l'expressió ha de ser CLASS o RECORD
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Els procediments no poden retornar cap valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Els constructors i destructors han de ser mètodes
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_L'operador no està sobrecarregat
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_No es pot sobrecarregar l'assignació per tipus iguals
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_No es pot sobrecarregar l'operador
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Aquí no es pot rellançar una excepció
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_No es permet la sintaxi estesa de NEW o DISPOSE en una classe
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_La sobrecàrrega de procediments no està activada
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_No es pot sobrecarregar aquest operador
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_L'operador comparatiu ha de retornar un valor booleà
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Només els mètodes virtuals poden ser abstractes
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_S'està fent ús d'una característica no permesa!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_No es permet la barreja de diferents tipus d'objectes (class, object, interface, etc)
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and
+% \var{interfaces} interttwined . E,g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Es desconeix la directiva del procediment "$1", s'ignora.
+parser_e_absolute_only_one_var=03095_E_Absolute només es pot associar a una variable
+% The procedure direcive you specified is unknown.
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE només es pot associar a una variable o constant
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Només es pot inicialitzar una variable
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Els mètodes abstractes no han de tenir cap definició (en el cos de la funció)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Aquesta funció sobrecarregada no pot ser local (ha de ser EXPORTED)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Els mètodes virtuals s'utilitzen sense un constructor a "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_S'ha definit la macro: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_S'ha indefinit la macro: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_S'ha ficat la macro $1 a $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_S'està compilant $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_S'està analitzant l'interfície de l'unitat $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_S'està analitzant l'implementació de $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_S'està compilant $1 per segona vegada
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No s'ha trobat la propietat a sobreescriure
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Només es permet una propietat predeterminada.
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propietat predeterminada ha de ser un conjunt de propietat
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Els constructors virtuals només son compatibles en models class object
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No hi ha cap propietat predeterminada disponible
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) does not have a default property.
+parser_e_cant_have_published=03114_E_La classe no pot tenir una secció PUBLISHED, utilitzeu el commutador {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_La declaració posterior de la classe "$1" s'ha de resoldre aquí per poder utilitzar la classe com anvantpassada
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_No es permeten els operadors locals
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_No es permet la directiva de procediment "$1" en la secció INTERFACE
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_No es permet la directiva del procediment "$1" en la secció IMPLEMENTATION
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_No es permet la directiva del procediment "$1" en la declaració procvar
+% This procedure directive cannot be part of a procedural of function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La funció "$1" ja està declarada com Public/Forward
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_No es poden utilitzar EXPORT i EXTERNAL conjuntament
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_Encara no es permet "$1" dins de procediment/funció inserits
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_S'ha deshabilitat l'inseriment
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_S'està escrivint el registre del navegador $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Pot ser que falti la dereferència del punter
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_El lector de l'assemblador seleccionat no és compatible
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+earser_e_proc_dir_conflict=03128_E_La directiva del procediment "$1" té conflictes amb altres directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convenció de la crida no concorda amb la posterior
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_La propietat no pot tenir un valor predeterminat
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_El valor predeterminat d'una propietat ha de ser constant
+% The value of a \var{default} declared property must be knwon at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_No es pot publicar el símbol, només pot ser una classe
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_No es pot publicar aquest tipus de propietat
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Es requereix nom d'importació
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_S'ha efectuat una divisió per zero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_L'operació de punt flotant no és vàlida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_El límit superior de l'abast és menor que el límit inferior
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_La cadena "$1" és més llarga que "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_La longitud de la cadena és major que el conjunt de caràcters
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Hi ha una expressió il·legal després d'una directiva del missatge
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Els manipuladors de missatges només accepten una crida per paràmetre de referència
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_L'etiqueta del missatge està duplicada: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_SELF només pot ser un paràmetre explícit en mètodes que son manipuladors dels missatges
+% The self parameter can be passed only explicit if it is a method which
+% is declared as message handler
+parser_e_threadvars_only_sg=03147_E_Les variables del fil només poden ser estàtiques o globals
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_L'assemblador directe no és compatible amb el format binari de la sortida
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+% \end{description}
+parser_w_no_objpas_use_mode=03149_W_No carregueu manualment l'unitat OBJPAS, utilitzeu {\$mode objfpc\} o {\$mode delphi\}
+% You are trying to load the ObjPas unit manual from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_No es pot utilitzar OVERRIDE en objectes
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_No es poden utilitzar els tipus de dades que requereixen inicialització/finalització en registres variables
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Les cadenes del recurs només poden ser estàtiques o globals
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Aquí no es pot utilitzar Exit amb arguments
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_El tipus del símbol ha de ser booleà
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_No es permet aquest símbol com a símbol per emmagatzemar
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Només les classes compilades amb el mode $M+ poden ser publicades
+% In the published section of a class can be only class as fields used which
+% are compiled in $M+ or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_S'esperava la directiva del procediment
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_El valor per un índex de la propietat ha de ser d'un tipus ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_El nom del procediment és massa curt per ser exportat
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No es pot generar una entrada DEFFILE per les variables globals d'una unitat
+parser_e_dlltool_unit_var_problem2=03161_E_Compileu sense l'opció -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Necessiteu el mode ObjFpc (-S2) o Delphi (-Sd) per compilar aquest mòdul
+% You need to use {\$MODE OBJFPC\} or {\$MODE DELPHI\} to compile this file
+% Or use the equivalent commandline switches -S2 or -Sd
+parser_e_no_export_with_index_for_target=03163_E_No es pot exportar amb índex sota $1
+% Exporting of functions or procedures with a specific index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_No es poden exportar variables sota $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_La sintaxi de GUID no és apropiada
+parser_w_interface_mapping_notfound=03168_W_El procediment anomenat "$1" no sembla apropiat per implementar $2.$3
+parser_e_interface_id_expected=03169_E_S'esperava identificador d'interfície
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class (TObject, IDispach)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_No es pot utilitzar el tipus "$1" com a índex de conjunt
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_No es permeten els constructors i destructors a l'interfície
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface
+parser_e_no_access_specifier_in_interfaces=03172_E_No es poden utilitzar els especificadors d'accés en l'interfície
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{published} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Una interfície no pot contenir camps
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_No es poden declarar procediments locals com EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Alguns camps d'abans de "$1" no s'han inicialitzat
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warms you when it detects such situations
+parser_e_skipped_fields_before=03176_E_Alguns camps d'abans de "$1" no s'han inicialitzat
+% In all syntax modes but Delphi mode, you can't leave some fields unitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Alguns camps de després de "$1" no s'han inicialitzat
+% You can leave some fields at the end of a type constant record unitialized
+% (the compiler will initialize them to zero automatically), this may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Directiva VarArgs sense CDecl i External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_SELF ha de ser un paràmetre normal
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_L'interfície "$1" no té identificació d'interfície
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Es desconeix el camp de la classe o l'identificador del mètode "$1"
+% Properties must refer to a field or method in the same class
+parser_w_proc_overriding_calling=03182_W_S'està sobreescrivint la convenció de la crida "$1" amb "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_noprocvarobj_const=03183_E_Les constants del tipus "procediment de l'objecte" només es poden inicialitzar amb NIL
+% You can't assign the address of a method to a typed constant which has a
+% "procedure of object" type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates an (which can't be known at compile time).
+parser_e_default_value_only_one_para=03184_E_El valor predeterminat només es pot assignar a un paràmetre
+parser_e_default_value_expected_for_para=03185_E_Es requereix el paràmetre predeterminat per "$1"
+parser_w_unsupported_feature=03186_W_No es permet l'ús d'aquesta característica!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Els conjunts del C es passen per referència
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_El conjunt de constants de C, han de ser l'últim argument
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_S'ha tornat a definir el tipus "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Les funcions declarades amb CDECL no tenen paràmetres alts
+% Functions declared with cdecl modifier do not pass an extra implicit parameter
+parser_w_cdecl_no_openstring=03191_W_Les funcions declarades amb CDECL no son compatibles amb les cadenes obertes
+% Openstring is not supported for cdecl'ared functions
+parser_e_initialized_not_for_threadvar=03192_E_No es poden inicialitzar variables definides com a variables del fil
+% Variables declared as threadvar can not be initialized with a default value
+% The variables will always be filled with zero at the start of a new thread
+parser_e_msg_only_for_classes=03193_E_Només es permet la directiva del missatge en classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_S'esperava procediment o funció
+% A class method can only be specified for procedures and functions
+parser_e_illegal_calling_convention=03195_E_S'ignora la directiva de la convenció de la crida: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most
+% non-i386 ports support only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_No es pot utilitzar REINTRODUCE en els objectes
+% \var{REINTRODUCE} is not supported for objects
+parser_e_paraloc_only_one_para=03197_E_Cada argument ha de tenir la seva pròpia localització
+% if locations for arguments are specified explicity as it is required by
+% some syscalls conventions, each argument must have its only location,
+% things like \var{procedure p (i,j:longint 'r');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Cada argument ha de tenir una localització explicita
+% if one argument has an explicit argument location, all arguments of a procedure
+% must have one
+parser_e_illegal_explicit_paraloc=03199_E_No es coneix la localització de l'argument
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_S'esperava variable tipus Integer de 32 Bits o Pointer
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_No es permeten les declaracions GOTO entre diferents procediments
+% It is not allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1:
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1;
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_El procediment és massa complex, requereix massa registres
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_L'expressió és il·legal
+% This can occur under many circumstancies. Mostly when trying to evaluate
+% constant expressions
+parser_e_invalid_integer=03204_E_L'expressió amb INTEGER no és vàlida, el resultat ha de ser INTEGER
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_El qualificador és il·legal
+% One of the following is happening:
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_El límit més alt és inferior al límit més baix de l'abast
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range
+parser_e_macpas_exit_wrong_param=03207_E_La sortida del paràmetre ha de ser el nom del procediment on s'utilitza
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_L'assignació de la variable "$1" del bucle FOR no és vàlida
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_No es pot declarar una variable local com EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_El procediment ja està declarat com EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface of
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_S'està utilitzant implícitament l'unitat Variants
+% The Variant type is used in the unit without any used unit using the variants unit.
+% The compiler has implicity added the Variants unit to the uses list.
+% To remove this warning, the Variants unit needs to be added to the USES statement.
+parser_e_no_static_method_in_interfaces=03212_E_No es poden utilitzar els mètodes de la classe i estàtics dins d'INTERFACES
+% The specifier \var{class} and directive \var{static} can be used in interfaces
+% because all methods of an interface must be public.
+parser_e_arithmetic_operation_overflow=03213_E_S'ha produït una sobrecàrrega en l'operació aritmètica
+% An operation on two integers values produced an overflow
+% \end{description}
+#
+# Type Checking
+#
+#
+# 04058 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Els tipus no concorden
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Els tipus son incompatibles: s'ha obtingut "$1", s'esperava "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Els tipus "$1" i "$2" no concorden
+% The types are not equal
+type_e_type_id_expected=04003_E_S'esperava un identificador de tipus
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_S'esperava un identificador de variable
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_S'esperava una expressió entera, però s'ha obtingut "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_S'esperava una expressió booleana, però s'ha obtingut "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_S'esperava una expressió ordinal
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_S'esperava un tipus punter, però s'ha obtingut "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_S'esperava un tipus de classe, però s'ha obtingut "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_No es pot avaluar l'expressió constant
+% This error can ocurr when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Els elements del conjunt no son compatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_L'operació no està implementada pels conjunts
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_S'està convertint automàticament el tipus de punt flotant a COMP, el qual és un tipus enter
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Utilitzeu DIV per obtenir un resultat enter
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Els tipus de la cadena no concorden a causa del mode $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_No es pot utilitzar SUCC o PRED en enumeracions amb assignació
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_No es poden llegir o escriure variables d'aquest tipus
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_No és pot utilitzar READLN o WRITELN en fitxers de tipus
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_No és pot utilitzar READ o WRITE en fitxers sense tipus
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_S'ha produït un conflicte de tipus entre els elements del conjunt
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) retorna el word/dword més alt/més baix
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword}
+% which returns the lower/upper word of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type case the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_S'esperava una expressió tipus INTEGER o REAL
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_El tipus "$1" no és correcte en el constructor del conjunt
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_El tipus de l'argument num.$1 és incompatible: s'ha obtingut "$2", s'esperava "$3"
+% You are trying to pass an invalid type for the specified parameter.
+% \end{description}
+type_e_no_method_and_procedure_not_compatible=04026_E_El mètode (variable) i el procediment (variable) no son compatibles
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_S'ha passat una constant il·legal a una funció matemàtica interna
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_No es pot trobar l'adreça de les constants
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_No es pot assignar l'argument
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_No es pot assignar el procediment/funció local a la variable del procediment
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_No es poden assignar els valors a una adreça
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_No es poden assignar valors a una variable declarada com a constant
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Es requereix tipus de conjunt
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_S'esperava tipus d'interfície, però s'ha obtingut "$1"
+type_w_mixed_signed_unsigned=04035_W_El resultat de la barreja d'expressions amb signe i paraules llargues és de 64 octets
+% If yoy divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Barrejar expressions amb signe i cardinals aquí, pot causar errors de l'abast
+% If you use a binari operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_La conversió de tipus té diferents tamanys ($1 -> $2) en les assignacions
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Els enumerats amb assignacions no es poden utilitzar com a índex de conjunts
+% When yoy declare an enumeration type which has assignments in it, as in C,
+% like the foloowing:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% yoy cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Els tipus Class o Object "$1" i "$2" no estan relacionats
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Els tipus de la classe "$1" i "$2" no estan relacionats
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_S'esperava tipus de classe o interfície, però s'ha obtingut "$1"
+type_e_type_is_not_completly_defined=04042_E_No s'ha definit completament el tipus "$1"
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_La comparació és sempre falsa a causa de l'abast dels valors
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Explicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_La comparació és sempre vertadera a causa de l'abast dels valors
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Explicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_S'està construint una classe "$1" amb mètodes abstractes
+% An instance of a class is created which contains non_implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_L'operand esquerra per a l'operador d'IN ha de tenir el tamany d'un octet
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_El tamany dels tipus no concorden, possible pèrdua de dades / errors de l'abast
+type_h_smaller_possible_range_check=04049_H_El tamany dels tipus no concorden, possible pèrdua de dades / errors de l'abast
+% There is an assignement to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data
+type_e_cant_take_address_of_abtract_method=04050_E_No es pot obtenir l'adreça d'un mètode abstracte
+% An abstract method has no body, so the address of an abstract method can not
+% be taken
+type_e_operator_not_allowed=04051_E_No es pot aplicar l'operador pel tipus d'operand
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_S'esperava una expressió constant
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_L'operació "$1" no és compatible pels tipus "$2" i "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_S'ha produït una conversió il·legal dels tipus: "$1" a "$2"
+% When doing a type-cast, you must take care that the sizes of the variable
+% and the destination type are the same
+type_h_pointer_to_longint_conv_not_portable=04055_H_La conversió entre ordinals i punters no és portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not
+% compile on a machineusing 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_La conversió entre ordinals i punters no és portable
+% If you typecast a pointer to a ordinal type of different size (or vice-versa)
+% this can cause problems. This is a warning to help finding the 32bit specific
+% code where cardinal/longint is used to typecast pointers to ordinals
+% A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_No es pot determinar a quina funció sobrecarregada cridar.
+% You are calling overloaded functions with a parameter that does not correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_La variable del comptador no és vàlida
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05056 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_No s'ha trobat l'dentificador "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_S'ha produït un error intern en SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_L'identificador "$1" està duplicat
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_L'identificador ja està definit en $1 en la línia $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Es desconeix l'identificador "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_No s'ha resolt la declaració posterior "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_S'ha produït un error en la definició del tipus
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is err¢neous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_No s'ha resolt el tipus posterior "$1"
+% A symbolwas forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Només les variables estàtiques poden ser utilitzades en mètodes estàtics o fora dels mètodes
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_S'esperava un tipus de registre o classe
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_No es permeten les instàncies de les classes o els objectes amb un mètode abstracte
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_No s'ha definit l'etiqueta "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_S'està utilitzant l'etiqueta "$1" però no està definida
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_La declaració de l'etiqueta no és vàlida
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_No es permeten GOTO i LABEL (utilitzeu el commutador -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_No s'ha trobat l'etiqueta
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_L'identificador no és una etiqueta
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_L'etiqueta ja està definida
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Declaració de tipus il·legal dels elements del conjunt
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_No s'ha resolt la definició de la classe posterior "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_No s'utilitza l'unitat "$1" en $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_No s'utilitza el paràmetre "$1"
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_No s'utilitza la variable local "$1"
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_S'ha assignat el paràmetre del valor "$1" però no s'utilitza
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_S'ha assignat la variable local "$1" però no s'utilitza
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_No s'utilitza $1 local "$2"
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_No s'utilitza el camp privat "$1.$2"
+sym_n_private_identifier_only_set=05030_N_S'ha assignat el camp privat "$1.$2" però no s'utilitza
+sym_n_private_method_not_used=05031_N_No s'utilitza el mètode privat "$1.$2"
+sym_e_set_expected=05032_E_S'esperava un tipus de conjunt
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_No s'ha definit el resultat de la funció
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_El tipus "$1" no està alineat correctament en el registre actual pel C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_No es coneix l'identificador del camp del registre "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_No s'ha inicialitzat la variable local "$1"
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_No s'ha inicialitzat la variable "$1"
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_L'identificador "$1" no identifica cap membre
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_S'ha trobat la declaració: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_L'element de dades és massa llarg
+% You get this when you declare an array whose size exceeds the
+% prescribed limit (2 Gb on 80368+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_S'ha trobat una implementació pel mètode d'interfície "$1" que no concorda
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Es desaconsella el símbol "$1"
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit/library. Usage of this symbol
+% should be avoied as much as possible.
+sym_w_non_portable_symbol=05044_W_El símbol "$1" no és portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_El símbol "$1" no està implementat
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_No es pot crear un tipus únic a partir d'aquest tipus
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}
+% \end{description}
+sym_h_uninitialized_local_variable=05057_H_La variable local "$1" no està inicialitzada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_La variable "$1" no està inicialitzada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+#
+# Codegenerator
+#
+# 06045 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_El tamany de la llista de paràmetres excedeix els 65535 octets
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Els tipus del fitxer han de ser paràmetres variables
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_Aquí no es permet l'ús de punters de tipus FAR
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_No es poden cridar les funcions declarades amb EXPORT
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possiblement s'ha produït una crida il·legal d'un constructor o destructor
+% The compiler detected that a constructor or destructor is called within a
+% method. This will probably lead to problems, since contructors/destructors
+% require parameters on entry
+cg_n_inefficient_code=06017_N_El codi és ineficient
+% You statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Aquest codi no s'executa mai
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Els mètodes abstractes no es poden cridar directament
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registre $1 pes $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_S'omet l'estructura de la pila
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_No es poden inserir mètodes d'objectes o classes
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_No es poden inserir crides a procvar
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No hi ha codi enmagetzemat pel procediment inserit
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_No es pot accedir a l'element zero d'un ansi/wide- o longstring, utilitzeu (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_No es poden cridar constructors o destructors dins de la clàusula 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_No es poden cridat els mètodes manipuladors de missatges directament
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Hi ha un salt dins o fora d'un block d'excepció
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_No es permeten les declaracions de control de flux en un bloc finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_El tamany dels paràmetres excedeix el límit per determinades cpu's
+% This indicates that you are declaring more than 64k ok parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_to_big=06042_W_El tamany de la variable local excedeix el límit per determinades cpu's
+% This indicates that you are declaring more than 32k of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Les variables locals excedeixen el límit permès
+% This indicates that you are declaring more than 32k of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_No es permet BREAK
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_No es permet CONTINUE
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+#
+# Assembler reader
+#
+# 07097 is the last one used
+#
+asmr_d_start_reading=07000_DL_S'està començant l'analització del bloc d'assemblador $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_S'ha finalitzat l'analizació del bloc d'assemblador $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Un patró que no és una etiqueta conté @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_S'ha produït un error mentre es muntava el desplaçament del registre
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_S'està utilitzant OFFSET sense identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_S'està utilitzant TYPE sense identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Aquí no es poden utilitzar variables locals o paràmetres
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Aquí heu d'utilitzar OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Aquí heu d'utilitzar $
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_No es poden utilitzar multiples símbols reassignats
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Els símbols reassignats només es poden afegir
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_L'expressió constant no és vàlida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_No es permet el símbol reassignat
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_La sintaxi de la referència no és vàlida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_No podeu accedir a $1 des d'aquest codi
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_No es permeten els símbols i etiquetes locals com a referències
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_L'utilització de la base i índex del registre no és vàlida
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Hi ha un possible error en la manipulació del camp de l'objecte
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_S'ha especificat un factor de l'escala erroni
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_S'estan utilitzant múltiples registres d'índex
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_El tipus de l'operand no és vàlid
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_La cadena $1 no és vàlida com operand opcode
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_No es permet l'ús de @CODE i @DATA
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_No es permeten les referències a etiquetes nul·les
+asmr_e_expr_zero_divide=07025_E_Divisió per zero en l'avaluador asm
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_L'expressió és il·legal
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_S'ignora la seqüència d'escapament: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_La referència del símbol no és vàlida
+asmr_w_fwait_emu_prob=07029_W_Fwait pot causar problemes d'emulació amb emu387
+asmr_w_fadd_to_faddp=07030_W_S'ha traduït $1 sense operand a $1P
+asmr_w_enter_not_supported_by_linux=07031_W_El Kernel del Linux no permet l'instrucció ENTER
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_S'està cridant a una funció sobrecarregada en asm
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_El tipus del símbol no és compatible amb l'operand
+asmr_e_constant_out_of_bounds=07034_E_El valor de la constant està fora dels límits
+asmr_e_error_converting_decimal=07035_E_S'ha produït un error mentre es convertia el decimal $1
+% A constant decimal value doen not have the correct syntax
+asmr_e_error_converting_octal=07036_E_S'ha produït un error mentre es convertia l'octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_S'ha produït un error mentre es convertia el binari $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_S'ha produït un error mentre es convertia l'hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_S'ha traduït $1 a $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 està associat a una funció sobrecarregada
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_No es pot utilitzar SELF fora d'un mètode
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_No es pot utilitzar OLDEBP fora d'un procediment niat
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Els procediments no poden retornar cap valor en codi asm
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_No es permet SEG
+asmr_e_size_suffix_and_dest_dont_match=07045_E_El tamany de sufix i objectiu o el tamany de l'origen no concorden
+% The register size and the opcode size suffix does not match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_El tamany de sufix i objectiu o el tamany de l'origen no concorden
+% The register size and the opcode size suffix does not match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Error de sintaxi de l'assemblador
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_La combinació d'opcode i operands no és vàlida
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_S'ha trobat un error de sintaxi de l'assemblador en l'operand
+asmr_e_syn_constant=07050_E_S'ha trobat un error de sintaxi de l'assemblador en la constant
+asmr_e_invalid_string_expression=07051_E_L'expressió de la cadena no és vàlida
+asmr_w_const32bit_for_address=07052_W_Constant amb símbol $1 per una adreça que no és en un punter
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Es desconeix l'opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Falta opcode o no és vàlid
+asmr_e_invalid_prefix_and_opcode=07055_E_La combinació del prefix i l'opcode $1 no és vàlida
+asmr_e_invalid_override_and_opcode=07056_E_La combinació de override i opcode $1 no és vàlida
+asmr_e_too_many_operands=07057_E_Hi ha massa operands en la línia
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_S'ignora NEAR
+asmr_w_far_ignored=07059_W_S'ignora FAR
+asmr_e_dup_local_sym=07060_E_El símbol local $1 està duplicat
+asmr_e_unknown_local_sym=07061_E_El símbol local $1 no està definit
+asmr_e_unknown_label_identifier=07062_E_No es coneix l'identificador de l''etiqueta $1
+asmr_e_invalid_register=07063_E_El nom del registre no és vàlid
+% There is an unknown register name used as operand
+asmr_e_invalid_fpu_register=07064_E_El nom del registre de punt flotant no és vàlid
+asmr_w_modulo_not_supported=07066_W_No es permet l'ús del mòdul
+asmr_e_invalid_float_const=07067_E_La constant de punt flotant $1 no és vàlida
+% The floating point constant declared in an assembler block is invalid
+asmr_e_invalid_float_expr=07068_E_L'expressió de punt flotant no és vàlida
+% The floating point expression declared in an assembler block is invalid
+asmr_e_wrong_sym_type=07069_E_El tipus del símbol no és correcte
+asmr_e_cannot_index_relative_var=07070_E_No es pot indexar una variable local o un paràmetre amb un registre
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_L'expressió que sobreescriu el segment no és vàlida
+asmr_w_id_supposed_external=07072_W_S'assumeix l'identificador $1 com extern
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_No es permeten les cadenes com a constants
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_No s'ha especificat el tipus de la variable
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_El codi de l'assemblador no ha retornat a la secció de text
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_$1 no és una directiva o un símbol local
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_S'està utilitzant un nom definit com una etiqueta local
+asmr_e_dollar_without_identifier=07078_E_S'està utilitzant el símbol Dol·lar sense un identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_L'adreça ha creat una constant de 32bit
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align és específic de la plataforma, utilitzeu .balign o .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Els paràmetres no poden accedir directament als camps
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_No es pot accedir directament als camps dels objectes o classes
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No s'ha especificat el tamany i no es pot determinar el tamany dels operands
+% You should specify explicity a size for the reference, because
+% compiler is unable to determine what size (byte, word, dword, etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_No es pot utilitzar RESULT en aquesta funció
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sense operand s'ha traduït a "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" s'ha traduït a "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" s'ha traduït a "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Aquí no es permet el caràcter <
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Aquí no es permet el caràcter >
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_No es permet l'ús d'ALIGN
+asmr_e_no_inc_and_dec_together=07094_E_Inc i Dec no poden estar junts
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_El reglist no és vàlid pel movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_El reglist no és vàlid per l'opcode
+asmr_e_68020_mode_required=07097_E_Es requereix un mode de cpu més alt ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No s'ha especificat i no es pot determinar el tamany dels operands, s'està utilitzant DWORD com a predeterminat
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_S'ha trobat un error de sintaxi mentre s'analitzava un operand desplaçat
+% ARM only, ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last one used
+#
+asmw_f_too_many_asm_files=08000_F_Hi ha massa arxius d'assemblador oberts
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_L'assemblador de sortida seleccionat no és compatible
+asmw_f_comp_not_supported=08002_F_No es permet l'ús de COMP
+asmw_f_direct_not_supported=08003_F_Direct no és compatible amb els escriptors binaris
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Només es permet l'assignació de dades en la secció bss
+asmw_f_no_binary_writer_selected=08005_F_No s'ha seleccionat un escriptor binari
+asmw_e_opcode_not_in_table=08006_E_Asm: L'opcode $1 no és a la taula
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 la combinació d'opcode i operands no és vàlida
+asmw_e_16bit_not_supported=08008_E_Asm: No es permeten les referències de 16 Bits
+asmw_e_invalid_effective_address=08009_E_Asm: L'adreça actual no és vàlida
+asmw_e_immediate_or_reference_expected=08010_E_Asm: S'esperava immediat o referència
+asmw_e_value_exceeds_bounds=08011_E_Asm: el valor $1 excedeix el límit $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: El salt curt està fora de l'abast $1
+asmw_e_undefined_label=08013_E_Asm: L'etiqueta $1 no està definida
+asmw_e_comp_not_supported=08014_E_Asm: El tipus comp no està permès en aquest objectiu
+asmw_e_extended_not_supported=08015_E_Asm: El tipus Extended no està permès en aquest objectiu
+asmw_e_duplicate_label=08016_E_Asm: L'etiqueta $1 està duplicada
+asmw_e_redefined_label=08017_E_Asm: S'ha tornat a definir l'etiqueta $1
+asmw_e_first_defined_label=08018_E_Asm: Aquí s'ha definit primer
+asmw_e_invalid_register=08019_E_Asm: el registre $1 no és vàlid
+#
+# Executing linker/assembler
+#
+# 09034 is the last one used
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_S'ha tornat a definir el SO d'origen
+exec_i_assembling_pipe=09001_I_S'està assemblant (canonada) $1
+exec_d_cant_create_asmfile=09002_E_No es pot crear el fitxer d'assemblador $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_objectfile=09003_E_No es pot creat el fitxer objecte $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_archivefile=09004_E_No es pot crear l'arxiu $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_w_assembler_not_found=09005_W_No s'ha trobat l'assemblador $1, s'està canviant a assemblament extern
+exec_t_using_assembler=09006_T_S'està utilitzant l'assemblador $1
+exec_w_error_while_assembling=09007_W_S'ha produït un error mentre s'assemblava el codi de sortida $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_w_cant_call_assembler=09008_W_No es pot cridar l'assemblador, error $1 canviant a assemblament extern
+exec_i_assembling=09009_I_S'està assemblant $1
+exec_i_assembling_smart=09010_I_S'està assemblant amb enllaçament intel·ligent $1
+exec_w_objfile_not_found=09011_W_No s'ha trobat l'objecte $1, l'enllaçament pot fallar !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_No s'ha trobat la biblioteca $1, l'enllaçament pot fallar !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_error_while_linking=09013_W_S'ha produït un error mentre s'enllaçava
+% Generic error while linking.
+exec_w_cant_call_linker=09014_W_No es pot cridar l'enllaçador, s'està canviant a l'enllaçament extern
+exec_i_linking=09015_I_S'està enllaçant $1
+exec_w_util_not_found=09016_W_No s'ha trobat l'utilitat $1, s'està canviant a enllaçament extern
+exec_t_using_util=09017_T_S'està utilitzant l'utilitat $1
+exec_e_exe_not_supported=09018_E_No es permet la creació d'executables
+exec_e_dll_not_supported=09019_E_No es permet la creació de biblioteques dinàmiques/compartides
+exec_i_closing_script=09020_I_S'està tancant la seqüència $1
+exec_w_res_not_found=09021_W_No s'ha trobat el compilador del recurs, s'està canviant a mode extern
+exec_i_compilingresource=09022_I_S'està compilant el recurs $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_No es pot enllaçar estàticament l'unitat $1, s'està canviant a enllaçament intel·ligent
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_No es pot utilitzar l'enllaçament intel·ligent amb l'unitat $1, s'està canviant a enllaçament estàtic.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_No es pot utilitzar l'enllaçament compartit amb l'unitat $1, s'està canviant a enllaçament estàtic
+exec_e_unit_not_smart_or_static_linkable=09026_E_No es pot enllaçar l'unitat $1 ni estàticament ni dinàmicament
+exec_e_unit_not_shared_or_static_linkable=09027_E_No es pot utilitzar l'enllaçament compartit ni estàtic amb l'unitat $1.
+%\end{description}
+# EndOfTeX
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_No es pot post-processar l'executable $1
+execinfo_f_cant_open_executable=09029_F_No es pot obrir l'executable $1
+execinfo_x_codesize=09030_X_Tamany del codi: $1 octets
+execinfo_x_initdatasize=09031_X_Tamany de les dades inicialitzades: $1 octets
+execinfo_x_uninitdatasize=09032_X_Tamany de les dades sense inicialitzar: $1 octets
+execinfo_x_stackreserve=09033_X_Espai reservat per la pila: $1 octets
+execinfo_x_stackcommit=09034_X_Espai utilitzat per la pila: $1 octets
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_S'està cercant l'unitat: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_S'està carregant la PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nom de la PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Senyaladors de la PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Crc de la PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Temps de la PPU: $1
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_file_too_short=10006_U_El fitxer PPU és massa curt
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_invalid_header=10007_U_L'encapçalament de la PPU no és vàlid (no hi ha PPU al principi)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_La versió $1 de la PPU no és vàlida
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_La PPU està compilada per a un altre processador
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_La PPU està compilada per un altre objectiu
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_source=10011_U_font PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_S'està escrivint $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_No es pot escriure el fitxer PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_No es pot llegir el fitxer PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_No s'esperava el final del fitxer PPU
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrada invàlida en el fitxer PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Hi ha hagut un problema calculant el Dbx de la PPU
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_El nom de l'unitat és il·legal: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Hi ha massa unitats
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Hi ha una referència circular entre les unitats $1 i $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_No es pot compilar l'unitat $1, no hi ha les fonts disponibles
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_No es pot trobar l'unitat $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_No es pot trobar l'unitat $1, però hi ha la $2
+unit_f_unit_name_error=10024_F_S'estava cercant l'unitat $1, però s'ha trobat $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Per compilar l'unitat System es necessita el commutador -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Hi ha hagut $1 errors compilant el mòdul, s'ha aturat!
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_S'està carregant desde $1 ($2) l'unitat $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_S'està tornant a compilar $1, s'ha canviat la suma de verificació a $2
+unit_u_recompile_source_found_alone=10029_U_S'està tornant a compilar $1, només s'han trobat les fonts
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_S'està tornant a compilar l'unitat, la biblioteca estàtica és més vella que el fitxer ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_S'està tornant a compilar l'unitat, la biblioteca compartida és més vella que el fitxer ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_S'està tornant a compilar l'unitat, obj i asm son més vells que el fitxer ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler of
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_S'està tornant a compilar l'unitat, obj és més vell que asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_S'està analitzant l'interfície de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_S'està analitzant l'implementació de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_S'està carregant l'unitat $1 per segona vegada
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_S'està comprovant el fitxer PPU $1 temps $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled
+# unit_h_cond_not_set_in_last_compile=10038_H_El condicional $1 no ha estat inicialitzat al començament de la última compilació de $2
+# % When recompilation of an unit ies required the compiler will check that
+# % the same conditionals are set for the recompilation. The compiler has
+# % found a conditional that currently is defined, but was not used the last
+# % time the unit was compiled
+# unit_h_cond_set_in_last_compile=10039_H_El condicional $1 ha estat inicialitzat al començament de la última compilació de $2
+# % When recompilation of an unit is required the compiler will check that
+# % the same conditionals are set for the recompilation. The compiler has
+# % found a conditional that was used the last time the unit was compiled, but
+# % the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_No es pot tornar a compilar l'unitat $1, però s'han trobat fitxers inclosos modificats
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_El fitxer $1 és més nou que la versió de la PPU $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_S'està utilitzant una unitat la qual no ha estat compilada amb el mode FPU correcte
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_S'estan carregant les unitats d'INTERFACE desde $1
+% When you use the \var{-vu} flag, the compiler warms that it starts
+% loading the units defined in the interface part of the unit
+unit_u_loading_implementation_units=10044_U_S'estan carregant les unitat d'IMPLEMENTATION desde $1
+% When you use the \var{-vu} flag, the compiler warms that it starts
+% loading the units defined in the implementation part of the unit
+unit_u_interface_crc_changed=10045_U_L'interfície CRC ha canviat per la unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed
+unit_u_implementation_crc_changed=10046_U_L'implementació CRC ha canviat per l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it the
+% CRC calculated has been changed after the implementation
+% has been parsed
+unit_u_finished_compiling=10047_U_S'ha acabat la compilació de l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has finished compiling the unit
+unit_u_add_depend_to=10048_U_S'ha afegit la dependència de $1 a $2
+% When you use the \var{-vu} flag, the compiler warms that it
+% has added a dependency between the two units
+unit_u_no_reload_is_caller=10049_U_No es torna a carregar, es crida: $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_No es torna a carregar, ja és en segona compilació: $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Senyalador per la recàrrega: $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Es torna a carregar forçadament
+% When you use the \var{-vu} flag, the compiler warms that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Estat previ de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_S'està compilant l'unitat $1 per segona vegada
+% When you use the \var{-vu} flag, the compiler warms that it starts
+% recompiling a unit for the second time. This can happend with independent
+% units
+unit_u_loading_unit=10055_U_S'està carregant l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it starts
+% loading the unit
+unit_u_finished_loading_unit=10056_U_S'ha acabat la càrrega de l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it finished
+% loading the unit
+unit_u_registering_new_unit=10057_U_S'està registrant l'unitat nova $1
+% When you use the \var{-vu} flag, the compiler warms that it has
+% found a new unit and registers it in the internal lists
+unit_u_reresolving_unit=10058_U_S'està tornant a resoldre l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_No es torna a resoldre l'unitat $1, encara s'estan carregant les unitats utilitzades
+% When you use the \var{-vu} flag, the compiler warms that it
+% skips to recalculate the internal data of the unit because there
+% is no data to racalculate
+% \end{description}
+# EndOfTeX
+#
+# Options
+#
+# 11039 is the las used one
+#
+option_usage=11000_$1 [opcions] <fitxer-entrada> [opcions]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Només es permet un fitxer font
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_El fitxer DEF només pot ser creat per OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_No es permeten els fitxers de resposta niats
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_No hi ha el nom del fitxer font en la línia d'ordres
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No hi ha cap opció dins del fitxer de configuració $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_El paràmetre $1 és il·legal
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? escriu las pàgines de l'ajuda
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Hi ha massa fitxers de configuració niats
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_No es pot obrir el fitxer $1
+% The option file cannot be found.
+option_reading_further_from=11010_N_S'estan llegint les opcions addicionals de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_L'objectiu ja està posat a $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Les biblioteques compartides no estan permeses en la plataforma DOS, es canvia a estàtiques
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Hi ha massa IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Hi ha massa ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Hi ha un condicional obert al final del fitxer
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Aquest executable no permet la generació d'informació del depurador
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Proveu de tornar a compilar amb -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Esteu utilitzant el commutador obsolet $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Esteu utilitzant el commutador obsolet $1, si us plau, utilitzeu $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_S'està canviant a assemblador d'escriptura del codi font a predeterminat
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_La sortida de l'assemblador seleccionada "$1" no és compatible amb "$2"
+option_asm_forced=11022_W_S'utilitza l'assemblador "$1" forçadament
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_S'estan llegint les opcions del fitxer $1
+% Options are also read from this file
+option_using_env=11027_T_S'estan llegint les opcions des de l'entorn $1
+% Options are also read from this environment string
+option_handling_option=11028_D_S'està gestionant l'opció "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** Premeu <Intro> ***
+option_start_reading_configfile=11030_H_S'està començant a llegir el fitxer de configuració $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_S'ha acabat de llegir el fitxer de configuració $1
+% End of config file parsing
+option_interpreting_option=11032_D_S'està executant l'opció "$1"
+option_interpreting_firstpass_option=11036_D_S'està executant l'opció "$1" per 1ª vegada
+option_interpreting_file_option=11033_D_S'està executant l'opció del fitxer "$1"
+option_read_config_file=11034_D=11034_D_S'està llegint el fitxer de configuració "$1"
+option_found_file=11035_D_S'ha trobat el nom del fitxer font "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_La pàgina del codi no està disponible
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler versió $FPCVERSION [$FPCDATE] per $FPCCPU
+Copyright (c) 1993-2005 per Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versió $FPCVERSION
+
+Data del compilador : $FPCDATE
+CPU del compilador : $FPCCPU
+
+Plataformes compatibles :
+ $OSTARGETS
+
+Aquest programa ve sota la Llicència Pública General de GNU
+Per a més informació llegiu COPYING.FPC
+
+Comuniqueu les errades, suggeriments, etc a:
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Poseu + després d'un commutador booleà per activar-lo, - per desactivar-lo
+**1a_El compilador no eliminarà el fitxer d'assemblador generat
+**2al_Escriu les línies del codi font en el fitxer de l'assemblador
+**2an_Escriu l'informació del node en el fitxer d'assemblador
+*L2ap_Utilitza canonades en lloc de crear fitxers temporals d'assemblador
+**2ar_Escriu info.d'alotj/desalotj del registre en el fitxer d'assemblador
+**2at_Escriu info.d'alotj/desalotj temporal en el fitxer d'assemblador
+**1A<x>_format de la sortida:
+**2Adefault_Utilitza assemblador predeterminat
+3*2Aas_Utilitza assemblador GNU AS
+3*2Anasmcoff_fitxer coff (Go32v2) utilitzant Nasm
+3*2Aasmelf_fitxer elf32 (Linux) utilitzant Nasm
+3*2Anasmwin32_fitxer objecte Win32 utilitzant Nasm
+3*2Anasmwdosx_fitxer objecte Win32/WDOSX utilitzant Nasm
+3*2Awasm_fitxer objecte utilitzant Wasm (Watcom)
+3*2Anasmobj_fitxer objecte utilitzant Nasm
+3*2Amasm_fitxer objecte utilitzant Masm (Microsoft)
+3*2Atasm_fitxer objecte utilitzant Tasm (Borland)
+3*2Aelf_elf32 (Linux) utilitzant escriptor intern
+3*2Acoff_coff (Go32v2) utilitzant escriptor intern
+3*2Apecoff_pecoff (Win32) utilitzant escriptor intern
+4*2Aas_assemblar utilitzant el GNU AS
+6*2Aas_fitxer objecte Unix utilitzant GNU AS
+6*2Agas_assemblador GNU Motorola
+6*2Amit_sintaxi MIT (antiga GAS)
+6*2Amot_assemblador Motorola estàndard
+A*2Aas_assemblar utilitzant GNU AS
+P*2Aas_assemblar utilitzant GNU AS
+S*2Aas_assemblar utilitzant GNU AS
+**1b_Genera informació de navegador
+**2bl_Genera informació dels símbols locals
+**1B_Munta tots els mòduls
+**1C<x>_Opcions de generació del codi:
+**2Cc<x>_predetermina la convenció de crida a <x>
+**2CD_Crea biblioteca dinàmica
+**2Ce_Compilació amb opcodes emulats de coma flotant
+**2Cf<x>_Selecciona instrucció fpu a utilitzar per <x>
+**2Cg_Genera codi PIC
+**2Ch<n>_<n> octets de la pila (entre 1023 i 67107840)
+**2Ci_Comprova E/S
+**2Cn_Omet l'enllaçament
+**2Co_Comprova el desbordament de les operacions amb enters
+**2Cr_Comprova l'abast
+**2CR_Verifica la validesa de la crida dels objectes del mètode
+**2Cs<n>_Posa el tamany de la pila a <n>
+**2Ct_Comprova la pila
+**2CX_Crea també biblioteca enllaçada intel·ligentment
+**1d<x>_Defineix el símbol <x>
+**1D_Genera un fitxer DEF
+**2Dd<x>_Posa la descripció a <x>
+**2Dv<x>_Posa la versió de DLL a <x>
+*O2Dw_Aplicació PM
+**1e<x>_Posa el camí a l'executable
+**1E_Igual que -Cn
+**1F<x>_Posa els noms dels fitxers i els camins:
+**2Fa<x>[,y]_Carrega primer les unitats <x> i [y], abans d'analitzar USES
+**2Fc<x>_Posa la pàgina del codi d'entrada a <x>
+**2FD<x>_Posa el directori on buscar les utilitats del compilador
+**2Fe<x>_Redirigeix la sortida dels errors a <x>
+**2FE<x>_Posa el path de sortida d'executables i unitats a <x>
+**2Fi<x>_Afegeix <x> al camí dels inclosos
+**2Fl<x>_Afegeix <x> al camí de les llibreries
+**2FL<x>_Utilitza <x> com enllaçador dinàmic
+**2Fo<x>_Afegeix <x> al camí dels objectes
+**2Fr<x>_Carrega el fitxer de missatges d'error <x>
+**2Fu<x>_Afegeix <x> al camí de les unitats
+**2FU<x>_Posa camí sortida de les unitats a <x>, substitueix -FE
+*g1g_Genera informació del depurador:
+*g2gc_genera controls pels punters
+*g2gd_Utilitza dbx
+*g2gg_Utilitza gsym
+*g2gh_Utilitza l'unitat de traçat de la pila (depura pèrdua de memòria)
+*g2gl_Utilitza l'unitat d'info. per mostrar +info per seguiments inversos
+*g2gv_Genera programes traçables amb valgrind
+*g2gw_Genera informació de depuració dwarf
+**1i_Informació:
+**2iD_Retorna la data del compilador
+**2iV_Retorna la versió del compilador
+**2iSO_Retorna el SO d'origen
+**2iSP_Retorna el processador d'origen
+**2iTO_Retorna el SO de destí
+**2iTP_Retorna el processador de destí
+**1I<x>_Afegeix <x> a la trajec.d'afegits
+**1k<x>_Passa <x> a l'enllaçador
+**1l_Escriu el logotipus
+**1M<x>_Fica el mode del llenguatge a <x>
+**2Mfpc_dialecte Free Pascal (predeterminat)
+**2Mobjfpc_Activa algunes extensions Delphi 2
+**2Mdelphi_Intenta ser compatible amb Delphi
+**2Mtp_Intenta ser compatible amb TP/BP 7.0
+**2Mgpc_Intenta ser compatible amb gpc
+**2Mmacpas_Intenta ser compatible amb dialectes Pascal del Macintosh
+**1n_No llegeix el fitxer de configuració predeterminat
+**1o<x>_Canvia el nom de l'executable produït a <x>
+**1O<x>_optimitzacions:
+3*2Og_genera codi més petit
+3*2OG_genera codi més ràpid (predeterminat)
+**2Or_manté determinades variables en els registres
+3*2Ou_habilita optimitzacions incertes (mireu docs)
+3*2O1_optimitzacions de nivell 1 (ràpides)
+3*2O2_optimitzacions de nivell 2 (-O1 + més lentes)
+3*2O3_optimitzacions de nivell 3 (-O2 repetidament, max 5 vegades)
+3*2Op<x>_processador de destí:
+3*3Op1_posa el processador de destí a 386/486
+3*3Op2_posa el processador de destí a Pentium/PentiumMMX (r)
+3*3Op3_posa el processador de destí a PPro/PII/c6x86/K6 (r)
+6*2Og_genera codi més petit
+6*2OG_genera codi més ràpid (predeterminat)
+6*2Ox_optimitza al màxim (Encara no és segur !!!)
+6*2O0_posa el processador de destí a MC68000
+6*2O2_posa el processador de destí a MC68020+ (predeterminat)
+**1pg_genera codi de perfil per gprof (defineix FPC_PROFILE)
+**1R<x>_Estil de lectura de l'assemblador:
+**2Rdefault_utilitza l'assemblador predeterminat
+3*2Ratt_llegeix assemblador d'estil AT&T
+3*2Rintel_llegeix assemblador d'estil Intel
+6*2RMOT_llegeix assemblador d'estil Motorola
+**1S<x>_Opcions de sintaxi:
+**2S2_Igual que -Mobjfpc
+**2Sc_Permet operadors tipus C (*=,+=,/= i -=)
+**2Sa_Inclou assertion code
+**2Sd_Igual que -Mdelphi
+**2Se_opcions d'error <x> és una combinació del següent:
+**3*_<n>: el compilador s'atura després de <n> errors (predeterminat és 1)
+**3*_w: el compilador s'atura també després dels avisos
+**3*_n: el compilador s'atura també després de les notes
+**3*_h: el compilador s'atura també després dels suggeriments
+**2Sg_Permet LABEL i GOTO
+**2Sh_Utilitza ansistrings
+**2Si_Permet INLINE estil C++
+**2SI<x>_posa l'estil de l'interfície a <x>
+**3SIcom_interfície compatible amb COM (predeterminat)
+**3SIcorba_interfície compatible amb CORBA
+**2Sm_Permet macros tipus C (globals)
+**2So_Igual que -Mtp
+**2Sp_Igual que -Mgpc
+**2Ss_El nom del constructor ha de ser init (destructor = done)
+**2St_Permet la paraula clau -static- en els objectes
+**1s_No cridis l'assemblador ni l'enllaçador
+**2sh_Genera la seqüència per enllaçar a l'anfitrió
+**2st_Genera la seqüència per enllaçar al destí
+**2sr_Salta la fase de localització de registres (utilitzeu amb -alr)
+**1T<x>_sistema operatiu de destí:
+3*2Termx_OS/2 via EMX (incloent extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2go32v2_versió 2 de DJ Deloire DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (no compatible)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin i MacOS X en PowerPC
+P*2Tlinux_Linux en PowerPC
+P*2Tmacos_MacOS (clàssic) en PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_Indefineix el símbol <x>
+**1U_Opcions de l'unitat:
+**2Un_No comprovar el nom de l'unitat
+**2Ur_generate release unit files
+**2Us_Compila una unitat del sistema
+**1v<x>_Detall. <x> és una combinació de les següents lletres :
+**2*_e : mostra errors (predet.) 0 : no mostrar res (excepte errors)
+**2*_w : mostra avisos u : mostra info de les unitats
+**2*_n : mostra notes t : mostra els fitxers selec./utilitz.
+**2*_h : mostra suggeriments c : mostra els condicionals
+**2*_i : mostra informació general d : mostra l'informació del depurador
+**2*_l : mostra números de línia r : compatibilitat Rhide/GCC
+**2*_a : mostra-ho tot x : informació de l'executable (win32)
+**2*_v : escriu fpcdebug.txt amb p : escriu tree.log amb arbre analitzat
+**2*_ molta informació de la depuració
+3*1W<x>_Opcions per a plataformes tipus Win32
+3*2WB<x>_Imatge a valor hexadecimal <x>
+3*2WC_Especifica aplicació tipus consola
+3*2WD_Utilitza DEFFILE per exportar les funcions de DLL o EXE
+3*2WF_Especifica aplicació tipus pantalla sencera (només OS/2)
+3*2WG_Especifica aplicació de tipus gràfic
+3*2WN_No generar codi deslocalitzat (necessari per la depuració)
+3*2WR_Genera codi reagrupat
+P*2WC_Especifica aplicació tipus consola (només MacOS)
+P*2WG_Especifica aplicació gràfica (només MacOS)
+P*2WT_Especifica aplicació tipus eina (eina MPW, només MacOS)
+**1X_Opcions de l'executable:
+**2Xc_passa --shared a l'enllaçador (només Unix)
+**2Xd_no utilitzar el camí normalitzat de biblioteques (necessària per compilar entre diferents SO)
+**2XD_intenta enllaçar les unitats dinàmicament (defineix FPC_LINK_DYNAMIC)
+**2XP<x>_avant posar el prefix <x> als noms de les utilitats binaries
+**2Xr<x>_posa el camí de les biblioteques a <x> (necessari per compilar entre diferents SO)
+**2Xs_elimina tots els símbols de l'executable
+**2XS_intenta enllaçar les unitats estàticament (predeterminat) (defineix FPC_LINK_STATIC)
+**2Xt_enllaça amb biblioteques estàtiques (es passa -static a l'enllaçador)
+**2XX_intenta enllaçar les unitats intel·ligentment (defineix FPC_LINK_SMART)
+**1*_
+**1?_mostra aquesta ajuda
+**1h_mostra aquesta ajuda sense esperar
+]
+
+#
+# The End...
diff --git a/compiler/msg/errord.msg b/compiler/msg/errord.msg
new file mode 100644
index 0000000000..69348f30e3
--- /dev/null
+++ b/compiler/msg/errord.msg
@@ -0,0 +1,2574 @@
+#
+# German (alternative) Language File for Free Pascal
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1998-2000 by the Free Pascal Development team
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ linenumber
+# u_ used
+# t_ tried
+# m_ macro
+# p_ procedure
+# c_ conditional
+# d_ debug message
+# b_ display overloaded procedures
+# x_ executable informations
+#
+
+#
+# General
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compiler: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Hostbetriebssystem: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Zielbetriebssystem: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Der Pfad der ausfhrbaren Datei ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_Der Unitpfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Der Includepfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Der Bibliothekspfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Der Objektdateienpfad: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Zeilen kompiliert, $2 Sekunden
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Speicher voll
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Resourcestringtabellendatei $1 wird geschrieben
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Fehler beim Schreiben der Resourcestringtabellendatei: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fataler Fehler:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Fehler:
+% Prefix for Errors
+general_i_warning=01014_I_Warnung:
+% Prefix for Warnings
+general_i_note=01015_I_Anmerkung:
+% Prefix for Notes
+general_i_hint=01016_I_Hinweis:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_Der Pfad "$1" existiert nicht
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Kompilieren abgebrochen
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Unerwartetes Dateiende
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment wasn't closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_Zeichenkette geht ber Zeilenende hinaus
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Unzul„ssiges Zeichen "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Syntaxfehler, "$1" erwartet, aber "$2" vorgefunden
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Die Include-Datei $1 wird jetzt gelesen
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Kommentarschachtelungstiefe $1 gefunden
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Compilerschalter $1 wurde ignoriert
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Compilerschalter $1 ist ungltig
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% doesn't know.
+scan_w_switch_is_global=02010_W_Dieser Compilerschalter hat globale Auswirkung
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Ungltige Char-Konstantante
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Datei $1 kann nicht ge”ffnet werden
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Includedatei $1 kann nicht ge”ffnet werden
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Ungltige Record Ausrichtung "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Ungltige minimale Gr”sse der Aufz„hlung "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 NORMAL or DEFAULT are valid in this case.
+scan_e_endif_expected=02017_E_$1 erwartet fr $1 $2 definiert in $3 Zeile $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Syntaxfehler im Argument einer $if Direktive
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_e_error_in_preproc_expr=02019_E_Syntaxfehler im Kontext einer $if Direktive
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Inhalt des Makros wurde nach der Auswertung bei 255 Zeichen abgeschnitten
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF ohne IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Benutzerdefiniert: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Benutzerdefiniert: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Benutzerdefiniert: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Benutzerdefiniert: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Benutzerdefiniert: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Benutzerdefiniert: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Ein Makro, welches den selben Namen wie ein Schlsselwort hat, wird ignoriert
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Makropufferberlauf w„hrend des Lesens oder Expandierens eines Makros
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Expansion des Makros berschreitet eine Makroschachtelungstiefe von 16
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Compilerschalter innerhalb von Kommentaren der Form // werden nicht unterstzt
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Bearbeite Schalter "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 bearbeitet
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Quelltext wird ignoriert bis...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Drcken Sie <Return> um fortzusetzen
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Nicht untersttzter Schalter $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Ungltige Compilerdirektive $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Wieder zurck in $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Nicht untersttzter Anwendungstyp: $1
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$APPTYPE\}} directive is supported by win32 applications only.
+scan_w_description_not_support=02046_W_Der Compilerschalter DESCRIPTION wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$VERSION\}} directive is only supported by win32 target.
+scan_n_only_exe_version=02048_N_VERSION kann in Units nicht verwendet werden
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Falsches Format fr VERSION-Directive $1
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_e_illegal_asmmode_specifier=02050_E_Unbekannter Assemblermodusname: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM-Leser-Schalter ist innerhalb einer Asm-Sequenz nicht m”glich, $1 wird erst in der n„chsten Sequenz wirksam
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Parameter fr Schalter falsch, verwenden Sie ON/OFF oder +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Resourcedateien werden vom aktuellen Zielbetriebssystem nicht untersttzt
+% The target you are compiling for doesn't support Resource files. The
+% only target which can use resource files is Win32
+scan_w_include_env_not_found=02054_W_$1 ist keine Umgebungsvariable
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Nicht erlaubter Wert fr MAXFPUREGISTER-Direktive
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Nur ein Resourcedatei wird vom aktuellen Zielbetriebssystem untersttzt
+% Only one resource file can be supported for this target - this is the case of
+% OS/2 (EMX) currently. The first one found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Makrountersttzung ist ausgeschaltet
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_Unbekannter Interfacetyp. Untersttzt wird COM, CORBA und DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID wird nur von PalmOS untersttzt
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME wird nur von PalmOS untersttzt
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Zeichenkettenkonstanten k”nnen maximal 255 Zeichen lang sein
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Include-Dateien k”nnen nur bis zu einer Tiefe von 16 geschachtelt werden
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Zu viele Ebenen von PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP ohne ein vorhergehendes PUSH
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Das Makro "$1" besitzt keinen Wert
+% Thus the conditional compiling expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Zum Modusumschalten kann nur ON/OFF/DEFAULT oder +/-/* verwendet werden
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Der Modus Umschalter "$1" ist hier nicht erlaubt
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Die Compile time Variable oder das Makro "$1" ist nicht definiert.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Der UTF-8 Kode ist gr”sser als 65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Ungltige UTF-8 Zeichenkette
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_UTF-8 Signatur gefunden, verwende UTF-8 Kode
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_Compile time Ausdruck: Erwartete $1 aber erhielt $2 bei $3
+% Type check of a compile time expression failed.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Syntaxfehler
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT-Prozeduren drfen nicht verschachtelt sein
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Prozedurtyp $1 wird ignoriert
+% This is a warning. \var{REGISTER},\var{REINTRODUCE} is ignored by FPC programs for now.
+% This is introduced first for Delphi compatibility.
+parser_e_no_overload_for_all_procs=03006_E_Nicht alle Deklarationen von "$1" sind mit OVERLOAD deklariert
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Doppelter Name fr exportierte Funktion $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Doppelter Index fr exportierte Funktion $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Ungltiger Index for exportierte Funktion
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Fr relozierbare DLL oder ausfhrbare Datei $1 funktionieren keine Debug-Information, deaktiviert.
+parser_w_parser_win32_debug_needs_WN=03012_W_Um Win32-Code debuggen zu k”nnen mssen die Relozierungen mit -WN option abgeschaltet werden.
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Konstruktor-Name muss INIT sein
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destruktor-Name muss DONE sein
+% You are declaring a constructor with a name which isn't \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Schlsselwort INLINE nicht untersttzt
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Konstruktor muss PUBLIC sein
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruktor muss PUBLIC sein
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasse darf nur einen Destruktor besitzen
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Lokale Klassendefinitionen sind nicht zul„ssig
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Anonyme Klassendefinitionen sind nicht zul„ssig
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_Das Objekt "$1" besitzt keine VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Ungltige Parameterliste
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Falsche Parameterzahl angegeben
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Bezeichner $1 ist keine Funktion, overload nicht m”glich
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it isn't a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Overload-Funktion darf nicht eine identische Parameterliste aufweisen
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Funktionskopf ist nicht identisch mit Forward-Deklaration $1
+% You declared a function with same parameters but
+% different result type or function specifiers.
+parser_e_header_different_var_names=03030_E_Funktionskopf von $1 passt nicht zur Forward-Deklaration, Variablename „ndert sich: $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Werte in Aufz„hlungen mssen aufsteigend sein
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_WITH kann nicht auf Variablen in anderen Segmenten angewendet werden
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Funktionsverschachtelung gr”sser als 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Bereichsprfungsfehler bei Konstantenbestimmung
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Bereichsprfungsfehler bei Konstantenbestimmung
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_doppelter CASE-Wert
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Obere Grenze der CASE-Bereichsangabe ist kleiner als untere Grenze
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Klassen sind als typisierte Konstanten unzul„ssig
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Funktionsvariablen von Overload-Funktionen sind unzul„ssig
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_Stringl„nge muss ein Wert zwischen 1 und 255 sein
+% The length of a string in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_Benutzen Sie die erweiterte Syntax von NEW und DISPOSE fr Objekt-Instanzen
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_Verwendung von NEW oder DISPOSE mit untypisierten Pointern ist ohne Aussage
+parser_e_no_new_dispose_on_void_pointers=03044_E_Verwendung von NEW oder DISPOSE mit untypisierten Pointern ist nicht m”glich
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Klassenbezeichner erwartet
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Typbezeichner ist hier nicht zul„ssig
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Methodenbezeichner erwartet
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Funktionskopf passt zu keiner Methode der Klasse $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedure/Function $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Ungltige Fliesskommakonstante
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL darf nur in Konstruktoren verwendet werden
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruktoren k”nnen keine Parameter haben
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Nur Klassenmethoden k”nnen ber den Klassennamen angesprochen werden
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Nur Klassenmethoden k”nnen in einer Klassenmethode angesprochen werden
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Konstante und CASE-Typ passen nicht zueinander
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Das Symbol kann nicht aus einer Bibliothek exportiert werden
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Eine Inherit-Methode wird durch $1 verdeckt
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Es gibt keine Vorg„ngerklasse mit einer Methode, die damit berschrieben werden k”nnte: $1
+% You try to \var{override} a virtual method of a parent class that doesn't
+% exist.
+parser_e_no_procedure_to_access_property=03059_E_Es gibt keine Member-Funktion um auf diese Property zuzugreifen
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Die Stored Property - Direktive ist noch nicht implementiert
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Ungltiges Symbol fr den Zugriff auf die Property
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Kann an dieser Stelle nicht auf das geschtzte Feld des Objekts zugreifen
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Kann an dieser Stelle nicht auf das private Feld des Objekts zugreifen
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_šberschriebene, virtuelle Methoden mssen den gleichen Ergebnistyp haben: "$2" wird berschrieben von "$1"
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Mit EXPORT deklarierte Funktionen drfen nicht verschachtelt sein
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Methoden drfen nicht EXPORTiert werden
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Aufrufe mit VAR-Parametern mssen exakt stimmen: "$1" gefunden, "$2" erwartet
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Klasse ist keine Elternklasse zur aktuellen Klasse
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF ist nur in Methoden erlaubt
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Methoden drfen nur in anderen Methoden direkt mit dem Klassen-Typbezeichner aufgerufen werden
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Unzul„ssige Verwendung von ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Bereichsprfungsfehler im SET-Konstruktor oder doppeltes Set-Element
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Zeiger auf Objekt erwartet
+% You specified an illegal type in a \var{New} statement.
+% The extended synax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Ausdruck muss ein Konstruktor-Aufruf sein
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Ausdruck muss ein Destruktor-Aufruf sein
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Unzul„ssige Reihenfolge der Record-Elemente
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Typ des Ausdrucks muss eine Klasse oder ein Recordtyp sein
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Prozeduren k”nnen keinen Wert zurckliefern
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Konstruktoren und Destruktoren mssen Methoden sein
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator besitzt kein Overload
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Es ist nicht m”glich, die Zuweisung fr gleiche Typen zu berladen
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Unm”gliche Operator-.berladung
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Ausl”sen einer Exception an dieser Stelle nicht m”glich
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Die erweiterte Syntax von New oder Dispose ist fr Klassen unzul„ssig
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Das šberladen von Prozeduren ist ausgeschaltet
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Es ist nicht m”glich, dieesen Operator zu berladen (benutzen Sie stattdessen '=')
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Vergleichsoperator muss einen booleschen Wert zurckgeben
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Nur virtuelle Methoden k”nnen abstrakt sein
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Benutzung einer nicht untersttzten Erweiterung!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Das Mischen von Klassen und Objekten ist unzul„ssig
+% You cannot derive \var{objects} and \var{classes} intertwined . That is,
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Unbekannte Prozedur, Direktive $1 wurde ignoriert
+% The procedure direcive you secified is unknown.
+parser_e_absolute_only_one_var=03095_E_ABSOLUTE kann nur auf eine alleinstehende Variable angewendet werden
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE kann nur auf Variablen und Konstanten angewendet werden
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Es kann nur EINE Variable initialisiert werden
+% You cannot specify more than one variable with a initial value
+% in Delphi syntax.
+parser_e_abstract_no_definition=03098_E_Abstrakte Methoden drfen keine Definition (mit Rumpf) haben
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Diese berladene Funktion darf nicht lokal sein (muss Exportiert werden)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Virtuelle Methoden wurden ohne Konstruktor verwendet in $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Makro definiert: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Makrodefinition gel”scht: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Wert des Makros $1 auf $2 gesetzt
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Kompiliere $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parse Interface von Unit $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parse Implementation von $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Kompiliere $1 zum zweiten Mal
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Es gibt keine Property diesen Namens, die berschrieben werden k”nnte
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Es ist nur eine einzelne Default-Property erlaubt, vererbte Default-Property in Klasse $1 gefunden
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Die Default-Property muss eine Array-Property sein
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtuelle Konstruktoren werden nur im Klassen-Objektmodell untersttzt
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Keine Default-Property verfgbar
+% You try to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Die Klasse kann keinen PUBLISHED Bereich haben, benutzen Sie den {$M+} Schalter
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Forward-Deklaration der Klasse $1 muss hier aufgel”st werden, wenn sie als Elternklasse benutzt werden soll
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokale Operatoren werden nicht untersttzt
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Prozedur-Direktive $1 unzul„ssig im Interface-Bereich
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Prozedur Direktive $1 unzul„ssig im Implementation-Bereich
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Prozedur-Direktive $1 unzul„ssig in einer Procvar-Deklaration
+% This procedure directive cannot be part of a procedural of function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Funktion ist bereits als Public oder Forward deklariert: $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Kann nicht EXPORT und EXTERNAL gleichzeitig benutzen
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_$1 noch nicht innerhalb von inline Prozeduren/Funktionen untersttzt
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining deaktiviert
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Schreibe Browser-Log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+\}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_M”glicherweise fehlt eine Zeiger-Dereferenzierung
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Gew„hlter Assembler-Leser nicht untersttzt
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Prozedur-Direktive $1 steht in Konflikt mit anderen Direktiven
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Aufrufkonvention passt nicht zur Forward-Deklaration
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Property kann keinen Vorgabewert haben
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Der Vorgabewert einer Property muss eine Konstante sein
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol darf nicht PUBLISHED sein, dies kann nur eine Klasse sein
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Diese Property-Art kann nicht Published sein
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Leerer Importname angegeben
+% Some targets need a name for the imported procedure or a cdecl specifier
+parser_e_division_by_zero=03138_E_Division durch Null
+% There is a division by zero encounted
+parser_e_invalid_float_operation=03139_E_Ungltige Fliesskomma-Operation
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Obere Grenze des Bereichs ist kleiner als die untere Grenze
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_String "$1" ist l„nger als $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Stringl„nge ist gr”sser als die L„nge des "array of char"
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Ungltiger Ausdruck nach der 'Message'-Direktive
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Message-Handler akzeptieren nur einen "Call by Reference" Parameter
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Doppeltes Message-Label: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_SELF darf nur in Message-Handlern ein expliziter Parameter sein
+% The self parameter can be passed only explicit if it is a method which
+% is declared as message method handler
+parser_e_threadvars_only_sg=03147_E_Threadvariablen k”nnen nur statisch oder global sein
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Direkter Assembler wird f+r bin„res Ausgabeformat nicht untersttzt
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Laden Sie die OBJPAS Unit nicht manuell, benutzen Sie statdessen {$mode objfpc} oder {$mode delphi}
+% You're trying to load the ObjPas unit manual from a uses clause. This is
+% not a good idea to do, you can better use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automaticly
+parser_e_no_object_override=03150_E_OVERRIDE darf in Objekten nicht verwendet werden
+% Override isn't support for objects, use VIRTUAL instead to override
+% a method of an anchestor object
+parser_e_cant_use_inittable_here=03151_E_Datentypen, die ein Initialiserung oder Finalisierung ben”tigen, k”nnen in varianten Records nicht verwendet werden
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings drfen nur statisch oder global sein
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_EXIT mit Argument darf hier nicht verwendet werden
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Der Typ des STORED-Symbols muss boolesch sein
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Dieses Symbol ist als Speichersymbol unzul„ssig
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Nur Klassen, die im "$M+"-Modus kompiliert wurden, drfen published sein
+% In the published section of a class can be only class as fields used which
+% are compiled in $M+ or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Prozedurdirektive erwartet
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Der Wert fr einen Property-Index muss ordinalen Typs sein
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Prozedurname zu kurz um exportiert zu werden
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Es kann kein DEFFILE-Eintrag fr unit-globale Variablen erzeugt werden
+parser_e_dlltool_unit_var_problem2=03161_E_Kompiliere ohne "-WD"-Option
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Es muss der Modus ObjFPC (-S2) oder Delphi (-Sd) aktiv sein, um dieses Modul zu bersetzen
+% You need to use {$mode objfpc} or {$mode delphi} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Der Index darf nicht kleiner als $1 sein
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Das Ziel $1 untersttzt das Exportieren von Variablen nicht
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Falscher GUID-Syntax
+parser_w_interface_mapping_notfound=03168_W_Eine Procedure mit dem Namen "$1", die $2.$3 implementieren k”nnte, kann nicht gefunden werden
+parser_e_interface_id_expected=03169_E_Interface-Bezeichner erwartet
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Der Typ "$1" kann nicht als Array-Index verwendet werden
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Kon- und Destruktoren sind in Interfaces nicht erlaubt
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Zugriffsbezeichner k”nnen in Interfaces nicht benutzt werden
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Ein Interface darf keine Felder enthalten
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Eine lokale Procedure kann nicht als EXTERNAL deklariert werden
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Einige Felder vor dem Feld "$1" sind nicht initialisiert
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Einige Felder vor dem Feld "$1" sind nicht initialisiert
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Einige Felder nach dem Feld "$1" sind nicht initialisiert
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Verwendung von VarArgs ohne CDecl oder External nicht m”glich
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self muss ein Call-By-Value-Parameter sein
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interface "$1" hat keine Interface-Identifikation
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Klassenfeld oder Methoden-Bezeichner "$1" unbekannt
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_šberschreibe die Calling Convention "$1" mit "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Die Konstante des Typs "procedure of object" kann nur mit NIL initialisiert werden
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Der Default Value kann nur einem Parameter zugewiesen werden
+parser_e_default_value_expected_for_para=03185_E_Standard Parameter fr "$1" ben”tigt
+parser_w_unsupported_feature=03186_W_Verwendung eines nicht untersttzten Features!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C Arrays werden "by reference" bergeben
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_C array of const muss letztes Argument sein
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Erneute Definition des Typs "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_cdecl'ared Functionen haben keinen high Parameter
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_cdecl'ared Functionen untersttzen keine open strings
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Als threadvar deklarierte Variable kann nicht initialisiert werden
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Message directive ist nur in Klassen erlaubt
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure oder Function erwartet
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Calling convention directive ignoriert: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE kann in Objekten nicht benutzt werden
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Jedes Argument muss seine eigene "location" haben
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Jedes Argument muss seine explizite "location" haben
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_"location" des Arguments unbekannt
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32 Bit-Integer oder Zeiger-Variable erwartet
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Goto Statements zwischen verschiedenen Prozeduren sind nicht erlaubt
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure zu komplex, sie erfordert zu viele Register
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Ungltiger Ausdruck
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Ungltiger integer Ausdruck
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Ungltiger Qualifier
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_High Range Limit < low Range Limit
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Exits Parameter muss der Name der Prozedur sein, in der es benutzt wird
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Ungltige Zuweisung zur for-loop Variable "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Lokale Variable kann nicht als EXTERNAL deklariert werden
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Prozedur ist bereits als EXTERNAL deklariert
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Implizite Verwendung einer Variant Unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Class und statische Methoden k”nnen nicht in INTERFACES verwendet werden
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow in arithmetischer Operation
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Protected oder private erwartet
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Typen passen nicht zusammen
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Inkompatible Typen: Habe "$1" erhalten, aber "$2" erwartet
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Typen sind verschieden bei $1 und $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Typbezeichner erwartet
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variablenbezeichner erwartet
+% This happens when you pass a constant to a \var{Inc} var or \var{Dec}
+% procedure. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Integer-Ausdruck erwartet, aber "$1" erhalten
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Booleschen Ausdruck erwartet, aber "$1" erhalten
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Ganzahligen Ausdruck erwartet
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Zeigertyp erwartet, aber "$1" erhalten
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Klassentyp erwartet, aber "$1" erhalten
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Kann konstanten Ausdruck nicht auswerten
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Set-Elemente sind nicht kompatibel
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operation fr Sets nicht implementiert
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Automatische Typumwandlung von Fliesskommatyp nach COMP (=integer mit 64 bit)
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Verwenden sie DIV um ein Integer-Ergebnis zu erhalten
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Stringtypen passen nicht zueinander, da in "$V+"-Modus
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ oder Pred kann nicht auf Aufz„hlungen mit Zuweisungen angewendet werden
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Kann Variablen dieses Typs nicht lesen oder schreiben
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Kann ReadLn und WriteLn nicht bei typisierten Dateien verwenden
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Kann Read und Write nicht bei untypisierten Dateien verwenden
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Typkonflikt zwischen den Elementen des Sets
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) gibt oberes/unteres Word/DWord zurck
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type case the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Integer- oder Real-Ausdruck erwartet
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Falscher Typ "$1" im Array-Konstruktor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Inkompatible Typen fr Argument Nr. #$1: habe $2 erhalten, aber $3 erwartet
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Methode (Variable) und Prozedur (Variable) sind nicht kompatibel
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Unzul„ssige Konstante an interne Algebrafunktion bergeben
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Von Konstanten kann keine Adresse bestimmt werden
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_An das Argument kann nichts zugewiesen werden
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Kann lokale Prozedur/Funktion nicht an Prozedurvariable zuweisen
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Kann einer Adresse keine Werte zuweisen
+% It's not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Kann einer Konstanten keine Werte zuweisen
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing make the parameter value or var.
+type_e_array_required=04033_E_Array Typ notwendig
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Interface Typ erwartet, aber "$1" erhalten
+type_w_mixed_signed_unsigned=04035_W_Mischen von signed Ausdrcken und Longwords ergibt ein 64bit Ergebnis
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mischen von signed Ausdrcken und kardinalen Typen hier kann einen Bereichsprfungsfehler verursachen
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast hat verschiedene Gr”ssen ($1 -> $2) in der Zuweisung
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enums mit Zuweisungen k”nnen nicht als Array-Index verwendet werden
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Klassen- oder Objekttypen "$1" and "$2" sind nicht verwandt
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Klassentypen "$1" und "$2" sind nicht verwandt
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Klassen- oder Interface-Typ erwartet, aber "$1" erhalten
+type_e_type_is_not_completly_defined=04042_E_Typ "$1" ist nicht vollst„ndig definiert
+type_w_string_too_long=04043_W_String literal hat mehr Zeichen als short string length
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_Wegen des Bereichs der Werte ist das Vergleichsergebnis immer falsch
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_Wegen des Bereichs der Werte ist das Vergleichsergebnis immer richtig
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Konstruktion der Klasse "$1" mit abstrakten Methoden
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_Der linke Operand des IN Operators sollte byte Gr”sse haben
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Unpassende Typgr”ssen, Gefahr des Datenverlusts oder Bereichsprfungsfehlers
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Unpassende Typgr”ssen, Gefahr des Datenverlusts oder Bereichsprfungsfehlers
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Die Adresse einer abstrakten Methode kann nicht verwendet werden
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_Der Operator passt nicht zum Typ des Operanden
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Konstanter Ausdruck erwartet
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operation "$1" wird fr die Typen "$2" und "$3" nicht untersttzt
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Illegale Typ-Konversion: "$1" nach "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konversion zwischen ordinalen Typen und Zeigern ist nicht portierbar
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konversion zwischen ordinalen Typen und Zeigern ist nicht portierbar
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Kann nicht bestimmen, welche der berladenen Funktionen aufgerufen werden soll
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Loop-Variable muss einen ordinalen Typ haben
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Bezeichner "$1" nicht gefunden
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Interner Fehler in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Doppelter Bezeichner "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Bezeichner ist bereits definiert in $1 in Zeile $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Unbekannter Bezeichner "$1"
+% The identifier encountered hasn't been declared, or is used outside the
+% scope where it's defined.
+sym_e_forward_not_resolved=05005_E_Forward-Deklaration "$1" nicht gefunden
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Fehler in Typdefinition
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward-Typ "$1" nicht gefunden
+% The compiler encountered an unknown type.
+sym_e_only_static_in_static=05010_E_Nur statische Variablen k”nnen in statischen oder „usseren Methoden verwendet werden
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Record- oder Klassen-Typ erwartet
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instanzen von Klassen oder Objekten mit abstrakten Methoden sind unzul„ssig
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label "$1" nicht definiert
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label "$1" benutzt aber nicht definiert
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Ungltige Label-Deklaration
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO und LABEL werden nicht untersttzt (verwenden Sie den Schalter -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label nicht gefunden
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Bezeichner ist kein Label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label ist bereits definiert
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Ungltige Typdeklaration von Set-Elementen
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward-Klassendefinition nicht gefunden: $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Unit "$1" wird von "$2" nicht verwendet
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter nicht verwendet: $1
+% This is a warning. The identifier was declared (locally or globally) but
+% wasn't used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokale Variable nicht verwendet: $1
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Werte-Parameter "$1" wurde zugewiesen aber nie verwendet
+% This is a warning. The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Lokale Variable "$1" wurde zugewiesen aber nicht verwendet
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Lokales $1-Element "$2" wird nicht verwendet
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Privates Feld $1.$2 wird nie verwendet
+sym_n_private_identifier_only_set=05030_N_Privates Feld $1.$2 wurde zugewiesen aber nie verwendet
+sym_n_private_method_not_used=05031_N_Private Methode $1.$2 wird nie verwendet
+sym_e_set_expected=05032_E_Mengentyp erwartet
+% The variable or expression isn't of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Funktionsergebnis scheint nicht gesetzt zu sein
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Typ "$1" ist im aktuellen Record mit C-Packing nicht korrekt ausgerichtet
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Unbekannter Record-Feldbezeichner $1
+% The field doesn't exist in the record definition.
+sym_w_uninitialized_local_variable=05036_W_Lokale Variable "$1" wird verwendet, bevor ihr ein Wert zugewiesen wurde
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_Variable "$1" scheint nicht initialisiert worden zu sein
+% These messages are displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% wasn't initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Bezeichener verweist nicht auf ein Element: $1
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the class you are trying to create. The procedure you specified
+% does not exist.
+sym_h_param_list=05039_H_Deklaration gefunden: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Datensegment zu gross (max. 2GB)
+% You get this when you declare an array whose size exceeds the 2GB limit.
+sym_e_no_matching_implementation_found=05042_E_Keine passende Implementation der Interface Methode "$1" gefunden
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" ist veraltet
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbol "$1" ist nicht portierbar
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" ist nicht implementiert
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Von diesem Typ kann kein eindeutiger Typ deklariert werden
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Die Variable "$1" scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Die Variable "$1" scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Gr”sse der Parameterliste bersteigt 65535 Bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Dateitypen mssen VAR Parameter sein
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_Die Verwendung eines FAR-Zeigers ist in dieser Art nicht erlaubt
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Mit EXPORT deklarierte Funktionen k”nnen nicht aufgerufen werden
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_M”glicherweise unzul„ssiger Aufruf eines Konstruktors oder Destruktors (passt nicht in diesen Kontext)
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Uneffiziente Programmierung
+% You construction seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Code wird niemals ausgefhrt
+% You specified a loop which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstrakte Methoden k”nnen nicht direkt aufgerufen werden
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 Gewichtung $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stackframe wird ausgelassen
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Objektmethoden k”nnen nicht Inline sein
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar-Aufrufe k”nnen nicht Inline sein
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Kein Code fr Inline-Prozedur gespeichert
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Auf Element Null von Ansi/Wide- oder Longstring kann nicht zugegriffen werden, benutzen Sie stattdessen (Set)Length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Konstruktoren und Destruktoren k”nnen in diesem Kontext nicht aufgerufen werden
+% Inside a \var{With} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Kann Messagehandler-Methode nicht direkt aufrufen
+% A message method handler method can't be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Sprung in- oder aus dem Exceptionblock heraus
+% It isn't allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Kontrollfluss-Anweisungen sind in einem Finally-Block nicht erlaubt
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Gr”sse der Parameter berschreitet die Grenze fr bestimmte CPUs
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Gr”sse der lokalen Variablen berschreitet die Grenze fr bestimmte CPUs
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Gr”sse der lokalen Variablen berschreitet die untersttzte Grenze
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK nicht zul„ssig
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE nicht zul„ssig
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Unbekannte Compiler-Prozedur "$1". šberprfe, ob die korrekte Laufzeit-Bibliothek verwendet wird.
+% The compiler expects that the runtime library contains some subrountines. If you see this error
+% and you didn't mess with the runtime library, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Starte $1 Stil Assembler Parsen
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Beende $1 Stil Assembler Parsen
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Nicht-Label Bezeichner enth„lt @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Fehler beim Ermitteln des Recordoffsets
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET ohne Bezeicner verwendet
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE verwendet ohne Bezeichner
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Lokale Variable oder Parameter k”nnen hier nicht verwendet werden
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the %ebp register so the
+% address can't be get directly.
+asmr_e_need_offset=07008_E_Hier muss OFFSET verwendet werden
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Hier muss "$" verwendet werden
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Verwendung von mehreren verschiebbaren Symbolen nicht m”glich
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Verschiebbares Symbol kann nur addiert werden
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Ungltiger Konstantenausdruck
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Verschiebbares Symbol ist nicht zul„ssig
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Ungltige Verweis-Syntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Sie k”nnen "$1" von diesem Code aus nicht erreichen
+% You can not read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokale Symbole/Labels sind nicht als Referenz zul„ssig
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Ungltige Verwendung von Basis- und Index-Registern
+% There is an error with the base and index register
+asmr_w_possible_object_field_bug=07018_W_M”glicher Fehler bei Objektfeld-Behandlung
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Falscher Skalierungsfaktor angegeben
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Mehrfache Verwendung fon Index-Registern
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Ungltiger Operandentyp
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Unglitge Zeichenkette als Opcode-Operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE und @DATA werden nicht untersttzt
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null-Label-Bezug nicht m”glich
+asmr_e_expr_zero_divide=07025_E_Division durch Null in Assembler-Ausdruck
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Ungltiger Ausdruck
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Escape-Sequenz ignoriert: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Ungltige Symbolverwendung
+asmr_w_fwait_emu_prob=07029_W_FWAIT kann Emulationsprobleme mit emu387 verursachen
+asmr_w_fadd_to_faddp=07030_W_$1 ohne Operand wurde in $1P bersetzt
+asmr_w_enter_not_supported_by_linux=07031_W_Der ENTER-Befehl wird vom Linux-Kernel nicht untersttzt
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Aufruf einer berladenen Funktion in Assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Nicht untersttzter Symboltyp fr Operand
+asmr_e_constant_out_of_bounds=07034_E_Wert der Konstante ausserhalb des zul„ssigen Bereichs
+asmr_e_error_converting_decimal=07035_E_Fehler beim Umwandeln in Dezimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Fehler beim Umwandeln in Oktal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Fehler beim Umwandeln in Bin„r $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Fehler beim Umwandeln in Hexadezimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 bersetzt nach $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 ist einer berladenen Funktion zugeordnet
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Kann SELF nicht ausserhalb einer Methode verwenden
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Kann OLDEBP ausserhalb einer verschachtelten Prozedur nicht verwenden
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Prozeduren k”nnen keinen Wert im Assembler-Code zurckliefern
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nicht untersttzt
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Gr”ssensuffix und Ziel- oder Quellgr”sse passen nicht zusammen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Gr”ssensuffix und Ziel- oder Quellgr”sse passen nicht zusammen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Assembler Syntaxfehler
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Ungltige Kombination von Opcode und Operanden
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Assembler Syntaxfehler im Operanden
+asmr_e_syn_constant=07050_E_Assembler Syntaxfehler in Konstanten
+asmr_e_invalid_string_expression=07051_E_Ungltiger Stringausdruck
+asmr_w_const32bit_for_address=07052_W_Konstante mit Symbol $1 fr Adresse erzeugt, die kein Pointer ist
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Unbekannter Opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Ungltiger oder fehlender Opcode
+asmr_e_invalid_prefix_and_opcode=07055_E_Ungltige Kombination von Prefix und Opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Ungltige Kombination von Override und Opcode: $1
+asmr_e_too_many_operands=07057_E_Zu viele Operanden in der Zeile
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignoriert
+asmr_w_far_ignored=07059_W_FAR ignoriert
+asmr_e_dup_local_sym=07060_E_Doppelters lokales Symbol $1
+asmr_e_unknown_local_sym=07061_E_Undefiniertes lokales Symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unbekannter Label-Bezeichner $1
+asmr_e_invalid_register=07063_E_Ungltiger Registername
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Ungltiger Name fr Fliesskommaregister
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo nicht untersttzt
+asmr_e_invalid_float_const=07067_E_Ungltige Fliesskommakonstante $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Ungltiger Fliesskommaausdruck
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Falscher Symboltyp
+asmr_e_cannot_index_relative_var=07070_E_Kann lokale Variable oder Parameter nicht mit Register indizieren
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Ungltiger Segmentoverride-Ausdruck
+asmr_w_id_supposed_external=07072_W_Bezeichner $1 ist vermutlich External
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings sind als Konstanten unzul„ssig
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Typ der Variablen nicht angegeben
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Assemblercode kehrt nicht zum Text zurck
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Keine Direktive oder lokales Symbol $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Verwendung eines definierten Namens als lokales Label
+asmr_e_dollar_without_identifier=07078_E_Dollarzeichen wird ohne Bezeichner verwendet
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32-Bit-Konstante fr Adresse erzeugt
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align ist abh„ngig von Zielplattform, verwende .balign oder .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Kann fr Parameter nicht direkt auf Felder zugreifen
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Kann auf Felder von Objekten/Klassen nicht direkt zugreifen
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Gr”sse nicht spezifiziert und auch keine M”glichkeit die Gr”sse der Operanden zu bestimmen
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_RESULT kann in dieser Funktion nicht verwendet werden
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" ohne Operand bersetzt in "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" bersetzt in "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" bersetzt in "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Das Zeichen < ist hier nicht erlaubt
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Das Zeichen > ist hier nicht erlaubt
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN wird nicht untersttzt
+asmr_e_no_inc_and_dec_together=07094_E_Inc und Dec k”nnen nicht gemeinsam vorkommen
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Ungltige Registerliste fr movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Ungltige Registerliste fr diesen opcode
+asmr_e_higher_cpu_mode_required=07097_E_H”herer cpu Modus notwendig ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Gr”sse nicht spezifiziert und auch keine M”glichkeit die Gr”sse der Operanden zu bestimmen. Es wird DWORD als Voreinstellung verwendet
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Syntax Fehler beim Analysieren eines shifter Operanden
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Zu viele Assembler-Dateien
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Gew„hlte Assemblerausgabe wird nicht untersttzt
+asmw_f_comp_not_supported=08002_F_Comp nicht untersttzt
+asmw_f_direct_not_supported=08003_F_Direct nicht untersttzt fr bin„res Schreiben
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Allozieren von Daten ist nur in "bss"-Abschnitten zul„ssig
+asmw_f_no_binary_writer_selected=08005_F_Kein Bin„rschreiber ausgew„hlt
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 nicht in Tabelle enthalten
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 ungltige Kombination von Opcode und Operanden
+asmw_e_16bit_not_supported=08008_E_Asm: 16-Bit-Verweise werden nicht unterttzt
+asmw_e_invalid_effective_address=08009_E_Asm: Ungltige effektive Adresse
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Konstanten Ausdruck oder Referenz erwartet
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 Wert berschreitet Grenzen $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: "Short jump" ist ausserhalb der Bereichs $1
+asmw_e_undefined_label=08013_E_Asm: Undefiniertes Label: $1
+asmw_e_comp_not_supported=08014_E_Asm: Comp wird fr diese Ziel nicht untersttzt
+asmw_e_extended_not_supported=08015_E_Asm: Extended Typ wird fr diese Ziel nicht untersttzt
+asmw_e_duplicate_label=08016_E_Asm: Doppeltes Label $1
+asmw_e_redefined_label=08017_E_Asm: Neu definiertes Label $1
+asmw_e_first_defined_label=08018_E_Asm: First beginnt hier
+asmw_e_invalid_register=08019_E_Asm: Ungltiges Register $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Quell-Betriebssystem wurde neu definiert
+exec_i_assembling_pipe=09001_I_Assembliere (pipe) $1
+exec_d_cant_create_asmfile=09002_E_Kann Assemblerdatei nicht erzeugen: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_objectfile=09003_E_Kann Objektdatei nicht erzeugen: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_archivefile=09004_E_Kann Archivdatei nicht erzeugen: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 nicht gefunden, schalte um zu externem Assemblieren
+exec_t_using_assembler=09006_T_Benutze Assembler: $1
+exec_e_error_while_assembling=09007_E_Fehler beim Assemblieren des Exitcodes $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Assembler kann nicht aufgerufen werden, Fehler $1 schalte um zu externem Assemblieren
+exec_i_assembling=09009_I_Assembliere $1
+exec_i_assembling_smart=09010_I_Assembliere mit Smartlinking $1
+exec_w_objfile_not_found=09011_W_Objekt $1 nicht gefunden, Linken kann fehlschlagen!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Bibliothek $1 nicht gefunden, Linken kann fehlschlagen!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Fehler beim Linken
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Linker kann nicht aufgerufen werden, schalte um zu externem Linken
+exec_i_linking=09015_I_Linke $1
+exec_e_util_not_found=09016_E_Hilfsprogramm $1 nicht gefunden, schalte um zu externem Linken
+exec_t_using_util=09017_T_Benutze Hilfsprogramm $1
+exec_e_exe_not_supported=09018_E_Erzeugen von ausfhrbaren Dateien nicht untersttzt
+exec_e_dll_not_supported=09019_E_Dynamische Bibliotheken nicht untersttzt
+exec_i_closing_script=09020_I_Schliesse Skript $1
+exec_e_res_not_found=09021_E_Resourcen Compiler nicht gefunden, schalte um zu externem Modus
+exec_i_compilingresource=09022_I_Kompiliere Resource $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Unit $1 kann nicht statisch gelinkt werden, schalte um zu smart Linken
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Unit $1 kann nicht smart gelinkt werden, schalte um zu statischem Linken
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Unit $1 kann nicht shared gelinkt werden, schalte um zu statischem Linken
+exec_e_unit_not_smart_or_static_linkable=09026_E_Unit $1 kann weder smart noch statisch gelinkt werden
+exec_e_unit_not_shared_or_static_linkable=09027_E_Unit $1 kann weder shared noch statisch gelinkt werden
+exec_d_resbin_params=09028_D_Resource Compiler "$1" wird mit "$2" als Kommandozeile aufgerufen
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_Kann ausfhrbare Datei nicht nachbearbeiten: $1
+execinfo_f_cant_open_executable=09129_F_Kann ausfhrbare Datei nicht ”ffnen: $1
+execinfo_x_codesize=09130_X_Gr”sse des Codes: $1 Bytes
+execinfo_x_initdatasize=09131_X_Gr”sse der initialisierten Daten: $1 Bytes
+execinfo_x_uninitdatasize=09132_X_Gr”sse der nicht initialisierten Daten: $1 Bytes
+execinfo_x_stackreserve=09133_X_Stack Bereich "reserved": $1 Bytes
+execinfo_x_stackcommit=09134_X_Stack Bereich "commited": $1 Bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Suche Unit: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Lade PPU: $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU-Name: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU-Flags: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU-CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU-Zeit: $1
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_file_too_short=10006_U_PPU-Datei zu kurz
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_invalid_header=10007_U_PPU Ungltiger Header (kein PPU am Anfang)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_PPU Ungltige Version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU ist fr einen anderen Prozessor kompiliert
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU ist fr ein anderes Zielsystem kompiliert
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU Quelle: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Schreibe $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Kann PPU-Datei nicht schreiben
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Kann PPU-Datei nicht lesen
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Unerwartetes Ende der PPU-Datei
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Ungltiger Eintrag in PPU-Datei: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx Z„hler-Problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Ungltiger Unitname: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Zu viele Units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Gegenseitige Abh„ngigkeit von Units zwischen $1 und $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Kann Unit "$1" nicht bersetzen, keine Quellen vorhanden
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Kann Unit "$1" nicht finden
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Unit "$1" wurde nicht gefunden, aber "$2" existiert
+unit_f_unit_name_error=10024_F_Unit "$1" gesucht, aber "$2" gefunden
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_šbersetzen der Systemunit erfordert den Schalter -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Es traten $1 Fehler beim šbersetzen des Moduls auf, halte an
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Lade aus $1 ($2) die Unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_šbersetze $1 erneut, Prfsumme fr $2 hat sich ge„ndert
+unit_u_recompile_source_found_alone=10029_U_šbersetze "$1", nur Quellcode gefunden
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_šbersetze Unit erneut, statische Biblothek ist „lter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_šbersetze Unit erneut, gemeinsame Bibliothek ist „lter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_šbersetze Unit erneut, obj und asm sind „lter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the assembler of
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_šbersetze Unit erneut, obj ist „lter als asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Analysiere Interface von $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Analysiere Implementation von $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Zweites Laden fr Unit "$1"
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU prfe Datei $1 Zeit $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 wurde beim Start beim letzten Kompilieren von $2 nicht gesetzt
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 wurde beim Start beim letzten Kompilieren von $2 gesetzt
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Kann Unit $1 nicht rekompilieren, aber ge„nderte Include-Datei gefunden
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Datei $1 ist neuer als die Release PPU Datei $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Eine Unit wurde nicht mit der korrekten FPU Mode kompiliert
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Interface Units werden von $1 geladen
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Implementation Units werden von $1 geladen
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Ge„nderte Interface CRC fr Unit $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Ge„nderte Implementation CRC fr Unit $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Kompilieren der Unit $1 beendet
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Fge die Abh„ngigkeit von $1 von $2 dazu
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Kein erneutes Laden, Unit $1 ist die Aufrufende
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Kein erneutes Laden der Unit, bereits beim zweiten Kompilieren: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Flag fr erneutes Laden: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Erzwungenes erneutes Laden
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Vorhergehender Status von $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_$1 wird bereits kompiliert, zweites Kompilieren gesetzt
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Unit $1 wird geladen
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Laden der Unit $1 beendet
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrierung der neuen Unit $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Erneutes resolving der Unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Erneutes Resolving der Unit $1 wird bersprungen, benutzte Units werden noch geladen
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [Optionen] <Eingabedatei> [Optionen]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Nur eine Quelldatei untersttzt
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF-Datei kann nur fr OS/2 erzeugt werden
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Verschachtelte Response-Dateien werden nicht untersttzt
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Kein Name fr Quelldatei auf der Kommandzeile
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Keine Angeben in Konfigurationsdatei "$1" gefunden
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Ungltiger Parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? zeigt Hilfetext an
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Zu viele verschachtelte Konfigurtionsdateien
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Kann Datei nicht ”ffnen $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lese weitere Optionen aus $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Zielsystem ist bereits gesetzt: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Gemeinsame Bibliotheken sind auf der DOS Platform nicht verfgbar, verwende stattdessen statische Bibliotheken
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Zu viele IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Zu viele ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Offene Bedingung am Dateiende
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Erzeugung von Debug-Informationen wird von dieser ausfhrbaren Datei nicht untersttzt
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Versuchen Sie mit -dGDB erneut zu kompilieren
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Sie verwenden den nun berflssigen Schalter $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Sie benutzen den nun berflssigen Schalter $1, bitte benutzen Sie $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Schalte Assembler auf den Standard-Assembler-Quellcodeschreiber
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Das gew„hlte Assembler-Ausgabeformat "$1" ist nicht mit "$2" kompatibel
+option_asm_forced=11022_W_Verwendung des Assemblers "$1" erzwungen
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Optionen werden aus der Datei $1 gelesen
+% Options are also read from this file
+option_using_env=11027_T_Optionen werden aus dem environment $1 gelesen
+% Options are also read from this environment string
+option_handling_option=11028_D_Handling der Option "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** Drcken sie die ENTER Taste ***
+option_start_reading_configfile=11030_H_Beginn des Lesens der config Datei $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Ende des Lesens der config Datei $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Option "$1" interpretieren
+option_interpreting_firstpass_option=11036_D_firstpass Option "$1" interpretieren
+option_interpreting_file_option=11033_D_Datei Option "$1" interpretieren
+option_read_config_file=11034_D_config Datei "$1" lesen
+option_found_file=11035_D_Name der Quelldatei "$1" gefunden
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Unbekannte code page
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler Version $FPCVER [$FPCDATE] fr $FPCTARGET
+Copyright (c) 1993-2005 Florian Kl„mpfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler Version $FPCVER
+
+Compiler Datum: $FPCDATE
+Compiler Zielsystem: $FPCCPU
+
+Untersttzte Zielsysteme:
+ $OSTARGETS
+
+Untersttzte CPU Instruktionen:
+ $INSTRUCTIONSETS
+
+Untersttzte FPU Instruktionen:
+ $FPUINSTRUCTIONSETS
+
+Dieses Programm unterliegt der GNU General Public Licence
+Weitere Informationen sind in COPYING.FPC zu finden
+
+Fehlerberichte, Vorschl„ge usw. bitte senden an:
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_nach booleschen Optionen geben Sie + zum Ein- bzw. - zum Ausschalten an
+**1a_l”sche die erzeugte Assembler-Datei nicht
+**2al_liste Quellcode-Zeilen in der Assembler-Datei
+**2an_liste "node info" in der Assembler-Datei
+*L2ap_benutze Pipes anstelle tempor„rer Assembler-Dateien
+**2ar_liste Registerbelegungsinformation in Assembler-Datei
+**2at_liste Temp. Variablenbelegungsinfo in Assembler-Datei
+**1A<x>_Ausgabe Format:
+**2Adefault_benutze den "default" Assembler
+3*2Aas_assembliere mit Hilfe von GNU AS
+3*2Anasmcoff_coff (Go32v2) Datei mit Hilfe von Nasm
+3*2Anasmelf_elf32 (Linux) Datei mit Hilfe von Nasm
+3*2Anasmwin32_Win32 Object Datei mit Hilfe von Nasm
+3*2Anasmwdosx_Win32/WDOSX Object Datei mit Hilfe von Nasm
+3*2Awasm_obj Datei mit Hilfe von Wasm (Watcom)
+3*2Anasmobj_obj Datei mit Hilfe von Nasm
+3*2Amasm_obj Datei mit Hilfe von Masm (Microsoft)
+3*2Atasm_obj Datei mit Hilfe von Tasm (Borland)
+3*2Aelf_elf32 (Linux) mit Hilfe von internen Schreiber
+3*2Acoff_coff (Go32v2) mit Hilfe von internen Schreiber
+3*2Apecoff_pecoff (Win32) mit Hilfe von internen Schreiber
+4*2Aas_assembliere mit Hilfe von GNU AS
+6*2Aas_Unix o-file mit Hilfe von GNU AS
+6*2Agas_GNU Motorola Assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola Assembler
+A*2Aas_assembliere mit Hilfe von GNU AS
+P*2Aas_assembliere mit Hilfe von GNU AS
+S*2Aas_assembliere mit Hilfe von GNU AS
+**1b_erzeuge Browser-Info
+**2bl_erzeuge Info zu lokalen Symbolen
+**1B_erzeuge alle Module (Build)
+**1C<x>_Optionen fr Code-Erzeugung:
+**2Cc<x>_Setze "default calling convention" zu <x>
+**2CD_erzeuge auch eine dynamische Bibliothek (nicht untersttzt)
+**2Ce_Kompiliere mit emulierten Fliesskomma opcodes
+**2Cf<x>_w„hle den Fliesskomma instruction set aus, siehe fpc -i wegen m”glicher Werte
+**2Cg_erzeuge PIC code
+**2Ch<n>_<n> Bytes Heap (zwischen 1023 und 67107840)
+**2Ci_I/O-Prfung
+**2Cn_lasse die Linkstufe aus
+**2Co_prfe šberlauf von Integer-Operationen
+**2Cp<x>_w„hle instruction set aus, siehe fpc -i wegen m”glicher Werte
+**2Cr_fhre Bereichsprfung durch
+**2CR_verifiziere die Gltigkiet des Aufrufs der Objektmethoden
+**2Cs<n>_setze Gr”sse des Stacks auf <n>
+**2Ct_fhre Stackprfung durch
+**2Cx_benutze Smartlinking
+**1d<x>_definiere das Symbol <x>
+**1D_erzeuge eine DEF-Datei
+**2Dd<x>_setze Beschreibung zu <x>
+**2Dv<x>_setze DLL Version zu <x>
+*O2Dw_erzeuge PM-Anwendung
+**1e<x>_setze Pfad zur ausfhrbaren Datei
+**1E_genau wie -Cn
+**1F<x>_Dateinamen und Pfade:
+**2Fa<x>[,y]_ein Program soll die Units <x> und [y] laden, bevor uses analysiert wird
+**2Fc<x>_setze die Eingabe-Codepage zu <x>
+**2FD<x>_setze das Verzeichnis fr die Compiler-Hilfsprogramme
+**2Fe<x>_leite die Fehlerausgabe um nach <x>
+**2FE<x>_setze den Pfad fr Exe/Unit-Dateien auf <x>
+**2Fi<x>_erg„nze <x> zum Include-Pfad
+**2Fl<x>_erg„nze <x> zum Bibliotheks-Pfad
+*L2FL<x>_benutze <x> als dynamischen Linker
+**2Fo<x>_erg„nze <x> zum Objektdatei-Pfad
+**2Fr<x>_lade die Fehler-Meldungs Datei <x>
+**2Fu<x>_erg„nze <x> zum Unit-Pfad
+**2FU<x>_Units werden nach <x> ausgegen, hat Vorrang vor -FE
+*g1g<x>_erzeuge Informationen zur Fehlersuche:
+*g2gc_Zeigerberprfung
+*g2gd_Verwende dbx
+*g2gg_Verwende gsym
+*g2gh_Heaptrace-Unit einbinden
+*g2gl_line info Unit einbinden, um mehr backtrace Informationen anzuzeigen
+*g2gv_erzeuge tracable mit valgrind
+*g2gw_erzeuge dwarf Informationen
+**1i_zeige alle Information ber den Compiler
+**2iD_zeige Compilerdatum
+**2iV_zeige Compilerversion
+**2iSO_zeige Compiler-Betriebssystem
+**2iSP_zeige Compilerprozessor
+**2iTO_zeige Ziel-Betriebssystem
+**2iTP_zeige Zielprozessor
+**1I<x>_erg„nze <x> zum Include-Pfad
+**1k<x>_bergebe <x> an den Linker
+**1l_zeige Logo
+**1M<x>_setze Sprachmodus zu <x>
+**2Mfpc_Free Pascal Dialekt (Voreinstellung)
+**2Mobjfpc_schalte einige Delphi 2 Erweiterungen ein
+**2Mdelphi_versuche zu Delphi kompatibel zu sein
+**2Mtp_versuche zu TP/BP 7.0 kompatibel zu sein
+**2Mgpc_versuche zu gpc kompatibel zu sein
+**2Mmacpas_versuche zu den MacIntosh Pascal-Dialekten kompatibel zu sein
+**1n_Standard-Konfigurationsdatei ignorieren
+**1N<x>node tree Optimierung
+**2Nu_unroll loops
+**1o<x>_die erzeugte, ausfhrbare Datei bekommt den Namen <x>
+**1O<x>_Optimierungen:
+3*2Og_erzeuge krzeren Code
+3*2OG_erzeuge schnelleren Code (Voreinstellung)
+**2Or_halte bestimmte Variablen in den Registern
+3*2Ou_schalte unsichere Optimierung ein (siehe Dokumentation)
+3*2O1_level 1 Optimierung (schnelle Optimierung)
+3*2O2_level 2 Optimierung (-O1 + langsamere Optimierung)
+3*2O3_level 3 Optimierung (-O2 mehrfach, maximal 5-mal)
+3*2Op<x>_Zielprozessor:
+3*3Op1_setze Zielprozessor zu 386/486
+3*3Op2_setze Zielprozessor zu Pentium/PentiumMMX (tm)
+3*3Op3_setze Zielprozessor zu PPro/PII/c6x86/K6 (tm)
+6*2Og_erzeuge krzeren Code
+6*2OG_erzeuge schnelleren Code (Voreinstellung)
+6*2Ox_optimiere maximal (noch BUGGY!!!)
+6*2O0_setze Zielprozessor zu MC68000
+6*2O2_setze Zielprozessor zu MC68020+ (Voreinstellung)
+**1pg_erzeuge Profiler-Code fr gprof
+**1R<x>_Assembler Code Format:
+**2Rdefault_benutze den default Assembler
+3*2Ratt_lese Assembler Code im AT&T Format
+3*2Rintel_lese Assembler im Intel Format
+6*2RMOT_lese Assembler im Motorola Format
+**1S<x>_Syntax-Optionen:
+**2S2_schalte einige der Delphi 2 Erweiterungen ein (wie -Mobjfpc)
+**2Sc_untersttze spezielle C Operatoren (*=,+=,/= and -=)
+**2Sa_erlaube assertion code.
+**2Sd_sei Delphi-kompatibel (wie -Mdelphi)
+**2Se<x>_Fehler Optionen. <x> ist eine der folgenden Kombinationen:
+**3*_<n> : Compiler h„lt nach <n> Fehlern (Voreinstellung ist 1)
+**3*_w : Compiler h„lt auch nach Warnungen
+**3*_n : Compiler h„lt auch nach Anmerkungen
+**3*_h : Compiler h„lt auch nach Hinweisen
+**2Sg_erlaube LABEL und GOTO
+**2Sh_benutze ANSI-Strings
+**2Si_benutze C++ artige INLINE
+**2SI<x>_setze den Stil des Interface zu <x>
+**3SIcom_COM kompatibles Interface (Voreinstellung)
+**3SIcorba_CORBA kompatibles Interface
+**2Sm_untersttze Makros wie in C (global)
+**2So_sei TP/BP 7.0 kompatibel (wie -Mtp)
+**2Sp_sei gpc-kompatibel (wie -Mgpc)
+**2Ss_Kon-und Destruktorname mssen "Init" und "Done" sein
+**2St_erlaube Schlsselwort static in Objekten
+**1s_rufe weder Assembler noch Linker auf (nur mit -a)
+**2sh_erzeuge Script um auf dem Host zu linken
+**2st_erzeuge Script um auf dem Zielsystem zu linken
+**2sr_berspringe die Phase der "register allocation" (mit -alr benutzen)
+**1T<x>_Ziel-Betriebssystem::
+3*2Temx_OS/2 via EMX (einschliesslich EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 of DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (nicht untersttzt)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tdarwin_Darwin und MacOS X on PowerPC
+P*2Tlinux_Linux auf PowerPC
+P*2Tmacos_MacOS (classic) auf PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_entferne die Definition fr das Symbol <x>
+**1U<x>_Unit-Optionen:
+**2Un_prfe den Unitnamen nicht
+**2Ur_erzeuge release unit Dateien
+**2Us_erzeuge eine Systemunit
+**1v<x>_Meldungen, <x> ist eine Kombination der folgenden Zeichen:
+**2*_e : Fehler (Standard) 0 : nichts (ausser Fehlern)
+**2*_w : Warnungen u : Unit Info
+**2*_n : Anmerkungen t : angesprochene/benutzte Dateien
+**2*_h : Hinweise c : Preprozessordirective
+**2*_i : allgemeine Info d : Debug Info
+**2*_l : Zeilennummern r : Rhide/GCC kompatibler Modus
+**2*_a : alles x : Exe-Datei Info (nur Win32)
+**2*_v : schreibe fpcdebug.txt mit p : schreibe tree.log mit Analysenbaum (parse tree)
+**2*_ ganz viel Informationen
+3*1W<x>_Win32-„hnliche Ziel-Optionen
+3*2WB_erzeuge ein relozierbares Image
+3*2WB<x>_Setze Image base auf den Hexadecimal Wert <x>
+3*2WC_spezifiziere "console type application"
+3*2WD_benutze DEFFILE um Funtionen der DLL oder EXE zu exportieren
+3*2WF_spezifiziere "full-screen type application" (nur OS/2)
+3*2WG_spezifiziere "graphic type application"
+3*2WN_erzeuge keinen "relocation code" (notwendig fr debugging)
+3*2WR_erzeuge "relocation code"
+P*2WC_spezifiziere "console type application" (nur MacOS)
+P*2WG_spezifiziere "graphic type application" (nur MacOS)
+P*2WT_spezifiziere "tool type application" (MPW tool, nur MacOS)
+**1X_Programm-Optionen:
+**2Xc_bergebe --shared an den Linker (nur Unix)
+**2Xd_den Standard Bibliotheks-Suchphad NICHT nutzen (ben”tigt fr cross compile)
+**2XD_versuche Units dynamisch zu linken (definiert FPC_LINK_DYNAMIC)
+**2Xm_erzeuge die "link map"
+**2XM<x>_setze den Namen der 'main' program Routine (default ist 'main')
+**2XP<x>_stelle den Namen der Compiler-Hilfsprogrammen den Prefix <x> voran
+**2Xr<x>_setze den Bibliotheks-Suchpfad zu <x> (ben”tigt fr cross compile)
+**2Xs_entferne alle Symbole von ausfhrbarer Datei
+**2XS_versuche Units statisch zu linken (default) (definiert FPC_LINK_STATIC)
+**2Xt_linke mit statischen Bibliotheken (-static wird an den Linker bergeben)
+**2XX_versuche Units smart zu linken (definiert FPC_LINK_SMART)
+**1*_
+**1?_zeigt diese Hilfe an
+**1h_zeigt diese Hilfe ohne Warten an
+]
+
+#
+# The End...
+#
+%%% scan_n_far_directive_ignored=02006_N_$F Direktive (FAR) ignoriert
+% The \var{FAR} directive is a 16-bit construction which is recorgnised
+% but ignored by the compiler, since it produces 32 bit code.
+%%% scan_n_stack_check_global_under_linux=02007_N_Stackprfung ist unter Linux global
+% Stack checking with the \var{-Cs} switch is ignored under \linux, since
+% \linux does this for you. Only displayed when \var{-vn} is used.
+%%% scan_e_too_much_endifs=02014_E_Zu viele $ENDIF oder $ELSE Direktiven
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+%%% scan_e_wrong_styled_switch=02031_E_Compilerschalter in (* ... *)-Kommentaren sind nicht erlaubt
+% Compiler switches should always be between \var{\{ \}} comment delimiters.
+%%% scan_w_decription_not_support=02046_W_DESCRIPTION kann nur bei OS/2- und Windows-Programmen verwendet werden
+% The \var{\{\$DESCRIPTION\}} directive is only supported for OS2 and Win32 targets.
+%%% scan_w_unsupported_asmmode_specifier=02050_W_Nicht untersttzter Assemblermodus $1 angegeben
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+%%% parser_w_proc_far_ignored=03001_W_Schlsselwort FAR wurde ignoriert
+% This is a warning. \var{FAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+%%% parser_w_proc_near_ignored=03002_W_Schlsselwort NEAR wurde ignoriert
+% This is a warning. \var{NEAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+%%% parser_w_proc_interrupt_ignored=03003_W_Ignoriere Prozedurtyp INTERRUPT
+% This is a warning. \var{INTERRUPT} is a i386 specific construct
+% and is igonred for other processors.
+%%% parser_e_no_dll_file_specified=03007_E_Keine DLL-Datei angegeben
+% No longer in use.
+%%% parser_e_illegal_open_parameter=03015_E_Ungltiger Open-Parameter
+% You are trying to use the wrong type for an open parameter.
+%%% parser_w_priv_meth_not_virtual=03017_W_Private Methoden drfen nicht VIRTUAL sein
+% You declared a method in the private part of a object (class) as
+% \var{virtual}. This is not allowed. Private methods cannot be overridden
+% anyway.
+%%% parser_object_has_no_vmt=03023_E_Das Objekt $1 hat keine VMT
+%%% parser_e_wrong_parameter_type=03025_E_Falscher Parametertyp angegeben fr Argument Nr. $1
+% There is an error in the parameter list of the function or procedure.
+% The compiler cannot determine the error more accurate than this.
+%%% parser_n_interface_name_diff_implementation_name=03032_N_Namen in Interface und Implementation sind verschieden!
+% This note warns you if the implementation and interface names of a
+% functions are different, but they have the same mangled name. This
+% is important when using overloaded functions (but should produce no error).
+%%% parser_p_procedure_start=03049_P_Prozedur/Funktion $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+%%% parser_w_overloaded_are_not_both_virtual=03064_W_Overload-Methode einer virtuellen Methode muss auch virtuell sein: $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+%%% parser_w_overloaded_are_not_both_non_virtual=03065_W_Overload-Methode einer nicht-virtuellen Methode muss auch nicht-virtuell sein: $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+%%% parser_e_overloaded_methodes_not_same_ret=03066_E_Overload-Methoden, die virtuell sind, mssen den gleichen Rckgabetyp haben: $1
+% If you declare virtual overloaded methods in a class definition, they must
+% have the same return type.
+%%% parser_e_asm_incomp_with_function_return=03087_E_Assembler-Funktion nicht mit diesem Rckgabetyp m”glich
+% You're trying to implement a \var{assembler} function, but the return type
+% of the function doesn't allow that.
+%%% parser_m_macro_defined=03101_M_Makro definiert: $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+%%% parser_m_macro_undefined=03102_M_Makro gel”scht: $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+%%% parser_m_macro_set_to=03103_M_Makro $1 auf $2 gesetzt
+% When \var{-vm} is used, the compiler tells you what values macros get.
+%%% parser_e_no_paras_allowed=03108_E_Array-Eigenschaften sind an dieser Stelle nicht erlaubt
+% You cannot use array properties at that point.
+%%% parser_e_name_keyword_expected=03122_E_Schlsselwort NAME erwartet
+% The definition of an external variable needs a \var{name} clause.
+%%% parser_e_register_calling_not_supported=03130_E_Register-Aufrufkonvention (fastcall) nicht untersttzt
+% The \var{register} calling convention, i.e., arguments are passed in
+% registers instead of on the stack is not supported. Arguments are always
+% passed on the stack.
+%%% parser_w_empty_import_name=03135_W_Leerer Importname angegeben
+% Both index and name for the import are 0 or empty
+%%% parser_e_used_proc_name_changed=03137_E_Funktionsinterner Name hat sich nach der Verwendung einer Funktion ge„ndert
+% This is an internal error; please report any occurrences of this error
+% to the \fpc team.
+%%% type_e_varid_or_typeid_expected=04010_E_Variable oder Typbezeichner erwartet
+% The argument to the \var{High} or \var{Low} function is not a variable
+% nor a type identifier.
+%%% sym_f_id_already_typed=05006_F_Bezeichnertyp ist bereits als Typ definiert
+% You are trying to redefine a type.
+%%% sym_e_type_id_not_defined=05008_E_Typbezeichner nicht definiert
+% The type identifier has not been defined yet.
+%%% sym_e_invalid_call_tvarsymmangledname=05011_E_Ungltiger Aufruf von tvarsym.mangledname()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+%%% sym_b_param_list=05039_B_Deklaration gefunden: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+%%% cg_e_too_complex_expr=06002_E_Ausdruck zu komplex - FPU Stackberlauf
+% Your expression is too long for the compiler. You should try dividing the
+% construct over multiple assignments.
+%%% cg_e_illegal_expression=06003_E_Ungltiger Ausdruck
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+%%% cg_e_invalid_integer=06004_E_Ungltiger Ausdruck, kein Integer
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+%%% cg_e_invalid_qualifier=06005_E_Ungltige Kombination
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+%%% cg_e_upper_lower_than_lower=06006_E_Oberes Bereichsende < unteres Bereichsende
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+%%% cg_e_illegal_count_var=06007_E_Unzul„ssige Z„hlvariable
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+%%% cg_e_cant_choose_overload_function=06008_E_Kann mich bestimmen, welche berladene Funktion aufgerufen werden soll
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+%%% cg_e_illegal_type_conversion=06010_E_Unzul„ssige Typumwandlung: "$1" in "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+%%% cg_d_pointer_to_longint_conv_not_portable=06011_D_Umwandlung zwischen ganzen Zahlen und Pointern ist zwischen verschiedenen Plattformen nicht portabel
+% If you typecast a pointer to a longint, this code will not compile
+% on a machine using 64bit for pointer storage.
+%%% cg_e_var_must_be_reference=06014_E_Unzul„ssiger "call by reference"-Parameter
+% You are trying to pass a constant or an expression to a procedure that
+% requires a \var{var} parameter. Only variables can be passed as a \var{var}
+% parameter.
+%%% cg_e_stackframe_with_esp=06019_E_Prozeduraufruf mit Stackframe ESP/SP
+% The compiler enocountered a procedure or function call inside a
+% procedure that uses a \var{ESP/SP} stackframe. Normally, when a call is
+% done the procedure needs a \var{EBP} stackframe.
+%%% cg_f_internal_error_in_getfloatreg=06021_F_Interner Fehler in getfloatreg(), Allozierungsfehler
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+%%% cg_f_unknown_float_type=06022_F_Unbekannter Fliesskommatyp
+% The compiler cannot determine the kind of float that occurs in an expression.
+%%% cg_f_secondvecn_base_defined_twice=06023_F_SecondVecn() Basis wurde zweimal definiert
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+%%% cg_f_extended_cg68k_not_supported=06024_F_Extended wird auf der m68k-Plattform nicht untersttzt
+% The var{extended} type is not supported on the m68k platform.
+%%% cg_f_32bit_not_supported_in_68000=06025_F_Vorzeichenlose 32-Bit-Typen werden im MC68000-Modus nicht unterstzt
+% The cardinal/dword is not supported on the m68k platform.
+%%% cg_f_internal_error_in_secondinline=06026_F_Interner Fehler in secondinline()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+%%% cg_e_stacklimit_in_local_routine=06028_E_Stacklimit in lokaler Routine berschritten
+% Your code requires a too big stack. Some operating systems pose limits
+% on the stack size. You should use less variables or try ro put large
+% variables on the heap.
+%%% cg_w_64bit_range_check_not_supported=06030_W_Bereichsberprfung fr 64-Bit-Integer wird fr die Zielplattform nicht untersttzt
+% 64 bit range check is not yet implemented for 32 bit processors.
+%%% cg_e_no_call_to_interrupt=06034_E_Direkter Aufruf von Interruptprozedur $1 ist nicht m”glich
+% You can not call an interrupt procedure directly from FPC code
+%%% cg_e_include_not_implemented=06036_E_Include und Exclude sind fr diesen Fall noch nicht implementiert
+% \var{include} and \var{exclude} are only partially
+% implemented for \var{i386} processors
+% and not at all for \var{m68k} processors.
+%%% asmr_w_override_op_not_supported=07003_W_Override-Operator wird nicht untersttzt
+% The Override operator is not supported
+%%% asmr_e_nor_not_supported=07065_E_NOR nicht untersttzt
+%%% exec_w_assembler_not_found=09005_W_Assembler $1 nicht gefunden, schalte um auf externes Assemblieren
+%%% exec_w_error_while_assembling=09007_W_Fehler w„hren des Assemblierens, Exitcode $1
+%%% exec_w_cant_call_assembler=09008_W_Kann den Assembler nicht aufrufen, Fehler $1 beim Umschalten auf externen Assembler
+%%% exec_w_error_while_linking=09013_W_Fehler w„hrend des Linkens
+%%% exec_w_cant_call_linker=09014_W_Kann Linker nicht aufrufen, schalte um auf externes Linken
+%%% exec_w_util_not_found=09016_W_Hilfsprogramm "$1" nicht gefunden, schalte um auf externes Linken
+%%% exec_w_res_not_found=09021_W_Resource Compiler nicht gefunden, schalte um auf externen Modus
+%%% unit_u_start_parse_interface=10034_U_Parse Interface-Abschnitt von "$1"
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+%%% unit_u_start_parse_implementation=10035_U_Parse Implementation-Abschnitt von "$1"
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+%%% option_defining_symbol=11037_D_Symbol $1 wird definiert
+%%% option_undefining_symbol=11038_D_Definition des Symbols $1 wird entfernt
diff --git a/compiler/msg/errore.msg b/compiler/msg/errore.msg
new file mode 100644
index 0000000000..16bbfd0e6c
--- /dev/null
+++ b/compiler/msg/errore.msg
@@ -0,0 +1,2403 @@
+#
+# $Id: errore.msg,v 1.124 2005/05/05 14:52:50 florian Exp $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# English (default) Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compiler: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Compiler OS: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Target OS: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Using executable path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_Using unit path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Using include path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Using library path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Using object path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Lines compiled, $2 sec
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_No memory left
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Writing Resource String Table file: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Writing Resource String Table file: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Warning:
+% Prefix for Warnings
+general_i_note=01015_I_Note:
+% Prefix for Notes
+general_i_hint=01016_I_Hint:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_Path "$1" does not exist
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilation aborted
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Unexpected end of file
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String exceeds line
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_illegal character "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Syntax error, "$1" expected but "$2" found
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Start reading includefile $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Comment level $1 found
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Ignored compiler switch "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Illegal compiler switch "$1"
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Misplaced global compiler switch
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Illegal char constant
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Can't open file "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Can't open include file "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Illegal record alignment specifier "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Illegal enum minimum-size specifier "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+scan_e_endif_expected=02017_E_$ENDIF expected for $1 $2 defined in $3 line $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Syntax error while parsing a conditional compiling expression
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Evaluating a conditional compiling expression
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_Macro contents are limited to 255 characters in length
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF without IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_User defined: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_User defined: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_User defined: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_User defined: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_User defined: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_User defined: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Keyword redefined as macro has no effect
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Macro buffer overflow while reading or expanding a macro
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Expanding of macros exceeds a depth of 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_compiler switches aren't supported in // styled comments
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Handling switch "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 found
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 found, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 found, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 found, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 found, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 found, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Skipping until...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Press <return> to continue
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Unsupported switch "$1"
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Illegal compiler directive "$1"
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Back in $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Unsupported application type: "$1"
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE is not supported by the target OS
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION is not supported by the target OS
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION is not supported by target OS
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION only for exes or DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Wrong format for VERSION directive "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Illegal assembler style specified "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM reader switch is not possible inside asm statement, "$1" will be effective only for next
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Wrong switch toggle, use ON/OFF or +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Resource files are not supported for this target
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Include environment "$1" not found in environment
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Illegal value for FPU register limit
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Only one resource file is supported for this target
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Macro support has been turned off
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_Illegal interface type specified. Valids are COM, CORBA or DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID is only supported for PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME is only supported for PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Constant strings can't be longer than 255 chars
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Including include files exceeds a depth of 16.
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Too many levels of PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_A POP without a preceding PUSH
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro or compile time variable "$1" does not have any value
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Wrong switch toggle, use ON/OFF/DEFAULT or +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Mode switch "$1" not allowed here
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Compile time variable or macro "$1" is not defined.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_UTF-8 code greater than 65535 found
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Malformed UTF-8 string
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_UTF-8 signature found, using UTF-8 encoding
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_Compile time expression: Wanted $1 but got $2 at $3
+% Type check of a compile time expression failed.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Syntax Error
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT procedure can't be nested
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Procedure type "$1" ignored
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Not all declarations of "$1" are declared with OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Duplicate exported function name "$1"
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Duplicate exported function index $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Invalid index for exported function
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Relocatable DLL or executable $1 debug info does not work, disabled.
+parser_w_parser_win32_debug_needs_WN=03012_W_To allow debugging for win32 code you need to disable relocation with -WN option
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Constructor name must be INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destructor name must be DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Procedure type INLINE not supported
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Constructor should be public
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destructor should be public
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Class should have one destructor only
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Local class definitions are not allowed
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Anonym class definitions are not allowed
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_The object "$1" has no VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Illegal parameter list
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Wrong number of parameters specified
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_overloaded identifier "$1" isn't a function
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_overloaded functions have the same parameter list
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_function header doesn't match the forward declaration "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_function header "$1" doesn't match forward : var name changes $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Values in enumeration types have to be ascending
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With can not be used for variables in a different segment
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_function nesting > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_range check error while evaluating constants
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_range check error while evaluating constants
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_duplicate case label
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Upper bound of case range is less than lower bound
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_typed constants of classes are not allowed
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_functions variables of overloaded functions are not allowed
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_string length must be a value from 1 to 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_use extended syntax of NEW and DISPOSE for instances of objects
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_use of NEW or DISPOSE for untyped pointers is meaningless
+parser_e_no_new_dispose_on_void_pointers=03044_E_use of NEW or DISPOSE is not possible for untyped pointers
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_class identifier expected
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_type identifier not allowed here
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_method identifier expected
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_function header doesn't match any method of this class "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procedure/function $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Illegal floating point constant
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL can be used in constructors only
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destructors can't have parameters
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Only class methods can be referred with class references
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Only class methods can be accessed in class methods
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Constant and CASE types do not match
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_The symbol can't be exported from a library
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_An inherited method is hidden by "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_There is no method in an ancestor class to be overridden: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_No member is provided to access property
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Stored property directive is not yet implemented
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Illegal symbol for property access
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Cannot access a protected field of an object here
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Cannot access a private field of an object here
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_overridden methods must have the same return type: "$2" is overriden by "$1" which has another return type
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_EXPORT declared functions can't be nested
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_methods can't be EXPORTed
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_call by var parameters have to match exactly: Got "$1" expected "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Class isn't a parent class of the current class
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF is only allowed in methods
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_methods can be only in other methods called direct with type identifier of the class
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Illegal use of ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_range check error in set constructor or duplicate set element
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Pointer to object expected
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Expression must be constructor call
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Expression must be destructor call
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Illegal order of record elements
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Expression type must be class or record type
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedures can't return a value
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_constructors and destructors must be methods
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator is not overloaded
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossible to overload assignment for equal types
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Impossible operator overload
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-raise isn't possible there
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_The extended syntax of new or dispose isn't allowed for a class
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Procedure overloading is switched off
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_It is not possible to overload this operator (overload = instead)
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Comparative operator must return a boolean value
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Only virtual methods can be abstract
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Use of unsupported feature!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_The mix of different kind of objects (class, object, interface, etc) isn't allowed
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Unknown procedure directive had to be ignored: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute can only be associated to one variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute can only be associated with a var or const
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Only one variable can be initialized
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Abstract methods shouldn't have any definition (with function body)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_This overloaded function can't be local (must be exported)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Virtual methods are used without a constructor in "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro defined: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro undefined: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 set to $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compiling $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsing interface of unit $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parsing implementation of $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compiling $1 for the second time
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No property found to override
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Only one default property is allowed
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_The default property must be an array property
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtual constructors are only supported in class object model
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No default property available
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_The class can't have a published section, use the {$M+} switch
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Forward declaration of class "$1" must be resolved here to use the class as ancestor
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Local operators not supported
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Procedure directive "$1" not allowed in interface section
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Procedure directive "$1" not allowed in implementation section
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Procedure directive "$1" not allowed in procvar declaration
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Function is already declared Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Can't use both EXPORT and EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" not yet supported inside inline procedure/function
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining disabled
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Writing Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_may be pointer dereference is missing
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Selected assembler reader not supported
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Procedure directive "$1" has conflicts with other directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Calling convention doesn't match forward
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Property can't have a default value
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_The default value of a property must be constant
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol can't be published, can be only a class
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_That kind of property can't be published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_An import name is required
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Division by zero
+% There is a division by zero encounted
+parser_e_invalid_float_operation=03139_E_Invalid floating point operation
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Upper bound of range is less than lower bound
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_string "$1" is longer than "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_string length is larger than array of char length
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Illegal expression after message directive
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Message handlers can take only one call by ref. parameter
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Duplicate message label: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self can only be an explicit parameter in methods which are message handlers
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars can be only static or global
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Direct assembler not supported for binary output format
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Don't load OBJPAS unit manually, use \{\$mode objfpc\} or \{\$mode delphi\} instead
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE can't be used in objects
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Data types which require initialization/finalization can't be used in variant records
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings can be only static or global
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit with argument can't be used here
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_The type of the storage symbol must be boolean
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_This symbol isn't allowed as storage symbol
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Only class which are compiled in $M+ mode can be published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Procedure directive expected
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_The value for a property index must be of an ordinal type
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Procedure name to short to be exported
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No DEFFILE entry can be generated for unit global vars
+parser_e_dlltool_unit_var_problem2=03161_E_Compile without -WD option
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_You need ObjFpc (-S2) or Delphi (-Sd) mode to compile this module
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Can't export with index under $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exporting of variables is not supported under $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Improper GUID syntax
+parser_w_interface_mapping_notfound=03168_W_Procedure named "$1" not found that is suitable for implementing the $2.$3
+parser_e_interface_id_expected=03169_E_interface identifier expected
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Type "$1" can't be used as array index type
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Con- and destructors aren't allowed in interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Access specifiers can't be used in INTERFACES
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_An interface can't contain fields
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Can't declare local procedure as EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Some fields coming before "$1" weren't initialized
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Some fields coming before "$1" weren't initialized
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Some fields coming after "$1" weren't initialized
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_VarArgs directive without CDecl and External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self must be a normal (call-by-value) parameter
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interface "$1" has no interface identification
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Unknown class field or method identifier "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Overriding calling convention "$1" with "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Typed constants of the type "procedure of object" can only be initialized with NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Default value can only be assigned to one parameter
+parser_e_default_value_expected_for_para=03185_E_Default parameter required for "$1"
+parser_w_unsupported_feature=03186_W_Use of unsupported feature!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C arrays are passed by reference
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_C array of const must be the last argument
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Type "$1" redefinition
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_cdecl'ared functions have no high parameter
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_cdecl'ared functions do not support open strings
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Cannot initialize variables declared as threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Message directive is only allowed in Classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure or Function expected
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Calling convention directive ignored: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE can't be used in objects
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Each argument must have it's own location
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Each argument must have an explicit location
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Unknown argument location
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32 Bit-Integer or pointer variable expected
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Goto statements aren't allowed between different procedures
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure too complex, it requires too much registers
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Illegal expression
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Invalid integer expression
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Illegal qualifier
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_High range limit < low range limit
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Exit's parameter must be the name of the procedure it is used in
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Illegal assignment to for-loop variable "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Can't declare local variable as EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procedure is already declared EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Implicit uses of Variants unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Class and static methods can't be used in INTERFACES
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow in arithmetic operation
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Protected or private expected
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE can't be used outside of parameter list
+% \var{slice} can be used only for arguments accepting an open array parameter
+parser_e_dispinterface_cant_have_parent=03216_E_A DISPINTERFACE can't have a parent class
+% A DISPINMTERFACE is a special type of interface which can't have a parent class
+parser_e_dispinterface_needs_a_guid=03217_E_A DISPINTERFACE needs a guid
+% A DISPINMTERFACE needs always an interface identification
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Type mismatch
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Incompatible types: got "$1" expected "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Type mismatch between "$1" and "$2"
+% The types are not equal
+type_e_type_id_expected=04003_E_Type identifier expected
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variable identifier expected
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Integer expression expected, but got "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Boolean expression expected, but got "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Ordinal expression expected
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_pointer type expected, but got "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_class type expected, but got "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Can't evaluate constant expression
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Set elements are not compatible
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operation not implemented for sets
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Automatic type conversion from floating type to COMP which is an integer type
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_use DIV instead to get an integer result
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_string types doesn't match, because of $V+ mode
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_succ or pred on enums with assignments not possible
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Can't read or write variables of this type
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Can't use readln or writeln on typed file
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Can't use read or write on untyped file.
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Type conflict between set elements
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) returns the upper/lower word/dword
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Integer or real expression expected
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Wrong type "$1" in array constructor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Incompatible type for arg no. $1: Got "$2", expected "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Method (variable) and Procedure (variable) are not compatible
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Illegal constant passed to internal math function
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Can't get the address of constants
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Argument can't be assigned to
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Can't assign local procedure/function to procedure variable
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Can't assign values to an address
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Can't assign values to const variable
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Array type required
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_interface type expected, but got "$1"
+type_w_mixed_signed_unsigned=04035_W_Mixing signed expressions and longwords gives a 64bit result
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mixing signed expressions and cardinals here may cause a range check error
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast has different size ($1 -> $2) in assignment
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enums with assignments can't be used as array index
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Class or Object types "$1" and "$2" are not related
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Class types "$1" and "$2" are not related
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Class or interface type expected, but got "$1"
+type_e_type_is_not_completly_defined=04042_E_Type "$1" is not completely defined
+type_w_string_too_long=04043_W_String literal has more characters than short string length
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_Comparison is always false due to range of values
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_Comparison is always true due to range of values
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Constructing a class "$1" with abstract methods
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_The left operand of the IN operator should be byte sized
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Type size mismatch, possible loss of data / range check error
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Type size mismatch, possible loss of data / range check error
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_The address of an abstract method can't be taken
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_The operator is not applicable for the operand type
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Constant Expression expected
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operation "$1" not supported for types "$2" and "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Illegal type conversion: "$1" to "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Conversion between ordinals and pointers is not portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Conversion between ordinals and pointers is not portable
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Can't determine which overloaded function to call
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Illegal counter variable
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identifier not found "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Internal Error in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Duplicate identifier "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identifier already defined in $1 at line $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Unknown identifier "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Forward declaration not solved "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Error in type definition
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward type not resolved "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Only static variables can be used in static methods or outside methods
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_record or class type expected
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instances of classes or objects with an abstract method are not allowed
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label not defined "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label used but not defined "$1"
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Illegal label declaration
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO and LABEL are not supported (use switch -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label not found
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_identifier isn't a label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_label already defined
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_illegal type declaration of set elements
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward class definition not resolved "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unit "$1" not used in $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter "$1" not used
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Local variable "$1" not used
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Value parameter "$1" is assigned but never used
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Local variable "$1" is assigned but never used
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Local $1 "$2" is not used
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Private field "$1.$2" is never used
+sym_n_private_identifier_only_set=05030_N_Private field "$1.$2" is assigned but never used
+sym_n_private_method_not_used=05031_N_Private method "$1.$2" never used
+sym_e_set_expected=05032_E_Set type expected
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Function result does not seem to be set
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type "$1" is not aligned correctly in current record for C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Unknown record field identifier "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Local variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_Variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_identifier idents no member "$1"
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Found declaration: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Data element too large
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_No matching implementation for interface method "$1" found
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" is deprecated
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbol "$1" is not portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" is not implemented
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Can't create unique type from this type
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Local variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Parameter list size exceeds 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_File types must be var parameters
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_The use of a far pointer isn't allowed there
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possible illegal call of constructor or destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Inefficient code
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_unreachable code
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstract methods can't be called directly
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 weight $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stack frame is omitted
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Object or class methods can't be inline.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar calls cannot be inline.
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No code for inline procedure stored
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Element zero of an ansi/wide- or longstring can't be accessed, use (set)length instead
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors or destructors can not be called inside a 'with' clause
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Cannot call message handler methods directly
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Jump in or outside of an exception block
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Control flow statements aren't allowed in a finally block
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Parameters size exceeds limit for certain cpu's
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Local variable size exceed limit for certain cpu's
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Local variables size exceeds supported limit
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK not allowed
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE not allowed
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Unknown compilerproc "$1". Check if you use the correct run time library.
+% The compiler expects that the runtime library contains some subrountines. If you see this error
+% and you didn't mess with the runtime library, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Starting $1 styled assembler parsing
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finished $1 styled assembler parsing
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Non-label pattern contains @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Error building record offset
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET used without identifier
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE used without identifier
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Cannot use local variable or parameters here
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_need to use OFFSET here
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_need to use $ here
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Cannot use multiple relocatable symbols
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Relocatable symbol can only be added
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Invalid constant expression
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Relocatable symbol is not allowed
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Invalid reference syntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_You can not reach $1 from that code
+% You can not read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Local symbols/labels aren't allowed as references
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Invalid base and index register usage
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Possible error in object field handling
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Wrong scale factor specified
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Multiple index register usage
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Invalid operand type
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Invalid string as opcode operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE and @DATA not supported
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label references are not allowed
+asmr_e_expr_zero_divide=07025_E_Divide by zero in asm evaluator
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Illegal expression
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_escape sequence ignored: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Invalid symbol reference
+asmr_w_fwait_emu_prob=07029_W_Fwait can cause emulation problems with emu387
+asmr_w_fadd_to_faddp=07030_W_$1 without operand translated into $1P
+asmr_w_enter_not_supported_by_linux=07031_W_ENTER instruction is not supported by Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Calling an overload function in assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Unsupported symbol type for operand
+asmr_e_constant_out_of_bounds=07034_E_Constant value out of bounds
+asmr_e_error_converting_decimal=07035_E_Error converting decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Error converting octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Error converting binary $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error converting hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 translated to $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 is associated to an overloaded function
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Cannot use SELF outside a method
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Cannot use OLDEBP outside a nested procedure
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedures can't return any value in asm code
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG not supported
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Size suffix and destination or source size do not match
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Size suffix and destination or source size do not match
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Assembler syntax error
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Invalid combination of opcode and operands
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Assembler syntax error in operand
+asmr_e_syn_constant=07050_E_Assembler syntax error in constant
+asmr_e_invalid_string_expression=07051_E_Invalid String expression
+asmr_w_const32bit_for_address=07052_W_constant with symbol $1 for address which is not on a pointer
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Unrecognized opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Invalid or missing opcode
+asmr_e_invalid_prefix_and_opcode=07055_E_Invalid combination of prefix and opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Invalid combination of override and opcode: $1
+asmr_e_too_many_operands=07057_E_Too many operands on line
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignored
+asmr_w_far_ignored=07059_W_FAR ignored
+asmr_e_dup_local_sym=07060_E_Duplicate local symbol $1
+asmr_e_unknown_local_sym=07061_E_Undefined local symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unknown label identifier $1
+asmr_e_invalid_register=07063_E_Invalid register name
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Invalid floating point register name
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo not supported
+asmr_e_invalid_float_const=07067_E_Invalid floating point constant $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Invalid floating point expression
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Wrong symbol type
+asmr_e_cannot_index_relative_var=07070_E_Cannot index a local var or parameter with a register
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings not allowed as constants
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_No type of variable specified
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_assembler code not returned to text section
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Not a directive or local symbol $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Using a defined name as a local label
+asmr_e_dollar_without_identifier=07078_E_Dollar token is used without an identifier
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bit constant created for address
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align is target specific, use .balign or .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Can't access fields directly for parameters
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Can't access fields of objects/classes directly
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No size specified and unable to determine the size of the operands
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Cannot use RESULT in this function
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" without operand translated into "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" translated into "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" translated into "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Char < not allowed here
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Char > not allowed here
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN not supported
+asmr_e_no_inc_and_dec_together=07094_E_Inc and Dec cannot be together
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Invalid reglist for movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Reglist invalid for opcode
+asmr_e_higher_cpu_mode_required=07097_E_Higher cpu mode required ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No size specified and unable to determine the size of the operands, using DWORD as default
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Syntax error while trying to parse a shifter operand
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Too many assembler files
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Selected assembler output not supported
+asmw_f_comp_not_supported=08002_F_Comp not supported
+asmw_f_direct_not_supported=08003_F_Direct not support for binary writers
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Allocating of data is only allowed in bss section
+asmw_f_no_binary_writer_selected=08005_F_No binary writer selected
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 not in table
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 invalid combination of opcode and operands
+asmw_e_16bit_not_supported=08008_E_Asm: 16 Bit references not supported
+asmw_e_invalid_effective_address=08009_E_Asm: Invalid effective address
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 value exceeds bounds $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Short jump is out of range $1
+asmw_e_undefined_label=08013_E_Asm: Undefined label $1
+asmw_e_comp_not_supported=08014_E_Asm: Comp type not supported for this target
+asmw_e_extended_not_supported=08015_E_Asm: Extended type not supported for this target
+asmw_e_duplicate_label=08016_E_Asm: Duplicate label $1
+asmw_e_redefined_label=08017_E_Asm: Redefined label $1
+asmw_e_first_defined_label=08018_E_Asm: First defined here
+asmw_e_invalid_register=08019_E_Asm: Invalid register $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Source operating system redefined
+exec_i_assembling_pipe=09001_I_Assembling (pipe) $1
+exec_d_cant_create_asmfile=09002_E_Can't create assembler file: $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Can't create object file: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Can't create archive file: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 not found, switching to external assembling
+exec_t_using_assembler=09006_T_Using assembler: $1
+exec_e_error_while_assembling=09007_E_Error while assembling exitcode $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Can't call the assembler, error $1 switching to external assembling
+exec_i_assembling=09009_I_Assembling $1
+exec_i_assembling_smart=09010_I_Assembling with smartlinking $1
+exec_w_objfile_not_found=09011_W_Object $1 not found, Linking may fail !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Library $1 not found, Linking may fail !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Error while linking
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Can't call the linker, switching to external linking
+exec_i_linking=09015_I_Linking $1
+exec_e_util_not_found=09016_E_Util $1 not found, switching to external linking
+exec_t_using_util=09017_T_Using util $1
+exec_e_exe_not_supported=09018_E_Creation of Executables not supported
+exec_e_dll_not_supported=09019_E_Creation of Dynamic/Shared Libraries not supported
+exec_i_closing_script=09020_I_Closing script $1
+exec_e_res_not_found=09021_E_resource compiler not found, switching to external mode
+exec_i_compilingresource=09022_I_Compiling resource $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_unit $1 can't be statically linked, switching to smart linking
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_unit $1 can't be smart linked, switching to static linking
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_unit $1 can't be shared linked, switching to static linking
+exec_e_unit_not_smart_or_static_linkable=09026_E_unit $1 can't be smart or static linked
+exec_e_unit_not_shared_or_static_linkable=09027_E_unit $1 can't be shared or static linked
+exec_d_resbin_params=09028_D_Calling resource compiler "$1" with "$2" as command line
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_Can't post process executable $1
+execinfo_f_cant_open_executable=09129_F_Can't open executable $1
+execinfo_x_codesize=09130_X_Size of Code: $1 bytes
+execinfo_x_initdatasize=09131_X_Size of initialized data: $1 bytes
+execinfo_x_uninitdatasize=09132_X_Size of uninitialized data: $1 bytes
+execinfo_x_stackreserve=09133_X_Stack space reserved: $1 bytes
+execinfo_x_stackcommit=09134_X_Stack space commited: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Unitsearch: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU Loading $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Name: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Flags: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU Crc: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Time: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_PPU File too short
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_PPU Invalid Header (no PPU at the begin)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_PPU Invalid Version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU is compiled for another processor
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU is compiled for an other target
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU Source: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Writing $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Can't Write PPU-File
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Error reading PPU-File
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_unexpected end of PPU-File
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Invalid PPU-File entry: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx count problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Illegal unit name: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Too much units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Circular unit reference between $1 and $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Can't compile unit $1, no sources available
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Can't find unit $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_Unit $1 was not found but $2 exists
+unit_f_unit_name_error=10024_F_Unit $1 searched but $2 found
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compiling the system unit requires the -Us switch
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_There were $1 errors compiling module, stopping
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Load from $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompiling $1, checksum changed for $2
+unit_u_recompile_source_found_alone=10029_U_Recompiling $1, source found only
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompiling unit, static lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompiling unit, shared lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompiling unit, obj and asm are older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompiling unit, obj is older than asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Parsing interface of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Parsing implementation of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Second load for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU Check file $1 time $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Can't recompile unit $1, but found modifed include files
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_File $1 is newer than Release PPU file $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Using a unit which was not compiled with correct FPU mode
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Loading interface units from $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Loading implementation units from $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Interface CRC changed for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Implementation CRC changed for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Finished compiling unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Add dependency of $1 to $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_No reload, is caller: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_No reload, already in second compile: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Flag for reload: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Forced reloading
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Previous state of $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Already compiling $1, setting second compile
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Loading unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Finished loading unit $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registering new unit $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-resolving unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Skipping re-resolving unit $1, still loading used units
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Only one source file supported
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF file can be created only for OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_nested response files are not supported
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_No source file name in command line
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No option inside $1 config file
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Illegal parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? writes help pages
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Too many config files nested
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Unable to open file $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Reading further options from $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Target is already set to: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Shared libs not supported on DOS platform, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_too many IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_too many ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_open conditional at the end of the file
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Debug information generation is not supported by this executable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Try recompiling with -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_You are using the obsolete switch $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_You are using the obsolete switch $1, please use $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Switching assembler to default source writing assembler
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Assembler output selected "$1" is not compatible with "$2"
+option_asm_forced=11022_W_"$1" assembler use forced
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Reading options from file $1
+% Options are also read from this file
+option_using_env=11027_T_Reading options from environment $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Handling option "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** press enter ***
+option_start_reading_configfile=11030_H_Start of reading config file $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_End of reading config file $1
+% End of config file parsing.
+option_interpreting_option=11032_D_interpreting option "$1"
+option_interpreting_firstpass_option=11036_D_interpreting firstpass option "$1"
+option_interpreting_file_option=11033_D_interpreting file option "$1"
+option_read_config_file=11034_D_Reading config file "$1"
+option_found_file=11035_D_found source file name "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Unknown code page
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2005 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVERSION
+
+Compiler Date : $FPCDATE
+Compiler CPU Target: $FPCCPU
+
+Supported targets:
+ $OSTARGETS
+
+Supported CPU instruction sets:
+ $INSTRUCTIONSETS
+
+Supported FPU instruction sets:
+ $FPUINSTRUCTIONSETS
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs,suggestions etc to:
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_put + after a boolean switch option to enable it, - to disable it
+**1a_the compiler doesn't delete the generated assembler file
+**2al_list sourcecode lines in assembler file
+**2an_list node info in assembler file
+*L2ap_use pipes instead of creating temporary assembler files
+**2ar_list register allocation/release info in assembler file
+**2at_list temp allocation/release info in assembler file
+**1A<x>_output format:
+**2Adefault_use default assembler
+3*2Aas_assemble using GNU AS
+3*2Anasmcoff_coff (Go32v2) file using Nasm
+3*2Anasmelf_elf32 (Linux) file using Nasm
+3*2Anasmwin32_Win32 object file using Nasm
+3*2Anasmwdosx_Win32/WDOSX object file using Nasm
+3*2Awasm_obj file using Wasm (Watcom)
+3*2Anasmobj_obj file using Nasm
+3*2Amasm_obj file using Masm (Microsoft)
+3*2Atasm_obj file using Tasm (Borland)
+3*2Aelf_elf32 (Linux) using internal writer
+3*2Acoff_coff (Go32v2) using internal writer
+3*2Apecoff_pecoff (Win32) using internal writer
+4*2Aas_assemble using GNU AS
+6*2Aas_Unix o-file using GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola assembler
+A*2Aas_assemble using GNU AS
+P*2Aas_assemble using GNU AS
+S*2Aas_assemble using GNU AS
+**1b_generate browser info
+**2bl_generate local symbol info
+**1B_build all modules
+**1C<x>_code generation options:
+**2Cc<x>_set default calling convention to <x>
+**2CD_create also dynamic library (not supported)
+**2Ce_Compilation with emulated floating point opcodes
+**2Cf<x>_Select fpu instruction set to use, see fpc -i for possible values
+**2Cg_Generate PIC code
+**2Ch<n>_<n> bytes heap (between 1023 and 67107840)
+**2Ci_IO-checking
+**2Cn_omit linking stage
+**2Co_check overflow of integer operations
+**2Cp<x>_select instruction set, see fpc -i for possible values
+**2Cr_range checking
+**2CR_verify object method call validity
+**2Cs<n>_set stack size to <n>
+**2Ct_stack checking
+**2CX_create also smartlinked library
+**1d<x>_defines the symbol <x>
+**1D_generate a DEF file
+**2Dd<x>_set description to <x>
+**2Dv<x>_set DLL version to <x>
+*O2Dw_PM application
+**1e<x>_set path to executable
+**1E_same as -Cn
+**1F<x>_set file names and paths:
+**2Fa<x>[,y]_for a program load first units <x> and [y] before uses is parsed
+**2Fc<x>_sets input codepage to <x>
+**2FD<x>_sets the directory where to search for compiler utilities
+**2Fe<x>_redirect error output to <x>
+**2FE<x>_set exe/unit output path to <x>
+**2Fi<x>_adds <x> to include path
+**2Fl<x>_adds <x> to library path
+**2FL<x>_uses <x> as dynamic linker
+**2Fo<x>_adds <x> to object path
+**2Fr<x>_load error message file <x>
+**2Fu<x>_adds <x> to unit path
+**2FU<x>_set unit output path to <x>, overrides -FE
+*g1g_generate debugger information:
+*g2gc_generate checks for pointers
+*g2gd_use dbx
+*g2gg_use gsym
+*g2gh_use heap trace unit (for memory leak debugging)
+*g2gl_use line info unit to show more info for backtraces
+*g2gv_generates programs tracable with valgrind
+*g2gw_generate dwarf debugging info
+**1i_information
+**2iD_return compiler date
+**2iV_return compiler version
+**2iSO_return compiler OS
+**2iSP_return compiler processor
+**2iTO_return target OS
+**2iTP_return target processor
+**1I<x>_adds <x> to include path
+**1k<x>_Pass <x> to the linker
+**1l_write logo
+**1M<x>_set language mode to <x>
+**2Mfpc_free pascal dialect (default)
+**2Mobjfpc_switch some Delphi 2 extensions on
+**2Mdelphi_tries to be Delphi compatible
+**2Mtp_tries to be TP/BP 7.0 compatible
+**2Mgpc_tries to be gpc compatible
+**2Mmacpas_tries to be compatible to the macintosh pascal dialects
+**1n_don't read the default config file
+**1N<x>node tree optimizations
+**2Nu_unroll loops
+**1o<x>_change the name of the executable produced to <x>
+**1O<x>_optimizations:
+3*2Og_generate smaller code
+3*2OG_generate faster code (default)
+**2Or_keep certain variables in registers
+3*2Ou_enable uncertain optimizations (see docs)
+3*2O1_level 1 optimizations (quick optimizations)
+3*2O2_level 2 optimizations (-O1 + slower optimizations)
+3*2O3_level 3 optimizations (-O2 repeatedly, max 5 times)
+3*2Op<x>_target processor:
+3*3Op1_set target processor to 386/486
+3*3Op2_set target processor to Pentium/PentiumMMX (tm)
+3*3Op3_set target processor to PPro/PII/c6x86/K6 (tm)
+6*2Og_generate smaller code
+6*2OG_generate faster code (default)
+6*2Ox_optimize maximum (still BUGGY!!!)
+6*2O0_set target processor to a MC68000
+6*2O2_set target processor to a MC68020+ (default)
+**1pg_generate profile code for gprof (defines FPC_PROFILE)
+**1R<x>_assembler reading style:
+**2Rdefault_use default assembler
+3*2Ratt_read AT&T style assembler
+3*2Rintel_read Intel style assembler
+6*2RMOT_read motorola style assembler
+**1S<x>_syntax options:
+**2S2_same as -Mobjfpc
+**2Sc_supports operators like C (*=,+=,/= and -=)
+**2Sa_include assertion code.
+**2Sd_same as -Mdelphi
+**2Se<x>_error options. <x> is a combination of the following:
+**3*_<n> : compiler stops after the <n> errors (default is 1)
+**3*_w : compiler stops also after warnings
+**3*_n : compiler stops also after notes
+**3*_h : compiler stops also after hints
+**2Sg_allow LABEL and GOTO
+**2Sh_Use ansistrings
+**2Si_support C++ styled INLINE
+**2Sk_load fpcylix unit
+**2SI<x>_set interface style to <x>
+**3SIcom_COM compatible interface (default)
+**3SIcorba_CORBA compatible interface
+**2Sm_support macros like C (global)
+**2So_same as -Mtp
+**2Sp_same as -Mgpc
+**2Ss_constructor name must be init (destructor must be done)
+**2St_allow static keyword in objects
+**1s_don't call assembler and linker
+**2sh_Generate script to link on host
+**2st_Generate script to link on target
+**2sr_Skip register allocation phase (use with -alr)
+**1T<x>_Target operating system:
+3*2Temx_OS/2 via EMX (including EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 of DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (not supported)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tdarwin_Darwin and MacOS X on PowerPC
+P*2Tlinux_Linux on PowerPC
+P*2Tmacos_MacOS (classic) on PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_undefines the symbol <x>
+**1U_unit options:
+**2Un_don't check the unit name
+**2Ur_generate release unit files
+**2Us_compile a system unit
+**1v<x>_Be verbose. <x> is a combination of the following letters:
+**2*_e : Show errors (default) 0 : Show nothing (except errors)
+**2*_w : Show warnings u : Show unit info
+**2*_n : Show notes t : Show tried/used files
+**2*_h : Show hints c : Show conditionals
+**2*_i : Show general info d : Show debug info
+**2*_l : Show linenumbers r : Rhide/GCC compatibility mode
+**2*_a : Show everything x : Executable info (Win32 only)
+**2*_b : Write file names messages with full path
+**2*_v : write fpcdebug.txt with p : Write tree.log with parse tree
+**2*_ lots of debugging info
+3*1W<x>_Win32-like target options
+3*2WB_Create a relocatable image
+3*2WB<x>_Set Image base to Hexadecimal <x> value
+3*2WC_Specify console type application
+3*2WD_Use DEFFILE to export functions of DLL or EXE
+3*2WF_Specify full-screen type application (OS/2 only)
+3*2WG_Specify graphic type application
+3*2WN_Do not generate relocation code (necessary for debugging)
+3*2WR_Generate relocation code
+P*2WC_Specify console type application (MacOS only)
+P*2WG_Specify graphic type application (MacOS only)
+P*2WT_Specify tool type application (MPW tool, MacOS only)
+**1X_executable options:
+**2Xc_pass --shared to the linker (Unix only)
+**2Xd_don't use standard library search path (needed for cross compile)
+**2XD_try to link units dynamic (defines FPC_LINK_DYNAMIC)
+**2Xm_generate link map
+**2XM<x>_set the name of the 'main' program routine (default is 'main')
+**2XP<x>_prepend the binutils names with the prefix <x>
+**2Xr<x>_set library search path to <x> (needed for cross compile)
+**2Xs_strip all symbols from executable
+**2XS_try to link units static (default) (defines FPC_LINK_STATIC)
+**2Xt_link with static libraries (-static is passed to linker)
+**2XX_try to link units smart (defines FPC_LINK_SMART)
+**1*_
+**1?_shows this help
+**1h_shows this help without waiting
+]
+
+#
+# The End...
diff --git a/compiler/msg/errores.msg b/compiler/msg/errores.msg
new file mode 100644
index 0000000000..429c3ddfa0
--- /dev/null
+++ b/compiler/msg/errores.msg
@@ -0,0 +1,2374 @@
+# **************** don't edit! *******************
+# edit erroresu.msg and convert it to iso-8859-15
+# by e.g.
+# recode utf-8..iso-8859-15
+# and save it as errores.msg
+# ************************************************
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Spanish Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilador: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SO del host: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SO de destino: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Usando la ruta para ejecutables: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_Usando la ruta para unidades: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Usando la ruta para inclusiones: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Usando la ruta para bibliotecas: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Usando la ruta para objetos: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Líneas compiladas, $2 seg
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_No queda suficiente memoria disponible
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Escribiendo archivo de recursos de tabla de cadenas: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Escribiendo archivo de recursos de tabla de cadenas: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Aviso:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Consejo:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_La ruta "$1" no existe
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_Compilación abortada
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Final de fichero inesperado
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_La cadena excede la línea
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Caracter inválido
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Error de sintaxis, se esperaba "$1" pero se encontró "$2"
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Empezando a leer el fichero incluido $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Nivel de comentario anidado $1 encontrado
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Directiva de compilación $1 ignorado
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Directiva de compilación $i inválida
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Esta opción de compilacion tiene un efecto global
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante de caracter inválido
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_No se puede abrir el fichero "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_No se puede abrir el fichero de inclusion "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Los campos de los registros pueden ser alineados solo a 1, 2, 4 o 16 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1, 2, 4, 8, 16 and 32 are valid in this case.
+scan_w_only_pack_enum=02016_W_Los tipos enumerados solo pueden ser almacenados en 1, 2 o 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_$1 esperado para $2 definido en la línea $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Error de sintaxis mientras se procesaba una expresión de compilación condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Evaluando una expresión de compilación condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_El contenido de las macros esta limitado a 255 caracteres de longitud
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sin IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Error de usuario: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Error de usuario: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Aviso de usuario: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Nota de usuario: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Consejo de usuario: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Informacion de usuario: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Palabra clave redefinida como macro no tiene efecto
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Desbordamiento del buffer de macro durante la lextura o expansión
+% Your macro or it's result was too long for the compiler.
+can_w_macro_too_deep=02030_W_La expansión de macros excede una profundidad de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Las directivas de compilacióon no estan soportadas en comentarios estilo //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Manejando la directiva "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 encontrado
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Omitiendo hasta...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Presione <retorno> para continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Conmutador "$1" no soportado
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Directiva de compilación "$1" inválida
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Vuelve en $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Tipo de aplicación no soportada: "$1"
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE no es soportado por el SO de destino
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION no es soportado por el SO de destino
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION no es soportado por el SO de destino
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION sólo para EXEs o DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Formato erroneo para la directiva VERSION: "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Estilo de ensamblador inváalido especificado: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_No es posible cambiar el lector dentro de una sentencia asm. "$1" solo sera efectivo en los siguientes
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Modificador de conmutador erróneo, use ON/OFF o +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Los ficheros de recursos no son soportados por la plataforma de destino
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Variable de entorno incluida "$1" no encontrada.
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valor inválido para el registro de la FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_La plataforma de destino solo soporta un archivo de recursos
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_El soporte para macros ha sido deshabilitado
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_El tipo de interfaz especificado es inválido. Debe ser COM, CORBA o DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID solo esta soportado para PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME solo esta soportado para PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Las constantes de cadena no pueden ser de mas de 255 caracteres de longitud
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_La inclusion de archivos no puede exceder 16 niveles
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Demasiados niveles de PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_A POP sin un PUSH previo
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro o variable de compilación "$1" no tiene ningún valor
+% Thus the conditional compiling expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Valor invalido para el conmutado, use ON/OFF/DEFAULT o +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_No esta permitido cambiar de modo a "$1" aqui
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Variable en tiempo de compilación "$1" no ha sido definida.
+% Thus the conditional compile time expression cannot be evaluated.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Analizador - Error de sintaxis
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Los procedimientos INTERRUPT no pueden ser anidados
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo de procedimiento "$1" ignorado
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_No todas las declaraciones de "$1" llevan OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Nombre de funcion exportada "$1" duplicado
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Indice de funcion exportada "$1" duplicado
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Indice de funcion exportada inválido
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_La informacion de depurado $1 para ejecutables o DLLs reubicables no funciona. Desactivado.
+parser_w_parser_win32_debug_needs_WN=03012_W_Para permitir el depurado en win32 las reubicaciones deben ser desactivadas con la opcion -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_El nombre del constructor debe ser INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_El nombre del destructor debe ser DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Procedimientos tipo INLINE no soportados
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_El constructor debería ser público
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_El destructor debería ser público
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Una clase debería tener solo un destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Las definiciones de clases locales no están permitidas
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Las definiciones de clases anónimas no están permitidas
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_El objeto "$1" no tiene VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista de parámetros inválida
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Numero de parámetros incorrecto
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_el identificador sobrecargado "$1" no es una función
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_funciones sobrecargadas tienen los mismos par metros
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_la cabecera de la función no concuerda con la declaración posterior "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_la cabecera de la funcion "$1" no concuerda con la posterior declaración : el nombre de la variable cambia $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_el orden de los valores en una enumeracion debe ser ascendente
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With no puede ser usado con variables en segmentos diferentes
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Anidado de funciones > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_error en la comprobación de rangos mientras se evaluaban constantes
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_error en la comprobacion de rangos mientras se evaluaban constantes
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_etiqueta de caso duplicada
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_El líimite superior del caso es menor que el inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_no se permiten constantes con tipo de clases
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_no se permite asignar a variables de funcion funciones sobrecargadas
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_la longitud de una cadena tiene que ser un valor entre 1 y 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_use la sintaxis estendida de DISPOSE y NEW para instancias de objetos
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_el uso de NEW o DISPOSE para punteros sin tipo no tiene sentido
+parser_e_no_new_dispose_on_void_pointers=03044_E_el uso de NEW o DISPOSE no es posible con punteros sin tipo
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_identificador de clase esperado
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_identificador de tipo no permitido aquí
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_identificador de método esperado
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_la cabecera de la funcion no concuerda con ningún método de esta clase "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_proceduimiento/función $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante de punto flotante inválida
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL solo puede ser usado en constructores
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Los destructores no pueden tener parámetros
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Solo los métodos de clases pueden ser referidos con referencias de clase
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Los métodos de clase solo pueden ser acceder a otros métodos de clase
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Los tipos de la constante y del CASE no concuerdan
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_El símbolo no puede ser exportado de una librería
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Un método heredado ha sido ocultado por "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_No hay un método en una clase antepasada para ser substituido: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_No se suministro un miembro para acceder a propiedad
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_La directiva de propiedad Stored no esta implementada aún
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_símbolo inváalido para el acceso a la propiedad
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_No se puede acceder a un campo protegido de un objeto aquí
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_No se puede acceder a un campo privado de un objeto aquí
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_los métodos reemplazados deben tener el mismo tipo de dato devuelto: "$2" es reemplazado por "$1" que devuelve otro tipo
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Las funciones declarados como EXPORT no pueden estar anidados
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_los métodos no pueden ser EXPORTados
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_en llamadas con parámetros VAR los tipos deben coincidir exactamente. Se recibio "$1" cuando se esperaba "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_La clase no es un ancestor de la clase actual
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF solo está permitido en métodos
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_los métodos solo pueden estar en otros métodos llamados directamente con el tipo identificador de la clase
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso inválido de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Error en la comprobación de rangos en el constructor del set, o elemento duplicado en el set
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Se esperaba un puntero a objeto
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_La expresión tiene que ser una llamada al constructor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_La expresión tiene que ser una llamada al destructor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Orden de los campos del registro incorrecto
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_El tipo de la expresión tiene que ser class o record
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Los procedimientos no pueden devolver ningún valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_constructores y destructores deben ser métodos
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_El operador no esta sobrecargado
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Imposible sobrecargar operador de asignacion para tipos iguales
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Sobrecarga de operador imposible
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-lanzamiento de la excepcion no es posible aquí
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_La sintaxis extendida de new o dispose no está permitida para una clase
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_La sobrecarga de funciones no esta activada
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_No es posible sobrecargar este operador (sobrecarge en cambio "=" )
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operador comparativo tiene que devolver un valor booleano
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Solo los métodos virtuales pueden ser abstractos
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Uso de característica no soportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_No se permite la mezcla de objetos de diferentes tipos (class, object, interface, etc)
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Directiva de procedimiento desconocida fue ignorada: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute solo puede estar asociado a una variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute solo puede ser asociado con var o const
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Solo una variable puede ser inicializada
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Métodos abstractos no deberían tener ninguna definición (con el cuerpo de la función)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Esta función sobrecargada no puede ser local (debe ser exportada)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Métodos virtuales están siendo usados sin un constructor en "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definido: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro indefinido: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 asignado a $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Interpretando interfaz de la unidad $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Interpretando implementacion de la unidad $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilando $1 por segunda vez
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No se encontro la propiedad a reemplazar
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Sólo se permite una única propiedad por defecto
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propiedad por defecto tiene que ser un array
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Solo las clases soportan constructores virtuales
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No hay propiedad por defecto disponible
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_La clase no puede tener una sección published, use el conmutador {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Declaración posterior de la clase "$1" tiene que ser resuelta aquí para usar la clase como antepasado
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Operadores locales no soportados
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Directiva de procedimiento "$1" no permitida en la sección de interfaz
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Directiva de procedimiento "$1" no permitida en la sección de implementacion
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Directiva de procedimiento "$1" no permitida en la declaración de tipo
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La función esta actualmente declarada como Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_No se pueden usar ambos EXPORT y EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" aún no soportado en procedimientos/funciones inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining deshabilitado
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Escribiendo Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_podría ser que falte la de-referencia del puntero
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Lector del ensamblador seleccionado no soportado
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Directiva de procedimiento "$1" causa conflicto con otras directivas
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convencion de llamada actual no concuerda con la definida anteriormente
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_La propiedad no puede tener un valor por defecto
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_El valor por defecto de una propiedad tiene que ser constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_El símbolo no puede ser published, solo puede ser una clase
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Este tipo de propiedad no puede ser published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Se requiere un nombre de importación
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Division por cero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Operacion de punto flotante no válida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Límite superior del rango es menor que el límite inferior
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_La cadena "$1" es mas larga que $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_La longitud de la cadena es mayor que el tamaño array de carácteres
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expresión inválida tras la directiva de mensaje
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Los méetodos de manejo de mensajes deben tener un único parámetro por referencia
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Etiqueta de mensaje duplicada: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self solo puede ser un parámetro explícito en manejadores de mensajes
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars sólo pueden ser globales o estáticos
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Ensamblador directo no soportado para formato binario de salida
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_No carges manuamente la unidad OBJPAS, usa \{\$mode objfpc\} o \{\$mode delphi\}
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE no puede ser usado en objetos
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Tipos de datos que requieran inicializacion/finalizacion no pueden ser usados en registros variables
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings solo pueden ser globales o estáaticos
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit con parámetro no puede ser usado aquí
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_El tipo del símbolo en stored debe ser de tipo booleano
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Este símbolo no puede ser usado en storage para una propiedad
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Solo clases compiladas en $M+ pueden ser publicadas
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Directiva de procedimiento esperada
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_El valor para el índice de una propiedad debe ser de tipo ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nombre del procedimiento demasiado corto para ser exportado
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No se puede generar una entrada DEFFILE para las variables globales de la unidad
+parser_e_dlltool_unit_var_problem2=03161_E_Compile sin la opcion -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Se requiere el modo ObjFpc (-S2) o Delphi (-Sd) para compilar este módulo
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_No se pueden exportar funciones o procedimientos por indice en $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exportar variables no esta soportado en $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintaxis de GUID incorrecta
+parser_w_interface_mapping_notfound=03168_W_No se encontro el procedimiento de nombre "$1" apropiado para implementar $2.$3
+parser_e_interface_id_expected=03169_E_identificador de interfaz esperado
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_El tipo "$1" no puede ser usado como indice en arrays
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_No se permiten constructores/destructores en interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_No se permiten especificadores de acceso en interfaces
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Una interfaz no puede contener campos
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_No se puede declarar un procedimiento local como externo
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Algunos campos anteriores a "$1" no fueron inicializados
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Algunos campos anteriores a "$1" no fueron inicializados
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Algunos campos tras "$1" no fueron inicializados
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Directiva VarArgs sólo es válida con CDecl o External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self debe ser un parámetro normal por valor
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_La interfaz "$1" no tiene identificacion
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Campo de la clase o método desconocido "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Varias convenciones de llamada especificadas, "$1" ignorado al especificar "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_constantes con tipo de tipo Procedure/Function (...) of Object solo pueden ser inicializados a NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Sólo se puede asignar valor por defecto a un parámetro
+parser_e_default_value_expected_for_para=03185_E_Parámetro por defecto requerido para "$1"
+parser_w_unsupported_feature=03186_W_¡Uso de una caracteristica no soportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Arrays tipo C son pasados por referencia
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Array tipo C de const debe ser el ultimo parámetro
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Redefinición del tipo "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Procedimientos y funciones declarados como cdecl no reciben de parámetro el límite superior
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_open strings no son soportados en funciones cdecl
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_No se pueden inicializar variables declaradas como threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_La directiva Message sólo es valida en clases
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Se esperaba un procedimiento o funcion
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Directiva de convención de llama "$1" ignorada
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE no puede ser utilizado en objetos
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Cada parámetro debe tener su propia posición
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Cada parámetro debe tener su propia posición
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Localizacón en el segmento desconocida
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Se esperaba una variable entera de 32 bits o un puntero
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_No se puede usar Goto para saltar a otro procedimiento
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedimiento demasiado complejo. Se requieren demasiados registros
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Expresión inválida
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_La expresión no evalua un número entero
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_calificador inválido
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_El limite superior especificado es menor que el inferior
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_El parámetro de Exit debe ser el nombre del mismo procedimiento en el que está
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Asignación inválida a la variable de bucle "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_No se puede declarar una variable local como externa
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_El procedimiento ya ha sido declarado como externo con anterioridad
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Uso implícito de la unidad Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Clases y métodos estáticos no pueden ser utilizados en interfaces
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Desbordamiento en la operación aritmética
+% An operation on two integers values produced an overflow
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Los tipos no concuerdan
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipos incompatibles: se encontró "$1" esperado "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Los tipos $1 y $2 no concuerdan
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificador de tipo esperado
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificador de variable esperado
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_expression entera esperada, pero se encontró "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Expresion booleana esperada, pero se encontró "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Espresión ordinal esperada
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Se esperaba un tipo puntero, pero se encontró "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Se esperaba un tipo de clase, pero se encontró "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_No se puede evaluar la espresión constante
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Elementos de sets incompatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operación no implementada para sets
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversion automática de tipo de punto flotante a COMP el cual es un tipo entero
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_usa DIV para tener un resultado entero
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Tipos de cadena no concuerdan por la presencia de la opción $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_No se permite el uso de Succ o Pred en enumeraciones que tienen valores asignados explícitamente
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_No se puede leer o escribir variables de este tipo
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_No se puede utilizar readln o writeln en ficheros con tipo
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_No se pueden usar read o write en ficheros sin tipo
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_El set contiene un elemento que no es de tipo compatible
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(longint/dword) devuelve la parte superior/inferior de tipo word
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Espresión entera o real esperada
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo "$1" erróneo en el constructor del array
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipo incompatible para el parámetro número $1: Se recibió "$2", cuando se esperaba "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Variables de tipo método y procedimiento no son compatibles entre si
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante pasada a la función matematica interna no válida
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_No se puede obtener una dirección de una constante
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_No se puede asignar un valor al parámetro
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_No se puede asignar un prodecimiento o funcion local a una variable
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_No se puede asignar un valor a una dirección
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_No se pueden asignar valores a variables constantes
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Se requiere un array para usar [ ]
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Se esperaba "interface" pero se encontró "$1"
+type_w_mixed_signed_unsigned=04035_W_Operaciones mezclando enteros de 32 bits con signo son convertidas a 64 bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mezclar operando con signo y sin signo aqui puede causar errores de comprobación de rango
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_La conversión de tipos ($1 -> $2) en la asignación tiene diferentes tamaños
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_No se pueden usar enums con asignaciones como indices de arrays
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Las clases u objetos "$1" y "$2" no están relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Los tipos de clases "$1" y "$2" no están relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Se esperaba una clase o interfaz, pero se encotró "$1"
+type_e_type_is_not_completly_defined=04042_E_El tipo "$1" no esta definido completamente aún
+type_w_string_too_long=04043_W_La cadena contiene mas caracteres que los admitidos por una cadena corta
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_La comparación es siempre falsa debido a los rangos de los valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_La comparación es siempre verdadera debido a los rangos de los valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Constuyendo un objeto de clase "$1" que contiene métodos abstractos
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_El operando a la izquierda de IN debe ser de tamaño un byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Diferencia del tamaño de los tipos puede causar pérdida de datos o errores de comprobación de rango
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Diferencia del tamaño de los tipos puede causar pérdida de datos o errores de comprobación de rango
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_No se puede obtener la dirección de un método abstracto
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_El operador no es aplicable con los operandos especificados
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Se esperaba una expresió constante
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_La operacion "$1" no está soportada para los tipos "$2" y "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_No es posible realizar una conversión de "$1" a "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_La conversion entre punteros y ordinales no es portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_La conversion entre punteros y ordinales no es portable
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_No se pudo determinar que funcion sobrecargada llamar
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Variable de contador inválida
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificador no encontrado "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Error interno en SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificador duplicado "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_El identificador ya está definido en $1 en la línea $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificador desconocido "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Declaración posterior no solucionada "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Error en definición de tipo
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Tipo posterior no resuelto "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Solo las variables estáticas pueden ser usadas en métodos estáticos o fuera de métodos
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_tipo record o class esperado
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_No se permiten instancias de clases u objetos con un métodos abstractos
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Etiqueta no definida "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Etiqueta "$1" usada pero no definida
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Declaración inválida de la etiqueta
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO y LABEL no son soportados (debe ser habilitado con -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Etiqueta no encontrada
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_el identificador no es una etiqueta
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Etiqueta ya definida
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Definicion de tipo set inválida
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Definición posterior de la clase "$1" no resuelta
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unidad "$1" no utilizada en $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parámetro "$1" no usado
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Variable local no usada "$1"
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Valor asignado a "$1" pero no utilizado
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Valor asignado a la variable local "$1" no utilizado
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Símbolo local $1 "$2" no utilizado
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Campo privado $1.$2 no utilizado
+sym_n_private_identifier_only_set=05030_N_Valor asignado al campo privado $1.$2 pero nunca es utilizado
+sym_n_private_method_not_used=05031_N_Método privado $1.$2 no utilizado
+sym_e_set_expected=05032_E_Tipo set esperado
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_El resultado de la función puede no haber sido asignado
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_El tipo "$1" no esta correctamente alineado para C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Identificador de campo de registro desconocido: "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_La variable local "$1" no parace haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_La variable "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_El identificador "$1" no identifica ningún miembro
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Declaracion encontrada: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Segmento de datos demasiado grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_No se encontro una implementación para el método "$1" de la interfaz
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Símbolo "$1" desaconsejado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_El símbolo "$1" no es portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_El símbolo "$1" no está implementado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_No se puede crear un tipo único a partir de este tipo
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_La variable local "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_La variable "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_El tamaño de la lista de par metros excede 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Los tipos File deben ser pasados por referencia
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_El uso de punteros "far" no esta permitido aqií
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_las funciones declaradas como EXPORT no pueden ser llamadas
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Posible llamada inválida de un constructor o destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_código ineficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_El código no será ejecutado nunca
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Los métodos abstractos no pueden ser llamados directamente
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registro $1 peso $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Se omite generar stack frame
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Métodos de objetos o clases no pueden ser inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Variables de procedimiento o función no pueden ser inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No hay código almacenado para procedimientos inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_No se puede acceder al elemento 0 de cadenas largas, use SetLength/Length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_No se pueden llamar a constructores o destructores en with
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_No se pueden llamar a métodos manejadores de mensajes directamente
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Salto fuera de un bloque de excepción
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_No se admiten instrucciones de control de flujo en un bloque finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_El tamaño del parámetro excede el límite de algunas CPU
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_El tamaño de las variables locales excede el límite de algunas CPU
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_El tamaño de las variables locales excede el límite de la CPU de destino
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK no permitido aquí
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE no permitido aquí
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Iniciando interpretado de ensamblador de estilo $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finalizado interpretado de ensamblador de estilo $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Una patrón que no es una etiqueta contiene @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Error construyendo desplazamiento de registro (record)
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET usado sin identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE usado sin identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_No es posible usar una variable local o parámetro aquí
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Es necesario el uso de OFFSET aquí
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Es necesario el uso de $ auqí
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_No es posible utilizar varios símbolos reubicables
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Símbolos reubicables solo pueden ser añadidos
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Espresió constante inválida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Símbolo reubicable no permitido
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Sintaxis de referencia inválida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_No se puede llegar a $1 desde este código
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_No está permitido el uso símbolos locales o etiquetas como referencias
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso inválido de registros indice y base
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Posible error en el manejo de campos de objetos
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Factor de escala erróneo
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso de multiples registros índice
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo del operando no válido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Cadena no vólida como operando de esta instrucción: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE y @DATA no son soportados
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Referencias a etiqueta nula no permitida
+asmr_e_expr_zero_divide=07025_E_Division entre cero en el evaluador de ensamblador
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expresión inválida
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sequencia de escape ignorada: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Referencia a símbolo inválida
+asmr_w_fwait_emu_prob=07029_W_Fwait puede causar problemas de emulación con emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sin operando interpretado como $1P
+asmr_w_enter_not_supported_by_linux=07031_W_La instruccion ENTER no está soportada por el kernel de Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Llamando a una funcion sobrecargada desde ensamblador
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Tipo de símbolo no soportado para el operando
+asmr_e_constant_out_of_bounds=07034_E_Valor de la constante fuera de rango
+asmr_e_error_converting_decimal=07035_E_Error convirtiendo decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Error convirtiendo octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Error convirtiendo binario $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error convirtiendo hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traducido a $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 esta asociado a una función sobrecargada
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_No se puede usar SELF fuera de un método
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_No se puede usar OLDEBP fuera de un procedimiento anidado
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_No es posible devolver un valor en procedimientos desde código asm
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG no soportado
+asmr_e_size_suffix_and_dest_dont_match=07045_E_No concuerdan el tamaño del prefijo y el del origen o destino
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_No concuerdan el tamaño del prefijo y el del origen o destino
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Error de sintaxis de ensamblador
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinación inválida de operacion y operandos
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Error de sintaxis de ensamblador en operando
+asmr_e_syn_constant=07050_E_Error de sintaxis de ensamblador en constante
+asmr_e_invalid_string_expression=07051_E_Espresión de cadena noáv lida
+asmr_w_const32bit_for_address=07052_W_constante con la direccion del símbolo $1 que no es un puntero
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Instrucción $1 no reconocida
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Falta la instrucción o no es válida
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinación de prefijo y operación inválidos: $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinación de sobrecarga y operación inválidos: $1
+asmr_e_too_many_operands=07057_E_Demasiados operandos en la línea
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorado
+asmr_w_far_ignored=07059_W_FAR ignorado
+asmr_e_dup_local_sym=07060_E_Símbolo local duplicado $1
+asmr_e_unknown_local_sym=07061_E_Símbolo local indefinido $1
+asmr_e_unknown_label_identifier=07062_E_Identificador de etiqueta desconocido $1
+asmr_e_invalid_register=07063_E_Nombre de registro incorrecto
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nombre de registro de punto flotante no válido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo no soportado
+asmr_e_invalid_float_const=07067_E_Constante de punto flotante no válida $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Espresión de punto flotante no válida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Tipo de símbolo erróneo
+asmr_e_cannot_index_relative_var=07070_E_No se puede indexar una var. local o un parámetro con un registro
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Espresión reemplazo de segmento inválida
+asmr_w_id_supposed_external=07072_W_Identificador $1 se supone externo
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Cadenas no permitidas como constantes
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_No hay tipo de variable especificado
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Código ensamblador no devuelto a sección de texto
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_No es una directiva o un símbolo local $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Usando un nombre definido como una etiqueta local
+asmr_e_dollar_without_identifier=07078_E_Tóken de dólar usado sin identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Constante de 32 bits creada para la dirección
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align es dependiente de la plataforma, use .balign o .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_No se puede acceder directamente a los campos de los parámetros
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_No se puede acceder directamente a los campos de objetos o clases
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No se especificó un tamaño y no es posible determinar el tamaño del operando
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_No se puede utilizar RESULT en esta función
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sin operando traducido como "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traducido como "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" traducido como "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_El carácter < no está permitido aquí
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_El carácter > no está permitido aqui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN no es soportado
+asmr_e_no_inc_and_dec_together=07094_E_Inc y Dec no pueden estar juntos en la misma instrucción
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Lista de registros inválida para movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Lista de registros inválida para la instrucción
+asmr_e_higher_cpu_mode_required=07097_E_Se requiere un modo de CPU superior ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No se especificó el tamaño del operando y no pudo ser determinado. Se utilizará DWORD por defecto
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Error de sintaxis tratando de interpretar un operando de desplazamiento
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Demasiados archivos de ensamblador abiertos
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Salida a ensamblador seleccionada no soportada
+asmw_f_comp_not_supported=08002_F_Comp no soportado
+asmw_f_direct_not_supported=08003_F_Direct no soportado por escritores binarios
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Sólo esta permitido alojar datos en la seccion bss
+asmw_f_no_binary_writer_selected=08005_F_No hay seleccionado un escritor binario
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 no está en la tabla
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 combinacion inválida de opcode y operandos
+asmw_e_16bit_not_supported=08008_E_Asm: Referencias de 16 Bit no soportadas
+asmw_e_invalid_effective_address=08009_E_Asm: Dirección efectiva no válida
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Inmediato o referencia esperado
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 valor excede los límites $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Salto corto es fuera de rango $1
+asmw_e_undefined_label=08013_E_Asm: Etiqueta no definida $1
+asmw_e_comp_not_supported=08014_E_Asm: El tipo Comp no está soportado en esta plataforma
+asmw_e_extended_not_supported=08015_E_Asm: El tipo Extended no está soportado en esta plataforma
+asmw_e_duplicate_label=08016_E_Asm: Etiquita $1 duplicada
+asmw_e_redefined_label=08017_E_Asm: Etiqueta $1 redefinida
+asmw_e_first_defined_label=08018_E_Asm: Se definió por primera vez aquí
+asmw_e_invalid_register=08019_E_Asm: Registro $1 inválido
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sistema operativo de origen redefinido
+exec_i_assembling_pipe=09001_I_Ensamblando (pipe) $1
+exec_d_cant_create_asmfile=09002_E_No se puede crear fichero ensamblador $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_No se puede crear fichero objeto: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_No se puede crear fichero de archivado: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Ensamblador $1 no encontrado, cambiando a ensamblado externo
+exec_t_using_assembler=09006_T_Usando ensamblador: $1
+exec_e_error_while_assembling=09007_E_Error mientras se ensamblaba, codigo de terminación $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_No se pudo llamar al ensamblador, error $1. Cambiando a ensamblador externo
+exec_i_assembling=09009_I_Ensamblando $1
+exec_i_assembling_smart=09010_I_Assembling con enlazado inteligente $1
+exec_w_objfile_not_found=09011_W_Objeto $1 no encontrado, el enlazado podria fallar!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Librería $1 no encontrada, el enlazado podria fallar!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Error durante el enlazado
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_No se puede llamar al enlazador, cambiando a enlazado externo
+exec_i_linking=09015_I_Enlazando $1
+exec_e_util_not_found=09016_E_Utilidad $1 no encontrada, cambiando a enlazado externo
+exec_t_using_util=09017_T_Utilizando utilidad $1
+exec_e_exe_not_supported=09018_E_Creacion de ejecutables no soportado
+exec_e_dll_not_supported=09019_E_Creacion de librerías dinámicas/compartidas no soportado
+exec_i_closing_script=09020_I_Cerrando script $1
+exec_e_res_not_found=09021_E_Compilador de recursos no encontrado, cambiando a modo externo
+exec_i_compilingresource=09022_I_Compilando resource $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_La unidad $1 no puede ser enlazada estáticamente, cambiando a enlazado inteligente
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_La unidad $1 no puede ser enlazada inteligentemente, cambiando a enlazado estático
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_La unidad $1 no admite enlazado compartido, cambiando a enlazado estático
+exec_e_unit_not_smart_or_static_linkable=09026_E_La unidad $1 no puede ser enlazada estática o inteligentemente
+exec_e_unit_not_shared_or_static_linkable=09027_E_La unidad $1 no admite enlazado compartido o estático
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_No se puede post-procesar el ejecutable $1
+execinfo_f_cant_open_executable=09029_F_No se puede abrir el ejecutable $1
+execinfo_x_codesize=09030_X_Tamaño de Código: $1 bytes
+execinfo_x_initdatasize=09031_X_Tamaño de datos inicializados: $1 bytes
+execinfo_x_uninitdatasize=09032_X_Tamaño de datos sin inicializar: $1 bytes
+execinfo_x_stackreserve=09033_X_Espacio reservado para la pila: $1 bytes
+execinfo_x_stackcommit=09034_X_Stack space commited: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Buscando unidad: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Cargando PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Nombre: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Banderas: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Fecha: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Fichero PPU demasiado corto
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Cabecera PPU inválida (no comienza por PPU)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Versión $1 inválida
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU está compilada para otro procesador
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU está compilada para otra plataforma
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_Origen PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Escribiendo $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_No se puede escribir el fichero PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Error leyendo fichero PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fin de fichero inesperado
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrada inválida en fichero PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problema en el contador PPU Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nombre de unidad inválido: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Demasiades unidades
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Referencia circular entre unidades $1 y $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_No se puede compilar la unidad $1, no hay código fuente disponible
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_No se puede encontrar la unidad $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_La unidad $1 no pudo ser encontrada, pero $2 existe
+unit_f_unit_name_error=10024_F_Se buscó la unidad $1 pero se encontró $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compilar la unidad System requiere el conmutador -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Hubo $1 errores compilando el modulo, parando
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Cargado de $1 ($2) unidad $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilando $1, checksum cambiado por $2
+unit_u_recompile_source_found_alone=10029_U_Recompilando $1, solo se encontró el código fuente
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilando unidad, la lib estática es más antigua que la ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilando unidad, la lib compartida es más antigua que la ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilando unidad, obj y asm son más antiguos que ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilando unidad, obj es más antiguo que asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Interpretando interfaz de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Interpretando implementacion de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Segunda carga para la unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Chequeo de fichero PPU $1 fecha $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_No se pudo recompilar la unida $1, pero se encontraron ficheros de inclusió modificados
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_El fichero $1 es mas moderno que la versión Release del archivo PPU $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Se esta utilizando una unidad que no fue compilada con el modo de FPU correcto
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Cargando unidades de interfaz de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Cargando unidades de implementación de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_CRC de la interfaz de la unidad $1 cambiado
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_CRC de la implementacion de la unidad $1 cambiado
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Finalizando compilado de la unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Añadida dependencia de $1 a $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_No hay recarga, es llamada de: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_No hay recarga, ya se esta en la segunda compilación de: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Marcado para recarga: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Recarga forzada
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Estado anterior de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ya se está compilando $1, estableciendo segunda compilación
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Cargando unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Carga de la unidad $1 completada
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrando nueva unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-resolviendo unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Saltando re-resolución de $1, aún se estan cargando las unidades utilizadas
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [opciones] <fichero_entrada> [opciones]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Solo es soportado un fichero fuente
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Fichero DEF solo puede ser creado para OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Ficheros de respuesta anidados no son soportados
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_No hay fichero fuente en la línea de comandos
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No hay opciones en el archivo de configuración $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parámetro incorrecto: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? escribe las páginas de ayuda
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Demasiados ficheros de configuración anidados
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Imposible abrir fichero $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Leyendo opciones adicionales de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Destino está ya puesto a: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Librerías compartidas no soportadas en la plataforma DOS, regresando a estáticas
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_demasiados IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_demasiados ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_condicional abierto al final del fichero
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_La generación de información de depuración no es soportada por este ejecutable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Prueba recompilando con -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Estas usando el conmutador obsoleto $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Estás usando el conmutador obsoleto $1, porfavor usa $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Cambiando a ensamblador de escritura de código fuente por defecto
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_La salida de ensamblador "$1" no es compatible con "$2"
+option_asm_forced=11022_W_Forzado el uso de ensamblador "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Leyendo opciones del fichero $1
+% Options are also read from this file
+option_using_env=11027_T_Leyendo opciones del entorno $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Procesando pción "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** presione retorno ***
+option_start_reading_configfile=11030_H_Inicio de lectura del archivo de configuración $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Fin de lectura del archivo de configuración $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretando opción "$1"
+option_interpreting_firstpass_option=11036_D_Interpretando primera pasada de la opción "$1"
+option_interpreting_file_option=11033_D_Interpretando opción de archivo "$1"
+option_read_config_file=11034_D_Leyendo archivo de configuración "$1"
+option_found_file=11035_D_encontrado nombre del archivo fuente "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Código de página desconocido
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2005 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versión $FPCVERSION
+
+Fecha del Compilador : $FPCDATE
+CPU de destino : $FPCCPU
+
+Plataformas soportadas:
+ $OSTARGETS
+
+Sets de instrucciones de la CPU soportados:
+ $INSTRUCTIONSETS
+
+Sets de instrucciones de la FPU soportados:
+ $FPUINSTRUCTIONSETS
+
+Este programa esta bajo la licencia GNU General Public Licence
+Para mas informació lea COPYING.FPC
+
+Para informar de errores, sugerencias, etc:
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_ponga + tras un conmutador booleano para activarlo, - para desactivarlo
+**1a_el compilador no borra los ficheros de ensamblador generados
+**2al_incluir los números de línea del codigo fuente en el archivo ensamblador
+**2an_incluir la informacion de nodos en el archivo ensamblador generado
+*L2ap_usar tuberías (pipes) en lugar de crear archivos de ensamblado temporales
+**2ar_incluir reserva y liberació de registros en el archivo ensamblador
+**2at_incluir informacion de reserva y liberación temporales en el archivo ensamblador
+**1A<x>_formato de salida:
+**2Adefault_usar ensamblador por defecto
+3*2Aas_ensamblar usando GNU AS
+3*2Anasmcoff_coff (Go32v2) usando Nasm
+3*2Anasmelf_elf32 (Linux) usando Nasm
+3*2Anasmwin32_objeto Win32 usando Nasm
+3*2Anasmwdosx_objeto Win32/WDOSX usando Nasm
+3*2Awasm_fichero obj usando Wasm (Watcom)
+3*2Anasmobj_fichero obj usando Nasm
+3*2Amasm_fichero obj usando Masm (Microsoft)
+3*2Atasm_fichero obj usando Tasm (Borland)
+3*2Aelf_elf32 (Linux) usando escritor interno
+3*2Acoff_coff (Go32v2) usando escritor interno
+3*2Apecoff_pecoff (Win32) usando escritor interno
+4*2Aas_ensamblar usando GNU AS
+6*2Aas_archivo o de Unix usando GNU AS
+6*2Agas_ensamblador GNU Motorola
+6*2Amit_Sintaxis MIT (GAS antiguo)
+6*2Amot_Ensamblador Motorola estándar
+A*2Aas_ensamblar usando GNU AS
+P*2Aas_ensamblar usando GNU AS
+S*2Aas_ensamblar usando GNU AS
+**1b_generar informacion de navegado
+**2bl_generar informació de símbolos locales
+**1B_construir(build) todos los modulos
+**1C<x>_opciones de generado de código:
+**2Cc<x>_cambiar la convencion de llamada por defecto a <x>
+**2CD_crear adicionalmente una librería dinámica (no soportado)
+**2Ce_Compilar con opcodes de punto flotante emulados
+**2Cf<x>_Cambiar el set de instrucciones de la FPU usado, fpc -i para posibles valores<x>
+**2Cg_Generar código PIC
+**2Ch<n>_<n> bytes heap (entre 1023 y 67107840)
+**2Ci_Comprobación de E/S
+**2Cn_omitir etapa de enlazado
+**2Co_comprobar desbordamiento en operaciones de enteros
+**2Cp<x>_Cambiar el set de instrucciones usado, fpc -i para posibles valores
+**2Cr_comprobación de rango
+**2CR_verificar validez de objetos de llamada
+**2Cs<n>_definir el tamaño de la pila a <n>
+**2Ct_comprobación de pila
+**2CX_crear adicionalmente una librerí con enlazado inteligente
+**1d<x>_define el símbol <x>
+**1D_generar fichero DEF
+**2Dd<x>_establece la descripción a <x>
+**2Dv<x>_establece la version de la DLL a <x>
+*O2Dw_Aplicación PM
+**1e<x>_establecer ruta al ejecutable
+**1E_igual que -Cn
+**1F<x>_establecer ficheros y rutas:
+**2Fa<x>[,y]_para hacer que el programa cargue las unidades <x> e [y] antes de procesar su uses
+**2Fc<x>_establece el código de pagina de la entrada a <x>
+**2FD<x>_establece la ruta donde buscar las utilidades del compilador
+**2Fe<x>_redirige la salida de errores a <x>
+**2FE<x>_establece la ruta de destino de exe/unidades a <x>
+**2Fi<x>_añade <x> a las rutas de inclusión
+**2Fl<x>_añade <x> a las rutas de librerías
+**2FL<x>_usa <x> como enlazador dinámico
+**2Fo<x>_añade <x> a las rutas de objetos
+**2Fr<x>_load error message file <x>
+**2Fu<x>_adds <x> a las rutas de unidades
+**2FU<x>_establece la ruta de salida de unidades a <x>, reemplaza -FE anteriores
+*g1g_generar información de depurado:
+*g2gc_generar comprobación de punteros
+*g2gd_usar dbx
+*g2gg_usar gsym
+*g2gh_usar unidad de trazado de memoria (para depurar pérdidas de memoria)
+*g2gl_usar informacion de líneas de las unidades para la traza de ejecución (backtrace)
+*g2gv_genera programas trazables con valgrind
+*g2gw_generar información de depurado dwarf
+**1i_información
+**2iD_devuelve la fecha del compilador
+**2iV_devuelve la versión del compilador
+**2iSO_devuelve el SO del compilador
+**2iSP_devuelve el procesador del compilador
+**2iTO_devuelve el SO de destino
+**2iTP_devuelve el procesador de destino
+**1I<x>_añade <x> a las rutas de iclusión
+**1k<x>_Pasar <x> al enlazador
+**1l_mostrar logo
+**1M<x>_establecer modo del lenguaje a <x>
+**2Mfpc_dialecto de free pascal(default)
+**2Mobjfpc_activar algunas extensiones de Delphi 2
+**2Mdelphi_tratar de ser compatible con Delphi
+**2Mtp_tratar de ser compatible con TP/BP 7.0
+**2Mgpc_tratar de ser compatible con gpc
+**2Mmacpas_tratar de ser compatible con dialectos de macintosh pascal
+**1n_no leer la configuración por defecto
+**1o<x>_cambiar el nombre del ejecutable producido a <x>
+**1O<x>_optimizaciones:
+3*2Og_generar código más pequeño
+3*2OG_generar código más rápido (defecto)
+**2Or_mantener algunas variables en registros
+3*2Ou_activar optimizaciones inseguras (ver docs)
+3*2O1_optimizaciones nivel 1 (optimizaciones rápidas)
+3*2O2_optimizaciones nivel 2 (-O1 + optimizaciones más lentas)
+3*2O3_optimizaciones nivel 3 (-O2 repetidamente, max 5 veces)
+3*2Op<x>_procesador de destino:
+3*3Op1_establecer procesador de destino a 386/486
+3*3Op2_establecer procesador de destino a Pentium/PentiumMMX (tm)
+3*3Op3_establecer procesador de destino a PPro/PII/c6x86/K6 (tm)
+6*2Og_generar código más pequeño
+6*2OG_generatr código más rápido (defecto)
+6*2Ox_optimizar al máximo (AUN CON ERRORES!!!)
+6*2O0_establecer procesador de destino a MC68000
+6*2O2_establecer procesador de destino a MC68020+ (defecto)
+**1pg_generar código de perfilado gprof (define FPC_PROFILE)
+**1R<x>_estilo de lectura de ensamblador:
+**2Rdefault_usar ensamblador por defecto
+3*2Ratt_leer ensamblador estilo AT&T
+3*2Rintel_leer ensamblador estilo Intel
+6*2RMOT_leer ensamblador estilo motorola
+**1S<x>_opciones de sintaxis:
+**2S2_igual que -Mobjfpc
+**2Sc_soportar operadores estilo C (*=,+=,/= and -=)
+**2Sa_incluir código de aserción.
+**2Sd_igual que -Mdelphi
+**2Se<x>_opciones de error. <x> es una combinación de los siguientes:
+**3*_<n> : detener el compilador tras <n> errores (por defecto 1)
+**3*_w : detener también tras avisos
+**3*_n : detener también tras notas
+**3*_h : detener también tras consejos
+**2Sg_permitir LABEL y GOTO
+**2Sh_Usar cadenas largas (ansistrings)
+**2Si_soportar INLINE estilo C++
+**2SI<x>_establecer estilo de interfaz a <x>
+**3SIcom_interfaces compatibles COM (defecto)
+**3SIcorba_interfaces compatibles CORBA
+**2Sm_soportar macros tipo C (global)
+**2So_igual que -Mtp
+**2Sp_igual que -Mgpc
+**2Ss_el nombre del constructor debe ser init (el destructor debe ser done)
+**2St_permitir la palabra reservada static en objetos
+**1s_no llamar al ensamblador ni enlazador
+**2sh_Generar script para enlazar en host
+**2st_Generar script para enlazar en destino
+**2sr_Saltar fase de reserva de registros (usar con -alr)
+**1T<x>_Sistema operativo de destino:
+3*2Temx_OS/2 usando EMX (incluyendo extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 de DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_extensor DOS compatible Watcom
+3*2Twdosx_extensor WDOSX DOS
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (no soportado)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin y MacOS X en PowerPC
+P*2Tlinux_Linux en PowerPC
+P*2Tmacos_MacOS (clásico) en PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_elimina la definición del símbolo <x>
+**1U_opciones de unidad:
+**2Un_no comprobar el nombre de la unidad
+**2Ur_generar unidades para distribución (release)
+**2Us_compilar la unidad System
+**1v<x>_Mostrar detalles. <x> es una combinación de las siguientes letras:
+**2*_e : Mostrar errores (defecto) 0 : No mostrar nada (excepto errores)
+**2*_w : Mostrar avisos u : Mostrar info. de la unidad
+**2*_n : Mostrar notas t : Mostrar archivos usados / intentados
+**2*_h : Mostrar consejos c : Mostrar condicionales
+**2*_i : Mostrar info. general d : Mostrar info. de depurado
+**2*_l : Mostrar num de lineas r : Modo compatible con Rhide/GCC
+**2*_a : Mostrar todo x : Info. del ejecutable (Win32 solo)
+**2*_v : escribe fpcdebug.txt con p : Escribir el árbol de parser en tree.log
+**2*_ mucha informacón de depurado
+3*1W<x>_opciones de Win32 o similares
+3*2WB<x>_Establece la dirección hex de base a <x>
+3*2WC_Especifica que la aplicación es de consola
+3*2WD_Usa DEFFILE para exportar funciones de la DLL o EXE
+3*2WF_Especifica aplicación de pantalla completa (OS/2 sólo)
+3*2WG_Especifica que la aplicación es para entorno gráfico
+3*2WN_No generar código de reubicación (necesario para depurar)
+3*2WR_Generar código de reubicación
+P*2WC_Especifica aplicación de colnsola (MacOS sólo)
+P*2WG_Especifica aplicación gráfica (MacOS sólo)
+P*2WT_Especifica aplicación de tipo herramienta (herramienta MPW, MacOS sólo)
+**1X_opciones de ejecutable:
+**2Xc_pasar --shared al enlazador (Unix sólo)
+**2Xd_no utilizar la ruta de librería por defecto (necesario para compilación cruzada)
+**2XD_tratar de enlazar dinámicamente (define FPC_LINK_DYNAMIC)
+**2XP<x>_pone <x> delante de los nombres de binutils
+**2Xr<x>_establece la ruta de librerías a <x> (necesario para compilación cruzada)
+**2Xs_eliminar todos los símbolos del ejecutable
+**2XS_tratar de enlazar estáticamente (defecto) (define FPC_LINK_STATIC)
+**2Xt_enlazar con librerias estáticas (-static es pasado al enlazador)
+**2XX_tratar de enlazar inteligentemente (define FPC_LINK_SMART)
+**1*_
+**1?_muestra esta ayuda
+**1h_muestra esta ayuda sin esperas
+]
+
+#
+# The End...
diff --git a/compiler/msg/errorf.msg b/compiler/msg/errorf.msg
new file mode 100644
index 0000000000..13238959ac
--- /dev/null
+++ b/compiler/msg/errorf.msg
@@ -0,0 +1,1899 @@
+#
+# $Id: errorf.msg,v 1.6 2004/09/04 21:18:47 armin Exp $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1998-2000 by the Free Pascal Development team
+#
+# French (cp850) Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ linenumber
+# u_ used
+# t_ tried
+# m_ macro
+# p_ procedure
+# c_ conditional
+# d_ debug message
+# b_ display overloaded procedures
+# x_ executable informations
+#
+
+#
+# General
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilateur : $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SystŠme d'exploitation source : $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SystŠme d'exploitation cible : $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_R‚pertoire pour fichiers executables : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_R‚pertoire de recherche d'unit‚s : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_R‚pertoire pour recherche de fichiers inclus : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_R‚pertoire pour librairies : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_R‚pertoire pour fichiers objets : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 lignes compil‚es, $2 secondes
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Plus de m‚moire disponible
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+% \end{description}
+#
+# Scanner
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+general_i_writingresourcefile=01010_I_Ecriture du fichier Resource : $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Ecriture du fichier Resource String Table : $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+% \end{description}
+#
+# Scanner
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Fin de fichier inattendue
+% this typically happens in on of the following cases :
+% \begin{itemize}
+% \item The source file ends befor then final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment wasn't closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String au-del… de la fin de ligne
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_caractŠre ill‚gal
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Erreur de syntaxe, $1 attendu mais $2 trouv‚
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_T_D‚but de lecture du fichier inclus $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Commentaire de niveau $1
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_far_directive_ignored=02006_N_$F directive (FAR) ignor‚e
+% The \var{FAR} directive is a 16-bit construction which is recorgnised
+% but ignored by the compiler, since it produces 32 bit code.
+scan_n_stack_check_global_under_linux=02007_N_Le controle de la gestion de la pile est global sous Linux
+% Stack checking with the \var{-Cs} switch is ignored under \linux, since
+% \linux does this for you. Only displayed when \var{-vn} is used.
+scan_n_ignored_switch=02008_N_Switch "$1" ignor‚
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Switch "$1" ill‚gal
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% doesn't know.
+scan_w_switch_is_global=02010_W_Ce switch a un effet global
+% When \var{-vw} is used, the compiler warns if a switch is global.
+scan_e_illegal_char_const=02011_E_Constante de type char ill‚gale
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range. The range
+% is 1-255.
+scan_f_cannot_open_input=02012_F_Impossible d'ouvrir le fichier $1
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Impossible d'ouvrir le fichier inclus $1
+% \fpc cannot find the source file you specified in a \var{\{\$include \}}
+% stateent.
+scan_e_too_much_endifs=02014_E_Trop de $ENDIFs ou de $ELSEs
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_w_only_pack_records=02015_W_L'alignement des Records peut uniquement ˆtre de 1,2,4,8 ou 16 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1,2,4 or 16 are valid in this case.
+scan_w_only_pack_enum=02016_W_Les ‚numerations peuvent seulement ˆtre sauvegard‚s en 1,2 ou 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_$1 attendu pour $2 d‚fini … la ligne $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Erreur de syntaxe pendant l'interpr‚tation d'une directive de compilation
+% There is an error in the expression following the \var{\{\$if \}} compiler
+% directive.
+scan_e_error_in_preproc_expr=02019_E_Erreur d'‚valuation d'une directive de compilation
+% There is an error in the expression following the \var{\{\$if \}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Le contenu d'une macro est tronqu‚ … 255 caractŠres
+% The contents of macros cannot be longer than 255 characters. This is a
+% safety in the compiler, to prevent buffer overflows. This is shown as a
+% warning, i.e. when the \var{-vw} switch is used.
+scan_e_endif_without_if=02021_E_ENDIF sans IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_D‚fini par l'utilisateur : $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_D‚fini par l'utilisateur : $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_D‚fini par l'utilisateur : $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_D‚fini par l'utilisateur : $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_D‚fini par l'utilisateur : $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_D‚fini par l'utilisateur : $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Impossible de redefinir un mot r‚serv‚
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_D‚bordement du buffer de la macro en lecture ou expansion
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_deep_ten=02030_W_L'expansion des macros d‚passe un niveau de 16.
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_wrong_styled_switch=02031_E_Les directives de compilation entre (* ... *) ne sont pas accept‚es
+% Compiler switches should always be between \var{\{ \}} comment delimiters.
+scan_d_handling_switch=02032_D_Interpr‚tation switch "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_C_ENDIF $1 trouv‚
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_C_IFDEF $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_C_IFOPT $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_C_IF $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_C_IFNDEF $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_C_ELSE $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_C_Passant jusqu'…...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Appuyez sur <Entr‚e> pour continuer
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Switch non support‚ $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_directive de compilation ill‚gale $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_T_De retour dans $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Type d'application non support‚e : $1
+% You get this warning, ff you specify an unknown application type
+% with the directive $APPTYPE
+scan_w_app_type_not_support=02045_W_$APPTYPE non support‚ par OS cible
+% The $APPTYPE directive is supported by win32 applications only
+scan_w_decription_not_support=02046_W_DESCRIPTION est support‚ seulement pour OS2 et Win32
+% The \var{\{\$DESCRIPTION\}} directive is only supported for OS2 and Win32 targets.
+scan_n_version_not_support=02047_N_VERSION non support‚ par OS cible
+% The \var{\{\$VERSION\}} directive is only supported by win32 target.
+scan_n_only_exe_version=02048_N_VERSION seulement pour exes ou DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Mauvais format de la directive VERSION $1
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_w_unsupported_asmmode_specifier=02050_W_Style assembleur non support‚ $1
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Changement de type d'interpr‚teur ASM … l'int‚rieur de code assembleur, $1 sera effectif seulement pour le prochain
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Mauvais argument de switch, utilisez ON/OFF ou +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Fichiers ressource non support‚ pour cette cible
+% The target you are compiling for doesn't support Resource files. The
+% only target which can use resource files is Win32
+scan_w_include_env_not_found=02054_W_Include pour variable d'environment $1 non trouv‚
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valeur invalide pour nombre limite de variables en registre FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+% \end{description}
+#
+# Parser
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+scan_w_only_one_resourcefile_supported=02056_W_Un fichier ressource est seulement support‚ pour cette cible
+% Only one resource file can be supported for this target - this is the case of
+% OS/2 (EMX) currently. The first one found is used, the others are discarded.
+%
+% \end{description}
+#
+# Parser
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parseur - Erreur de syntaxe
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_w_proc_far_ignored=03001_W_Directive pour proc‚dure FAR ignor‚
+% This is a warning. \var{FAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+parser_w_proc_near_ignored=03002_W_Directive pour proc‚dure NEAR ignor‚
+% This is a warning. \var{NEAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+parser_w_proc_interrupt_ignored=03003_W_Directive pour proc‚dure INTERRUPT ignor‚
+% This is a warning. \var{INTERRUPT} is a i386 specific construct
+% and is igonred for other processors.
+parser_e_dont_nest_interrupt=03004_E_Une proc‚dure de type INTERRUPT ne peut ˆtre locale
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Procedure type $1 ignored
+% This is a warning. \var{REGISTER},\var{REINTRODUCE} is ignored by FPC programs for now.
+% This is introduced first for Delphi compatibility.
+parser_e_no_overload_for_all_procs=03006_E_Not all declarations of $1 are declared with OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_no_dll_file_specified=03007_E_Pas de fichier DLL sp‚cifi‚
+% No longer in use.
+parser_e_export_name_double=03008_E_Nom de fonction export‚e doubl‚ $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Index de fonction export‚e doubl‚ $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Index non valide pour fonction export‚e
+% DLL function index must be in the range 1..$FFFF
+parser_w_parser_reloc_no_debug=03011_W_Les DLL ou EXE relogeables sont incompatibles avec les informations de d‚bogage, d‚bogage d‚sactiv‚.
+parser_w_parser_win32_debug_needs_WN=03012_W_Pour permettre le d‚bogage de code win32, utilisez l'option -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Le nom du constructeur doit ˆtre INIT
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Le nom du destructeur doit ˆtre DONE
+% You are declaring a constructor with a name which isn't \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_illegal_open_parameter=03015_E_ParamŠtre ouvert non valide
+% You are trying to use the wrong type for an open parameter.
+parser_e_proc_inline_not_supported=03016_E_Directive de fonction INLINE non support‚e
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_priv_meth_not_virtual=03017_W_Les m‚thodes priv‚es ne devraient pas ˆtre virutelles
+% You declared a method in the private part of a object (class) as
+% \var{virtual}. This is not allowed. Private methods cannot be overridden
+% anyway.
+parser_w_constructor_should_be_public=03018_W_Le constructeur devrait ˆtre public
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Le destructeur devrait ˆtre public
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Les classes ne devraient avoir qu'un selu destructeur
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Les D‚finitions locales de classes ne sont pas autoris‚es
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Les d‚finitions de classes anonymes sont interdites
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_object_has_no_vmt=03023_E_L'object $1 n'a pas de table de m‚thodes virtuelles (VMT)
+parser_e_illegal_parameter_list=03024_E_Liste de paramŠtres ill‚gale
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_type=03025_E_Mauvais type pour paramŠtre #$1
+% There is an error in the parameter list of the function or procedure.
+% The compiler cannot determine the error more accurate than this.
+parser_e_wrong_parameter_size=03026_E_Mauvais nombre de paramŠtres sp‚cifi‚
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_L'identificateur surcharg‚ $1 n'est pas une fonction
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it isn't a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Les fonctions surcharg‚es ont les mˆmes paramŠtres
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_L'entˆte de la fonction ne correspond pas … la d‚claration $1
+% You declared a function with same parameters but
+% different result type or function specifiers.
+parser_e_header_different_var_names=03030_E_L'entˆte de la fonction $1 ne correspond pas … la d‚claration : le nom de variable change $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Les valeurs d'une ‚num‚ration doivent ˆtre en ordre ascendant
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_n_interface_name_diff_implementation_name=03032_N_Les noms d'interface et d'implementation sont diff‚rents $1 => $2
+% This note warns you if the implementation and interface names of a
+% functions are different, but they have the same mangled name. This
+% is important when using overloaded functions (but should produce no error).
+parser_e_no_with_for_variable_in_other_segments=03033_E_With ne peut ˆtre utilis‚ pour des variables dans un autre segment
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Niveau d'inbrication de fonctions > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Erreur d'intervalle dans l'‚valuation d'une constante
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Erreur d'intervalle dans l'‚valuation d'une constante
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Valeur en double dans une instruction CASE
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Valeur max inf‚rieure … la valeur min dans CASE
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Les constantes typ‚es de classes sont interdites
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Impossible d'assigner … une variable fonctionelle une fonction surcharg‚e
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_La longueur d'une STRING doit ˆtre situ‚e entre 1 et 255
+% The length of a string in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+% (This is not true for \var{Longstrings} and \var{AnsiStrings}.
+parser_w_use_extended_syntax_for_objects=03042_W_Utilisez la syntaxe ‚tendue de NEW et DISPOSE pour les objets
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_L'usage de NEW ou DISPOSE pour des pointeurs non typ‚s est sans signification meaningless
+parser_e_no_new_dispose_on_void_pointers=03044_E_L'usage de NEW ou DISPOSE pour des pointeurs non typ‚s est sans signification meaningless
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \vat{delphi} modes.
+parser_e_class_id_expected=03045_E_Identificateur de classe attendu
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identificateur de type interdit ici
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Identificateur de m‚thode attendu
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_La fonction ne correspond … aucune m‚thode de cette classe $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_p_procedure_start=03049_P_proc‚dure/fonction $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante r‚elle ill‚gale
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL peut uniquement ˆtre utilis‚ dans un constructeur
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Les destructeurs ne peuvent avoir de paramŠtres
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Seules des m‚thodes de classes peuvent ˆtre r‚f‚r‚ avec des r‚f‚rences de classes
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Seuls des m‚thodes de classes peuvent ˆtre appel‚s dans une m‚thode de classe
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_La constante et le type de CASE ne conserpodnet pas
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Le symbole ne peut ˆtre export‚ d'une librairie
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Une m‚thode h‚rit‚e est cach‚e par $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Il n'y a pas de m‚thode dans l'ancˆtre que l'on peut surcharger : $1
+% You try to \var{override} a virtual method of a parent class that doesn't
+% exist.
+parser_e_no_procedure_to_access_property=03059_E_Il manque un champ pour sp‚cifier l'accŠss … la property
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Directive de property Stored non implement‚e
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Symbole ill‚gal pour accŠs … la property
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Impossible d'acc‚der … un champ "protected" d'un object ici
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Impossible d'acc‚der … un champ "private" d'un object ici
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_w_overloaded_are_not_both_virtual=03064_W_M‚thode surchargeant une m‚thode virtuelle devrait ˆtre virtuelle : $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+parser_w_overloaded_are_not_both_non_virtual=03065_W_M‚thode surchargeant une m‚thode non virtuelle devrait ˆtre non virtuelle : $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+parser_e_overloaded_methodes_not_same_ret=03066_E_M‚thodes virtuelles surcharg‚es doivent avoir le mˆme type r‚sultat : $1
+% If you declare virtual overloaded methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Des fonctions d‚clar‚es comme EXPORT ne peuvent ˆtre locales
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Les m‚thodes ne peuvent pas ˆtre EXPORT‚es
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Un appel avec paramŠtre par variable doivent ˆtre du type exact de la d‚claration
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Cette classe n'est pas un paarent de la classe actuelle
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF est seulement possible dans les m‚thodes
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Les m‚thodes ne peuvent ˆtre appel‚s avec un type qu'… l'int‚rieur d'une m‚thode
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Utilisation non valide de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Erreur d'intervalle ou ‚l‚ment dupliqu‚ dans un constructeur d'ensemble
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Pointeur d'object attendu
+% You specified an illegal type in a \var{New} statement.
+% The extended synax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Expression doit ˆtre un appel … un constructeur
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Expression doit ˆtre un appel … un destructeur
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Mauvais ordre des ‚l‚ments d'un record
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_L'expression doit ˆtre de type record ou objet
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Les proc‚dures ne peuvent retourner une valeur
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Les constructeurs et destructeurs doivent ˆtre des m‚thodes
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator n'est pas surcharg‚
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossible de surcharger l'assignement pour des types ‚gaux
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Impossible operator overload
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-raise impossible ici
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_La syntaxe ‚tendue de new ou dispose n'est pas valide pour une classe
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_asm_incomp_with_function_return=03087_E_Directive "Assembler" incompatible avec le type de la fonction
+% You're trying to implement a \var{assembler} function, but the return type
+% of the function doesn't allow that.
+parser_e_procedure_overloading_is_off=03088_E_L'overloading de proc‚dure est d‚sactiv‚
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Impossible de red‚finir cet op‚rateur
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Un op‚ratuer de comparaison doit retourner une valeur bool‚enne
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Seule une m‚thode virtuelle peut ˆtre abstraite
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Utilisation d'une caract‚ristique non support‚e !
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Il est interdit de m‚langer des objets et des classes
+% You cannot derive \var{objects} and \var{classes} intertwined . That is,
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Directive de proc‚dure non reconnue a due ˆtre ignor‚e : $1
+% The procedure direcive you secified is unknown. Recognised procedure
+% directives are \var{cdecl}, \var{stdcall}, \var{popstack}, \var{pascal}
+% \var{register}, \var{export}.
+parser_e_absolute_only_one_var=03095_E_absolute put seulement ˆtre associ‚ … une seule variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute peut seulement ˆtre associ‚ … une variable ou une constante
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Seule UNE variable peut ˆtre initialis‚e
+% You cannot specify more than one variable with a initial value
+% in Delphi syntax.
+parser_e_abstract_no_definition=03098_E_Les m‚thodes "Abstract" ne peuvent pas avoir d'implementation
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Cette fonction surcharg‚e ne peut ˆtre locale (doit ˆtre export‚e)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Des m‚thodes virtuelles sont utilis‚es sans constructeur pour $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_m_macro_defined=03101_M_Macro d‚finie : $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+parser_m_macro_undefined=03102_M_Macro non d‚finie : $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+parser_m_macro_set_to=03103_M_Macro $1 … pour valeur $2
+% When \var{-vm} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilation de $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_U_Lecture de l'interface de l'unit‚ $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_U_Lecture de l'implementation de $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_D_Compilation de $1 pour la seconde fois
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_paras_allowed=03108_E_Les propri‚t‚s vecteurs ne sont pas accept‚es ici
+% You cannot use array properties at that point.
+parser_e_no_property_found_to_override=03109_E_Aucune propri‚t‚ trouv‚e pour override
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Seule une propri‚t‚ pard‚faut autoris‚e, il y en a une dans la classe $1
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propri‚t‚ par d‚faut doit ˆtre une propri‚t‚ vecteur
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Les constructeurs virtuels sont seulement possible pour les classes
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Pas de propri‚t‚ par d‚faut
+% You try to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_PUBLISHED non autoris‚ ici pour des classes, utilisez {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_La d‚claration anticip‚e de la classe $1 doit ˆtre r‚solue ici pour pouvoir ˆtreparent
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Les op‚rateurs ne peuvent ˆtre locaux
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_La directive de proc‚dure $1 n'est pas autoris‚e en interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_La directive de proc‚dure $1 n'est pas autoris‚e en impl‚mentation
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_La directive de proc‚dure n'est pas valide pour une variable
+% This procedure directive cannot be part of a procedural of function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La fonction $1 est d‚j… d‚clar‚e comme publique ou forward
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_EXPORT et EXTERNAL sont incompatibles
+% These two procedure directives are mutually exclusive
+parser_e_name_keyword_expected=03122_E_Le mot r‚serv‚ NAME est requis ici
+% The definition of an external variable needs a \var{name} clause.
+parser_w_not_supported_for_inline=03123_W_$1 n'est pas support‚ pour des fonctions INLINE
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining d‚sactiv‚
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Ecriture du Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_le d‚r‚f‚rencement du pointeur semble manquer
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Lecteur de code assembleur non support‚
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_La directive de proc‚dure $1 est en conflit avec d'autres directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convention d'appel ne correspond pas … la fonction pr‚d‚finie
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_register_calling_not_supported=03130_E_Appel avec registres (fastcall) non support‚
+% The \var{register} calling convention, i.e., arguments are passed in
+% registers instead of on the stack is not supported. Arguments are always
+% passed on the stack.
+parser_e_property_cant_have_a_default_value=03131_E_Cette propri‚t‚ ne peut avoir de valeur par d‚faut
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_La valeur par d‚faut d'une propri‚t‚ doit ˆtre une constante
+% The value of a \var{default} declared property must be knwon at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Ce symbole n'est pas une classe et ne peut donc pas ˆtre PUBLISHED
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Ce genre de propri‚t‚ ne peut ˆtre PUBLISHED
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_w_empty_import_name=03135_W_Nom d'importation vide
+% Both index and name for the import are 0 or empty
+parser_e_empty_import_name=03136_W_Empty import name specified
+% Some targets need a name for the imported procedure or a cdecl specifier
+parser_e_used_proc_name_changed=03137_E_Le nom interne de la fonction … chang‚ aprŠs son usage
+% This is an internal error; please report any occurrences of this error
+% to the \fpc team.
+parser_e_division_by_zero=03138_E_Division par z‚ro
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Op‚ration en virgule flottatne invalide
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Limite sup‚rieure inf‚rieure … la limite inf‚rieure d'un intervalle
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_String "$1" est plus long que $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_longueur du String sup‚rieure … la longueur du CHAR ARRAY
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expression invalide aprŠs directive MESSAGE
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_MESSAGE handler peuvent seulement accepter un paramŠtre par r‚f‚rence
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Duplicate message label: %1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_SELF ne peut ˆtre un paramŠtre explicite que dans les MESSAGE handlers
+% The self parameter can be passed only explicit if it is a method which
+% is declared as message method handler
+parser_e_threadvars_only_sg=03147_E_THREADVARS peuvent seulement ˆtre statiques ou globaux
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Assembleur direct non support‚ pour la sortie binaire
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Ne chargez pas l'unit‚ OBJPAS manuellement, utilisez {$mode objfpc} ou {$mode delphi}
+% You're trying to load the ObjPas unit manual from a uses clause. This is
+% not a good idea to do, you can better use the {$mode objfpc} or {$mode delphi}
+% directives which load the unit automaticly
+parser_e_no_object_override=03150_E_OVERRIDE nepeut ˆtre utilis‚ pour des objets
+% Override isn't support for objects, use VIRTUAL instead to override
+% a method of an anchestor object
+% \end{description}
+#
+# Type Checking
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+parser_e_cant_use_inittable_here=03151_E_Les types de donn‚es n‚cessitant des initialisations ne peuvent faire partie de RECORD variables
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_RESOURCESTRINGS doivent ˆtre statiques ou globaux
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit avec un argument ne peut ˆtre utilis‚ ici
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Le type du symbole STORED doit ˆtre un bool‚en
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Ce symbole n'est pas admis comme symbole STORED
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Selues les classes compil‚es en mode $M+ peuvent ˆtre PUBLISHED
+% In the published section of a class can be only class as fields used which
+% are compiled in $M+ or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Directive de proc‚dure attendue
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Le type d'un index de propri‚t‚ doit ˆtre un type ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nom de proc‚dure trop court pour ˆtre exprot‚
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Impossible de cr‚er une entr‚e DEFFILE pour des variables globales d'unit‚s
+parser_e_dlltool_unit_var_problem2=03161_E_Compilez sans l'option -WD
+% \end{description}
+#
+# Type Checking
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Incompatibilit‚ de types
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Incompatible types: got $1 expected $2
+% There is no conversion possible between the two types
+type_e_not_equal_types=04002_E_Incompatibilit‚ de types entre $1 et $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificateur de type attendu
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificateur de variable attendu
+% This happens when you pass a constant to a \var{Inc} var or \var{Dec}
+% procedure. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Integer expression expected
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Expression bool‚enne attendue, mais "$1" obtenu
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Expression ordinale attendue
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Type pointeur attendu
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Type classe attendu
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_varid_or_typeid_expected=04010_E_Identificateur de variable ou de type attendu
+% The argument to the \var{High} or \var{Low} function is not a variable
+% nor a type identifier.
+type_e_cant_eval_constant_expr=04011_E_Impossible d'‚valuer l'expression constante
+% No longer in use.
+type_e_set_element_are_not_comp=04012_E_Elements d'ensembles non compatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Op‚ration non permise pour des ensembles
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversion automatique de r‚el vers COMP qui est un type entier
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Utilisez DIV pour obtenir un r‚sultat entier
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Types string incompatibles, … cause du mode $V+
+% When compiling in \var{\{\$V+ \}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_succ ou pred impossible pour des ‚num‚rations avec valeurs fix‚es
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Impossible de lire ou d'‚crire des variables de ce type
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% booleans, reals, pchars and strings can be read from/written to a text file.
+type_e_no_readln_writeln_for_typed_file=04019_E_Impossible d'utiliser READLN ou WRITELN pour un ficher typ‚
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Impossible d'utiliser READ ou WRITE pour un FILE non typ‚
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Confit de type pour des ‚l‚ments d'un ensemble
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(longint/dword) retourne le word bas/haut
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword}
+% which returns the lower/upper word of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type case the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Expression entiŠre ou r‚elle attendue
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Mauvais type dans array constructor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Type incompatible type pour arg #$1: $2 au lieu de $3
+% You are trying to pass an invalid type for the specified parameter.
+% \end{description}
+type_e_no_method_and_procedure_not_compatible=04026_E_Method (variable) et Procedure (variable) sont incompatibles
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante invalide pass‚e … une fonction math‚matique interne
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Impossible d'obtenir l'adresse d'une constante
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+% \end{description}
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+type_e_argument_cant_be_assigned=04029_E_Impossible d'assigner une valeur … l'argument
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Impossible d'assigner une fonction ou proc‚dure locale … une variable de proc‚dure
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Can't assign values to an address
+% It's not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Can't assign values to const variable
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing make the parameter value or var.
+% \end{description}
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificateur non trouv‚ $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Internal Error in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Duplicate identifier $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identifier already defined in $1 at line $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Unknown identifier $1
+% The identifier encountered hasn't been declared, or is used outside the
+% scope where it's defined.
+sym_e_forward_not_resolved=05005_E_Forward declaration not solved $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_f_id_already_typed=05006_F_Identifier type already defined as type
+% You are trying to redefine a type.
+sym_e_error_in_type_def=05007_E_Error in type definition
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_type_id_not_defined=05008_E_Type identifier not defined
+% The type identifier has not been defined yet.
+sym_e_forward_type_not_resolved=05009_E_Forward type not resolved $1
+% The compiler encountered an unknown type.
+sym_e_only_static_in_static=05010_E_Only static variables can be used in static methods or outside methods
+% A static method of an object can only access static variables.
+sym_e_invalid_call_tvarsymmangledname=05011_E_Invalid call to tvarsym.mangledname()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_f_type_must_be_rec_or_class=05012_F_record or class type expected
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instances of classes or objects with an abstract method are not allowed
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label not defined $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label used but not defined $1
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Illegal label declaration
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO und LABEL are not supported (use switch -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label not found
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_identifier isn't a label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_label already defined
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_illegal type declaration of set elements
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward class definition not resolved $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Unit $1 not used in $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter not used $1
+% This is a warning. The identifier was declared (locally or globally) but
+% wasn't used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Local variable not used $1
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Value parameter $1 is assigned but never used
+% This is a warning. The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Local variable $1 is assigned but never used
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Local $1 $2 is not used
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Private field $1.$2 is never used
+sym_n_private_identifier_only_set=05030_N_Private field $1.$2 is assigned but never used
+sym_n_private_method_not_used=05031_N_Private method $1.$2 never used
+
+sym_e_set_expected=05032_E_Set type expected
+% The variable or expression isn't of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Function result does not seem to be set
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type $1 is not aligned correctly in current record for C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Unknown record field identifier $1
+% The field doesn't exist in the record definition.
+sym_n_uninitialized_local_variable=05036_W_Local variable $1 does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% wasn't initialized first (i.e. appeared in the right-hand side of an
+% assigment)
+sym_n_uninitialized_variable=05037_W_Variable $1 does not seem to be initialized
+% These messages are displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% wasn't initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_identifier idents no member $1
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the class you are trying to create. The procedure you specified
+% does not exist.
+sym_b_param_list=05039_B_Found declaration: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+% \end{description}
+#
+# Codegenerator
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+sym_e_segment_too_large=05040_E_Data segment too large (max. 2GB)
+% You get this when you declare an array whose size exceeds the 2GB limit.
+% \end{description}
+#
+# Codegenerator
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_break_not_allowed=06000_E_BREAK not allowed
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06001_E_CONTINUE not allowed
+% You're trying to use \var{continue} outside a loop construction.
+cg_e_too_complex_expr=06002_E_Expression too complicated - FPU stack overflow
+% Your expression is too long for the compiler. You should try dividing the
+% construct over multiple assignments.
+cg_e_illegal_expression=06003_E_Illegal expression
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+cg_e_invalid_integer=06004_E_Invalid integer expression
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+cg_e_invalid_qualifier=06005_E_Illegal qualifier
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+cg_e_upper_lower_than_lower=06006_E_High range limit < low range limit
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+cg_e_illegal_count_var=06007_E_Illegal counter variable
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+cg_e_cant_choose_overload_function=06008_E_Can't determine which overloaded function to call
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+cg_e_parasize_too_big=06009_E_Parameter list size exceeds 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_illegal_type_conversion=06010_E_Illegal type conversion
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+cg_d_pointer_to_longint_conv_not_portable=06011_D_Conversion between ordinals and pointers is not portable across platforms
+% If you typecast a pointer to a longint, this code will not compile
+% on a machine using 64bit for pointer storage.
+cg_e_file_must_call_by_reference=06012_E_File types must be var parameters
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_The use of a far pointer isn't allowed there
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_var_must_be_reference=06014_E_illegal call by reference parameters
+% You are trying to pass a constant or an expression to a procedure that
+% requires a \var{var} parameter. Only variables can be passed as a \var{var}
+% parameter.
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possible illegal call of constructor or destructor (doesn't match to this context)
+% No longer in use.
+cg_n_inefficient_code=06017_N_Inefficient code
+% You construction seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_unreachable code
+% You specified a loop which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_stackframe_with_esp=06019_E_procedure call with stackframe ESP/SP
+% The compiler encountered a procedure or function call inside a
+% procedure that uses a \var{ESP/SP} stackframe. Normally, when a call is
+% done the procedure needs a \var{EBP} stackframe.
+cg_e_cant_call_abstract_method=06020_E_Abstract methods can't be called directly
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_f_internal_error_in_getfloatreg=06021_F_Internal Error in getfloatreg(), allocation failure
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_f_unknown_float_type=06022_F_Unknown float type
+% The compiler cannot determine the kind of float that occurs in an expression.
+cg_f_secondvecn_base_defined_twice=06023_F_SecondVecn() base defined twice
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_f_extended_cg68k_not_supported=06024_F_Extended cg68k not supported
+% The var{extended} type is not supported on the m68k platform.
+cg_f_32bit_not_supported_in_68000=06025_F_32-bit unsigned not supported in MC68000 mode
+% The cardinal is not supported on the m68k platform.
+cg_f_internal_error_in_secondinline=06026_F_Internal Error in secondinline()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_d_register_weight=06027_D_Register $1 weight $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_e_stacklimit_in_local_routine=06028_E_Stack limit excedeed in local routine
+% Your code requires a too big stack. Some operating systems pose limits
+% on the stack size. You should use less variables or try ro put large
+% variables on the heap.
+cg_d_stackframe_omited=06029_D_Stack frame is omitted
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_w_64bit_range_check_not_supported=06030_W_Range check for 64 bit integers is not supported on this target
+% 64 bit range check is not yet implemented for 32 bit processors.
+cg_e_unable_inline_object_methods=06031_E_Object or class methods can't be inline.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar calls can't be inline.
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No code for inline procedure stored
+% The compiler couldn't store code for the inline procedure.
+cg_e_no_call_to_interrupt=06034_E_Direct call of interrupt procedure $1 is not possible
+% You can not call an interrupt procedure directly from FPC code
+cg_e_can_access_element_zero=06035_E_Element zero of an ansi/wide- or longstring can't be accessed, use (set)length instead
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_include_not_implemented=06036_E_Include and exclude not implemented in this case
+% \var{include} and \var{exclude} are only partially
+% implemented for \var{i386} processors
+% and not at all for \var{m68k} processors.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors or destructors can not be called inside a 'with' clause
+% Inside a \var{With} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Cannot call message handler method directly
+% A message method handler method can't be called directly if it contains an
+% explicit self argument
+% \end{description}
+# EndOfTeX
+#
+# Assembler reader
+#
+cg_e_goto_inout_of_exception_block=06039_E_Jump in or outside of an exception block
+% It isn't allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+% \end{description}
+cg_e_control_flow_outside_finally=06040_E_Control flow statements aren't allowed in a finally block
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+# EndOfTeX
+asmr_d_start_reading=07000_D_Starting $1 styled assembler parsing
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_D_Finished $1 styled assembler parsing
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Non-label pattern contains @
+% A identifier which isn't a label can't contain a @.
+asmr_w_override_op_not_supported=07003_W_Override operator not supported
+% The Override operator is not supported
+asmr_e_building_record_offset=07004_E_Error building record offset
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET used without identifier
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE utilis‚ sans identificateur
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Cannot use local variable or parameters here
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the %ebp register so the
+% address can't be get directly.
+asmr_e_need_offset=07008_E_need to use OFFSET here
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_need to use $ here
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Cannot use multiple relocatable symbols
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Relocatable symbol can only be added
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Invalid constant expression
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Relocatable symbol is not allowed
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Invalid reference syntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Impossible d'atteindre $1 depuis ce code
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Local symboles/labels ne sont pas autoris‚s
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Invalid base and index register usage
+% There is an error with the base and index register
+asmr_w_possible_object_field_bug=07018_W_Erreur possible dans l'utilisation d'un champ d'un object
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Wrong scale factor specified
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Multiple index register usage
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Invalid operand type
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Invalid string as opcode operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE and @DATA not supported
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label references are not allowed
+asmr_e_expr_zero_divide=07025_E_Divide by zero in asm evaluator
+asmr_e_expr_illegal=07026_E_Illegal expression
+asmr_e_escape_seq_ignored=07027_E_escape sequence ignored: $1
+asmr_e_invalid_symbol_ref=07028_E_Invalid symbol reference
+asmr_w_fwait_emu_prob=07029_W_Fwait can cause emulation problems with emu387
+asmr_w_fadd_to_faddp=07030_W_FADD without operand translated into FADDP
+asmr_w_enter_not_supported_by_linux=07031_W_ENTER instruction is not supported by Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Calling an overload function in assembler
+asmr_e_unsupported_symbol_type=07033_E_Unsupported symbol type for operand
+asmr_e_constant_out_of_bounds=07034_E_Constant value out of bounds
+asmr_e_error_converting_decimal=07035_E_Error converting decimal $1
+asmr_e_error_converting_octal=07036_E_Error converting octal $1
+asmr_e_error_converting_binary=07037_E_Error converting binary $1
+asmr_e_error_converting_hexadecimal=07038_E_Error converting hexadecimal $1
+asmr_h_direct_global_to_mangled=07039_H_$1 translated to $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 is associated to an overloaded function
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Cannot use SELF outside a method
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Cannot use OLDEBP outside a nested procedure
+asmr_e_void_function=07043_W_Functions with void return value can't return any value in asm code
+asmr_e_SEG_not_supported=07044_E_SEG not supported
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Size suffix and destination or source size do not match
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Size suffix and destination or source size do not match
+asmr_e_syntax_error=07047_E_Assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Invalid combination of opcode and operands
+asmr_e_syn_operand=07049_E_Assembler syntax error in operand
+asmr_e_syn_constant=07050_E_Assembler syntax error in constant
+asmr_e_invalid_string_expression=07051_E_Invalid String expression
+asmr_w_const32bit_for_address=07052_bit constant created for address
+asmr_e_unknown_opcode=07053_E_Instruction non reconnue $1
+asmr_e_invalid_or_missing_opcode=07054_E_Invalid or missing opcode
+asmr_e_invalid_prefix_and_opcode=07055_E_Invalid combination of prefix and opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Invalid combination of override and opcode: $1
+asmr_e_too_many_operands=07057_E_Too many operands on line
+asmr_w_near_ignored=07058_W_NEAR ignored
+asmr_w_far_ignored=07059_W_FAR ignored
+asmr_e_dup_local_sym=07060_E_Duplicate local symbol $1
+asmr_e_unknown_local_sym=07061_E_Undefined local symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unknown label identifier $1
+asmr_e_invalid_register=07063_E_Invalid register name
+asmr_e_invalid_fpu_register=07064_E_Invalid floating point register name
+asmr_e_nor_not_supported=07065_E_NOR not supported
+asmr_w_modulo_not_supported=07066_W_Modulo not supported
+asmr_e_invalid_float_const=07067_E_Invalid floating point constant $1
+asmr_e_invalid_float_expr=07068_E_Invalid floating point expression
+asmr_e_wrong_sym_type=07069_E_Wrong symbol type
+asmr_e_cannot_index_relative_var=07070_E_Cannot index a local var or parameter with a register
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+asmr_e_string_not_allowed_as_const=07073_E_Strings not allowed as constants
+asmr_e_no_var_type_specified=07074_No type of variable specified
+asmr_w_assembler_code_not_returned_to_text=07075_E_assembler code not returned to text section
+asmr_e_not_directive_or_local_symbol=07076_E_Not a directive or local symbol $1
+asmr_w_using_defined_as_local=07077_E_Using a defined name as a local label
+#
+# Assembler/binary writers
+#
+asmr_e_dollar_without_identifier=07078_E_Dollar utilis‚ sans identificateur
+asmr_w_32bit_const_for_address=07079_W_32bit constante cr‚‚e pour une addresse
+asmr_n_align_is_target_specific=07080_N_.align d‚pend de la cible, utilisez .balign ou .p2align
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Impossible d'acc‚der directement aux champs pour des paramŠtres
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Impossible d'acc‚der aux champs d'objectsou de classes directement
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+#
+# Assembler/binary writers
+#
+asmw_f_too_many_asm_files=08000_F_Too many assembler files
+asmw_f_assembler_output_not_supported=08001_F_Selected assembler output not supported
+asmw_f_comp_not_supported=08002_F_Comp not supported
+asmw_f_direct_not_supported=08003_F_Direct not support for binary writers
+asmw_e_alloc_data_only_in_bss=08004_E_Allocating of data is only allowed in bss section
+asmw_f_no_binary_writer_selected=08005_F_No binary writer selected
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 not in table
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 invalid combination of opcode and operands
+asmw_e_16bit_not_supported=08008_E_Asm: 16 Bit references not supported
+asmw_e_invalid_effective_address=08009_E_Asm: Invalid effective address
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 value exceeds bounds $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Short jump is out of range $1
+#
+# Executing linker/assembler
+#
+asmw_e_undefined_label=08013_E_Asm: Label $1 non d‚fini
+
+#
+# Executing linker/assembler
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Source operating system redefined
+exec_i_assembling_pipe=09001_I_Assembling (pipe) $1
+exec_d_cant_create_asmfile=09002_E_Can't create assember file $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_objectfile=09003_E_Impossible de cr‚er le fichier object : $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_archivefile=09004_E_Impossible de cr‚er le fichier archive : $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_w_assembler_not_found=09005_W_Assembler $1 not found, switching to external assembling
+exec_t_using_assembler=09006_T_Using assembler: $1
+exec_w_error_while_assembling=09007_W_Error while assembling exitcode $1
+exec_w_cant_call_assembler=09008_W_Can't call the assembler, error $1 switching to external assembling
+exec_i_assembling=09009_I_Assembling $1
+exec_i_assembling_smart=09010_I_Assemblage smartlink $1
+exec_w_objfile_not_found=09011_W_Object $1 not found, Linking may fail !
+exec_w_libfile_not_found=09012_W_Library $1 not found, Linking may fail !
+exec_w_error_while_linking=09013_W_Error while linking
+exec_w_cant_call_linker=09014_W_Can't call the linker, switching to external linking
+exec_i_linking=09015_I_Linking $1
+exec_w_util_not_found=09016_W_Utilitaire $1 non trouv‚, force la liaison externe
+exec_t_using_util=09017_T_Utilitaire $1 trouv‚
+exec_e_exe_not_supported=09018_E_Cr‚ation d'executables impossible
+exec_e_dll_not_supported=09019_E_Dynamic Libraries not supported
+exec_i_closing_script=09020_I_Closing script $1
+exec_w_res_not_found=09021_W_resource compiler not found, switching to external mode
+exec_i_compilingresource=09022_I_Compiling resource $1
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09023_F_Can't post process executable $1
+execinfo_f_cant_open_executable=09024_F_Can't open executable $1
+execinfo_x_codesize=09025_X_Size of Code: $1 bytes
+execinfo_x_initdatasize=09026_X_Size of initialized data: $1 bytes
+execinfo_x_uninitdatasize=09027_X_Size of uninitialized data: $1 bytes
+execinfo_x_stackreserve=09028_X_Stack space reserved: $1 bytes
+execinfo_x_stackcommit=09029_X_Stack space commited: $1 bytes
+# Unit loading
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Unitsearch: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU Loading $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Name: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Flags: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU Crc: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Time: $1
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_file_too_short=10006_U_PPU File too short
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_invalid_header=10007_U_PPU Invalid Header (no PPU at the begin)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_PPU Invalid Version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU is compiled for an other processor
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU is compiled for an other target
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU Source: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Writing $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Can't Write PPU-File
+% An err
+unit_f_ppu_read_error=10014_F_reading PPU-File
+% Unexpected end of file
+unit_f_ppu_read_unexpected_end=10015_F_unexpected end of PPU-File
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_invalid_entry=10016_F_Invalid PPU-File entry: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx count problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Illegal unit name: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Too much units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Circular unit reference between $1 and $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Can't compile unit $1, no sources available
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Impossible de trouver l'unit‚ $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Unit‚ $1 non trouv‚ mais $2 existe
+unit_f_unit_name_error=10024_F_Unit‚ $1 cherch‚ mais $2 trouv‚
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compiling the system unit requires the -Us switch
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_There were $1 errors compiling module, stopping
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Load from $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompiling $1, checksum changed for $2
+unit_u_recompile_source_found_alone=10029_U_Recompiling $1, source found only
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompiling unit, static lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompiling unit, shared lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompiling unit, obj and asm are older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the assembler of
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompiling unit, obj is older than asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_start_parse_interface=10034_U_Parsing interface of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_start_parse_implementation=10035_U_Parsing implementation of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Second load for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU Check file $1 time $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+option_usage=11000_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Only one source file supported
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF file can be created only for OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_nested response files are not supported
+% you cannot nest response files with the \var {@file} command-line option.
+option_no_source_found=11004_F_No source file name in command line
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Aucune option trouv‚e dans le fichier de configuration $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Illegal parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? writes help pages
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Too many config files nested
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Unable to open file $1
+% The option file cannot be found.
+option_reading_further_from=11010_N_Reading further options from $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Target is already set to: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Shared libs not supported on DOS platform, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_too many IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_too many ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_open conditional at the end of the file
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Debug information generation is not supported by this executable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Try recompiling with -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_You are using the obsolete switch $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_W_You are using the obsolete switch $1, please use $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Switching assembler to default source writing assembler
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Assembler output selected "$1" is not compatible with "$2"
+option_asm_forced=11022_W_"$1" assembler use forced
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Compilateur Free Pascal version $FPCVER [$FPCDATE] pour $FPCTARGET
+Copyright (c) 1998-2000 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Compilateur Free Pascal version $FPCVER
+
+Date du compilateur : $FPCDATE
+Cible du compilateur : $FPCTARGET
+# the next lines are NOT translated on purpose !!!
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs,suggestions etc to:
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+option_help_pages=11025_[
+**0*_mettre + aprŠs un bool‚en pour activer l'option, - pour la d‚sactiver
+**1a_conserve les fichiers assembleurs cr‚‚s pendant la compilation
+**2al_liste le code source dans les fichiers assembleur
+**2ar_liste les allocations de registres dans les fichiers assembleur
+**2at_liste les allocations de donn‚es temporaire dans la pile
+**1b_g‚nŠre les informations pour le browser
+**2bl_g‚nŠre les informations locales ‚galement
+**1B_recompile toutes les unit‚s
+**1C<x>_options de g‚n‚ration de code :
+3*2CD_cr‚erune librairie dynamique
+**2Ch<n>_<n> taille du tas en bytes (entre 1023 et 67107840)
+**2Ci_IO-checking
+**2Cn_pas de linking
+**2Co_g‚nŠre des tests d'overflow pour les op‚rations sur les entiers
+**2Cr_Controle d'intervalles
+**2Cs<n>_sp‚cifie <n> comme taille de la pile
+**2Ct_test de d‚bordement de pile
+3*2CS_cr‚er une librairie statique
+3*2Cx_utiliser le smartlinking
+**1d<x>_d‚finit le symbole <x>
+*O1D_g‚nŠre un fichier DEF
+*O2Dd<x>_assigne la description … <x>
+*O2Dw_application en mode prot‚g‚
+**1e<x>_d‚finit le chemin vers l'ex‚cutable
+**1E_comme -Cn
+**1F<x>_d‚finit des chemins et noms de fichiers :
+**2FD<x>_d‚finit le r‚pertoire o— chercher les utilitaires de compilation
+**2Fe<x>_redirige les erreurs vers le fichier <x>
+**2FE<x>_r‚pertoire pour les exe/unit‚s : <x>
+**2Fi<x>_ajoute <x> … la liste des r‚pertoires pour fichiers inclus
+**2Fl<x>_ajoute <x> … la liste des r‚pertoires pour librairies
+*L2FL<x>_utilises <x> comme lieur dynamique
+**2Fo<x>_ajoute <x> … la liste des r‚pertoires pour fichiers objets
+**2Fr<x>_charge le fichier erreur <x>
+**2Fu<x>_ajoute <x> … la liste des r‚pertoires pour unit‚s
+**2FU<x>_d‚finit le r‚pertoire d'‚criture des unit‚s … <x>, en d‚pit de -FE
+*g1g<x>_g‚nŠre des informations de d‚bogage :
+*g2gg_utilise gsym
+*g2gd_utilise dbx
+*g2gh_use l'unit‚ de tracage du tas
+*g2gc_generate checks for pointers
+**1i_information
+**2iD_donne la date du compilateur
+**2iV_donne la version du compilateur
+**2iSO_donne l'OS du compilateur
+**2iSP_donne le processeur du compilateur
+**2iTO_donne l'OS cible
+**2iTP_donne le processeur cible
+**1I<x>_ajoute <x> … la liste des r‚pertoires pour fichiers inclus
+**1k<x>_transmet <x> au linker
+**1l_‚crit le logo
+**1n_ne pas lire le fichier de configuration par d‚faut
+**1o<x>_change le nom de l'executable en <x>
+**1pg_g‚nŠre du code pour profiler avec gprof
+*L1P_utilise des pipes au lieu de cr‚er des fichiers temporaires
+**1S<x>_options de syntaxe :
+**2S2_autorise quelques extensions Delphi 2
+**2Sc_autorise les operateurs type C (*=,+=,/= et -=)
+**2Sd_essaye d'ˆtre compatible avec Delphi
+**2Se_stoppe la compilation … la premiŠre erreur
+**2Sg_autorise LABEL et GOTO
+**2Sh_Utilise les ansistrings
+**2Si_supporte les INLINE type C++
+**2Sm_support des macros comme C (global)
+**2So_essaye d'ˆtre compatible avec TP/BP 7.0
+**2Sp_essaye d'ˆtre compatible avec GPC
+**2Ss_les constructeurs doivent s'appeler init (et les destructeurs done)
+**2St_autorise "static" dans les objects
+**1s_n'appelle pas l'assembleur ni le linker
+**1u<x>_rend le symbole <x> non d‚fini
+**1U_options d'unit‚s :
+**2Un_ne pas v‚rifier le nom de l'unit‚
+**2Us_compiler en temps qu'unit‚ systŠme
+**1v<x>_donne des informations. <x> est une combination des lettres suivantes :
+**2*_e : montre les erreurs (d‚faut) d : informations de d‚boggage
+**2*_w : montre les avertissements u : montre les info sur les unit‚s
+**2*_n : montre les notes t : montre les fichiers essay‚s/utilis‚s
+**2*_h : montre les suggestions m : montre les macros d‚finies
+**2*_i : montre des infos g‚n‚rales p : montre les proc‚dures compil‚es
+**2*_l : montre les num‚ros de lignes c : montre les conditionniels
+**2*_a : montre tout 0 : ne montre rien (sauf les erreurs)
+**2*_b : montre toutes les proc‚dures r : mode compatibilit‚ Rhide/GCC
+**2*_ quand une erreur survient x : infos Executable (Win32 seulement)
+**2*_
+**1X_options pour executable :
+*L2Xc_lien avec librairie C
+**2XD_lien avec la librarie dynamique (d‚finit FPC_LINK_DYNAMIC)
+**2Xs_enlˆve tous les symboles de l'executable
+**2XS_lien avec les librairies statiques (d‚finit FPC_LINK_STATIC)
+**0*_options sp‚cifiques au processeur :
+3*1A<x>_format de sortie :
+3*2Aas_fichier objet g‚n‚r‚ par GNU AS
+3*2Aasaout_fichier objet g‚n‚r‚ par GNU AS pour aout (Go32v1)
+3*2Anasmcoff_fichier COFF (Go32v2) avec Nasm
+3*2Anasmelf_fichier ELF32 (Linux) avec Nasm
+3*2Anasmobj_fichier OBJ avec Nasm
+3*2Amasm_fichier OBJ avec Masm (Mircosoft)
+3*2Atasm_fichier OBJ avec Tasm (Borland)
+3*2Acoff_coff (Go32v2) using internal writer
+3*2Apecoff_pecoff (Win32) using internal writer
+3*1R<x>_type lecture assembleur :
+3*2Ratt_lit l'assembleur AT&T
+3*2Rintel_lit l'assembleur Intel
+3*2Rdirect_copie le texte assembleur directement dans le fichier assembleur
+3*1O<x>_optimisations :
+3*2Og_g‚nŠre du code compact
+3*2OG_g‚nŠre du code rapide (defaut)
+3*2Or_garde certaines variables dans des registres (toujours BUGGY!!!)
+3*2Ou_autorise les optimisations incertaines (voir docs)
+3*2O1_optimisations niveau 1 (optimisations rapides)
+3*2O2_optimisations niveau 2 (-O1 + optimisations plus lentes)
+3*2O3_optimisations niveau 3 (comme -O2u)
+3*2Op<x>_processeur cible :
+3*3Op1_d‚finit 386/486 comme processeur cible
+3*3Op2_d‚finit Pentium/PentiumMMX (tm) comme processeur cycle
+3*3Op3_d‚finit PPro/PII/c6x86/K6 (tm) comme processeur cycle
+3*1T<x>_systŠme d'expliotation cible:
+3*2TEMX_OS/2 via EMX (et les extensions EMX/RSX)
+3*2TGO32V2_version 2 de l'extension DOS de DJ Delorie
+3*2TLINUX_Linux
+3*2TNETWARE_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2TOS2_OS/2 / eComStation
+3*2TSUNOS_SunOS/Solaris
+3*2TWDOSX_WDOSX DOS extension
+3*2TWIN32_Windows 32 Bits
+6*1A<x>_output format
+6*2Aas_Unix o-file using GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola assembler
+6*1O_optimizations:
+6*2Oa_turn on the optimizer
+6*2Og_generate smaller code
+6*2OG_generate faster code (default)
+6*2Ox_optimize maximum (still BUGGY!!!)
+6*2O2_set target processor to a MC68020+
+6*1R<x>_styles d'assembleur :
+6*2RMOT_lire l'assembleur type motorola
+6*1T<x>_SystŠme d'exploitation cible :
+6*2TAMIGA_Commodore Amiga
+6*2TATARI_Atari ST/STe/TT
+6*2TMACOS_Macintosh m68k
+6*2TLINUX_Linux-68k
+**1*_
+**1?_affiche cette aide
+6*1R<x>_version de l'assembleur lu
+6*2RMOT_read motorola style assembler
+6*1T<x>_Target operating system:
+6*2TAMIGA_Commodore Amiga
+6*2TATARI_Atari ST/STe/TT
+6*2TMACOS_Macintosh m68k
+6*2TLINUX_Linux-68k
+**1*_
+**1?_shows this help
+**1h_affiche cette aide sans attente
+]
+
+#
+# The End...
diff --git a/compiler/msg/errorhe.msg b/compiler/msg/errorhe.msg
new file mode 100644
index 0000000000..52e109c046
--- /dev/null
+++ b/compiler/msg/errorhe.msg
@@ -0,0 +1,2362 @@
+#
+# $Id: errorhe.msg,v 1.5 2005/04/10 08:11:14 florian Exp $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Hebrew Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_îäãø: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_îòøëú äôòìä: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_îòøëú äôòìä îéåòãú: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_îùúîù áðúéá äøöä: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_îùúîù áðúéá äéçéãåú: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_îùúîù áðúéá äîåñó: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_îùúîù áðúéá äñôøéä: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Using object path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 ùåøåú äåãøå, á$2 ùðéåú
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_ìà ðùàø æëøåï
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_ëåúá àú ÷åáõ îùàáé èáìú äîçøåæåú: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_ëåúá àú ÷åáõ îùàáé èáìú äîçøåæåú: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_ùâéàä ÷øéèéú:
+% Prefix for Fatal Errors
+general_i_error=01013_I_ùâéàä:
+% Prefix for Errors
+general_i_warning=01014_I_äúøàä:
+% Prefix for Warnings
+general_i_note=01015_I_äòøä:
+% Prefix for Notes
+general_i_hint=01016_I_øîæ:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_äðúéá "$1" àéðå ÷ééí
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_ääéãåø áåèì
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_ñåó ÷åáõ ìà öôåé
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_îçøåæú âåìùú îùåøä
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_úå ìà çå÷é "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_ùâéàú úçáéø: îöôä ì "$1" àáì "$2" ðîöà
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_îúçéì ÷øéàä ùì ÷åáõ úåñôåú $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_øîú äòøåú $1 ðîöàä
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_îúòìí îîúâ îäãø "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_îúâ îäãø "$1" àéðå çå÷é
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_îé÷åí ùâåé ìîúâ îäãø âìåáìé
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_úå ÷áåò ìà çå÷é
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_ìà ðéúï ìôúåç àú ÷åáõ "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_ìà ðéúï ìôúåç àú ÷åáõ äúåñôåú "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_ðéúï ìééùø ùãåú øùåîä ø÷ ì1,2,4,8,16 å32 áúéí áìáã
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1, 2, 4, 8, 16 and 32 are valid in this case.
+scan_w_only_pack_enum=02016_W_ðéúï ìùîåø îðéä ø÷ á1,2 àå 4 áúéí áìáã
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_îöôä ì$ENDIF áäâãøä $1 $2 äðîöàú á$3 ùåøä $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_ùâéàú úçáéø áòú ðéúåç îùôè úðàé
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_äòøëú îùôè úðàé
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_úåëï äî÷øå îåâáì ìàåøê ùì 255 úååéí
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF ììà IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_äâãøú îùúîù: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_äâãøú îùúîù: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_äâãøú îùúîù: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_äâãøú îùúîù: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_äâãøú îùúîù: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_äâãøú îùúîù: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_îéìú îôúç äîåâãøú îçãù ëî÷øå àéðä îëéìä äùôòä
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_âìéùú îàâø î÷øå áòú ÷øéàä àå äøçáä ùì î÷øå
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_deep_ten=02030_W_äøçáú î÷øå âåìùú îòåî÷ ùì 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_ îúâé ôòåìú îäãø àéðí ðúîëéí áäòøåú îñåâ //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_îèôì áîúâ "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ðîöà ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_ðîöà IFDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_ðîöà IFOPT $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_ðîöà IF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_ðîöà IFNDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ðîöà ELSE $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_îãìâ...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_ìçõ òì <return> ìäîùéê
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_îúâ "$1" àéðå ðúîê
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_äåøàú äîäãø "$1" àéðä çå÷éú
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_çæøä á$1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_àéï úîéëä ìñåâ äàôìé÷öéä: "$1"
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE àéðå ðúîê ò"é ääîòøëú äôòìä äîáå÷ùú
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION àéðå ðúîê ò"é îòøëú ääôòìä äîáå÷ùú
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION àéðå ðúîê ò"é îòøëú äôòìä äîáå÷ùú
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION ø÷ ì÷áöé exe àå DLL
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_ôåøîè ùâåé ìäåøàú VERSION: "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_ñâðåï äàñîáìø ùöåééï "$1" àéðå çå÷é
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_îúâ ÷åøà äASM àéðå àôùøé áúåê îùôè àñîáìé. "$1" éäéä éùôéò ø÷ áäëøæä äáàä/
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_ùéîåù ùâåé áîúâ. äùúîù áON/OFF àå á +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_÷åáõ äîùàáéí àéðå ðúîê áéòã äðáçø
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_îùúðä äñáéáä "$1" ìà ðîöà áñáéáä
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_òøê ìà çå÷é ìäâáìåú àåâø äFPC
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_ø÷ ÷åáõ îùàáéí àçã ðúîê áéòã æä
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_äúîéëä áî÷øå ëåáä
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_äåëøæ ñåâ îîù÷ ìà çå÷é. äâãøåú çå÷éåú äí COM, CORBA àå DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID ðúîê ø÷ áPALMOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME ðúîê ø÷ áPALMOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_îçøåæú ÷áåòä ìà éëåìä ìäéåú îòì 255 úååéí
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_äåñôú ÷áöé äinclude âìù îòåî÷ ä16
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_éåúø îéãé ùëáåú PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP ììà ùçøåø ùì PUSH
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_î÷øå "$1" ìà îëéì òøëéí
+% Thus the conditional compiling expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_ùéîåù áîúâ ùâåé, äùúîù á ON/OFF/DEFAULT àå á+/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_îöá îúâ "$1" ìà îåøùä
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_îùúðä æîï äéãåø "$1" ìà äåâãø.
+% Thus the conditional compile time expression cannot be evaluated.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_îôøù - ùâéàä úçáéøéú
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_ôøåöãåøú ôñé÷ä àéðä éëåìä ìäéåú î÷åððú
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_îúòìí îñåâ ôøåöãåøä "$1"
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_ìà ëì ääëæøåú ùì "$1" áòìåú äëøæú OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_ëôéìåéåú áééöåà ùí äôåð÷öéä "$1"
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_ëôéìåéåú áééöåà àéðã÷ñ äôåð÷öéä "$1"
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_àéðã÷ñ ìà ú÷éï ìééöåà äôåð÷öéä
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_ùéðåé îé÷åí ðúåðé äðéôåé ìà òåáãéí ì÷áöé DLL àå ÷áöé äøöä. äúáèì.
+parser_w_parser_win32_debug_needs_WN=03012_W_ìàôùø ðéôåé ùâéàåú ìwin32 éù ìáèì àú ùéðåé äîé÷åí ò"é äàôùøåú -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_ùí éåöø çééá ìäéåú INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_ùí äåøñ çééá ìäéåú DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_ôøåöãåøú INLINE ìà ðúîëú
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_éåöø öøéê ìäéåú öéáåøé
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_äåøñ öøéê ìäéåú öéáåøé
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_îçì÷ä öøéëä äåøñ àçã áìáã
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_äâãøåú îçì÷ä î÷åîéåú àéðí îåøùåú
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_äâãøåú îçì÷ä àðåðéîéåú àéðí îåøùåú
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_äàåáéé÷è "$1" ììà VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_øùéîú ôøîèøéí ìà çå÷éú
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_öåééï îñôø ùâåé ùì ôøîèøéí
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_îæää äîøåáä ùéîåù "$1" àéðå ôåð÷öéä
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_ôåð÷öéåú îøåáåú ùéîåù îëéìåú àú àåúí øùéîú ôøîèøéí
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_äâãøú äôåð÷öéä àéðä úåàîú àú ääâãøä äî÷ãéîä "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_äâãøú äôåð÷öéä "$1" àéðä úåàîú àú äîéîåù: ùí îùúðä äùúðä $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_òøëéí áñåâ îðéä çééáéí ìäéåú áñãø òåìä
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With àéðå îñåâì ìäùúîù áîùúðéí îî÷èò ùåðä
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_ôåð÷öéä î÷åððú > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_ùâéàä ááãé÷ú èååç áòú äòøëú ÷áåòéí
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_ùâéàä ááãé÷ú èååç áòú äòøëú ÷áåòéí
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_äëæøú úååéú ëôåìä ácase
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_äèååç äñåôé ÷èï îäèååç ääúçìúé
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_äëøæú èéôåñ ÷áåòéí ùì îçì÷åú àñåøä
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_îùúðéí ùì ôåð÷öéåú îøåáåú ùéîåù àéðí îåøùåú
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_àåøê îçøåæú çééá ìäéåú òí òøëéí î1 ì255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_äùúîù áúçáéø îåøçá ùì NEW åDISPOSE ìòåú÷éí ùì àåáéé÷è
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_äùéîåù áîöáéò ìà îåâãø òí NEW å DISPOSE çñø îùîòåú
+parser_e_no_new_dispose_on_void_pointers=03044_E_áìúé àôùøé ìäùúîù áîöáéò ìà îåâãø òí NEW àå DISPOSE
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_îöôä ìîæää îçì÷ä
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_ñåâ îæää ìà îåøùä áîé÷åí äðåëçé
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_îöôä ìîæää îúåãé
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_äâãøú äôåð÷öéä ìà æää ìîúåãåú ùì äîçì÷ä "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_ôøåöãåøä/ôåð÷öéä $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_÷áåò ùì îñôø îîùé àéðå çå÷é
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL éëåì ìäéåú áùéîåù ø÷ áúåê éåöø
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_äåøñéí ìà éëåìéí ìäëéì ôøîèøéí
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_ø÷ îúåãåú îçì÷ä éëåìåú ìäéåú îåâãøåú áäúééçñåú îçì÷ä
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_ø÷ îúåãú îçì÷ä éëåìä ìâùú ìîúåãú îçì÷ä
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_÷áåòéí åñåâ CASE àéðí îúàéîéí
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_ìà ðéúï ìééöà àú äñîì îñôøééä
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_îúåãú éøåùä ðñúøú ò"é "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_àéï îúåãä áîçì÷ä ùì äàá àùø ðéúï ìùëúá: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_ìà ðéúï îñôø ìâùú ìîàôééï
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_îàôééï ùîåø àéðå îáåöò òãééï
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_ñéîï ìà çå÷é ìâéùú äîàôééï
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_ìà ðéúï ìâùú ìùãä îåâï áàåáéé÷è äðåëçé
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_ìà ðéúï ìâùú ìùãä ôøèé áàåá÷ééè äðåëçé
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_îúåãä îøåáú ùéîåù çééáú ìäéåú æää áñåâ äîùúðä: "$2" áùéîåù ò"é "$1", àùø îëéìä ñåâ îùúðä àçø
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_äâããøú ôåð÷öéåú EXPORT ìà éëåìåú ìäéåú î÷åððåú
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_àé àôùø ìééöà àú äîúåãä
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_äùéîåù áôøîèø ùì îùúðä çééá ìäéåú æää: îëéì "$1" îöôä ì"$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_äîçì÷ä àéððä îçì÷ú àá ùì äîçì÷ä äðåëçéú
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF îåøùä ø÷ áîúåãåú
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_îúåãåú éëåìåú ìäé÷øà éùéøåú ø÷ áúåê îúåãåú àçøåú òí ñåâ îæää ùìäîçì÷ä
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_ùéîåù ìà çå÷é ùì ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_ùâéàä ááãé÷ú èååç áñãøú éåöøéí àå ùëôåì ñãøä
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_îöôä ìîöáéò àåáéé÷è
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_äáéèåé çééá ìäéåú ÷øéàú éåöø
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_äáéèåé çééá ìäéåú ÷øéàú äåøñ
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_ñãø ìà çå÷é ùì àìîðèéí áøùåîä
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_ñåâ áéèåé çééá ìäéåú áéèåé øùåîä àå îçì÷ä
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_ôøåöãåøä ìà éëåìä ìäçæéø òøê
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_äéåöøéí åääåøñéí çééáéí ìäéåú îúåãééí
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_äàåôøéèåø ìà îøåáä ùéîåù
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_ìà ðéúï ìäöéá òøëéí ìñåâéí îøåáé ùéîåù
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_áìúé àôùøé ìäùúîù áàåôøèåø îøåáä ùéîåù
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_ìà ðéúï ìäøéí çøéâä
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_äúçáéø äîåøçá ùì NEW àå DISPOSE ìà îåøùä ìîçì÷åú
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_äàôùøåú ìôøåöãåøåú îøåáåú ùéîåù ëáåé
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_It is not possible to overload this operator (overload = instead)
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Comparative operator must return a boolean value
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Only virtual methods can be abstract
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Use of unsupported feature!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_The mix of different kind of objects (class, object, interface, etc) isn't allowed
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Unknown procedure directive had to be ignored: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute can only be associated to one variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute can only be associated with a var or const
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Only one variable can be initialized
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Abstract methods shouldn't have any definition (with function body)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_This overloaded function can't be local (must be exported)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Virtual methods are used without a constructor in "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro defined: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro undefined: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 set to $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compiling $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsing interface of unit $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parsing implementation of $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compiling $1 for the second time
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No property found to override
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Only one default property is allowed
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_The default property must be an array property
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtual constructors are only supported in class object model
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No default property available
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_The class can't have a published section, use the {$M+} switch
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Forward declaration of class "$1" must be resolved here to use the class as ancestor
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Local operators not supported
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Procedure directive "$1" not allowed in interface section
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Procedure directive "$1" not allowed in implementation section
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Procedure directive "$1" not allowed in procvar declaration
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Function is already declared Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Can't use both EXPORT and EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" not yet supported inside inline procedure/function
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining disabled
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Writing Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_may be pointer dereference is missing
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Selected assembler reader not supported
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Procedure directive "$1" has conflicts with other directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Calling convention doesn't match forward
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Property can't have a default value
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_The default value of a property must be constant
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol can't be published, can be only a class
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_That kind of property can't be published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_An import name is required
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Division by zero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Invalid floating point operation
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Upper bound of range is less than lower bound
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_string "$1" is longer than "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_string length is larger than array of char length
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Illegal expression after message directive
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Message handlers can take only one call by ref. parameter
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Duplicate message label: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self can only be an explicit parameter in methods which are message handlers
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars can be only static or global
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Direct assembler not supported for binary output format
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Don't load OBJPAS unit manually, use \{\$mode objfpc\} or \{\$mode delphi\} instead
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE can't be used in objects
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Data types which require initialization/finalization can't be used in variant records
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings can be only static or global
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit with argument can't be used here
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_The type of the storage symbol must be boolean
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_This symbol isn't allowed as storage symbol
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Only class which are compiled in $M+ mode can be published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Procedure directive expected
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_The value for a property index must be of an ordinal type
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Procedure name to short to be exported
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No DEFFILE entry can be generated for unit global vars
+parser_e_dlltool_unit_var_problem2=03161_E_Compile without -WD option
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_You need ObjFpc (-S2) or Delphi (-Sd) mode to compile this module
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Can't export with index under $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exporting of variables is not supported under $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Improper GUID syntax
+parser_w_interface_mapping_notfound=03168_W_Procedure named "$1" not found that is suitable for implementing the $2.$3
+parser_e_interface_id_expected=03169_E_interface identifier expected
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Type "$1" can't be used as array index type
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Con- and destructors aren't allowed in interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Access specifiers can't be used in INTERFACES
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_An interface can't contain fields
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Can't declare local procedure as EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Some fields coming before "$1" weren't initialized
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Some fields coming before "$1" weren't initialized
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Some fields coming after "$1" weren't initialized
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_VarArgs directive without CDecl and External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self must be a normal (call-by-value) parameter
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interface "$1" has no interface identification
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Unknown class field or method identifier "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Overriding calling convention "$1" with "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Typed constants of the type "procedure of object" can only be initialized with NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Default value can only be assigned to one parameter
+parser_e_default_value_expected_for_para=03185_E_Default parameter required for "$1"
+parser_w_unsupported_feature=03186_W_Use of unsupported feature!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C arrays are passed by reference
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_C array of const must be the last argument
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Type "$1" redefinition
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_cdecl'ared functions have no high parameter
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_cdecl'ared functions do not support open strings
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Cannot initialize variables declared as threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Message directive is only allowed in Classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure or Function expected
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Calling convention directive ignored: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE can't be used in objects
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Each argument must have it's own location
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Each argument must have an explicit location
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Unknown argument location
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32 Bit-Integer or pointer variable expected
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Goto statements aren't allowed between different procedures
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure too complex, it requires too much registers
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Illegal expression
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Invalid integer expression
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Illegal qualifier
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_High range limit < low range limit
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Exit's parameter must be the name of the procedure it is used in
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Illegal assignment to for-loop variable "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Can't declare local variable as EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procedure is already declared EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Implicit uses of Variants unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Class and static methods can't be used in INTERFACES
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_âìéùä áôòåìä îúîèéú
+% An operation on two integers values produced an overflow
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Type mismatch
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Incompatible types: got "$1" expected "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Type mismatch between "$1" and "$2"
+% The types are not equal
+type_e_type_id_expected=04003_E_Type identifier expected
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variable identifier expected
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Integer expression expected, but got "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Boolean expression expected, but got "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Ordinal expression expected
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_pointer type expected, but got "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_class type expected, but got "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Can't evaluate constant expression
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Set elements are not compatible
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operation not implemented for sets
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Automatic type conversion from floating type to COMP which is an integer type
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_use DIV instead to get an integer result
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_string types doesn't match, because of $V+ mode
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_succ or pred on enums with assignments not possible
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Can't read or write variables of this type
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Can't use readln or writeln on typed file
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Can't use read or write on untyped file.
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Type conflict between set elements
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) returns the upper/lower word/dword
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Integer or real expression expected
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Wrong type "$1" in array constructor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Incompatible type for arg no. $1: Got "$2", expected "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Method (variable) and Procedure (variable) are not compatible
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Illegal constant passed to internal math function
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Can't get the address of constants
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Argument can't be assigned to
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Can't assign local procedure/function to procedure variable
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Can't assign values to an address
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Can't assign values to const variable
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Array type required
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_interface type expected, but got "$1"
+type_w_mixed_signed_unsigned=04035_W_Mixing signed expressions and longwords gives a 64bit result
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mixing signed expressions and cardinals here may cause a range check error
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast has different size ($1 -> $2) in assignment
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enums with assignments can't be used as array index
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Class or Object types "$1" and "$2" are not related
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Class types "$1" and "$2" are not related
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Class or interface type expected, but got "$1"
+type_e_type_is_not_completly_defined=04042_E_Type "$1" is not completely defined
+type_w_string_too_long=04043_W_String literal has more characters than short string length
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_Comparison is always false due to range of values
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_Comparison is always true due to range of values
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Constructing a class "$1" with abstract methods
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_The left operand of the IN operator should be byte sized
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Type size mismatch, possible loss of data / range check error
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Type size mismatch, possible loss of data / range check error
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_The address of an abstract method can't be taken
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_The operator is not applicable for the operand type
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Constant Expression expected
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operation "$1" not supported for types "$2" and "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Illegal type conversion: "$1" to "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Conversion between ordinals and pointers is not portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Conversion between ordinals and pointers is not portable
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Can't determine which overloaded function to call
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Illegal counter variable
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identifier not found "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Internal Error in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Duplicate identifier "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identifier already defined in $1 at line $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Unknown identifier "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Forward declaration not solved "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Error in type definition
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward type not resolved "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Only static variables can be used in static methods or outside methods
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_record or class type expected
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instances of classes or objects with an abstract method are not allowed
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label not defined "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label used but not defined "$1"
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Illegal label declaration
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO and LABEL are not supported (use switch -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label not found
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_identifier isn't a label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_label already defined
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_illegal type declaration of set elements
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward class definition not resolved "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unit "$1" not used in $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter "$1" not used
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Local variable "$1" not used
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Value parameter "$1" is assigned but never used
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Local variable "$1" is assigned but never used
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Local $1 "$2" is not used
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Private field "$1.$2" is never used
+sym_n_private_identifier_only_set=05030_N_Private field "$1.$2" is assigned but never used
+sym_n_private_method_not_used=05031_N_Private method "$1.$2" never used
+sym_e_set_expected=05032_E_Set type expected
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Function result does not seem to be set
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type "$1" is not aligned correctly in current record for C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Unknown record field identifier "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Local variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_Variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_identifier idents no member "$1"
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Found declaration: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Data element too large
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_No matching implementation for interface method "$1" found
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" is deprecated
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbol "$1" is not portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" is not implemented
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Can't create unique type from this type
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+% \end{description}
+sym_h_uninitialized_local_variable=05057_H_Local variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Parameter list size exceeds 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_File types must be var parameters
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_The use of a far pointer isn't allowed there
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possible illegal call of constructor or destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Inefficient code
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_unreachable code
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstract methods can't be called directly
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 weight $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stack frame is omitted
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Object or class methods can't be inline.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar calls cannot be inline.
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No code for inline procedure stored
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Element zero of an ansi/wide- or longstring can't be accessed, use (set)length instead
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors or destructors can not be called inside a 'with' clause
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Cannot call message handler methods directly
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Jump in or outside of an exception block
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Control flow statements aren't allowed in a finally block
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Parameters size exceeds limit for certain cpu's
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Local variable size exceed limit for certain cpu's
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Local variables size exceeds supported limit
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK not allowed
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE not allowed
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Starting $1 styled assembler parsing
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finished $1 styled assembler parsing
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Non-label pattern contains @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Error building record offset
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET used without identifier
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE used without identifier
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Cannot use local variable or parameters here
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_need to use OFFSET here
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_need to use $ here
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Cannot use multiple relocatable symbols
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Relocatable symbol can only be added
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Invalid constant expression
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Relocatable symbol is not allowed
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Invalid reference syntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_You can not reach $1 from that code
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Local symbols/labels aren't allowed as references
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Invalid base and index register usage
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Possible error in object field handling
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Wrong scale factor specified
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Multiple index register usage
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Invalid operand type
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Invalid string as opcode operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE and @DATA not supported
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label references are not allowed
+asmr_e_expr_zero_divide=07025_E_Divide by zero in asm evaluator
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Illegal expression
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_escape sequence ignored: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Invalid symbol reference
+asmr_w_fwait_emu_prob=07029_W_Fwait can cause emulation problems with emu387
+asmr_w_fadd_to_faddp=07030_W_$1 without operand translated into $1P
+asmr_w_enter_not_supported_by_linux=07031_W_ENTER instruction is not supported by Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Calling an overload function in assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Unsupported symbol type for operand
+asmr_e_constant_out_of_bounds=07034_E_Constant value out of bounds
+asmr_e_error_converting_decimal=07035_E_Error converting decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Error converting octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Error converting binary $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error converting hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 translated to $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 is associated to an overloaded function
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Cannot use SELF outside a method
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Cannot use OLDEBP outside a nested procedure
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedures can't return any value in asm code
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG not supported
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Size suffix and destination or source size do not match
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Size suffix and destination or source size do not match
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Assembler syntax error
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Invalid combination of opcode and operands
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Assembler syntax error in operand
+asmr_e_syn_constant=07050_E_Assembler syntax error in constant
+asmr_e_invalid_string_expression=07051_E_Invalid String expression
+asmr_w_const32bit_for_address=07052_W_constant with symbol $1 for address which is not on a pointer
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Unrecognized opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Invalid or missing opcode
+asmr_e_invalid_prefix_and_opcode=07055_E_Invalid combination of prefix and opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Invalid combination of override and opcode: $1
+asmr_e_too_many_operands=07057_E_Too many operands on line
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignored
+asmr_w_far_ignored=07059_W_FAR ignored
+asmr_e_dup_local_sym=07060_E_Duplicate local symbol $1
+asmr_e_unknown_local_sym=07061_E_Undefined local symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unknown label identifier $1
+asmr_e_invalid_register=07063_E_Invalid register name
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Invalid floating point register name
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo not supported
+asmr_e_invalid_float_const=07067_E_Invalid floating point constant $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Invalid floating point expression
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Wrong symbol type
+asmr_e_cannot_index_relative_var=07070_E_Cannot index a local var or parameter with a register
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings not allowed as constants
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_No type of variable specified
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_assembler code not returned to text section
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Not a directive or local symbol $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Using a defined name as a local label
+asmr_e_dollar_without_identifier=07078_E_Dollar token is used without an identifier
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bit constant created for address
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align is target specific, use .balign or .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Can't access fields directly for parameters
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Can't access fields of objects/classes directly
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No size specified and unable to determine the size of the operands
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Cannot use RESULT in this function
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" without operand translated into "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" translated into "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" translated into "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Char < not allowed here
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Char > not allowed here
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN not supported
+asmr_e_no_inc_and_dec_together=07094_E_Inc and Dec cannot be together
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Invalid reglist for movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Reglist invalid for opcode
+asmr_e_higher_cpu_mode_required=07097_E_Higher cpu mode required ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No size specified and unable to determine the size of the operands, using DWORD as default
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Syntax error while trying to parse a shifter operand
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Too many assembler files
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Selected assembler output not supported
+asmw_f_comp_not_supported=08002_F_Comp not supported
+asmw_f_direct_not_supported=08003_F_Direct not support for binary writers
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Allocating of data is only allowed in bss section
+asmw_f_no_binary_writer_selected=08005_F_No binary writer selected
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 not in table
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 invalid combination of opcode and operands
+asmw_e_16bit_not_supported=08008_E_Asm: 16 Bit references not supported
+asmw_e_invalid_effective_address=08009_E_Asm: Invalid effective address
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 value exceeds bounds $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Short jump is out of range $1
+asmw_e_undefined_label=08013_E_Asm: Undefined label $1
+asmw_e_comp_not_supported=08014_E_Asm: Comp type not supported for this target
+asmw_e_extended_not_supported=08015_E_Asm: Extended type not supported for this target
+asmw_e_duplicate_label=08016_E_Asm: Duplicate label $1
+asmw_e_redefined_label=08017_E_Asm: Redefined label $1
+asmw_e_first_defined_label=08018_E_Asm: First defined here
+asmw_e_invalid_register=08019_E_Asm: Invalid register $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Source operating system redefined
+exec_i_assembling_pipe=09001_I_Assembling (pipe) $1
+exec_d_cant_create_asmfile=09002_E_Can't create assember file: $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Can't create object file: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Can't create archive file: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 not found, switching to external assembling
+exec_t_using_assembler=09006_T_Using assembler: $1
+exec_e_error_while_assembling=09007_E_Error while assembling exitcode $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Can't call the assembler, error $1 switching to external assembling
+exec_i_assembling=09009_I_Assembling $1
+exec_i_assembling_smart=09010_I_Assembling with smartlinking $1
+exec_w_objfile_not_found=09011_W_Object $1 not found, Linking may fail !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Library $1 not found, Linking may fail !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Error while linking
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Can't call the linker, switching to external linking
+exec_i_linking=09015_I_Linking $1
+exec_e_util_not_found=09016_E_Util $1 not found, switching to external linking
+exec_t_using_util=09017_T_Using util $1
+exec_e_exe_not_supported=09018_E_Creation of Executables not supported
+exec_e_dll_not_supported=09019_E_Creation of Dynamic/Shared Libraries not supported
+exec_i_closing_script=09020_I_Closing script $1
+exec_e_res_not_found=09021_E_resource compiler not found, switching to external mode
+exec_i_compilingresource=09022_I_Compiling resource $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_unit $1 can't be statically linked, switching to smart linking
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_unit $1 can't be smart linked, switching to static linking
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_unit $1 can't be shared linked, switching to static linking
+exec_e_unit_not_smart_or_static_linkable=09026_E_unit $1 can't be smart or static linked
+exec_e_unit_not_shared_or_static_linkable=09027_E_unit $1 can't be shared or static linked
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_Can't post process executable $1
+execinfo_f_cant_open_executable=09029_F_Can't open executable $1
+execinfo_x_codesize=09030_X_Size of Code: $1 bytes
+execinfo_x_initdatasize=09031_X_Size of initialized data: $1 bytes
+execinfo_x_uninitdatasize=09032_X_Size of uninitialized data: $1 bytes
+execinfo_x_stackreserve=09033_X_Stack space reserved: $1 bytes
+execinfo_x_stackcommit=09034_X_Stack space commited: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Unitsearch: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU Loading $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Name: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Flags: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU Crc: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Time: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_PPU File too short
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_PPU Invalid Header (no PPU at the begin)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_PPU Invalid Version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU is compiled for another processor
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU is compiled for an other target
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU Source: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Writing $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Can't Write PPU-File
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Error reading PPU-File
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_unexpected end of PPU-File
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Invalid PPU-File entry: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx count problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Illegal unit name: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Too much units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Circular unit reference between $1 and $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Can't compile unit $1, no sources available
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Can't find unit $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_Unit $1 was not found but $2 exists
+unit_f_unit_name_error=10024_F_Unit $1 searched but $2 found
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compiling the system unit requires the -Us switch
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_There were $1 errors compiling module, stopping
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Load from $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompiling $1, checksum changed for $2
+unit_u_recompile_source_found_alone=10029_U_Recompiling $1, source found only
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompiling unit, static lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompiling unit, shared lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompiling unit, obj and asm are older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompiling unit, obj is older than asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Parsing interface of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Parsing implementation of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Second load for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU Check file $1 time $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Can't recompile unit $1, but found modifed include files
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_File $1 is newer than Release PPU file $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Using a unit which was not compiled with correct FPU mode
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Loading interface units from $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Loading implementation units from $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Interface CRC changed for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Implementation CRC changed for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Finished compiling unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Add dependency of $1 to $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_No reload, is caller: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_No reload, already in second compile: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Flag for reload: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Forced reloading
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Previous state of $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Already compiling $1, setting second compile
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Loading unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Finished loading unit $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registering new unit $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-resolving unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Skipping re-resolving unit $1, still loading used units
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Only one source file supported
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF file can be created only for OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_nested response files are not supported
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_No source file name in command line
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No option inside $1 config file
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Illegal parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? writes help pages
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Too many config files nested
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Unable to open file $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Reading further options from $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Target is already set to: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Shared libs not supported on DOS platform, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_too many IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_too many ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_open conditional at the end of the file
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Debug information generation is not supported by this executable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Try recompiling with -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_You are using the obsolete switch $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_You are using the obsolete switch $1, please use $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Switching assembler to default source writing assembler
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Assembler output selected "$1" is not compatible with "$2"
+option_asm_forced=11022_W_"$1" assembler use forced
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Reading options from file $1
+% Options are also read from this file
+option_using_env=11027_T_Reading options from environment $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Handling option "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** press enter ***
+option_start_reading_configfile=11030_H_Start of reading config file $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_End of reading config file $1
+% End of config file parsing.
+option_interpreting_option=11032_D_interpreting option "$1"
+option_interpreting_firstpass_option=11036_D_interpreting firstpass option "$1"
+option_interpreting_file_option=11033_D_interpreting file option "$1"
+option_read_config_file=11034_D_Reading config file "$1"
+option_found_file=11035_D_found source file name "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Unknown code page
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2005 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVERSION
+
+Compiler Date : $FPCDATE
+Compiler CPU Target: $FPCCPU
+
+Supported targets:
+ $OSTARGETS
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs,suggestions etc to:
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_put + after a boolean switch option to enable it, - to disable it
+**1a_the compiler doesn't delete the generated assembler file
+**2al_list sourcecode lines in assembler file
+**2an_list node info in assembler file
+*L2ap_use pipes instead of creating temporary assembler files
+**2ar_list register allocation/release info in assembler file
+**2at_list temp allocation/release info in assembler file
+**1A<x>_output format:
+**2Adefault_use default assembler
+3*2Aas_assemble using GNU AS
+3*2Anasmcoff_coff (Go32v2) file using Nasm
+3*2Anasmelf_elf32 (Linux) file using Nasm
+3*2Anasmwin32_Win32 object file using Nasm
+3*2Anasmwdosx_Win32/WDOSX object file using Nasm
+3*2Awasm_obj file using Wasm (Watcom)
+3*2Anasmobj_obj file using Nasm
+3*2Amasm_obj file using Masm (Microsoft)
+3*2Atasm_obj file using Tasm (Borland)
+3*2Aelf_elf32 (Linux) using internal writer
+3*2Acoff_coff (Go32v2) using internal writer
+3*2Apecoff_pecoff (Win32) using internal writer
+4*2Aas_assemble using GNU AS
+6*2Aas_Unix o-file using GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola assembler
+A*2Aas_assemble using GNU AS
+P*2Aas_assemble using GNU AS
+S*2Aas_assemble using GNU AS
+**1b_generate browser info
+**2bl_generate local symbol info
+**1B_build all modules
+**1C<x>_code generation options:
+**2Cc<x>_set default calling convention to <x>
+**2CD_create also dynamic library (not supported)
+**2Ce_Compilation with emulated floating point opcodes
+**2Cf<x>_Select fpu instruction set to use to <x>
+**2Cg_Generate PIC code
+**2Ch<n>_<n> bytes heap (between 1023 and 67107840)
+**2Ci_IO-checking
+**2Cn_omit linking stage
+**2Co_check overflow of integer operations
+**2Cr_range checking
+**2CR_verify object method call validity
+**2Cs<n>_set stack size to <n>
+**2Ct_stack checking
+**2CX_create also smartlinked library
+**1d<x>_defines the symbol <x>
+**1D_generate a DEF file
+**2Dd<x>_set description to <x>
+**2Dv<x>_set DLL version to <x>
+*O2Dw_PM application
+**1e<x>_set path to executable
+**1E_same as -Cn
+**1F<x>_set file names and paths:
+**2Fa<x>[,y]_for a program load first units <x> and [y] before uses is parsed
+**2Fc<x>_sets input codepage to <x>
+**2FD<x>_sets the directory where to search for compiler utilities
+**2Fe<x>_redirect error output to <x>
+**2FE<x>_set exe/unit output path to <x>
+**2Fi<x>_adds <x> to include path
+**2Fl<x>_adds <x> to library path
+**2FL<x>_uses <x> as dynamic linker
+**2Fo<x>_adds <x> to object path
+**2Fr<x>_load error message file <x>
+**2Fu<x>_adds <x> to unit path
+**2FU<x>_set unit output path to <x>, overrides -FE
+*g1g_generate debugger information:
+*g2gc_generate checks for pointers
+*g2gd_use dbx
+*g2gg_use gsym
+*g2gh_use heap trace unit (for memory leak debugging)
+*g2gl_use line info unit to show more info for backtraces
+*g2gv_generates programs tracable with valgrind
+*g2gw_generate dwarf debugging info
+**1i_information
+**2iD_return compiler date
+**2iV_return compiler version
+**2iSO_return compiler OS
+**2iSP_return compiler processor
+**2iTO_return target OS
+**2iTP_return target processor
+**1I<x>_adds <x> to include path
+**1k<x>_Pass <x> to the linker
+**1l_write logo
+**1M<x>_set language mode to <x>
+**2Mfpc_free pascal dialect (default)
+**2Mobjfpc_switch some Delphi 2 extensions on
+**2Mdelphi_tries to be Delphi compatible
+**2Mtp_tries to be TP/BP 7.0 compatible
+**2Mgpc_tries to be gpc compatible
+**2Mmacpas_tries to be compatible to the macintosh pascal dialects
+**1n_don't read the default config file
+**1o<x>_change the name of the executable produced to <x>
+**1O<x>_optimizations:
+3*2Og_generate smaller code
+3*2OG_generate faster code (default)
+**2Or_keep certain variables in registers
+3*2Ou_enable uncertain optimizations (see docs)
+3*2O1_level 1 optimizations (quick optimizations)
+3*2O2_level 2 optimizations (-O1 + slower optimizations)
+3*2O3_level 3 optimizations (-O2 repeatedly, max 5 times)
+3*2Op<x>_target processor:
+3*3Op1_set target processor to 386/486
+3*3Op2_set target processor to Pentium/PentiumMMX (tm)
+3*3Op3_set target processor to PPro/PII/c6x86/K6 (tm)
+6*2Og_generate smaller code
+6*2OG_generate faster code (default)
+6*2Ox_optimize maximum (still BUGGY!!!)
+6*2O0_set target processor to a MC68000
+6*2O2_set target processor to a MC68020+ (default)
+**1pg_generate profile code for gprof (defines FPC_PROFILE)
+**1R<x>_assembler reading style:
+**2Rdefault_use default assembler
+3*2Ratt_read AT&T style assembler
+3*2Rintel_read Intel style assembler
+6*2RMOT_read motorola style assembler
+**1S<x>_syntax options:
+**2S2_same as -Mobjfpc
+**2Sc_supports operators like C (*=,+=,/= and -=)
+**2Sa_include assertion code.
+**2Sd_same as -Mdelphi
+**2Se<x>_error options. <x> is a combination of the following:
+**3*_<n> : compiler stops after the <n> errors (default is 1)
+**3*_w : compiler stops also after warnings
+**3*_n : compiler stops also after notes
+**3*_h : compiler stops also after hints
+**2Sg_allow LABEL and GOTO
+**2Sh_Use ansistrings
+**2Si_support C++ styled INLINE
+**2SI<x>_set interface style to <x>
+**3SIcom_COM compatible interface (default)
+**3SIcorba_CORBA compatible interface
+**2Sm_support macros like C (global)
+**2So_same as -Mtp
+**2Sp_same as -Mgpc
+**2Ss_constructor name must be init (destructor must be done)
+**2St_allow static keyword in objects
+**1s_don't call assembler and linker
+**2sh_Generate script to link on host
+**2st_Generate script to link on target
+**2sr_Skip register allocation phase (use with -alr)
+**1T<x>_Target operating system:
+3*2Temx_OS/2 via EMX (including EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 of DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (not supported)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin and MacOS X on PowerPC
+P*2Tlinux_Linux on PowerPC
+P*2Tmacos_MacOS (classic) on PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_undefines the symbol <x>
+**1U_unit options:
+**2Un_don't check the unit name
+**2Ur_generate release unit files
+**2Us_compile a system unit
+**1v<x>_Be verbose. <x> is a combination of the following letters:
+**2*_e : Show errors (default) 0 : Show nothing (except errors)
+**2*_w : Show warnings u : Show unit info
+**2*_n : Show notes t : Show tried/used files
+**2*_h : Show hints c : Show conditionals
+**2*_i : Show general info d : Show debug info
+**2*_l : Show linenumbers r : Rhide/GCC compatibility mode
+**2*_a : Show everything x : Executable info (Win32 only)
+**2*_v : write fpcdebug.txt with p : Write tree.log with parse tree
+**2*_ lots of debugging info
+3*1W<x>_Win32-like target options
+3*2WB<x>_Set Image base to Hexadecimal <x> value
+3*2WC_Specify console type application
+3*2WD_Use DEFFILE to export functions of DLL or EXE
+3*2WF_Specify full-screen type application (OS/2 only)
+3*2WG_Specify graphic type application
+3*2WN_Do not generate relocation code (necessary for debugging)
+3*2WR_Generate relocation code
+P*2WC_Specify console type application (MacOS only)
+P*2WG_Specify graphic type application (MacOS only)
+P*2WT_Specify tool type application (MPW tool, MacOS only)
+**1X_executable options:
+**2Xc_pass --shared to the linker (Unix only)
+**2Xd_don't use standard library search path (needed for cross compile)
+**2XD_try to link units dynamic (defines FPC_LINK_DYNAMIC)
+**2XP<x>_prepend the binutils names with the prefix <x>
+**2Xr<x>_set library search path to <x> (needed for cross compile)
+**2Xs_strip all symbols from executable
+**2XS_try to link units static (default) (defines FPC_LINK_STATIC)
+**2Xt_link with static libraries (-static is passed to linker)
+**2XX_try to link units smart (defines FPC_LINK_SMART)
+**1*_
+**1?_shows this help
+**1h_shows this help without waiting
+]
+
+#
+# The End...
diff --git a/compiler/msg/errorn.msg b/compiler/msg/errorn.msg
new file mode 100644
index 0000000000..57136e56df
--- /dev/null
+++ b/compiler/msg/errorn.msg
@@ -0,0 +1,2454 @@
+%%% Reordering of msg/errorn.msg respective to msg/errore.msg
+%%% Contains all comments from msg/errorn.msg
+#
+# $Id: errorn.msg,v 1.6 2004/01/22 21:19:36 florian Exp $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1998-2000 by the Free Pascal Development team
+#
+# Dutch Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ linenumber
+# u_ used
+# t_ tried
+# m_ macro
+# p_ procedure
+# c_ conditional
+# d_ debug message
+# b_ display overloaded procedures
+# x_ executable informations
+#
+
+#
+# Enkele punten om bij het vertalen in het achterhoofd te houden:
+#
+# - "Methoden" wordt vaak foutief als "methodes" geschreven.
+# - "Typen" wordt vaak foutief als "types" geschreven.
+# - "Illegal" wordt niet met "illegaal" vertaald, maar met "ongeldig".
+# Illegaal betekent onwettig in het Nederlands.
+# - Zo wordt "execute" niet met "executeren" vertaalt maar met "uitvoeren".
+# Programma, hebt u nog een laatste wens voordat de trekker wordt
+# overgehaald?
+# - In het Nederlands schrijft men woorden vaker aan elkaar dan in het
+# Engels: "compiler switch" (2 woorden) wordt "compileroptie" (1 woord).
+# Let ook op voorvoegingen: "Interface and implementation names" wordt:
+# "Interface- en implementatienamen" (streepje!)
+# - Pas op met het vernederlandsen van Engelse woorden. Bijvoorbeeld
+# "identifieerder". Voor deze categorie woorden bestaat geen goede
+# vertaling. Iedereen die zo'n vernederlandsing ziet krijgt echter gelijk
+# een pijnscheut in zijn taalknobbel. Soms helpt een woordenboek, anders
+# is het beter om de engelse term te laten staan. Wat improvisatie helpt
+# soms ook, "symbool" is niet precies hetzelfde maar kan in dit geval
+# prima als vertaling gebruikt worden.
+
+#
+# General
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Gebruikte compiler: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Bronsysteem: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Doelsysteem: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Programmalocatie: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_Locatie units: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Locatie includes: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Locatie bibliotheken: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Locatie objectbestanden: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Regels gecompileerd, $2 sec.
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Geen geheugen meer vrij
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+% \end{description}
+#
+# Scanner
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+general_i_writingresourcefile=01010_I_Schrijven van resource string tabel bestand: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Schrijven van resource string tabel bestand: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+% \end{description}
+#
+# Scanner
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+general_i_fatal=01012_I_Fatale fout:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Fout:
+% Prefix for Errors
+general_i_warning=01014_I_Waarschuwing:
+% Prefix for Warnings
+general_i_note=01015_I_Noot:
+% Prefix for Notes
+general_i_hint=01016_I_Tip:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_Pad "$1" bestaat niet
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilatie afgebroken
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Onverwacht einde van bestand
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment wasn't closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String langer dan regel
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_ongeldig teken "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Taalfout: $2 verwacht in kolom $1
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Ingevoegd bestand $1 word geopend
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Commentaar van niveau $1 gevonden
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Genegeerde compileroptie $1
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Foutieve compileroptie $1
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% doesn't know.
+scan_w_switch_is_global=02010_W_Deze compileroptie heeft ook een globaal effect
+% When \var{-vw} is used, the compiler warns if a switch is global.
+scan_e_illegal_char_const=02011_E_Foutieve constante voor een karakter
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range. The range
+% is 1-255.
+scan_f_cannot_open_input=02012_F_Kan bestand "$1" niet openen
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Kan ingevoerd bestand niet openen $1
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Ongeldige alignatie-aanduiding voor records: "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Ongeldige enumeratie grootte aanduiding "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+scan_e_endif_expected=02017_E_$ENDIF verwacht voor $1 op $2 $3 lijn $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Taalfout bij het compileren van een conditionele compilatie uitdrukking
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_e_error_in_preproc_expr=02019_E_Evalueren van een conditionele compilatie uitdrukking
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Macro inhoud is afgekapt op 255 karakters voor evaluatie
+% The contents of macros cannot be longer than 255 characters. This is a
+% safety in the compiler, to prevent buffer overflows. This is shown as a
+% warning, i.e. when the \var{-vw} switch is used.
+scan_e_endif_without_if=02021_E_ENDIF zonder IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Gebruiker definitie: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Gebruiker definitie: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Gebruiker definitie: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Gebruiker definitie: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Gebruiker definitie: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Gebruiker definitie: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Sleutelwoord herdefinieren als macro heeft geen effect
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Macro buffer overflow bij lezen of expansie van macro
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Uitwerken van macros heeft niveau 16 overschreden
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Compiler opties in delphi commentaar stijl zijn niet ondersteund
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Behandel schakelaar "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 gevonden
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Negeer tot...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Druk <return> om verder te gaan
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Niet ondersteunde optie $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Ongeldige compiler optie $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Terug in $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+%
+%
+%
+scan_w_unsupported_app_type=02044_W_Niet ondersteund programmatype: $1
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_w_app_type_not_support=02045_W_$APPTYPE niet ondersteund op doelsysteem
+% The \var{\{\$APPTYPE\}} directive is supported by win32 applications only.
+scan_w_description_not_support=02046_W_DESCRIPTIION is niet ondersteund op het geselecteerde OS
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION is niet ondersteund door het doel OS.
+% The \var{\{\$VERSION\}} directive is only supported by win32 target.
+scan_n_only_exe_version=02048_N_VERSION kan alleen voor executables of bibliotheken
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_verkeerd formaat voor VERSION directive $1
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_e_illegal_asmmode_specifier=02050_E_Ongeldige assembler-stijl opgegeven: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM lezer-optie is niet mogelijk in een asm instructie, $1 ingesteld voor volgende blok
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Verkeerde optiewaarde, gebruik ON/OFF of +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Resource bestanden worden niet ondersteund op doel OS
+% The target you are compiling for doesn't support Resource files. The
+% only target which can use resource files is Win32
+%
+% \end{description}
+#
+# Parser
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+scan_w_include_env_not_found=02054_W_Include omgevingsvariabele $1 niet gevonden in omgeving
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Ongeldige waarde voor FPU register limiet
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+% \end{description}
+#
+# Parser
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+scan_w_only_one_resourcefile_supported=02056_W_Slechts 1 resource bestand ondersteund voor dit operating systeem.
+% The target you are compiling for supports only one resource file. This is the
+% case of OS/2 (EMX) currently. The first resource file found is used, the
+% others are discarded.
+% \end{description}
+#
+# Parser
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+scan_w_macro_support_turned_off=02057_W_Macro ondersteuning is uitgeschakeld
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_Ongeldig interface type opgegeven. Geldige waarden zijn COM, CORBA of DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID is slechts ondersteund op PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME is slechts ondersteund op PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Constante tekenreeksen (strings) kunnen niet langer dan 255 karakters zijn.
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Include bestanden kunnen maar tot op 16 niveaus genest worden
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Te veel PUSH niveaus
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP instructie zonder voorafgaande PUSH instructie
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro of compilatie-variabele "$1" heeft geen waarde
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Verkeerde schakel-waarde. Gebruik ON/OFF/DEFAULT of +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_MODE schakel "$1" is niet toegestaan op deze plaats.
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Macro of compilatie-variabele "$1" is niet gedefinieerd
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_UTF-8 code groter dan 65535 gevonden
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Ongeldige UTF-8 tekenreeks
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_UTF-8 handtekening gevonden, gebruik UTF-8 codering
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_Compilatie-expressie: "$1" gevraagd, maar kreeg "$2" op "$3"
+% Type check of a compile time expression failed.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Taalfout
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT procedures kunnen niet genest worden
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Procedure type $1 ignored
+% This is a warning. \var{REGISTER},\var{REINTRODUCE} is ignored by FPC programs for now.
+% This is introduced first for Delphi compatibility.
+parser_e_no_overload_for_all_procs=03006_E_Not all declarations of $1 are declared with OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Dubbel geexporteerde functienaam $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Dubbel geexporteerde functie index $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Ongeldige index for geexporteerde functie
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Relocatable bibliotheek of applicatie $1 debug informatie niet ondersteund.
+parser_w_parser_win32_debug_needs_WN=03012_W_Om win32 code te debuggen moet relocatie afgezet worden door de -WN optie
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Constructornaam moet INIT zijn
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destructornaam moet DONE zijn
+% You are declaring a constructor with a name which isn't \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Procedure type INLINE wordt niet ondersteund
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Constructor mag niet private or protected zijn
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destructor mag niet private or protected zijn
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasse heeft slechts 1 destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Lokale klassedefinities zijn niet toegestaan
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Anonieme klassedefinities zijn niet toegestaan
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_Het object "$1Ã" heeft geen VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Foutieve parameterlijst
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Onjuist aantal parameters meegegeven
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Overladen symbool "$1" is geen procedure of functie
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it isn't a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Overroepen procedures hebben identieke parameterlijst
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Declaratie komt niet overeen met eerdere declaratie: $1
+% You declared a function with same parameters but
+% different result type or function specifiers.
+parser_e_header_different_var_names=03030_E_Procedurehoofding $1 komt niet overeen met eerdere declaratie: variabelenaam veranderd $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Waarden in opsommingstypes moeten steeds stijgen
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With kan niet gebruikt worden voor variabelen in verschillende segmenten
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Procedure meer dan 31 keer genest
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Bereikfout bij evalueren constanten
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Bereikscontrolefout bij evalueren constantes.
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Dubbel case-element
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Bovengrens van casebereik is lager dan ondergrens
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Getypeerde constanten van klassen zijn niet toegestaan
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Procedurele variabelen van overroepen procedures zijn niet toegestaan
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_Stringlengte moet tussen 1 en 255 liggen
+% The length of a string in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+% (This is not true for \var{Longstrings} and \var{AnsiStrings}.
+parser_w_use_extended_syntax_for_objects=03042_W_Gebruik de uitgebreide syntax van DISPOSE en NEW om nieuwe instanties van klassen te genereren
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_Het gebruik van NEW of DISPOSE voor pointers zonder type is zinloos
+parser_e_no_new_dispose_on_void_pointers=03044_E_Het gebruik van NEW of DISPOSE is niet mogelijk voor pointers zonder type
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Klasse verwacht
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Typesymbool is hier niet toegestaan
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Methode verwacht
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Proceduredeclaratie komt niet overeen met een methode van deze klasse $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procedure/functie $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Foutieve vlottende-komma constante
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL mag alleen in constructors gebruikt worden
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destructors hebben geen parameters
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Alleen klassemethoden kunnen gerefereerd worden via een klasse
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Alleen klassemethoden zijn toegankelijk in klassen
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Type van constante komt niet overeen met dat van de case uitrukking
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Het symbool kan niet uitgevoerd worden uit een bibliotheek
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Een virtuele methode moet met OVERRIDE overroepen worden: $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Er is geen geerfde methode die overroepen kan worden: $1
+% You try to \var{override} a virtual method of a parent class that doesn't
+% exist.
+parser_e_no_procedure_to_access_property=03059_E_Er is geen lid om de eigenschap te bereiken
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Stored prorperty directive is not yet implemented
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Ongeldig symbool voor eigenschaptoegang
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Kan niet in beschermd veld van een object schrijven
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Kan niet in prive-veld van een object schrijven
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Overridden methodes moeten dezelfde resultaat type hebben: "$2" wordt overridden door Ã"1$1" met een ander type
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Als EXPORT gedeclareerde procedures kunnen niet genest worden
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Methoden kunnen niet geexporteerd worden.
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Typen van referentieparameters moeten exact overeenkomen. "$1" gekregen, "$2" verwacht.
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Deze klasse is geen ouderklasse van de huidige klasse
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF is alleen toegelaten in methoden.
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Methoden kunnen alleen in andere methoden worden aangeroepen met type symbool
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Ongeldig gebruik van ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Bereikfout in setconstructor of dubbel setelement
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Pointer naar klasse verwacht
+% You specified an illegal type in a \var{New} statement.
+% The extended synax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Uitdrukking moet een constructoraanroep zijn.
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Uitdrukking moet een destructoraanroep zijn
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Ongeldige volgorde van record leden
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Type van uitdrukking moet class of record type zijn
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedures kunnen geen resultaat teruggeven
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Constructors en destructors moeten methoden zijn
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator is niet hergedefineerd
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Het is niet toegestaan de toewijzingsoperator te overroepen voor gelijke typen
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Het overroepen van deze operator is onmogelijk
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-raise is hier niet mogelijk
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_De uitgebreide syntax van NEW of DISPOSE is niet toegestaan voor klassen
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Procedure overroepen is afgezet
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Deze operator kan niet overroepen worden.
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Vergelijkingsoperator moet een boolean type als resultaat hebben.
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Enkel virtuele methoden kunnen abstract zijn
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Gebruik van niet ondersteunde functionaliteit!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_CLASSES and OBJECTS kunnen niet gemengd worden.
+% You cannot derive \var{objects} and \var{classes} intertwined . That is,
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Onbekende proceduredirective is genegeerd: $1
+% The procedure direcive you secified is unknown. Recognised procedure
+% directives are \var{cdecl}, \var{stdcall}, \var{popstack}, \var{pascal}
+% \var{register}, \var{export}.
+parser_e_absolute_only_one_var=03095_E_Absolute kan maar aan een variabele verbonden worden.
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute kan slechts aan variabelen of constanten verbonden worden.
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Slechts 1 variabele kan geinitialiseerd worden.
+% You cannot specify more than one variable with a initial value
+% in Delphi syntax.
+parser_e_abstract_no_definition=03098_E_Abtracte methoden kunnen niet gedefineerd worden
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Deze overroepen procedure kan niet lokaal zijn (moet geexporteerd worden)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Gebruik van virtuele methoden zonder constructor in "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro gedefinieerd: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro definitie verwijderd: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 heeft waarde $2 gekregen
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilatie van $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsen van de interface van unit $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parsen van de implementatie van unit $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilatie van $1 voor de tweede keer.
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Geen eigenschap gevonden om te herdefinieren
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Slechts 1 standaardeigenschap is toegestaan, geerfde standaardeigenschap in kind gevonden.
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Standaardeigenschappen moeten van type array zijn.
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtuele constructors worden alleen ondersteunt in het klassemodel
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Geen standaardeigenschap gevonden
+% You try to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_De klasse kan geen gepubliceerde sectie hebben, gebruik {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Declaratie van klasse $1 moet worden opgelost om de klasse als ouder te gebruiken
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokale operatoren worden niet ondersteund
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Procedure directive $1 niet toegestaan in interfacesectie
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Procedure directive $1 niet toegestaan in implementatiesectie
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Procedure directive $1 niet toegestaan in procvar declaratie
+% This procedure directive cannot be part of a procedural of function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Functie is al publiek/forward gedeclareerd $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Kan niet zowel EXPORT als EXTERNAL gebruiken
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_$1 wordt niet ondersteund voor inline procedure/functie
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining uitgeschakeld
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Schrijven van browser logfile $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_misschien is het een pointer, ^ ontbreekt dan
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Geselecteerde assemblerlezer wordt niet ondersteund
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Procedure directive $1 geeft conflicten met andere directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Aanroep conventie klopt niet met voorwaartse
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Eigenschap kan geen standaard waarde hebben
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_De standaard waarde van een eigenschap moet een constante zijn
+% The value of a \var{default} declared property must be knwon at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbool kan niet worden gepubliceerd, alleen mogelijk voor een klasse
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Dit soort eigenschappen kunnen niet worden gepubliceerd
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Lege importnaam opgegeven
+% Some targets need a name for the imported procedure or a cdecl specifier
+parser_e_division_by_zero=03138_E_Deling door nul
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Ongeldige vlottende-komma bewerking.
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Bovengrens van bereik is lager dan ondergrens
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_string "$1" is langer dan $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Stringlengte moet tussen 1 en 255 liggen
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Ongeldige uitdrukking achter message optie
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Message handlers aanvaarden slechts 1 variabele parameter
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Dubbel message label: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self kan alleen een explicite parameter zijn bij string message handlers
+% The self parameter can be passed only explicit if it is a method which
+% is declared as message method handler
+parser_e_threadvars_only_sg=03147_E_Threadvariabelen kunnen alleen globaal of statisch zijn
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Directe assemblercode wordt niet ondersteund door de interne assembler.
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Laad de OBJPAS unit niet manueel, gebruik {$mode objfpc} of {$mode delphi}.
+% You're trying to load the ObjPas unit manual from a uses clause. This is
+% not a good idea to do, you can better use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automaticly
+parser_e_no_object_override=03150_E_OVERRIDE kan niet gebruikt worden in objecten
+% Override isn't support for objects, use VIRTUAL instead to override
+% a method of an anchestor object
+parser_e_cant_use_inittable_here=03151_E_Datatypen die initializatie/finalizatie vereisen zijn niet toegestaan in variabele records.
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+% \end{description}
+#
+# Type Checking
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings kunnen alleen statisch of globaal zijn.
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit met parameter is hier niet toegestaan
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_De stored directive verwacht een boolean argument.
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Dit symbool is niet toegestaan achter het stored sleutelwoord.
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Alleen klassen gecompileerd in $M+ modus kunnen een published sectie hebben.
+% In the published section of a class can be only class as fields used which
+% are compiled in $M+ or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Proceduredirective verwacht.
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_De waarde voor een eigenschapindex moet een ordinale waarde zijn.
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Procedurenaam te kort om te exporteren.
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Kan geen DEFFILE item genereren voor globale variabelen.
+parser_e_dlltool_unit_var_problem2=03161_E_Compileer zonder -WD optie
+% \end{description}
+#
+# Type Checking
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+parser_f_need_objfpc_or_delphi_mode=03162_F_U moet OBJFPC (-S2) of DELPHI (-Sd) mode gebruiken om deze code te compileren
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Kan niet exporteren met indexen kleiner dan $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exporteren van variabelen is niet ondersteund op $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Ongeldige GUID aanduiding
+parser_w_interface_mapping_notfound=03168_W_PGeen procedure genaamd "$1Ã" om "$2.$3" te implementeren gevonden
+parser_e_interface_id_expected=03169_E_Interface aanduiding verwacht
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Type "$1" kan niet als array index type gebruikt worden
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Constructors and destructors zijn niet toegestaan in interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Toegangsmethoden kunnen niet gebruikt worden in interfaces
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Een interface definitie kan geen velden bevatten
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Can lokale procedure niet als EXTERNAL definieren
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Sommige velden voor "$1Ã" zijn niet geinitialiseerd
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Sommige velden voor "$1" zijn niet geinitialiseerd
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Sommige velden na "$1" zijn niet geinitialiseerd
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_VARARGS aanduiding zonder CDECL of EXTERNAL
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_SELF moet een normale waarde parameter zijn
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interface "$1" heeft geen interface definitie
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Ongekend klasse-veld of methode aanduiding "$1Ã"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Aanroep-modus "$1Ã" vervangen door "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Getypeerde constanten van type "procedure of object" kunnen alleen met NIL geinitialiseerd worden
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_De default aanduiding kan maar bij 1 parameter horen.
+parser_e_default_value_expected_for_para=03185_E_Default parameter vereist voor "$1"
+parser_w_unsupported_feature=03186_W_Gebruik van niet-ondersteunde mogelijkheden
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C arrays worden via referentie doorgegeven
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_"C array of const" moet het laatste argument zijn
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Type "$1Ã" herdefinitie
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_CDECL functies hebben geen HIGH parameter
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_CDECL functies ondersteunen geen open strings
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Kan THREADVAR variabelen niet initialiseren
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_de MESSAGE aanduiding is alleen toegestaan in classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure of functie verwacht
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Aanroep-specificatie genegeerd: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE kan niet in objecten worden gebruikt
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Elk argument moet zijn eigen locatie hebben
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Elk argument moet een expliciete locatie hebben
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Ongekende argument locatie
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32-bit integer of pointer variabele verwacht
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_GOTO opdrachten zijn niet toegestaan tussen verschillende procedures
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure te moeilijk, te veel registers vereist
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Ongeldige uitdrukking
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Ongeldige integer uitdrukking
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Ongeldige aanduiding
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Bovengrens kleiner dan ondergrens
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Exit parameter moet de naam zijn van de procedure waarin het gebruikt wordt
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Ongeldige toekenning aan lus-variabele "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Kan een locale variabele niet als EXTERNAL aanduiden
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_De procedure is reeds als EXTERNAL aangeduid
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Impliciet gebruik van de VARIANTS unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Class en statische methoden kunnen niet gebruikt worden in interfaces
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow in wiskundige berekening
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Protected of Private verwacht
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Typen stemmen niet overeen
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Incompatibele typen: kreeg $1, verwachtte $2
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Typen komen niet overeen $1 en $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Typesymbool verwacht
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variabelesymbool verwacht
+% This happens when you pass a constant to a \var{Inc} var or \var{Dec}
+% procedure. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Gehele uitdrukking verwacht, $1 gekregen
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Boolean waarde verwacht, kreeg echter "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Ordinale expressie verwacht
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Pointer type verwacht, "$1" gekregen
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Klasse type verwacht, "$1" gekregen
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Kan constante expressie niet evalueren
+% No longer in use.
+type_e_set_element_are_not_comp=04012_E_Elementen van set zijn niet compatible
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Bewerking niet ondersteund voor sets
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Typeconversie van vlottende-komma type naar COMP, wat een integer type is.
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Gebruik DIV voor gehele getallen om geheel resultaat te krijgen
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_String typen stemmen niet overeen wegens de $V+ modus
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_SUCC of PRED op enumeratietypen met toekenningen zijn niet mogelijk
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Kan dit type variabelen niet lezen of schrijven
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% booleans, reals, pchars and strings can be read from/written to a text file.
+type_e_no_readln_writeln_for_typed_file=04019_E_Kan geen readln of writeln op getypeerde bestanden doen.
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Kan geen read of write doen op ongetypeerde bestanden.
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Typeconflict tussen setelementen.
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(longint/dword) geeft hoog/laag (ipv byte) woord terug.
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword}
+% which returns the lower/upper word of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type case the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Integer of vlottende-komma uitdrukking verwacht
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Verkeerd type "$1" in array constructor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Incompatibel type voor argument #$1: kreeg $2, verwachtte $3
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Methode (variabele) en Procedure (variable) zijn niet compatible
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Ongeldige constante opgegeven aan interne wiskundige functie
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Een constante heeft geen adres
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+% \end{description}
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+type_e_argument_cant_be_assigned=04029_E_Kan geen waarde toekennen aan argument
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Kan geen lokale procedure toekennen aan procedure variabele
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Kan geen waarde toekennen aan een adres
+% It's not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Kan geen waarde toekennen aan constante
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing make the parameter value or var.
+% \end{description}
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+type_e_array_required=04033_E_ARRAY type verwacht
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Interface type verwacht, maar kreeg "$1"
+type_w_mixed_signed_unsigned=04035_W_Mengen van mogelijk negatieve uitdrukkingen en longwords geeft een 64-bits resultaat
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mengen van mogelijk negatieve uitdrukkingen en cardinals kan tot range check fouten leiden
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast heeft een verschillende grootte ($1 -> $2) in toekenning
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enumeratie typen met vaste waarden kunnen niet als array index gebruikt worden
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Klasse of object types "$1Ã" en "$2" zijn niet verwant
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Klasse types "$1" en "$2" zijn niet verwant
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Klasse of interface type verwacht, maar kreeg Ã"$1Ã"
+type_e_type_is_not_completly_defined=04042_E_Type "$1Ã" is niet volledig gedefinieerd
+type_w_string_too_long=04043_W_String constante heeft meer karakters dan de lengte van een shortstring
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_De vergelijking is steeds onwaar omwille van de interval waarden
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_e vergelijking is steeds waar omwille van de interval waarden
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Constructie van een klasse "$1" met abstracte methoden
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_De linker operand van de IN operator moet de grootte van een byte hebben
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Grootte-fout voor type, mogelijk verlies van gegevens/interval-check fout
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Grootte-fout voor type, mogelijk verlies van gegevens/interval-check fout
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Het adres van een abstracte methode kan niet opgevraagd worden
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_De operator kan niet gebruikt worden op dit type operand
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Constante uitdrukking verwacht
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operatie "$1" niet ondersteund voor types "$2" en "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Ongeldige type-conversie: "$1" naar "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Conversies tussen ordinalen en pointers is niet overzetbaar naar andere platformen
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Conversies tussen ordinalen en pointers is niet overzetbaar naar andere platformen
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Kan niet beslissen welke overladen functie te kiezen
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Ongeldige lus variabele
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Symbool niet gevonden $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Interne fout in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Dubbel symbool $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Symbool reeds gedefinieerd in $1 op lijn $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Onbekende symbool $1
+% The identifier encountered hasn't been declared, or is used outside the
+% scope where it's defined.
+sym_e_forward_not_resolved=05005_E_Voorwaartse declaratie niet opgelost $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Fout in type definitie
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward declaratie niet opgelost $1
+% The compiler encountered an unknown type.
+sym_e_only_static_in_static=05010_E_Alleen statische variabelen kunnen gebruikt worden in statische methoden
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Record- of klassetype verwacht
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_U kunt geen vertegenwoordiger van een klasse met abstracte methoden instantieren
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label niet gedefineerd $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label "$1" gebruikt maar niet gedefinieerd
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Label foutief gedefineerd
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO en LABEL zijn afgezet (gebruik -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label niet gevonden
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Symbool is geen label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label is al gedefineerd
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Type declaratie van set elementen is foutief
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Voorwaartse definitie van klasse niet opgelost $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Unit $1 wordt niet gebruikt in $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter niet gebruikt $1
+% This is a warning. The identifier was declared (locally or globally) but
+% wasn't used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokale variabele niet gebruikt $1
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Waarde parameter $1 is gedeclareerd maar niet gebruikt.
+% This is a warning. The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Lokale variabele $1 gedeclareerd maar niet gebruikt.
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Lokaal $1 $2 is niet gebruikt
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Privaat veld $1.$2 wordt niet gebruikt
+sym_n_private_identifier_only_set=05030_N_Privaat veld $1.$2 gedeclareerd maar niet gebruikt.
+sym_n_private_method_not_used=05031_N_Private methode $1.$2 wordt nooit gebruikt.
+
+
+sym_e_set_expected=05032_E_Set type verwacht
+% The variable or expression isn't of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Resultaat van functie lijkt niet te zijn toegekend
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type $1 is not aligned correctly in current record for C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Onbekend record lid $1
+% The field doesn't exist in the record definition.
+sym_w_uninitialized_local_variable=05036_W_Lokale variabele "$1" lijkt niet geinitialiseerd
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_okale variabele "$1" lijkt niet geinitialiseerd
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Geen lid met de naam $1
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the class you are trying to create. The procedure you specified
+% does not exist.
+sym_h_param_list=05039_H_NDeclaratie "$1" gevonden
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Data segment te groot (max. 2GB)
+% You get this when you declare an array whose size exceeds the 2GB limit.
+% \end{description}
+#
+# Codegenerator
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+sym_e_no_matching_implementation_found=05042_E_Geen overeenstemmende implementatie voor interface methode "$1" gevonden
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbool "$1Ã" is afgeraden
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbool "$1" is niet overzetbaar naar andere platformen
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbool "$1" is niet geimplementeerd
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Kan geen uniek type aanmaken van dit type
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_ Lokale variabele "$1" lijkt niet geinitialiseerd
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Lokale variabele "$1" lijkt niet geinitialiseerd
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Parameters gebruiken meer dan 64 kilobyte
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_File variabelen moeten altijd var parameters zijn
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_U kunt daar geen far pointer gebruiken
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Procedures die als EXPORT gedeclareerd staan kunnen niet aangeroepen worden
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Mogelijke ongeldige aanroep van constructor of destructor
+% No longer in use.
+cg_n_inefficient_code=06017_N_Inefficiente code
+% You construction seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Deze code wordt nooit uitgevoerd
+% You specified a loop which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstracte methoden kunnen niet direct aangeroepen worden
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 gewicht $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stackframe wordt niet gemaakt
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Kan inline niet gebruiken voor object methoden
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Kan inline niet gebruiken voor procvar aanroepen
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Geen code voor inline procedure opgeslagen
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Element nul van een ansi/wide- of longstring is niet toegankelijk, gebruik (set)length.
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors of destructors kunnen niet aangeroepen worden binnen een 'with' clausule
+% Inside a \var{With} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Een message handler methode kan niet direct aangeroepen worden.
+% A message method handler method can't be called directly if it contains an
+% explicit self argument
+% \end{description}
+# EndOfTeX
+#
+# Assembler reader
+#
+cg_e_goto_inout_of_exception_block=06039_E_Sprong in of uit een exception blok
+% It isn't allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+% \end{description}
+cg_e_control_flow_outside_finally=06040_E_Control flow statements niet toegestaan in een finally blok
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+# EndOfTeX
+cg_w_parasize_too_big=06041_W_Grootte van de parameters is te groot voor bepaalde CPUs
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Grootte van lokale variabelen is te groot voor sommige CPUs
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Lokale variabelen te groot
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK niet toegelaten
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE niet toegelaten
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Ongekende schakel-aanduiding "$1". Kijk na of u de correcte looptijd bibliotheek gebruikt
+% The compiler expects that the runtime library contains some subrountines. If you see this error
+% and you didn't mess with the runtime library, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Begonnen met verwerken van $1 assembler
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Gedaan met verwerken van $1 assembler
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Symbool dat geen label is bevat "@"
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Fout bij berekenen offset in record
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET gebruikt zonder symbool
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE gebruikt zonder symbool
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Kan hier geen lokale variabele of parameter gebruiken
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the %ebp register so the
+% address can't be get directly.
+asmr_e_need_offset=07008_E_OFFSET moet hier gebruikt worden
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Gebruik van $ is hier verplicht
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Kan niet meerdere verplaatsbare symbolen gebruiken
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Een verplaatsbaar symbool kan enkel toegevoegd worden
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Ongeldige constante uitdrukking
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Verplaatsbaar symbool niet toegelaten
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Ongeldige geheugenlocatie schrijfwijze
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_$1 niet bereikbaar vanuit deze code
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokale symbolen/labels niet toegestaan als referenties
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Ongeldig gebruik van basis en index register
+% There is an error with the base and index register
+asmr_w_possible_object_field_bug=07018_W_Mogelijke fout in behandeling velden van object.
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Ongeldige schaalfactor
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Meervoudig indexregister gebruik
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Ongeldig operandus type
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Ongeldige tekenreeks als instructie operandus: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE en @DATA worden niet ondersteund
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label verwijzingen zijn niet toegelaten
+asmr_e_expr_zero_divide=07025_E_Deling door nul
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Ongeldige uitdrukking
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Expliciete reeks genegeerd: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Ongeldige symboolverwijzing
+asmr_w_fwait_emu_prob=07029_W_Fwait kan emulatieproblemen met emu387 veroorzaken
+asmr_w_fadd_to_faddp=07030_W_$1 zonder operand vertaald naar $1P
+asmr_w_enter_not_supported_by_linux=07031_W_De ENTER instructie wordt niet ondersteund door de Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Een overroepen functie wordt aangeroepen vanuit assemblercode
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Niet ondersteund symbool type voor operandus
+asmr_e_constant_out_of_bounds=07034_E_Constante waarde valt buiten bereik
+asmr_e_error_converting_decimal=07035_E_Fout bij omzetten van decimaal getal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Fout bij omzetten van octaal getal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Fout bij omzetten van binair getal $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Fout bij omzetten van hexadecimaal getal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 vertaald naar $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 is geassocieerd met een overroepen functie
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Kan SELF niet buiten een methode gebruiken
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Kan OLDEBP niet buiten een genestelde procedure gebruiken
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Functies met een ongedefinieerde teruggeefwaarde kunnen geen waarde teruggeven
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG niet ondersteund
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Grootte-achtervoegsel en doel- of brongrootte komen niet overeen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Grootte-achtervoegsel en doel- of brongrootte komen niet overeen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Assembler taalfout
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Ongeldige combinatie van instructie en operandi
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Assembler taalfout in operandum
+asmr_e_syn_constant=07050_E_Assembler taalfout in constante
+asmr_e_invalid_string_expression=07051_E_Ongeldige String uitdrukking
+asmr_w_const32bit_for_address=07052_W_ Constante met symbool $1 voor adres dat zich niet op een pointer bevindt
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Ongekende opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Ongeldige of ontbrekende instructie
+asmr_e_invalid_prefix_and_opcode=07055_E_Ongeldige combinatie van voorvoegsel en instructie: $1
+asmr_e_invalid_override_and_opcode=07056_E_Ongeldige combinatie van segment overroeping en instructie: $1
+asmr_e_too_many_operands=07057_E_Te veel operandi op een lijn
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR genegeerd
+asmr_w_far_ignored=07059_W_FAR genegeerd
+asmr_e_dup_local_sym=07060_E_Dubbel lokaal symbool $1
+asmr_e_unknown_local_sym=07061_E_Niet gedefinieerd lokaal symbool $1
+asmr_e_unknown_label_identifier=07062_E_Onbekende labelnaam $1
+asmr_e_invalid_register=07063_E_Ongeldige register naam
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Ongeldig vlottende-komma registernaam
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo wordt niet ondersteund
+asmr_e_invalid_float_const=07067_E_Ongeldige vlottende-komma constante $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Ongeldige vlottende-komma uitdrukking
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Verkeerd symbool type
+asmr_e_cannot_index_relative_var=07070_E_Een lokale variabele of parameter kan niet geindedxeerd worden met een register
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Ongeldige segment overroeping
+asmr_w_id_supposed_external=07072_W_Symbool $1 wordt verondersteld extern te zijn
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings zijn niet toegelaten als constante
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Geen type van de variabele gegeven
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_De assembler code stopt niet in een '.text' gedeelte
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Geen aanwijzing of lokaal symbool $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Een gedfinieerde naam wordt gebruikt als assembler label
+
+#
+# Assembler/binary writers
+#
+asmr_e_dollar_without_identifier=07078_E_Dollar teken gebruikt zonder identifier
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bit constante aangemaakt voor adres
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align is doel specifiek, gebruik .balign of .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Kan velden niet direct gebruiken voor parameters.
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Kan velden van objecten/klassen niet direct aanspreken
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+#
+# Assembler/binary writers
+#
+asmr_e_unable_to_determine_reference_size=07083_E_Geen grootte aangegegeven en kan de grootte van de operanden niet bepalen
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Kan RESULT aanduiding niet gebruiken in deze functie
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1Ã" zonder operand vertaald naar "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" vertaald naar "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" vertaald naar "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Karakter < hier niet toegestaan
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Karakter > hier niet toegestaan
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN niet ondersteund
+asmr_e_no_inc_and_dec_together=07094_E_INC en DEC kunnen niet samengaan
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Ongeldige register lijst voor movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Ongeldige register lijst voor opcode
+asmr_e_higher_cpu_mode_required=07097_E_hogere CPU mode vereist ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Grootte niet opgegeven en kan de grootte van de operanden niet bepalen. De standaard DWORD wordt gebruikt
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Syntax fout bij het bepalen van een shift operand
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Te veel assemblerbestanden
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_De geselecteerde assembler modus wordt hier niet ondersteund
+asmw_f_comp_not_supported=08002_F_Het COMP type wordt hier niet ondersteund
+asmw_f_direct_not_supported=08003_F_Directe assembler modus wordt niet ondersteund door de binaire assemblerschrijver
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Ruimte voor gegevens reserveren mag enkel in een bss gedeelte
+asmw_f_no_binary_writer_selected=08005_F_Binaire assemblerschrijver geselecteerd
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 not gevonden in interne tabel
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 Ongeldige combinatie van instructie en operandi
+asmw_e_16bit_not_supported=08008_E_Asm: 16 Bit geheugenlocaties worden niet ondersteund
+asmw_e_invalid_effective_address=08009_E_Asm: Ongeldig direct adres
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Constante of geheugenadres verwacht
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 waarde overschrijdt grenzen van $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Korte spronginstructie gaat te ver $1
+
+#
+# Executing linker/assembler
+#
+asmw_e_undefined_label=08013_E_Asm: Ongedefinieerd label $1
+
+
+#
+# Executing linker/assembler
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+asmw_e_comp_not_supported=08014_E_Asm: COMP type niet ondersteund voor dit platfirl
+asmw_e_extended_not_supported=08015_E_Asm: EXTENDED type niet ondersteund voor dit platform
+asmw_e_duplicate_label=08016_E_Asm: Label dubbel gebruikt: $1
+asmw_e_redefined_label=08017_E_Asm: Label opnieuw gedefinieerd: $1
+asmw_e_first_defined_label=08018_E_Asm: eerste definitie hier
+asmw_e_invalid_register=08019_E_Asm: ongeldig register $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Bronbesturingssysteem geherdefinieerd
+exec_i_assembling_pipe=09001_I_Assembleren (pijp) van $1
+exec_d_cant_create_asmfile=09002_E_Kan geen assembler bestand $1 niet maken
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_objectfile=09003_E_Kan geen object bestand openen: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_archivefile=09004_E_kan geen archief bestand openen: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 niet gevonden. Schakel over op externe assemblage
+exec_t_using_assembler=09006_T_Gebruikte assembler: $1
+exec_e_error_while_assembling=09007_E_Fout bij het assembleren, exit code $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Kan de assembler niet oproepen, fout $1. Schakel over op externe assemblage
+exec_i_assembling=09009_I_Assembleren van $1
+exec_i_assembling_smart=09010_I_Assembleren slim-link $1
+exec_w_objfile_not_found=09011_W_Bestand $1 niet gevonden, linken kan foutlopen !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Bibliotheek $1 niet gevonden, linken kan foutlopen !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Fout bij het linken
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Kan de linker niet oproepen, schakel over op extern linken
+exec_i_linking=09015_I_Linken van $1
+exec_e_util_not_found=09016_E_Gereedschap $1 niet gevonden, schakel over op extern linken
+exec_t_using_util=09017_T_Gebruik tool $1
+exec_e_exe_not_supported=09018_E_Creatie van executable bestanden niet ondersteund.
+exec_e_dll_not_supported=09019_E_Dynamische bibliotheken niet ondersteund
+exec_i_closing_script=09020_I_Afsluiten batch $1
+exec_e_res_not_found=09021_E_Resource compiler niet gevonde, schakel over op externe modus
+exec_i_compilingresource=09022_I_Compileer resource $1
+#
+# Executable information
+#
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Unit $1 kan niet statisch gelinkt worden. Schakel over op slim linken
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Unit $1 kan niet slim gelinkt worden. Schakel over op statisch linken
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Unit $1 kan niet gedeeld gelinkt worden, Schakel over op statisch linken
+exec_e_unit_not_smart_or_static_linkable=09026_E_Unit $1 kan niet slim of statisch gelinkt worden
+exec_e_unit_not_shared_or_static_linkable=09027_E_Unit $1 kan niet gedeeld of statisch gelinkt worden
+exec_d_resbin_params=09028_D_Oproep resource compiler "$1" met "$2" als commando-lijn opties
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_Kan applicatie niet nabehandelen $1
+execinfo_f_cant_open_executable=09129_F_Kan applicatie niet openen $1
+execinfo_x_codesize=09130_X_Grootte van de code: $1 bytes
+execinfo_x_initdatasize=09131_X_Grootte van geinitialiseerde data: $1 bytes
+execinfo_x_uninitdatasize=09132_X_Grootte van niet-geinitialiseerde data: $1 bytes
+execinfo_x_stackreserve=09133_X_Gereserveerde stackruimte: $1 bytes
+execinfo_x_stackcommit=09134_X_Toegewezen stackruimte: $1 bytes
+# Unit loading
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Unit zoeken: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU Laden $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Naam: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Vlaggen: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Tijd: $1
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_file_too_short=10006_U_PPU bestand te kort
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_invalid_header=10007_U_PPU Ongeldige kop (geen PPU aan het begin)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_PPU Ongeldige versie $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU is gecompileerd voor een andere processor
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU is gecompileerd voor een ander doelsysteem
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU bron: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Schrijven van $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Kan PPU bestand niet schrijven
+% An err
+unit_f_ppu_read_error=10014_F_Lezen van PPU bestand
+% Unexpected end of file
+unit_f_ppu_read_unexpected_end=10015_F_Onverwacht einde van PPU-bestand
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_invalid_entry=10016_F_Ongeldig PPU bestand post: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx aantal probleem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Ongeldige unitnaam: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Te veel units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Uses statement veroorzaakt vicieuze cirkel tussen $1 en $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Kan unit $1 niet compileren, geen broncode beschikbaar
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Kan unit $1 niet vinden
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Unit $1 niet gevonden maar $2 bestaat
+unit_f_unit_name_error=10024_F_Unit $1 gezocht maar $2 gevonden
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_De systeemunit compileren vereist de -Us schakelaar
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Er waren fouten $1 bij het compileren van een module, compilatie gestopt.
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Laden van $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Hercompileer $1, checksum voor $2 veranderd
+unit_u_recompile_source_found_alone=10029_U_herkompileer $1, alleen bron gevonden
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Hercompileer unit, statische bibliotheek ouder dan ppu-bestand
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Hercompileer unit, dynamische bibliotheek ouder dan ppu-bestand
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Hercompileer unit, object en asm zijn ouder dan ppu-bestand
+% When you use the \var{-vu} flag, the compiler warns if the assembler of
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Hercompileer unit, object is ouder dan assembler
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Interface van $1 wordt geparsed
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Implementatie van $1 wordt geparsed
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Tweede maal unit $1 laden
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU Controleren van bestand $1 tijd $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+% \end{description}
+# EndOfTeX
+#
+# Options
+#
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Kan unit $1 niet hercompileren, maar vond gewijzigde include bestanden
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Bestand $1 is nieuwer dan release PPU bestand $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Er wordt een unit gebruikt die niet met de correcte FPU modus is gecompileerd
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Laden van interface units voor unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Laden van implementatie units voor unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Interface CRC voor unit $1 is gewijzigd
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Implementatie CRC voor unit $1 is gewijzigd
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Klaar met compileren van unit Â$1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Afhankelijkheid van $1 toegevoegd aan $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Niet herladen, oproeper is: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Niet herladen, reads in tweede compilatie: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Vlaggen voor herladen: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Verplicht herladen
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Vorige toestand van $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_$1 wordt reeds gecompileerd, tweede compile wordt gezet
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Laden unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Klaar met laden van unit $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Nieuwe unit $1 wordt geregistreerd
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Opnieuw oplossen van unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Oplossen van unit $1 wordt overgeslagen, gebruikte units worden nog geladen
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [opties] <bestand> [opties]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Maar een (1) bronbestand wordt ondersteunt
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Een DEF file kan alleen worden gemaakt voor OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Geneste optie bestanden niet ondersteund
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Geen bronbestand op de commando-lijn
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_geen opties in configuratie bestand $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Ongeldige parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? druk hulp af
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Te veel geneste instellingsbestanden
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Kan bestand $1 niet openen
+% The option file cannot be found.
+option_reading_further_from=11010_D_Meer instellingen worden gelezen van $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Doel is reeds ingesteld op: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Shared bibliotheken niet onderteund onder DOS, val terug op statisch
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Te veel IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Te veel ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Open voorwaardelijke aan eind van bestand
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Debug informatie generatie wordt niet ondersteund door deze applicatie
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Hercompileer de compiler-applicatie met -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_U gebruikt een in onbruik geraakte schakeloptie $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_U gebruikt een in onbruik geraakte schakeloptie $1, gebruik $2 a.u.b.
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_De assembler wordt veranderd in de standaard assemblerschrijver
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Geselecteerde assembler "$1" is niet verenigbaar met "$2"
+option_asm_forced=11022_W_Gebruik van "$1" assembler opgelegd
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_using_file=11026_T_Opties worden gelezen van bestand $1
+% Options are also read from this file
+option_using_env=11027_T_Opties worden gelezen van omgevingsvariabelen $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Behandelen van optie "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__***Druk op de ENTER toets***
+option_start_reading_configfile=11030_H_Start lezen van configuratie bestand $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Einde van lezen van configuratie bestand $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Optie $1 wordt behandeld
+option_interpreting_firstpass_option=11036_D_Behandel prioritaire optie "$1"
+option_interpreting_file_option=11033_D_Behandel bestandsoptie "$1"
+option_read_config_file=11034_D_Lezen configuratie bestand "$1"
+option_found_file=11035_D_Bronbestand "$1" gevonden
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Ongekende coderingspagina
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler versie $FPCVER [$FPCDATE] voor $FPCTARGET
+Copyright (c) 1998-2004 door Florian Klaempfl en anderen
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versie $FPCVER
+
+Compiler datum: $FPCDATE
+Compiler doelsysteem: $FPCTARGET
+
+Dit programma wordt verspreid onder de GNU General Public Licence
+Voor meer informatie, lees COPYING.FPC. Hiervan is helaas geen
+Nederlandse vertaling beschikbaar.
+
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+option_help_pages=11025_[
+**0*_+ schakelt optie aan, - af
+**1a_De compiler verwijdert gegenereerd assemblerbestand niet
+**2al_Toon broncode in assemblerbestand
+**2ar_Toon register allocatie/release informatie in assemblerbestand
+**2at_Toon tijdelijke allocatie/release informatie in assemblerbestand
+**1b_genereer browser info
+**2bl_genereer info voor lokale symbolen info
+**1B_Bouw alle modules
+**1C_Codegeneratie opties
+3*2CD_Creeer dynamische bibliotheek
+**2Ch<n>_<n> bytes heap (tussen 1023 en 67107840)
+**2Ci_IO-checking
+**2Cn_Laat linken achterwege
+**2Co_Controleer overflow van integeroperaties
+**2Cr_Bereikcontrole (range check)
+**2Cs<n>_Stel stack grootte in op <n>
+**2Ct_Stack controle
+3*2CS_Cre‰er dynamische bibliotheek
+3*2Cx_Gebruik slim linken
+**1d<x>_definieer het symbool <x>
+*O1D_genereer een DEF bestand
+*O2Dd<x>_Zet beschrijving op <x>
+*O2Dw_PM applicatie
+**1e<x>_Zet pad naar applicaties
+**1E_Zelfde als -Cn
+**1F_Zet bestandsnamen en paden
+**2Fe<x>_Zend foutboodschappen naar bestand <x>
+*L2Fg<x>_Zelfde als -Fl
+**2Fi<x>_Voegt <x> toe aan invoegpad
+**2Fl<x>_Voegt <x> toe aan bibliotheek-pad
+*L2FL<x>_Gebruik <x> als dynamische linker
+**2Fo<x>_Voeg <x> toe aan object-pad
+**2Fr<x>_Lees foutmeldingen uit bestand <x>
+**2Fu<x>_Voeg <x> toe aan unit pad
+**2FU<x>_Schrijf units in folder <x>, (primeert op -FE)
+*g1g_genereer debuginformatie
+*g2gg_gebruik gsym
+*g2gd_gebruik dbx
+*g2gh_laad heaptrc unit automatisch
+*g2gl_Gebruik regelinformatie unit voor meer informatie in backtraces
+*g2gc_genereer controles voor pointers
+**1i_informatie
+**2iD_Toon compilerdatum
+**2iV_Toon compilerversie
+**2iSO_Toon compiler-OS
+**2iSP_Toon compilerprocessor
+**2iTO_Toon doel-OS
+**2iTP_Toon doelprocessor
+**1I<x>_Voeg <x> toe aan invoegpad
+**1k<x>_Geef <x> door aan de linker
+**1l_Druk logo af
+**1n_Standaard configuratie bestand niet lezen
+**1o<x>_Stel de naam van het applicatiebestand in op <x>
+**1pg_genereer profile code voor gprof
+*L1P_Gebruik pipes in plaats van tijdelijke assembler bestanden
+**1S_Syntax instellingen
+**2S2_Stel Delphi 2 uitbreidingen in
+**2Sc_Ondersteun operatoren als in C (*=,+=,/= en -=)
+**2sa_Voeg assertion code toe
+**2S2_Tracht Delphi compatibel te zijn
+**2Se<x>_Compiler stopt na <x> fouten (standaard 1)
+**2Sg_Laat LABEL en GOTO toe
+**2Sh_Gebruik ansistrings
+**2Si_Ondersteun INLINE
+**2Sm_Ondersteun macros zoals in C (globaal)
+**2So_Probeer TP/BP 7.0 compatibel te zijn
+**2Sp_Probeer GNU Pascal compatibel te zijn
+**2Ss_Constructor naam moet init zijn (destructor moet done zijn)
+**2St_Sta static sleutelwoord toe in objecten
+**1s_Roep assembler en linker niet op (slechts met -a)
+**1sh_Genereer een script om op het hostplatform te linken
+**1sr_Voer geen registertoewijzing uit (optimalizaties worden uitgeschakeld)
+**1st_Genereer een script om op het doelplatform te linken
+**1u<x>_Verwijdert symbooldefinitie <x>
+**1U_unit opties
+**2Un_Unit naam niet nagaan
+**2Us_Compileer een systeemunit
+**1v<x>_Wees uitvoerig. <x> is een combinatie van volgende letters:
+**2*_e : Toon fouten (standaard) d : Toon debug informatie
+**2*_w : Toon waarschuwingen u : Toon gebruikte bestanden
+**2*_n : Toon notas t : Toon geteste bestanden
+**2*_h : Toon hints m : Toon gedefinieerde macros
+**2*_i : Toon algemene informatie p : Toon gecompileerde routines
+**2*_l : Toon regelnummers c : Toon voorwaardelijken
+**2*_a : Toon alles 0 : Toon alleen fouten
+**2*_b : Toon alle procedures r : Rhide/GCC compatibiliteit modus
+**2*_ declaraties indien een x : Executable informatie (alleen Win32)
+**2*_ fout optreedt
+**1X_applicatie instellingen
+*L2Xc_link met de C bibliotheek
+**2Xs_verwijder alle symbolen uit applicatie
+**2XD_link met dynamische bibliotheken (definieert FPC_LINK_DYNAMIC)
+**2XS_link met statische bibliotheken (definieert FPC_LINK_STATIC)
+**2XS_link slim (definieert FPC_LINK_STATIC_SMART)
+**0*_Processor specifieke instellingen:
+3*1A_Output formaat
+3*2Aas_assembleer met GNU AS
+3*2Aasaout_assembleer met GNU AS voor aout (Go32v1)
+3*2Anasmcoff_Coff (Go32v2) bestand met Nasm
+3*2Anasmelf_elf32 (linux) bestand met Nasm
+3*2Anasmobj_obj bestand met Nasm
+3*2Amasm_obj bestand met Masm (Microsoft)
+3*2Atasm_obj bestand met Tasm (Borland)
+3*2Acoff_coff (Go32v2) met interne assembler
+3*2Apecoff_pecoff (Win32) met interne assembler
+3*1R<x>_Geef de grammatica voor de assemblerlezer op:
+3*2Ratt_Lees assembler in AT&T stijl
+3*2Rintel_Lees assembler in Intel stijl
+3*2Rdirect_Kopieer assemblercode rechtstreeks naar assemblerbestand
+3*1O<x>_optimalizaties
+3*2Og_Genereer kleinere code
+3*2OG_Genereerd snellere code (standaard)
+3*2Or_Houdt zekere variabelen in registers (Nog steeds BUGGY!!!)
+3*2Ou_Probeer onzekere optimalizaties (zie documentatie)
+3*2O1_Niveau 1 optimalizaties (snelle optimizaties)
+3*2O2_Niveau 2 optimalizaties (-O1 + tragere optimizaties)
+3*2O3_Niveau 3 optimalizaties (Zelfde als -O2u)
+3*2Op_Doelprocessor
+3*3Op1_Stel doelprocessor in op 386/486
+3*3Op2_Stel doelprocessor in op Pentium/PentiumMMX (tm)
+3*3Op3_Stel doelprocessor in op PPro/PII/c6x86/K6 (tm)
+6*1T<x>_Doel besturingssysteem:
+3*2TGO32V2_version 2 of DJ Delorie DOS extender
+3*2TLINUX_Linux
+3*2TOS2_OS/2 / eComStation
+3*2TWIN32_Windows 32 Bit
+3*1W<x>_Win32 Doel opties
+3*2WB<x>_Stel Image base in op (hexadecimale) waarde <x>
+3*2WC_Maak een console applicatie
+3*2WD_Gebruik DEFFILE om functies van bibliotheek of applicatie te exporteren
+3*2WG_Maak een grafische applicatie
+3*2WN_Genereer geen relocatie code (nodig voor debuggen)
+3*2WR_Genereer relocatie code
+6*1A_output formaat
+6*2Aas_Unix o-bestand met GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (oude GAS)
+6*2Amot_Standaard Motorola assembler
+6*1O_optimizaties
+6*2Oa_Gebruik de optimizaties
+6*2Og_Genereer kleinere code
+6*2OG_Genereer snellere code (standaard)
+6*2Ox_Optimizeer maximaal (nog steeds BUGGY!!!)
+6*2O2_Stel doelprocessor in op MC68020+
+6*1R<x>_assembler reading style:
+6*2RMOT_read motorola style assembler
+6*1T<x>_Target operating system:
+6*2TAMIGA_Commodore Amiga
+6*2TATARI_Atari ST/STe/TT
+6*2TMACOS_Macintosh m68k
+6*2TLINUX_Linux-68k
+**1*_
+**1?_Toont deze hulp
+**1h_Toont deze hulp zonder wachten
+]
+
+#
+# The End...
diff --git a/compiler/msg/errorpl.msg b/compiler/msg/errorpl.msg
new file mode 100644
index 0000000000..7c8a3d78e9
--- /dev/null
+++ b/compiler/msg/errorpl.msg
@@ -0,0 +1,2385 @@
+#
+# $Id: errorpl.msg,v 1.5 2004/09/04 21:18:47 armin Exp $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Polish (CP 852) Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Kompilator: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_OS kompilatora: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Docelowy OS: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_—cie¾ka narz©dzi: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_—cie¾ka moduˆ¢w: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_—cie¾ka include'¢w: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_—cie¾ka bibliotek: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_—cie¾ka obiekt¢w: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 linii skompilowanych w $2 sek
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Brak pami©ci
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Zapisywanie pliku zasob¢w: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Bˆ¥d podczas zapisywania pliku zasob¢w: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Bˆ¥d krytyczny:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Bˆ¥d:
+% Prefix for Errors
+general_i_warning=01014_I_Ostrze¾enie:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Podpowied«:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_—cie¾ka "$1" nie istnieje
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_Kompilacja zatrzymana
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Nieoczekiwany koniec pliku
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment wasn't closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String przekracza jedn¥ lini©
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Nieprawidˆowy znak $1 ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Bˆ¥d skˆadni, oczekiwano $1 ale napotkano $2
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_T_Rozpocz©cie czytania pliku include $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Znaleziono komentarz $1 stopnia
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Zignorowany przeˆ¥cznik kompilatora $1
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Nieprawidˆowy przeˆ¥cznik kompilatora $1
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% doesn't know.
+scan_w_switch_is_global=02010_W_Przeˆ¥cznik globalny w nieprawidˆowym miejscu
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Nieprawidˆowa staˆa znakowa
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Nie mo¾na otworzy† pliku $1
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Nie mo¾na otworzy† pliku include $1
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Pola rekord¢w mog¥ by† wyr¢wnane tylko do 1,2,4,8,16 lub 32 bajt¢w
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For $PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for $ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas $ALIGN also supports MAC68K, POWER and RESET.
+scan_w_only_pack_enum=02016_W_Wyliczenia mog¥ by† zapisane tylko na 1, 2 lub 4 bajtach
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_Oczekiwano $ENDIF dla $1 $2 zdefiniowanych w linii $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Bˆ¥d skˆadni podczas parsowania dyrektyw kompilacji warunkowej
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_e_error_in_preproc_expr=02019_E_Bˆ¥d obliczania wyra¾enia kompilacji warunkowej
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Tre˜† makra zostaˆa obci©ta po 255 znaku
+% The contents of macros canno be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF bez IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Zdefiniowany przez u¾ytkownika: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Zdefiniowany przez u¾ytkownika: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Zdefiniowane przez u¾ytkownika: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Zdefiniowana przez u¾ytkownika: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Zdefiniowana przez u¾ytkownika: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Zdefiniowana przez u¾ytkownika: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Sˆowo kluczowe nie mo¾e zosta† przedefiniowane przez makro
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Przepeˆnienie bufora podczas czytania lub rozwijania makra
+% Your macro or it's result was too long for the compiler.
+scan_e_macro_deep_ten=02030_E_Rozwijanie makra przerwane po 16 rozwini©ciach.
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_wrong_styled_switch=02031_E_Przeˆ¥czniki kompilatora nie s¥ dozwolone w komentarzach typu (* ... *)
+% Compiler switches should always be between \var{\{ \}} comment delimiters.
+scan_d_handling_switch=02032_D_Obsˆugiwanie przeˆ¥cznika "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_C_Znaleziono ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_C_Znaleziono IFDEF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_C_Znalezino IFOPT $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_C_Znaleziono IF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_C_Znaleziono IFNDEF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_C_Znaleziono ELSE $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_C_Omijanie...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Naci˜nij <enter> aby kontynuowa†
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Nieobsˆugiwany przeˆ¥cznik $1
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Nieprawidˆowa dyrektywa $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Z powrotem w $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Nieprawidˆowy typ aplikacji: $1
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_Typ aplikacji nieobsˆugiwany przez docelowy OS
+% The \var{\{\$APPTYPE\}} directive is supported by win32 applications only.
+scan_w_description_not_support=02046_W_Dyrektywa DESCRIPTION jest obsˆugiwany tylko przez OS2 i Win32
+% The \var{\{\$DESCRIPTION\}} directive is only supported for OS2 and Win32 targets.
+scan_n_version_not_support=02047_N_Dyrektywa VERSION nie jest obsˆugiwana przez OS
+% The \var{\{\$VERSION\}} directive is only supported by win32 target.
+scan_n_only_exe_version=02048_N_Dyrektywa VERSION jest dost©na tylko dla program¢w i DLLi
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Nieprawidˆowy format dyrektywy VERSION $1
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_w_unsupported_asmmode_specifier=02050_W_Nieprawidˆowy styl asemblera $1
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Przeˆ¥cznik stylu asemblera niedozwolony w bloku asemblera, $1 b©dzie dziaˆa† dopiero w nast©pnym bloku
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Zˆa warto˜† przeˆ¥cznika, u¾yj ON/OFF lub +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Pliki zasob¢w nie s¥ obsˆugiwane przez OS
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Zmienna ˜rodowiskowa $1 nie odnaleziona
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Nieprawidˆowa warto˜† limitu rejestru FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Tylko jeden plik zasob¢w jest obsˆugiwany przez docelowy OS
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Obsˆuga makr jest wyˆ¥czona
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_Nieprawidˆowy typ interfejsu. Prawidˆowe s¥ COM, CORBA i DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02060_W_APPNAME jest obsˆugiwane tylko przez PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02061_W_Dyrektywa APPNAME jest obsˆugiwana tylko przez PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Staˆe ˆaäcuchowe nie mog¥ by† dˆu¾sze ni¾ 255 znak¢w
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Przekroczono maksymaln¥ ilo˜† zagnie¾d¾onych include (16)
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Zbyt du¾o poziom¢w PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_Napotkano POP bez poprzedzaj¥cego go PUSH
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Makro lub zmienna "$1" nie ma przypisanej warto˜ci
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Nieprawidˆowy przeˆ¥cznik, u¾yj ON/OFF/DEFAULT lub +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Przeˆ¥cznik trybu "$1" jest niedozwolony w tym miejscu
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Zmienna "$1" jest niezdefiniowana
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_utf8_bigger_than_65535=02069_E_Napotkano kod UTF-8 wi©kszy od 65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Znieksztaˆcony string UTF-8
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_Napotkano sygnatur© UTF-8, u¾ycie kodowania UTF-8
+% The compiler found an UTF-8 encoding signature ($ef, $bb, $bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Bˆ¥d skˆadni
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Procedura typu INTERRUPT nie mo¾e by† zagnie¾d¾ona
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Dyrektywa $1 zignorowana
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Nie wszystkie deklaracje $1 s¥ przeci¥¾one
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Zduplikowana nazwa eksportu $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Zduplikowany indeks eksportowanej funkcji $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Nieprawidˆowa warto˜† indeksu funkcji
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Informacje debugera w DLLu lub programie $1 nie dziaˆaj¥, wyˆ¥czone.
+parser_w_parser_win32_debug_needs_WN=03012_W_Aby m¢c debugowa† kod win32 musisz wyˆ¥czy† generowanie kodu relokacji przeˆ¥cznikiem -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Konstruktor musi nazywa† si© INIT
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destruktor musi nazywa† si© DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Typ INLINE nieobsˆugiwany (u¾yj opcji -Si)
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Konstruktor powinien by† publiczny
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruktor powinien by† publiczny
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasa powinna mie† tylko jeden destruktor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Definicje lokalne w klasie s¥ niedozwolone
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Definicje anonimowych klas s¥ niedozwolone
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_object_has_no_vmt=03023_E_Obiekt $1 nie posiada VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Nieprawidˆowa lista parametr¢w
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Nieprawidˆowa ilo˜† parametr¢w
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Przeci¥¾ony identyfikator $1 nie jest funkcj¥
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Przeci¥¾ona funkcja musi mie† chocia¾ jeden parametr wyr¢¾niaj¥cy
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Nagˆ¢wek funkcji nie pasuje do deklaracji $1
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Nagˆ¢wek funkcji $1 nie pasuje : nazwy parametr¢w zmienione $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Ci¥g warto˜ci typu wyliczeniowego musi by† rosn¥cy
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With nie mo¾e by† u¾yte ze zmiennymi w innym segmencie
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Przekroczono limit zagnie¾d¾enia funkcji
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Bˆ¥d zakresu podczas obliczania staˆej
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Bˆ¥d zakresu podczas obliczania staˆej
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Zduplikowana etykieta w instrukcji case
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_G¢rna granica zakresu jest mniejsza od dolnej
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Staˆa typowana nie mo¾e by† klas¥ ani obiektem
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Do zmiennych proceduralnych nie mo¾na przypisa† przeci¥¾onych funkcji
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_Dˆugo˜† stringa musi zawiera† si© mi©dzy 1 a 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_U¾yj rozszerzonej skˆadni NEW i DISPOSE dla obiekt¢w
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_U¾ycie NEW lub DISPOSE nie ma sensu dla nietypowanych wska«nik¢w
+parser_e_no_new_dispose_on_void_pointers=03044_E_U¾ycie NEW lub DISPOSE jest niemo¾liwe dla nietypowanych wska«nik¢w
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Oczekiwano identyfikatora klasy
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identyfikator typu jest niedozwolony w tym miejscu
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Oczekiwano identyfikatora metody
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Nagˆ¢wek funkcji nie pasuje do ¾adnej metody tej klasy $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedura/Funkcja $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Nieprawidˆowa warto˜† staˆej zmiennoprzecinkowej
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL mo¾e by† u¾yte tylko w konstruktorach
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruktory nie mog¥ mie† parametr¢w
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Tylko metody klasy mog¥ by† wywoˆywane w ten spos¢b
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_W metodach klasy mo¾esz u¾ywa† tylko metod klasy
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Staˆa i zmienna u¾yta w CASE nie s¥ tego samego typu
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Symbol nie mo¾e by† wyeksportowany
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Dziedziczona metoda jest ukryta przez $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Nie ma takiej metody w dziedziczonej klasie: $1
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Brak metody do odczytania wˆasno˜ci
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Dyrektywa stored nie jest jeszcze zaimplementowana
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Nieprawidˆowy symbol dla dost©pu do wˆasno˜ci
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Nie mo¾na si© odwoˆywa† do pola protected obiektu w tym miejscu
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Nie mo¾na si© odwoˆywa† do pola private obiektu w tym miejscu
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Przeci¥¾one metody wirtualne powinny mie† taki sam typ zwracanych warto˜ci: "$2" jest przeci¥¾one przez "$" o innym zwracanym typie
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Eksportowane funkcje nie mog¥ by† zagnie¾d¾one
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Metody nie mog¥ by† eksportowane
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Przy przekazywaniu przez referencj© parametry musz¥ by† tego samego typu: Otrzymano $1, a oczekiwano $2
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Ta klasa nie jest przodkiem bie¾¥cej klasy
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF jest dost©pne tylko w metodach
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Metody mog¥ by† wywoˆane bezpo˜rednio identyfikatorem typu klasy tylko w innych metodach
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Nieprawidˆowe u¾ycie ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Bˆ¥d zakresu lub zduplikowany element w deklaracji zbioru
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Oczekiwano wska«nika do obiektu
+% You specified an illegal type in a \var{New} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Wyra¾enie musi by† wywoˆaniem konstruktora
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Wyra¾enie musi by† wywoˆaniem destruktora
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Nieprawidˆowa kolejno˜† element¢w rekordu
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Wyra¾enie musi by† rekordem lub klas¥
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedury nie mog¥ zwraca† warto˜ci
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Konstruktory i destruktory musz¥ by† metodami
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator nie jest przeci¥¾ony
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Nie mo¾a przeci¥¾y† przypisania dla takich samych typ¢w
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Niemo¾liwe przeci¥¾enie operatora
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Ponowne wywoˆanie wyj¥tku niemo¾liwe w tym miejscu
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Rozszerzona skˆadnia new i dispose jest niedozwolona dla klas
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Przeci¥¾anie procedur jest wyˆ¥czone
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Przeci¥¾enie tego operatora jest niemo¾liwe
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operator por¢wnania musi zwraca† warto˜† typu Boolean
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Tylko metody wirtualne mog¥ by† abstrakcyjne
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_U¾ycie nieobsˆugiwanej funkcji kompilatora!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Mieszanie r¢¾nych typ¢w obiekt¢w (obiekt¢w, klas, interfejs¢w) jest niedozwolone
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Nieznana dyrektywa procedury zostaˆa zignorowana: $1
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute mo¾e by† powi¥zane tylko z jedn¥ zmienn¥
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute mo¾e by† u¾yte tylko w stosunku do zmiennej lub staˆej
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Tylko jedna zmienna mo¾e by† zainicjowana
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Metody abstrakcyjne nie mog¥ by† zaimplementowane
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Ta przeci¥¾ona funkcja nie mo¾e by† lokalna (musi by† wyeksportowana)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Metody wirtualne u¾yte bez konstruktora $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Makro zdefiniowane: $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Makro wymazane: $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Makro $1 ustawione na $2
+% When \var{-vm} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Kompilowanie $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsowanie cz©˜ci interface moduˆu $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parsowanie cz©˜ci implementation moduˆu $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Kompilowanie $1 po raz drugi
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Nie znaleziono wˆasno˜ci do przeci¥¾enia
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Dozwolona jest tylko jedna wˆasno˜† domy˜lna, a znaleziono odziedziczon¥ wˆasno˜† domy˜ln¥ $1
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Wˆasno˜ci¥ domy˜ln¥ musi by† tablica
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Wirtualne konstruktory s¥ dost©pne tylko w klasach
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Brak domy˜lnej wˆasno˜ci w tej klasie
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Klasa nie mo¾e mie† sekcji published, u¾yj przeˆ¥cznika {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Deklaracja naprz¢d klasy $1 musi by† rozwi¥zana, aby u¾y† klasy jako przodka innej klasy
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokalne przeci¥¾enia operator¢w niedost©pne
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Dyrektywa $1 niedozwolona w sekcji interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Dyrektywa $1 niedozwolona w sekcji implementation
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Dyrektywa $1 niedozwolona w deklaracji typu proceduralnego
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Funkcja jest ju¾ zadeklarowana jako Public/Forward $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Nie mo¾na u¾y† jednocze˜nie EXPORT i EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_$1 nieobsˆugiwane w procedurze/funkcji inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inline wyˆ¥czone
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Zapisywanie logu przegl¥darki $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Mo¾liwe, ¾e brakuje dereferencji wska«nika
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Wybrany tryb asemblera nie jest obsˆugiwany
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Dyrektywa $1 koliduje z innymi dyrektywami
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Konwencja wywoˆywania musi by† taka sama w cz©sci interface i implementation
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Ta wˆasno˜† nie mo¾e mie† domy˜lnej warto˜ci
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Domy˜lna warto˜† wˆasno˜ci musi by† staˆ¥
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol nie mo¾e by† w sekcji published
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Ten typ warto˜ci nie mo¾e by† w sekcji published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_W_Wymagana jest nazwa importu
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Dzielenie przez zero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Nieprawidˆowa operacja zmiennoprzecinkowa
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_G¢rna granica zakresu jest mniejsza od dolnej
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_String "$1" jest dˆu¾szy ni¾ $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Dˆugo˜† stringa jest wi©ksza ni¾ dˆugo˜† tablicy znak¢w
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Nieprawidˆowe wyra¾enie przy dyrektywie message
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Funkcje obsˆuguj¥ce komunikaty (message) mog¥ pobiera† tylko jeden parametr przez referencj©
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Zduplikowana etykieta komunikatu: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self mo¾e by† parametrem tylko metod obsˆuguj¥cych komunikaty
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Zmienne threadvar mog¥ by† tylko statyczne lub globalne
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Wstawki asemblera niedost©pne gdy wyj˜ciowym formatem jest wbudowane zapisywanie binarne
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Nie ˆaduj moduˆu OBJPAS bezpo˜rednio - u¾yj trybu obiektowego (objfpc, delphi)
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE nie mo¾e by† u¾yte dla obiekt¢w
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Typy danych wymagaj¥ce inicjalizacji/finalizcji nie mog¥ by† u¾yte w rekordach z wariantami
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestring mo¾e by† tylko statyczny lub globalny
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit z argumentem nie mo¾e by† tu u¾yte
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Symbol przechowywania wˆasno˜ci musi by† typu boolean
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Ten symbol nie mo¾e by† symbolem przechowywania wˆasno˜ci
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Tylko klasy skompilowane w trybie $M+ mog¥ by† w sekcji published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Oczekiwano dyrektywy procedury
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Warto˜† indeksu wˆasno˜ci musi by† typu porz¥dkowego
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Zbyt kr¢tka nazwa procedury, aby eksportowa†
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Nie mo¾na wygenerowa† pozycji DEFFILE dla zmiennych globalnych moduˆu
+parser_e_dlltool_unit_var_problem2=03161_E_Skompiluj bez opcji -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Aby skompilowa† ten moduˆ wymagany jest tryb ObjFpc (-S2) lub Delphi (-Sd)
+% You need to use {$mode objfpc} or {$mode delphi} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Nie mo¾na wyeksportowa† z indeksem pod $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Nie mo¾na wyeksportowa† zmiennych pod $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Nieprawidˆowa skˆadnia identyfikatora GUID
+parser_w_interface_mapping_notfound=03168_W_Nie znaleziono procedury "$1", kt¢ra mogˆaby implementowa† $2.$3
+parser_e_interface_id_expected=03169_E_Oczekiwano interfejsu
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Typ "$1" nie mo¾e by† u¾yty jako indeks tablicy
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Konstruktory i destruktory s¥ niedozwolone w interfejsach
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Okre˜lenia dost©pu nie mog¥ by† u¾yte w interfejsach
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Interfejs nie mo¾e posiada† p¢l
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_external=03174_E_Lokalne procedury nie mog¥ by† zadeklarowane jako EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Niekt¢re pola przed "$1" nie zostaˆy zainicjalizowane
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Niekt¢re pola przed "$1" nie zostaˆy zainicjalizowane
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Niekt¢re pola po "$1" nie zostaˆy zainicjalizowane
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Dyrektywa VarArgs bez CDecl i External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self musi by† normalnym parametrem (przekazywanym przez warto˜†)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interfejs "$1" nie posiada identyfikatora GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Nieznana metoda albo pole klasy "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Zmiana sposobu wywoˆywania z "$1" na "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Typowane staˆe typu "procedure of object" mog¥ by† inicjowane tylko NILem
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Domy˜lna warto˜† mo¾e by† przypisana tylko jednemu parametrowi
+parser_e_default_value_expected_for_para=03185_E_Domy˜lna warto˜† wymagana dla "$1"
+parser_w_unsupported_feature=03186_W_U¾ycie (jeszcze) nieobsˆugiwanej funkcji kompilatora!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Tablice C s¥ przekazywane przez referencj©
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Tablica staˆych musi by† ostatnim argumentem
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Powt¢rna definicja typu "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Funkcje cdecl nie maj¥ parametru high
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Funkcje cdecl nie obsˆuguj¥ open strings
+%Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Nie mo¾na zainicjalizowa† zmiennych zadeklarowanych jako threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Dyrektywa Message jest dozwolona tylko w klasach
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Oczekiwano procedury lub funkcji
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Dyrektywa "$1" zignorowana
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_Nie mo¾na u¾y† REINTRODUCE dla obiekt¢w
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Ka¾dy argument musi posiada† swoj¥ pozycj©
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Ka¾dy argument musi posiada† swoj¥ pozycj©
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Nieznana pozycja argumentu
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Oczekiwano 32 bitowej liczby typu Integer albo wska«nika
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Nie mo¾na u¾y† instrukcji GOTO pomi©dzy procedurami
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Zbyt rozbudowana procedura, spr¢buj rozbi† j¥ na mniejsze
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Nieprawidˆowe wyra¾enie
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Nieprawidˆowe wyra¾enie (powinno zw¢ci† liczb© caˆkowit¥)
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Nieprawidˆowy kwalifikator
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_G¢rna granica zakresu jest mniejsza od dolnej
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Parametr funkcji EXIT musi by† nazw¥ procedury, w kt¢rej jej u¾yto
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Nieprawidˆowe przypisanie do licznika p©tli "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Lokalne zmienne nie mog¥ by† zadeklarowane jako EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procedura ju¾ zadeklarowana jako EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Dopisanie moduˆu Variants do sekcji uses
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Metody statyczne nie mog¥ by† u¾yte w interfejsach
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Wyst¥piˆo przepeˆnienie w operacji arytmetycznej
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Oczekiwano "protected" albo "private"
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last one used
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Nieprawidˆowy typ
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Niezgodno˜† typ¢w: otrzymano "$1" oczekiwano "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Niezgodno˜† typ¢w pomi©dzy $1 i $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Oczekiwano identyfikatora typu
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Oczekiwano identyfikatora zmiennej
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Oczekiwano wyra¾enia caˆkowitego, ale otrzymano "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Oczekiwano wyra¾enia logicznego, ale otrzymano "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Oczekiwano wyra¾enia porz¥dkowego
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Oczekiwano wska«nika, ale otrzymano "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Oczekiwano klasy, ale otrzymano "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Nie mo¾na obliczy† warto˜ci wyra¾enia
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Niekompatybilne elementy zbioru
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operacja niezaimplementowana dla zbioru
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Konwersja typu zmiennoprzecinkowego do caˆkowitego typu COMP
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_U¾yj DIV zamiast '/' aby wynik byˆ caˆkowity
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Typy string¢w nie pasuj¥ z powodu trybu $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ i Pred nie dziaˆaj¥ dla wyliczeä z przypisaniami
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Nie mo¾na zapisa† lub odczyta† zmiennych tego typu
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Nie mo¾na u¾y† readln ani writeln na pliku tego typu
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Nie mo¾na u¾y† readln ani writeln na nietypowanym pliku
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Konflikt typ¢w pomi©dzy elementami zbioru
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) zwraca starsze/mˆodsze sˆowo/podw¢jne sˆowo
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Oczekiwano wyra¾enia caˆkowitego lub zmiennoprzecinkowego
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Nieprawidˆowy typ $1 w konstruktorze tablicy
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Nieprawidˆowy typ parametru nr $1: Otrzymano $2, a oczekiwano $3
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Metoda i Procedura nie s¥ zgodne (jako zmienne)
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Nieprawidˆowa staˆa przekazana do wbudowanej funkcji matematycznej
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Nie mo¾na pobra† adresu staˆej
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Ten argument nie mo¾e by† przekazany przez referencj©
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Nie mo¾na przypisa† lokalnej procedury/funkcji do zmiennej proceduralnej
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Nie mo¾na przypisa† warto˜ci adresowi
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Nie mo¾na staˆej przypisa† warto˜ci
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Dozwolone tylko dla tablic
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Oczekiwano interfejsu ale otrzymano "$1"
+type_w_mixed_signed_unsigned=04035_W_U¾ywanie zmiennych typu Cardinal w wyra¾eniach ze znakiem daje 64bitowy wynik
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetical
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_U¾ywanie zmiennych typu Cardinal w wyra¾eniach ze znakiem mo¾e spowodowa† bˆ¥d zakresu w tym miejscu
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a cardinal while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to cardinal before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Rzutowanie typ¢w r¢¾nych rozmiar¢w ($1 -> $2) w przypisaniu
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Typ wyliczeniowy z przypisanymi warto˜ciami nie moze by† u¾yty do ideksowania tablicy
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Typy obiektowe "$1" i "$2" nie s¥ pokrewne
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Typy obiektowe "$1" i "$2" nie s¥ pokrewne
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Oczekiwano klasy lub interfejsu ale otrzymano "$1"
+type_e_type_is_not_completly_defined=04042_E_Typ "$1" nie jest kompletnie zdefiniowany
+type_w_string_too_long=04043_W_Przekroczona maksymalna dˆugo˜† ˆaäcucha
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_To por¢wnanie zawsze zwraca faˆsz z powodu zakres¢w warto˜ci zmiennych
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_To por¢wnanie zawsze zwraca faˆsz z powodu zakres¢w warto˜ci zmiennych
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Tworzenie klasy "$1" posiadaj¥cej metody abstrakcyjne
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_Lewy operand operatora IN powinien by† wielko˜ci jednego bajta
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Typy r¢¾nej wielko˜ci - mo¾liwa utrata danych lub bˆ¥d zakresu
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Typy r¢¾nej wielko˜ci - mo¾liwa utrata danych lub bˆ¥d zakresu
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Nie mo¾na uzyska† adresu metody abstrakcyjnej
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_Operator nie pasuje do operandu
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Oczekiwano staˆego wyra¾enia
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operacja "$1" niedozwolona dla typ¢w "$2" i "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Nieprawidˆowa konwersja typ¢w: "$1" do "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konwersja pomi©dzy typami caˆkowitymi i wska«nikami jest nieprzeno˜na
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konwersja pomi©dzy typami caˆkowitymi i wska«nikami jest nieprzeno˜na
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Nie mo¾na okre˜li†, kt¢r¥ z przeci¥¾onych funkcji wywoˆa†
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Nieprawidˆowy typ licznika p©tli
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last one used
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Nie odnaleziono identyfikatora $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Bˆ¥d wewn©trzny w SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Zduplikowany identyfikator $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identyfikator ju¾ zdefiniowany w $1 w lini $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Nieznany identyfikator $1
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Deklaracaja naprz¢d nie rozwi¥zana $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Bˆ¥d w definicji typu
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Brak definicji typu $1
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Tylko zmienne statyczne mog¥ by† u¾ywane w metodach statycznych
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Oczekiwano rekordu lub klasy
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instancje klas i obiekt¢w z metodami abstrakcyjnymi niedozwolone
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Etykieta nie zostaˆa zdefiniowana $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Etykieta niezdefiniowana przed u¾yciem $1
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Nieprawidˆowa deklaracja etykiety
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO i LABEL nieobsˆugiwane (u¾yj opcji -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Nie odnaleziono etykiety
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Identyfikator nie jest etykiet¥
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Powt¢rna definicja etykiety
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Nieprawidˆowa deklaracja typu zbiorowego
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Brak implementacji klasy $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Moduˆ $1 nieu¾ywany w $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parametr $1 nieu¾ywany
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokalna zmienna $1 nieu¾ywana
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Warto˜c przypisana do $1 nie jest nigdzie u¾yta
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Warto˜c przypisana do $1 nie jest nigdzie u¾yta
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Lokalna(y) $1 $2 nie zostaˆ(a) u¾yta(y)
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Prywatne pole $1.$2 nieu¾ywane
+sym_n_private_identifier_only_set=05030_N_Warto˜c przypisana do lokalnego pola $1.$2 nie jest nigdzie u¾yta
+sym_n_private_method_not_used=05031_N_Metoda prywatna $1.$2 nieu¾ywana
+sym_e_set_expected=05032_E_Oczekiwano typu zbiorowego
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Nie wygl¥da na to, ¾eby warto˜† zwracana przez funkcj© byˆa ustawiona
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Typ $1 jest «le wyr¢wnany dla C w bie¾¥cym rekordzie
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Nieznany identyfikator pola rekordu $1
+% The field doesn't exist in the record definition.
+sym_n_uninitialized_local_variable=05036_W_Nie wygl¥da na to, ¾eby lokalna zmienna $1 byˆa zainicjowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_n_uninitialized_variable=05037_W_Nie wygl¥da na to, ¾eby zmienna $1 byˆa zainicjowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Identyfikator nie wskazuje ¾adnej metody ani pola $1
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Znaleziono deklaracj©: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Element jest zbyt du¾y
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Nie znaleziono implementacji metody interfejsu "$1"
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" jest przestarzaˆy
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbolu "$1" nie da si© przenie˜† na inne platformy
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" nie jest zaimplementowany
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Nie mo¾na utworzy† unikalnego typu z tego typu
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Zmienna lokalna "$1" mo¾e nie by† zainicjalizowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Zmienna "$1" mo¾e nie by† zainicjalizowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Rozmiar listy parametr¢w przekracza 65535 bajt¢w
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Zmienne plikowe musz¥ by† przekazywane przez referencje
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_U¾ycie wska«nika far niedozwolone w tym miejscu
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Mo¾liwe nieprawidˆowe wywoˆanie konstruktora/destruktora
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Niewydajny kod
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Kod nie zostanie nigdy wykonany
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Nie mo¾na bezpo˜rednio wywoˆa† metod abstrakcyjnych
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Rejestr $1 waga $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Pomini©to ramk© stosu
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Metody obiekt¢w i klas nie mog¥ by† inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Wywoˆania procedur ze zmiennych proceduralnych nie mog¥ by† inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Brak kodu dla procedury inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Brak dost©pu do zerowego elementu ansi/wide- lub longstringa, u¾yj (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Konstruktory i destruktory nie mog¥ by† wywoˆywane w klauzuli 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Nie mo¾na wywoˆa† bezpo˜rednio metody obsˆuguj¥cej komunikaty
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Skok do bloku lub poza blok exception
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Break, Continue i Exit nie s¥ dozwolone w bloku finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Rozmiar parametr¢w przekroczyˆ limit dla niekt¢rych procesor¢w
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Rozmiar zmiennych lokalnych przekroczyˆ limit dla dla niekt¢rych procesor¢w
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Rozmiar zmiennych lokalnych przekroczyˆ dopuszczalny limit
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK mo¾na u¾y† tylko wewn¥trz p©tli
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE mo¾na u¾y† tylko wewn¥trz p©tli
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Rozpocz©cie parsowania bloku asemblera w stylu $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Zakoäczenie parsowania bloku asemblera w stylu $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_½aden identyfikator (poza etykietami) nie mo¾e zawiera† @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Bˆ¥d tworzenia offsetu rekordu
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET u¾yty bez identyfikatora
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE u¾yte bez identyfikatora
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Nie mo¾na u¾ywa† lokalnych zmiennych i parametr¢w w tym miejscu
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Nale¾y tu u¾y† OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Nale¾y u¾y† tu $
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Mo¾na u¾y† tylko jednego symbolu relokacyjnego
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Symbole relokacyjne mog¥ by† tylko dodane
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Nieprawidˆowe staˆe wyra¾enie
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Nie mo¾na u¾y† symbolu relokacyjnego w tym miejscu
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Nieprawidˆowa skˆadnia referencji
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Nie mo¾na osi¥gn¥† $1 z tego kodu
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokalne symbole/etykiety nie s¥ dozwolone jako referencje
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Nieprawidˆowe u¾ycie rejestru indeksu i bazy
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Mo¾liwy bˆ¥d w obsˆugiwaniu pola obiektu
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Nieprawidˆowa skala
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_U¾ycie wielu rejestr¢w indeksu
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Nieprawidˆowy typ operandu
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Nieprawidˆowy string jako operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE i @DATA nieobsˆugiwane
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Puste etykiety referencji s¥ niedozwolone
+asmr_e_expr_zero_divide=07025_E_Dzielenie przez zero
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Nieprawidˆowe wyra¾enie
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sekwencja zignorowana: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Nieprawidˆowa referencja symbolu
+asmr_w_fwait_emu_prob=07029_W_Fwait mo¾e powodowa† problemy emulacji z emu387
+asmr_w_fadd_to_faddp=07030_W_$1 bez operandu przetˆumaczone na $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instrukcja ENTER nie jest obsˆugiwana przez j¥dro Linuksa
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Wywoˆanie przeci¥¾onej funkcji z poziomu asemblera
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Nieobsˆugiwany typ symbolu dla operandu
+asmr_e_constant_out_of_bounds=07034_E_Warto˜† staˆa przekracza zakres
+asmr_e_error_converting_decimal=07035_E_Bˆ¥d konwersji liczby dziesi©tnej $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Bˆ¥d konwersji liczby ¢semkowej $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Bˆ¥d konwersji liczby dw¢jkowej $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Bˆ¥d konwersji liczby szesnastkowej $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 przetˆumaczone na $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 jest przypisane do przeci¥¾onej funkcji
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Nie mo¾na u¾y† SELF poza metod¥
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Nie mo¾na u¾y† OLDEBP poza zagnie¾d¾on¥ procedur¥
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedury nie mog¥ zwraca† warto˜ci w kodzie asemblera
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nie obsˆugiwane
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Przyrostek okre˜laj¥cy rozmiar nie pasuje do «r¢dˆa lub celu
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Przyrostek okre˜laj¥cy rozmiar nie pasuje do «r¢dˆa lub celu
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Bˆ¥d skˆadni asemblera
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Nieprawidˆowa kombinacja opkodu i operandu
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Bˆ¥d skˆadni asemblera w operandzie
+asmr_e_syn_constant=07050_E_Bˆ¥d skˆadni asemblera w staˆej
+asmr_e_invalid_string_expression=07051_E_Nieprawidˆowe wyra¾enie ze stringiem
+asmr_w_const32bit_for_address=07052_W_Staˆa $1 prawdopodobnie nie powinna by† wska«nikiem
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Nieznany opkod $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Nieprawidˆowy opkod lub brak opkodu
+asmr_e_invalid_prefix_and_opcode=07055_E_Nieprawidˆowa kombinacja prefiksu i opkodu: $1
+asmr_e_invalid_override_and_opcode=07056_E_Nieprawidˆowa kombinacja override i opkodu: $1
+asmr_e_too_many_operands=07057_E_Zbyt du¾o operand¢w
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR zignorowane
+asmr_w_far_ignored=07059_W_FAR zignorowane
+asmr_e_dup_local_sym=07060_E_Zduplikowany symbol lokalny $1
+asmr_e_unknown_local_sym=07061_E_Niezdefiniowany symbol lokalny $1
+asmr_e_unknown_label_identifier=07062_E_Nieznana etykieta $1
+asmr_e_invalid_register=07063_E_Nieprawidˆowa nazwa rejestru
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nieprawidˆowa nazwa rejestru zmiennoprzecinkowego
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo nieobsˆugiwane
+asmr_e_invalid_float_const=07067_E_Nieprawidˆowa staˆa zmiennoprzecinkowa $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Nieprawidˆowe wyra¾enie zmiennoprzecinkowe
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Nieprawidˆowy typ symbolu
+asmr_e_cannot_index_relative_var=07070_E_Nie mo¾na ideksowa† rejestrem zmiennej lokalnej/parametru
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Stringi nie mog¥ by† staˆymi
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Nie okre˜lono typu zmiennej
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_brak powrotu do sekcji text w kodzie asemblera
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_To nie jest ani dyrektywa, ani symbol lokalny: $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_U¾ycie zdefiniowanej nazwy jako lokalnej etykiety
+asmr_e_dollar_without_identifier=07078_E_Brak identyfikatora przy znaku dolara
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bitowa staˆa u¾yta jako adres
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align nie jest przeno˜ne mi©dzy platformami, u¾yj .balign lub .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Nie mo¾na odwoˆywa† si© bezpo˜rednio do p¢l parametr¢w
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Nie mo¾na odwoˆywa† si© bezpo˜rednio do p¢l obiekt¢w/klas
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Nie okre˜lono rozmiaru operandu
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Nie mo¾na u¾y† RESULT w tej funkcji
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" bez operandu przetˆumaczone na "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" przetˆumaczone na "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" przetˆumaczone na "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Znak < niedozwolony w tym miejscu
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Znak > niedozwolony w tym miejscu
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN nieobsˆugiwane
+asmr_e_no_inc_and_dec_together=07094_E_Inc i Dec nie mog¥ wyst©powa† razem
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Nieprawidˆowa lista rejestr¢w dla movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Nieprawidˆowa lista rejestr¢w dla opkodu
+asmr_e_higher_cpu_mode_required=07097_E_Ta instrukcja wymaga wy¾szego typu procesora ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Nie okre˜lono rozmiaru operand¢w, domy˜lne u¾ycie DWORD
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Bˆ¥d skˆadni przy operandzie shifter
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Zbyt du¾o plik¢w asemblera
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Wybrany typ wyj˜ciowy asemblera nieobsˆugiwany
+asmw_f_comp_not_supported=08002_F_Comp nieobsˆugiwany
+asmw_f_direct_not_supported=08003_F_Direct nieobsˆugiwane przy zapisywaniu bezpo˜rednim
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Alokacja danych jest dozwolona tylko w sekcji bss
+asmw_f_no_binary_writer_selected=08005_F_Nie wybrano sposobu zapisywania binari¢w
+asmw_e_opcode_not_in_table=08006_E_Asm: Brak opkodu $1 w tablicy
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 nieprawidˆowa kombinacja opkodu i operand¢w
+asmw_e_16bit_not_supported=08008_E_Asm: 16bitowe referencje nieobsˆugiwane
+asmw_e_invalid_effective_address=08009_E_Asm: Nieprawidˆowy adres efektywny
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 warto˜† przekracza zakres $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Kr¢tki skok poza zasi©g $1
+asmw_e_undefined_label=08013_E_Asm: Nieznana etykieta $1
+asmw_e_comp_not_supported=08014_E_Asm: Typ Comp nieobsˆugiwany dla tego celu
+asmw_e_extended_not_supported=08015_E_Asm: Typ Extended nieobsˆugiwany dla tego celu
+asmw_e_duplicate_label=08016_E_Asm: Zduplikowana etykieta $1
+asmw_e_redefined_label=08017_E_Asm: Etykieta powt¢rnie zdefiniowana $1
+asmw_e_first_defined_label=08018_E_Asm: Najpierw zdefiniowana tutaj
+asmw_e_invalid_register=08019_E_Asm: Nieprawidˆowy rejestr $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Zmieniono «r¢dˆowy system operacyjny
+exec_i_assembling_pipe=09001_I_Asemblowanie (potok) $1
+exec_d_cant_create_asmfile=09002_E_Nie mo¾na utworzy† plik¢w asemblera: $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Nie mo¾na utworzy† pliku: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Nie mo¾na utworzy† pliku: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 nie znaleziony, przeˆ¥czenie na zewn©trzn¥ asemblacj©
+exec_t_using_assembler=09006_T_U¾ywanie assemblera: $1
+exec_e_error_while_assembling=09007_E_Bˆ¥d asemblera, kod wyj˜cia $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Nie mo¾na wywoˆa† asemblera, bˆ¥d $1 przeˆ¥czenie na zewn©trzn¥ asemblacj©
+exec_i_assembling=09009_I_Asemblowanie $1
+exec_i_assembling_smart=09010_I_Asemblowanie do linkowania smart $1
+exec_w_objfile_not_found=09011_W_Obiekt $1 nieodnaleziony, linkowanie mo¾e si© nie powie˜†!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Biblioteka $1 nieodnaleziona, Linkowanie mo¾e si© nie powie˜†!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Bˆ¥d podczas linkowania
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Nie mo¾na wywoˆa† linkera, przeˆ¥czenie na zewn©trzne linkowanie
+exec_i_linking=09015_I_Linkowanie $1
+exec_e_util_not_found=09016_E_Narz©dzie $1 nieodnalezione, przeˆ¥czenie na zewn©trzne linkowanie
+exec_t_using_util=09017_T_Uruchamianie $1
+exec_e_exe_not_supported=09018_E_Tworzenie plik¢w wykonywalnych nieobsˆugiwane
+exec_e_dll_not_supported=09019_E_Tworzenie bibliotek dynamicznych/wsp¢ˆdzielonych nieobsˆugiwane
+exec_i_closing_script=09020_I_Zamykanie skryptu $1
+exec_e_res_not_found=09021_E_Kompilator zasob¢w nieodnaleziony, przeˆ¥czenie na tryb zewn©trzny
+exec_i_compilingresource=09022_I_Kompilacja zasobu $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Moduˆ $1 nie mo¾e by† linkowany statycznie, przeˆ¥czenie na linkowanie smart
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Moduˆ $1 nie moze by† linkowany smart, przeˆ¥czenie na linkowanie statyczne
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Moduˆ $1 nie mo¾e by† linkowany dynamicznie, przeˆ¥czenie na linkowanie statyczne
+exec_e_unit_not_smart_or_static_linkable=09026_E_Moduˆ $1 nie mo¾e by† linkowany statycznie ani smart
+exec_e_unit_not_shared_or_static_linkable=09027_E_Moduˆ $1 nie mo¾e by† linkowany statycznie ani dynamicznie
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_Nie mo¾na przetwarza† pliku $1
+execinfo_f_cant_open_executable=09029_F_Nie mo¾na otworzy† pliku wykonywalnego $1
+execinfo_x_codesize=09030_X_Rozmiar kodu: $1 bajt¢w
+execinfo_x_initdatasize=09031_X_Rozmiar zainicjowanych danych: $1 bajt¢w
+execinfo_x_uninitdatasize=09032_X_Rozmiar niezainicjowanych danych: $1 bajt¢w
+execinfo_x_stackreserve=09033_X_Zarezerwowany rozmiar stosu: $1 bajt¢w
+execinfo_x_stackcommit=09034_X_Aktywny rozmiar stosu: $1 bajt¢w
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Poszukiwanie moduˆu: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Otwieranie PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nazwa PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Flagi PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Crc PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Czas PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Plik PPU zbyt kr¢tki
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Nieprawidˆowy nagˆ¢wek PPU (brak PPU na pocz¥tku)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Nieprawidˆowa wersja PPU $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU jest skompilowany dla innego procesora
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU skompilowany dla innej platformy docelowej
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_r¢dˆo PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Zapisywanie $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Nie mo¾na zapisa† pliku PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Bˆ¥d podczas czytania pliku PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Nieoczekiwane zakoäczenie pliku PPU
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Nieprawidˆowy plik PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Bˆ¥d podczas liczenia PPU Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nieprawidˆowa nazwa moduˆu: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Zbyt du¾o moduˆ¢w
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Zap©tlone nawi¥zanie pomi©dzy moduˆami $1 i $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Nie mo¾na skompilowa† moduˆu $1, brak «r¢deˆ
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Nie mo¾na znale«† moduˆu $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Nie znaleziono moduˆu $1 ale istnieje $2
+unit_f_unit_name_error=10024_F_Szukano moduˆu $1 ale znaleziono tylko $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Kompilowanie moduˆu System wymaga u¾ycia przeˆ¥cznika -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Napotkano $1 bˆ©d¢w podczas kompilacji moduˆu, zatrzymanie
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_adowanie z $1 ($2) moduˆu $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Rekompilacja $1, suma kontrolna zmieniona dla $2
+unit_u_recompile_source_found_alone=10029_U_Rekompilacja $1, znaleziono tylko «r¢dˆo
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Rekompilacja moduˆu, biblioteka statyczna jest starsza ni¾ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Rekompilacja moduˆu, biblioteka wsp¢ˆdzielona jest starsza ni¾ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Rekompilacja moduˆu, obj i asm s¥ starsze ni¾ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Rekompilacja moduˆu, obj jest starszy ni¾ asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Parsowanie cz©˜ci interface moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Parsowanie cz©˜ci implementation moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Drugie zaˆadowanie pliku $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Sprawdzanie pliku PPU: $1 czas: $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Warunek $1 nie byˆ ustawiony na pocz¥tku ostatniej kompilacji moduˆu $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Warunek $1 nie byˆ ustawiony na pocz¥tku ostatniej kompilacji moduˆu $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Nie mo¾na skompilowa† moduˆu $1, znaleziono zmodyfikowane pliki include
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Plik $1 jest nowszy ni¾ plik $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_U¾ycie moduˆu skompilowanego z innym formatem zapisu liczb zmiennoprzecinkowych
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_adowanie moduˆ¢w z cz©«ci interface moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_adowanie moduˆ¢w z cz©«ci implementation moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Zmieniona suma CRC sekcji interface moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Zmieniona suma CRC sekcji implementation moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Zakoäczono kompilacj© moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Dodanie zale¾no˜ci $1 do $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Omini©cie przeˆadowania moduˆu, to ten sam moduˆ: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Omini©cie przeˆadowania moduˆu, trwa druga kompilacaja: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Flaga do przeˆadowania: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Wymuszone przeˆadowanie moduˆu
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Poprzedni stan moduˆu $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ju¾ kompilowane $1, ustawienie drugiej kompilacji
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_adowanie moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Zakoäczenie ˆadowania moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Rejestrowanie nowego moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Powt¢rne odnajdowanie moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Omini©cie powt¢rnego odnajdowania moduˆu $1, ci¥gle ˆaduje u¾ywane moduˆy
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [opcje] <nazwapliku> [opcje]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Obsˆugiwany tylko jeden plik «r¢dˆowy
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Plik DEF mo¾e by† stworzony tylko pod OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Zagnie¾d¾enia plik¢w nieobsˆugiwane
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Brak nazwy pliku w lini poleceä
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Brak opcji w pliku konfiguracyjnym $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Nieprawidˆowy parametr: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? wy˜wietla pomoc
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Za du¾o zagnie¾d¾onych plik¢w konfiguracyjnych
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Nie mo¾na otworzy† pliku konfiguracyjnego $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Czytanie dalszych opcji z $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Cel jest ju¾ ustawiony na: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Biblioteki wsp¢ˆdzielone nie s¥ obsˆugiwane w DOSie, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Za du¾o IF(N)DEF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Za du¾o ENDIF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Warunek wci¥¾ otwarty na koäcu pliku
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Generowanie informacji do debugowania nieobsˆugiwane przez t¥ wersj© kompilatora
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Spr¢buj przekompilowa† z -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_U¾ycie przedawnionego przeˆ¥cznika $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_U¾ycie przedawnionego przeˆ¥cznika $1, prosz© u¾y† $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Przeˆ¥czenie na domy˜lny zapis asemblera
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Wybrane wyj˜cie asemblera "$1" nie jest zgodne z "$2"
+option_asm_forced=11022_W_Wymuszenie u¾ycia asemblera "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Czytanie opcji z pliku $1
+% Options are also read from this file
+option_using_env=11027_T_Czytanie opcji ze zmiennej ˜rodowiskowej $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Obsˆugiwanie opcji "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** naci˜nij enter ***
+option_start_reading_configfile=11030_H_Rozpocz©to czytanie pliku konfiguracyjnego $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Zakoäczono czytanie pliku konfiguracyjnego $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretowanie opcji "$1"
+option_interpreting_firstpass_option=11036_D_Interpretowanie opcji "$1"
+option_interpreting_file_option=11033_D_Interpretowanie opcji plikowej "$1"
+option_read_config_file=11034_D_Czytanie pliku konfiguracyjnego "$1"
+option_found_file=11035_D_Znaleziono nazw© pliku «r¢dˆowego "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Nieznana strona kodowa
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler wersja $FPCVERSION [$FPCDATE] dla $FPCCPU
+Copyright (c) 1993-2005 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler wersja $FPCVERSION
+
+Data kompilatora : $FPCDATE
+Platforma docelowa: $FPCCPU
+
+Wspierane platformy:
+ $OSTARGETS
+
+Wspierane instrukcje CPU:
+ $INSTRUCTIONSETS
+
+Wspierane instrukcje FPU:
+ $FPUINSTRUCTIONSETS
+
+Ten program jest oparty na GNU General Public Licence
+Przeczytaj COPYING.FPC aby dowiedzie† si© wi©cej
+
+Zgˆaszanie bˆ©d¢w, sugestii itp.
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_wpisz + po przeˆ¥czniku aby go aktywowa†, - aby dezaktywowa†
+**1a_kompilator nie usuwa wygenerowanego pliku asemblera
+**2al_wypisuje numery linii do pliku asemblera
+**2an_wypisuje informacje o w©zˆach do pliku asemblera
+*L2ap_u¾ycie potok¢w zamiast tymczasowych plik¢w asemblera
+**2ar_wypisuje alokacje/zwalnianie rejestr¢w do pliku asemblera
+**2at_wypisuje tymczasowe alokacje/zwalnianie do pliku asemblera
+**1A<x>_format wyj˜ciowy:
+**2Adefault_u¾ycie domy˜lnego asemblera
+3*2Aas_asemblacja przy u¾yciu GNU AS
+3*2Anasmcoff_plik coff (Go32v2) przy u¾yciu Nasm
+3*2Anasmelf_plik elf32 (Linux) przy u¾yciu Nasm
+3*2Anasmwin32_plik obj (Win32) przy u¾yciu Nasm
+3*2Anasmwdosx_plik obj (Win32/WDOSX) przy u¾yciu Nasm
+3*2Awasm_plik obj przy u¾yciu Wasm (Watcom)
+3*2Anasmobj_plik obj przy u¾yciu Nasm
+3*2Amasm_plik obj przy u¾yciu Masm (Microsoft)
+3*2Atasm_plik obj przy u¾yciu Tasm (Borland)
+3*2Aelf_bezpo˜redni zapis do pliku elf32 (Linux)
+3*2Acoff_bezpo˜redni zapis do pliku coff (Go32v2)
+3*2Apecoff_bezpo˜redni zapis do pliku pecoff (Win32)
+4*2Aas_asemblacja przy u¾yciu GNU AS
+6*2Aas_o-file (Unix) przy u¾yciu GNU AS
+6*2Agas_asembler GNU Motorola
+6*2Amit_skˆadnia MIT (dawniej GAS)
+6*2Amot_standardowy asembler Motorola
+A*2Aas_asemblacja przy u¾yciu GNU AS
+P*2Aas_asemblacja przy u¾yciu GNU AS
+S*2Aas_asemblacja przy u¾yciu GNU AS
+**1b_generuje informacje przegl¥darki
+**2bl_generuje informacje o lokalnych symbolach
+**1B_budowanie wszystkich moduˆ¢w
+**1C<x>_opcje generacji kodu:
+**2Cc<x>_ustawia domy˜lny spos¢b wywoˆania funkcji/procedur na <x>
+**2CD_tworzenie tak¾e bibliotek dynamicznych (niedost©pne)
+**2Ce_kompilacja z emulowanymi opkodami zmiennoprzecinkowymi
+**2Cf<x>_ustawia u¾ywany zbi¢r instrukcji FPU na <x> (u¾yj "fpc -i", aby zobaczy† mo¾liwe warto˜ci)
+**2Cg_generowanie kodu PIC
+**2Ch<n>_rozmiar sterty w bajtach (pomi©dzy 1023 i 67107840)
+**2Ci_sprawdzanie operacji wej˜cia/wyj˜cia
+**2Cn_pomini©cie etapu linkowania
+**2Co_sprawdzanie przepeˆnienia liczb caˆkowitych
+**2Cp<x>_ustawia u¾ywany zbi¢r instrukcji na <x> (u¾yj "fpc -i", aby zobaczy† mo¾liwe warto˜ci)
+**2Cr_sprawdzanie zakresu
+**2CR_sprawdzanie poprawno˜ci wywoˆywania metod obiekt¢w
+**2Cs<n>_ustawienie rozmiar stosu na <n>
+**2Ct_sprawdzanie stosu
+**2CX_tworzenie bibliotek smartlinked
+**1d<x>_zdefiniowanie symbolu <x>
+*O1D_generacja pliku DEF
+*O2Dd<x>_ustawienie opisu na <x>
+**2Dv<x>_ustawienie wersji DLL na <x>
+*O2Dw_aplikacja PM
+**1e<x>_ustawienie ˜cie¾ki do asemblera i linkera
+**1E_to samo co -Cn
+**1F<x>_ustawianie nazw i ˜cie¾ek:
+**2Fa<x>[,y]_wczytuje <x> (i [y]) zanim zostani¥ wczytane moduˆy z sekcji USES
+**2Fc<x>_ustawienie strony kodowej «r¢deˆ na <x>
+**2FD<x>_ustawienie katalogu z narz©dziami kompilatora
+**2Fe<x>_przekierowanie komunikat¢w o bˆ©dach do pliku <x>
+**2FE<x>_ustawienie katalogu dla skompilowanych program¢w/moduˆ¢w na <x>
+**2Fi<x>_dodanie <x> do ˜cie¾ki include'¢w
+**2Fl<x>_dodanie <x> do ˜cie¾ki bibliotek
+**2FL<x>_u¾ycie <x> jako dynamicznego linkera
+**2Fo<x>_dodanie <x> do ˜cie¾ki obiekt¢w
+**2Fr<x>_ˆadowanie pliku <x> z komunikatami bˆ©d¢w
+**2Fu<x>_dodanie <x> do ˜cie¾ki moduˆ¢w
+**2FU<x>_ustawienie katalogu dla skompilowanych moduˆ¢w, uniewa¾nia -FE
+*g1g_generacja informacji debuggera:
+*g2gc_generacja kodu sprawdzaj¥cego wska«niki
+*g2gd_u¾ycie dbx
+*g2gg_u¾ycie gsym
+*g2gh_u¾ycie moduˆu ˜ledzenia sterty(do wykrywania wyciek¢w pami©ci)
+*g2gl_u¾ycie moduˆu z informacjami o numerach linii programu
+*g2gv_generacja kodu mo¾liwego do ˜ledzenia przy pomocy valgrind
+*g2gw_generacja informacji debuggera dwarf
+**1i_informacje
+**2iD_zwraca dat© kompilatora
+**2iV_zwraca wersj© kompilatora
+**2iSO_zwraca OS kompilatora
+**2iSP_zwraca typ procesora kompilatora
+**2iTO_zwraca docelowy OS
+**2iTP_zwraca docelowy typ kompilatora
+**1I<x>_dodanie <x> do ˜cie¾ki include'¢w
+**1k<x>_podanie <x> do linkera
+**1l_wypisanie logo
+**1M<x>_ustawia tryb j©zyka na <x>
+**2Mfpc_dialekt free pascala (domy˜lny)
+**2Mobjfpc_wˆ¥czenie niekt¢rych rozszerzeä Delphi 2
+**2Mdelphi_kompatybilno˜† z Delphi
+**2Mtp_kompatybilno˜† z TP/BP 7.0
+**2Mgpc_kompatybilno˜† z gpc
+**2Mmac_kompatybilno˜† z dialektami pascala na Macintosha
+**1n_zignorowanie standardowego pliku konfiguracyjnego
+**1N<x>optymalizacje w©zˆ¢w drzewa
+**2Nu_rozwijanie p©tli
+**1o<x>_zmiana nazwy skompilowanego programu na <x>
+3*1O<x>_optymalizacje:
+3*2Og_generacja mniejszego kodu
+3*2OG_generacja szybszego kodu (domy˜lne)
+3*2Or_trzymanie niekt¢rych zmiennych w rejestrach
+3*2Ou_wˆ¥czenie niepewnych optymalizacji (zobacz w dokumentacji)
+3*2O1_optymalizacje pierwszego stopnia (szybkie)
+3*2O2_optymalizacje drugiego stopnia (-O1 + wolniejsze)
+3*2O3_optymalizacje trzeciego stopnia (powtarzane maksymalnie 5 razy -02)
+3*2Op<x>_procesor docelowy:
+3*3Op1_ustawienie procesora docelowego na 386/486
+3*3Op2_ustawienie procesora docelowego na Pentium/PentiumMMX (tm)
+3*3Op3_ustawienie procesora docelowego na PPro/PII/c6x86/K6 (tm)
+6*2Og_generacja mniejszego kodu
+6*2OG_generacja szybszego kodu (domy˜lne)
+6*2Ox_maksymalne optymalizacje (ci¥gle zawieraj¥ B¨DY!!!)
+6*2O0_ustawia docelowy procesor na MC68000
+6*2O2_ustawia docelowy procesor na MC68020+ (domy˜lne)
+**1pg_generacja kodu do profilowania przy pomocy gprof (definiuje FPC_PROFILE)
+**1R<x>_styl asemblera u¾ywanego w «r¢dˆach:
+**2Rdefault_u¾ycie domy˜lnego asemblera
+3*2Ratt_styl AT&T
+3*2Rintel_styl Intel
+6*2RMOT_styl Motorola
+**1S<x>_opcje skˆadni:
+**2S2_to samo co -Mobjfpc
+**2Sc_wspieranie operator¢w C (*=,+=,/= oraz -=)
+**2Sa_doˆ¥czanie kodu asercji
+**2Sd_to samo co -Mdelphi
+**2Se<x>_opcje bˆ©d¢w. <x> jest kombinacj¥:
+**3*_<n> : kompilator zatrzymuje si© po <x> bˆ©dach (domy˜lnie 1)
+**3*_w : kompilator zatrzymuje si© tak¾e na ostrze¾eniach
+**3*_n : kompilator zatrzymuje si© tak¾e na notkach
+**3*_h : kompilator zatrzymuje si© tak¾e na podpowiedziach
+**2Sg_zezwolenie na LABEL i GOTO
+**2Sh_u¾ycie ansistring¢w
+**2Si_wspieranie INLINE w stylu C++
+**2SI<x>_ustawia styl interfejs¢w na <x>
+**3SIcom_interfejsy kompatybilne z COM (domy˜lne)
+**3SIcorba_interfejsy kompatybilne z CORBA
+**2Sm_wspieranie makr jak w C (opcja globalna)
+**2So_to samo co -Mtp
+**2Sp_to samo co -Mgpc
+**2Ss_konstruktory musz¥ mie† nazw© init (destruktory - done)
+**2St_zezwalanie na sˆowo kluczowe static w obiektach
+**1s_pomini©cie wywoˆania asemblera i linkera
+**2sh_generacja skryptu do linkowania na ho˜cie
+**2st_generacja skryptu do linkowania na celu
+**2sr_omini©cie fazy alokowania rejestr¢w (u¾ywaj z -alr)
+**1T<x>_docelowy system operacyjny:
+3*2Temx_OS/2 na EMX (wliczaj¥c EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_DJ Delorie DOS extender - wersja 2
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_DOS extendery zgodne z Watcomem
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_32-bitowy Windows
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (nie wspierane)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin i MacOS X na PowerPC
+P*2Tlinux_Linux na PowerPC
+P*2Tmacos_MacOS (klasyczny) na PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_usuni©cie symbolu <x>
+**1U_opcje moduˆ¢w:
+**2Un_pomini©cie sprawdzania nazwy moduˆu
+**2Ur_generacja moduˆu do wydania (release)
+**2Us_kompilacja moduˆu system
+**1v<x>_obszerne opisy. <x> jest kombinacj¥ nast©puj¥cych liter i cyfr:
+**2*_e : pokazuje bˆ©dy (domy˜lne) 0 : nic nie pokazuje (opr¢cz bˆ©d¢w)
+**2*_w : pokazuje ostrze¾enia u : pokazuje informacje o moduˆach
+**2*_n : pokazuje notki t : pokazuje pr¢bowane/u¾yte pliki
+**2*_h : pokazuje podpowiedzi c : pokazuje warunki
+**2*_i : pokazuje og¢lne informacje d : pokazuje informacje debugowania
+**2*_l : pokazuje numery lini r : tryb kompatybilno˜ci z Rhide/GCC
+**2*_a : pokazuje wszystko x : informacje o pliku exe (tylko Win32)
+**2*_v : zapisuje plik fpcdebug.txt p : zapisuje tree.log z drzewem
+**2*_ z du¾¥ ilo˜ci¥ informacji parsowania
+3*1W<x>_opcje dla Win32 i podobnych
+3*2WB_tworzenie relokacyjnego obrazu
+3*2WB<x>_ustawienie bazy obrazu na szesnastkow¥ warto˜† <x>
+3*2WC_aplikacja konsolowa
+3*2WD_u¾ycie DEFFILE do eksportu funkcji z DLLa lub EXE
+3*2WF_aplikacja peˆnoekranowa (tylko OS/2)
+3*2WG_aplikacja graficzna
+3*2WN_nie generuje kodu relokacji (potrzebne do debugowania)
+3*2WR_generuje kod relokacji
+P*2WC_aplikacja konsolowa (tylko MacOS)
+P*2WG_aplikacja graficzna (tylko MacOS)
+P*2WT_aplikacja narz©dziowa (narz©dzie MPW, tylko MacOS)
+**1X_opcje plik¢w wykonywalnych:
+**2Xc_podaje --shared do linkera (tylko Unix)
+**2Xd_nie u¾ywa standardowej ˜cie¾ki bibliotek (potrzebne do cross-kompilacji)
+**2XD_linkowanie dynamiczne (definiuje FPC_LINK_DYNAMIC)
+**2Xm_generuje link map
+**2XM<x>_ustawia nazw© gˆ¢wnego bloku programu (domy˜lnie 'main')
+**2XP<x>_poprzedza nazw© binutils tekstem <x>
+**2Xr<x>_ustawia ˜cie¾k© bibliotek na <x> (potrzebne do cross-kompilacji)
+**2Xs_wyci©cie wszystkich symboli z pliku
+**2XS_linkowanie statycznie (domy˜lne)(definiuje FPC_LINK_STATIC)
+**2Xt_linkuje z bibliotekami statycznymi (podaje -static do linkera)
+**2XX_linkowanie smart (definiuje FPC_LINK_SMART)
+**1*_
+**1?_pokazanie pomocy
+**1h_pokazanie pomocy bez zatrzymywania
+]
+
+#
+# The End...
diff --git a/compiler/msg/errorpli.msg b/compiler/msg/errorpli.msg
new file mode 100644
index 0000000000..ab758cec8f
--- /dev/null
+++ b/compiler/msg/errorpli.msg
@@ -0,0 +1,2385 @@
+#
+# $Id: errorpli.msg,v 1.4 2003/11/03 08:11:28 michael Exp $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Polish (ISO 8859-2) Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Kompilator: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_OS kompilatora: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Docelowy OS: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_¦cie¿ka narzêdzi: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_¦cie¿ka modu³ów: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_¦cie¿ka include'ów: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_¦cie¿ka bibliotek: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_¦cie¿ka obiektów: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 linii skompilowanych w $2 sek
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Brak pamiêci
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Zapisywanie pliku zasobów: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_B³±d podczas zapisywania pliku zasobów: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_B³±d krytyczny:
+% Prefix for Fatal Errors
+general_i_error=01013_I_B³±d:
+% Prefix for Errors
+general_i_warning=01014_I_Ostrze¿enie:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Podpowied¼:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_¦cie¿ka "$1" nie istnieje
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_Kompilacja zatrzymana
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Nieoczekiwany koniec pliku
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment wasn't closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String przekracza jedn± liniê
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Nieprawid³owy znak $1 ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_B³±d sk³adni, oczekiwano $1 ale napotkano $2
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_T_Rozpoczêcie czytania pliku include $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Znaleziono komentarz $1 stopnia
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Zignorowany prze³±cznik kompilatora $1
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Nieprawid³owy prze³±cznik kompilatora $1
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% doesn't know.
+scan_w_switch_is_global=02010_W_Prze³±cznik globalny w nieprawid³owym miejscu
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Nieprawid³owa sta³a znakowa
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Nie mo¿na otworzyæ pliku $1
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Nie mo¿na otworzyæ pliku include $1
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Pola rekordów mog± byæ wyrównane tylko do 1,2,4,8,16 lub 32 bajtów
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For $PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for $ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas $ALIGN also supports MAC68K, POWER and RESET.
+scan_w_only_pack_enum=02016_W_Wyliczenia mog± byæ zapisane tylko na 1, 2 lub 4 bajtach
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_Oczekiwano $ENDIF dla $1 $2 zdefiniowanych w linii $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_B³±d sk³adni podczas parsowania dyrektyw kompilacji warunkowej
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_e_error_in_preproc_expr=02019_E_B³±d obliczania wyra¿enia kompilacji warunkowej
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Tre¶æ makra zosta³a obciêta po 255 znaku
+% The contents of macros canno be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF bez IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Zdefiniowany przez u¿ytkownika: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Zdefiniowany przez u¿ytkownika: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Zdefiniowane przez u¿ytkownika: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Zdefiniowana przez u¿ytkownika: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Zdefiniowana przez u¿ytkownika: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Zdefiniowana przez u¿ytkownika: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_S³owo kluczowe nie mo¿e zostaæ przedefiniowane przez makro
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Przepe³nienie bufora podczas czytania lub rozwijania makra
+% Your macro or it's result was too long for the compiler.
+scan_e_macro_deep_ten=02030_E_Rozwijanie makra przerwane po 16 rozwiniêciach.
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_wrong_styled_switch=02031_E_Prze³±czniki kompilatora nie s± dozwolone w komentarzach typu (* ... *)
+% Compiler switches should always be between \var{\{ \}} comment delimiters.
+scan_d_handling_switch=02032_D_Obs³ugiwanie prze³±cznika "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_C_Znaleziono ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_C_Znaleziono IFDEF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_C_Znalezino IFOPT $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_C_Znaleziono IF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_C_Znaleziono IFNDEF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_C_Znaleziono ELSE $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_C_Omijanie...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Naci¶nij <enter> aby kontynuowaæ
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Nieobs³ugiwany prze³±cznik $1
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Nieprawid³owa dyrektywa $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Z powrotem w $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Nieprawid³owy typ aplikacji: $1
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_Typ aplikacji nieobs³ugiwany przez docelowy OS
+% The \var{\{\$APPTYPE\}} directive is supported by win32 applications only.
+scan_w_description_not_support=02046_W_Dyrektywa DESCRIPTION jest obs³ugiwany tylko przez OS2 i Win32
+% The \var{\{\$DESCRIPTION\}} directive is only supported for OS2 and Win32 targets.
+scan_n_version_not_support=02047_N_Dyrektywa VERSION nie jest obs³ugiwana przez OS
+% The \var{\{\$VERSION\}} directive is only supported by win32 target.
+scan_n_only_exe_version=02048_N_Dyrektywa VERSION jest dostêna tylko dla programów i DLLi
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Nieprawid³owy format dyrektywy VERSION $1
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_w_unsupported_asmmode_specifier=02050_W_Nieprawid³owy styl asemblera $1
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Prze³±cznik stylu asemblera niedozwolony w bloku asemblera, $1 bêdzie dzia³aæ dopiero w nastêpnym bloku
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Z³a warto¶æ prze³±cznika, u¿yj ON/OFF lub +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Pliki zasobów nie s± obs³ugiwane przez OS
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Zmienna ¶rodowiskowa $1 nie odnaleziona
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Nieprawid³owa warto¶æ limitu rejestru FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Tylko jeden plik zasobów jest obs³ugiwany przez docelowy OS
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Obs³uga makr jest wy³±czona
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_Nieprawid³owy typ interfejsu. Prawid³owe s± COM, CORBA i DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02060_W_APPNAME jest obs³ugiwane tylko przez PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02061_W_Dyrektywa APPNAME jest obs³ugiwana tylko przez PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Sta³e ³añcuchowe nie mog± byæ d³u¿sze ni¿ 255 znaków
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Przekroczono maksymaln± ilo¶æ zagnie¿d¿onych include (16)
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Zbyt du¿o poziomów PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_Napotkano POP bez poprzedzaj±cego go PUSH
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Makro lub zmienna "$1" nie ma przypisanej warto¶ci
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Nieprawid³owy prze³±cznik, u¿yj ON/OFF/DEFAULT lub +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Prze³±cznik trybu "$1" jest niedozwolony w tym miejscu
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Zmienna "$1" jest niezdefiniowana
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_utf8_bigger_than_65535=02069_E_Napotkano kod UTF-8 wiêkszy od 65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Zniekszta³cony string UTF-8
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_Napotkano sygnaturê UTF-8, u¿ycie kodowania UTF-8
+% The compiler found an UTF-8 encoding signature ($ef, $bb, $bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - B³±d sk³adni
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Procedura typu INTERRUPT nie mo¿e byæ zagnie¿d¿ona
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Dyrektywa $1 zignorowana
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Nie wszystkie deklaracje $1 s± przeci±¿one
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Zduplikowana nazwa eksportu $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Zduplikowany indeks eksportowanej funkcji $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Nieprawid³owa warto¶æ indeksu funkcji
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Informacje debugera w DLLu lub programie $1 nie dzia³aj±, wy³±czone.
+parser_w_parser_win32_debug_needs_WN=03012_W_Aby móc debugowaæ kod win32 musisz wy³±czyæ generowanie kodu relokacji prze³±cznikiem -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Konstruktor musi nazywaæ siê INIT
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destruktor musi nazywaæ siê DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Typ INLINE nieobs³ugiwany (u¿yj opcji -Si)
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Konstruktor powinien byæ publiczny
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruktor powinien byæ publiczny
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasa powinna mieæ tylko jeden destruktor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Definicje lokalne w klasie s± niedozwolone
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Definicje anonimowych klas s± niedozwolone
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_object_has_no_vmt=03023_E_Obiekt $1 nie posiada VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Nieprawid³owa lista parametrów
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Nieprawid³owa ilo¶æ parametrów
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Przeci±¿ony identyfikator $1 nie jest funkcj±
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Przeci±¿ona funkcja musi mieæ chocia¿ jeden parametr wyró¿niaj±cy
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Nag³ówek funkcji nie pasuje do deklaracji $1
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Nag³ówek funkcji $1 nie pasuje : nazwy parametrów zmienione $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Ci±g warto¶ci typu wyliczeniowego musi byæ rosn±cy
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With nie mo¿e byæ u¿yte ze zmiennymi w innym segmencie
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Przekroczono limit zagnie¿d¿enia funkcji
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_B³±d zakresu podczas obliczania sta³ej
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_B³±d zakresu podczas obliczania sta³ej
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Zduplikowana etykieta w instrukcji case
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Górna granica zakresu jest mniejsza od dolnej
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Sta³a typowana nie mo¿e byæ klas± ani obiektem
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Do zmiennych proceduralnych nie mo¿na przypisaæ przeci±¿onych funkcji
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_D³ugo¶æ stringa musi zawieraæ siê miêdzy 1 a 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_U¿yj rozszerzonej sk³adni NEW i DISPOSE dla obiektów
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_U¿ycie NEW lub DISPOSE nie ma sensu dla nietypowanych wska¼ników
+parser_e_no_new_dispose_on_void_pointers=03044_E_U¿ycie NEW lub DISPOSE jest niemo¿liwe dla nietypowanych wska¼ników
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Oczekiwano identyfikatora klasy
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identyfikator typu jest niedozwolony w tym miejscu
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Oczekiwano identyfikatora metody
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Nag³ówek funkcji nie pasuje do ¿adnej metody tej klasy $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedura/Funkcja $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Nieprawid³owa warto¶æ sta³ej zmiennoprzecinkowej
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL mo¿e byæ u¿yte tylko w konstruktorach
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruktory nie mog± mieæ parametrów
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Tylko metody klasy mog± byæ wywo³ywane w ten sposób
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_W metodach klasy mo¿esz u¿ywaæ tylko metod klasy
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Sta³a i zmienna u¿yta w CASE nie s± tego samego typu
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Symbol nie mo¿e byæ wyeksportowany
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Dziedziczona metoda jest ukryta przez $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Nie ma takiej metody w dziedziczonej klasie: $1
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Brak metody do odczytania w³asno¶ci
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Dyrektywa stored nie jest jeszcze zaimplementowana
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Nieprawid³owy symbol dla dostêpu do w³asno¶ci
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Nie mo¿na siê odwo³ywaæ do pola protected obiektu w tym miejscu
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Nie mo¿na siê odwo³ywaæ do pola private obiektu w tym miejscu
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Przeci±¿one metody wirtualne powinny mieæ taki sam typ zwracanych warto¶ci: "$2" jest przeci±¿one przez "$" o innym zwracanym typie
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Eksportowane funkcje nie mog± byæ zagnie¿d¿one
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Metody nie mog± byæ eksportowane
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Przy przekazywaniu przez referencjê parametry musz± byæ tego samego typu: Otrzymano $1, a oczekiwano $2
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Ta klasa nie jest przodkiem bie¿±cej klasy
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF jest dostêpne tylko w metodach
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Metody mog± byæ wywo³ane bezpo¶rednio identyfikatorem typu klasy tylko w innych metodach
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Nieprawid³owe u¿ycie ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_B³±d zakresu lub zduplikowany element w deklaracji zbioru
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Oczekiwano wska¼nika do obiektu
+% You specified an illegal type in a \var{New} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Wyra¿enie musi byæ wywo³aniem konstruktora
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Wyra¿enie musi byæ wywo³aniem destruktora
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Nieprawid³owa kolejno¶æ elementów rekordu
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Wyra¿enie musi byæ rekordem lub klas±
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedury nie mog± zwracaæ warto¶ci
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Konstruktory i destruktory musz± byæ metodami
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator nie jest przeci±¿ony
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Nie mo¿a przeci±¿yæ przypisania dla takich samych typów
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Niemo¿liwe przeci±¿enie operatora
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Ponowne wywo³anie wyj±tku niemo¿liwe w tym miejscu
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Rozszerzona sk³adnia new i dispose jest niedozwolona dla klas
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Przeci±¿anie procedur jest wy³±czone
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Przeci±¿enie tego operatora jest niemo¿liwe
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operator porównania musi zwracaæ warto¶æ typu Boolean
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Tylko metody wirtualne mog± byæ abstrakcyjne
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_U¿ycie nieobs³ugiwanej funkcji kompilatora!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Mieszanie ró¿nych typów obiektów (obiektów, klas, interfejsów) jest niedozwolone
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Nieznana dyrektywa procedury zosta³a zignorowana: $1
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute mo¿e byæ powi±zane tylko z jedn± zmienn±
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute mo¿e byæ u¿yte tylko w stosunku do zmiennej lub sta³ej
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Tylko jedna zmienna mo¿e byæ zainicjowana
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Metody abstrakcyjne nie mog± byæ zaimplementowane
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Ta przeci±¿ona funkcja nie mo¿e byæ lokalna (musi byæ wyeksportowana)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Metody wirtualne u¿yte bez konstruktora $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Makro zdefiniowane: $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Makro wymazane: $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Makro $1 ustawione na $2
+% When \var{-vm} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Kompilowanie $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsowanie czê¶ci interface modu³u $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parsowanie czê¶ci implementation modu³u $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Kompilowanie $1 po raz drugi
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Nie znaleziono w³asno¶ci do przeci±¿enia
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Dozwolona jest tylko jedna w³asno¶æ domy¶lna, a znaleziono odziedziczon± w³asno¶æ domy¶ln± $1
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_W³asno¶ci± domy¶ln± musi byæ tablica
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Wirtualne konstruktory s± dostêpne tylko w klasach
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Brak domy¶lnej w³asno¶ci w tej klasie
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Klasa nie mo¿e mieæ sekcji published, u¿yj prze³±cznika {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Deklaracja naprzód klasy $1 musi byæ rozwi±zana, aby u¿yæ klasy jako przodka innej klasy
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokalne przeci±¿enia operatorów niedostêpne
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Dyrektywa $1 niedozwolona w sekcji interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Dyrektywa $1 niedozwolona w sekcji implementation
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Dyrektywa $1 niedozwolona w deklaracji typu proceduralnego
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Funkcja jest ju¿ zadeklarowana jako Public/Forward $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Nie mo¿na u¿yæ jednocze¶nie EXPORT i EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_$1 nieobs³ugiwane w procedurze/funkcji inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inline wy³±czone
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Zapisywanie logu przegl±darki $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Mo¿liwe, ¿e brakuje dereferencji wska¼nika
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Wybrany tryb asemblera nie jest obs³ugiwany
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Dyrektywa $1 koliduje z innymi dyrektywami
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Konwencja wywo³ywania musi byæ taka sama w czêsci interface i implementation
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Ta w³asno¶æ nie mo¿e mieæ domy¶lnej warto¶ci
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Domy¶lna warto¶æ w³asno¶ci musi byæ sta³±
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol nie mo¿e byæ w sekcji published
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Ten typ warto¶ci nie mo¿e byæ w sekcji published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_W_Wymagana jest nazwa importu
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Dzielenie przez zero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Nieprawid³owa operacja zmiennoprzecinkowa
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Górna granica zakresu jest mniejsza od dolnej
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_String "$1" jest d³u¿szy ni¿ $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_D³ugo¶æ stringa jest wiêksza ni¿ d³ugo¶æ tablicy znaków
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Nieprawid³owe wyra¿enie przy dyrektywie message
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Funkcje obs³uguj±ce komunikaty (message) mog± pobieraæ tylko jeden parametr przez referencjê
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Zduplikowana etykieta komunikatu: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self mo¿e byæ parametrem tylko metod obs³uguj±cych komunikaty
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Zmienne threadvar mog± byæ tylko statyczne lub globalne
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Wstawki asemblera niedostêpne gdy wyj¶ciowym formatem jest wbudowane zapisywanie binarne
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Nie ³aduj modu³u OBJPAS bezpo¶rednio - u¿yj trybu obiektowego (objfpc, delphi)
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE nie mo¿e byæ u¿yte dla obiektów
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Typy danych wymagaj±ce inicjalizacji/finalizcji nie mog± byæ u¿yte w rekordach z wariantami
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestring mo¿e byæ tylko statyczny lub globalny
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit z argumentem nie mo¿e byæ tu u¿yte
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Symbol przechowywania w³asno¶ci musi byæ typu boolean
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Ten symbol nie mo¿e byæ symbolem przechowywania w³asno¶ci
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Tylko klasy skompilowane w trybie $M+ mog± byæ w sekcji published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Oczekiwano dyrektywy procedury
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Warto¶æ indeksu w³asno¶ci musi byæ typu porz±dkowego
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Zbyt krótka nazwa procedury, aby eksportowaæ
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Nie mo¿na wygenerowaæ pozycji DEFFILE dla zmiennych globalnych modu³u
+parser_e_dlltool_unit_var_problem2=03161_E_Skompiluj bez opcji -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Aby skompilowaæ ten modu³ wymagany jest tryb ObjFpc (-S2) lub Delphi (-Sd)
+% You need to use {$mode objfpc} or {$mode delphi} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Nie mo¿na wyeksportowaæ z indeksem pod $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Nie mo¿na wyeksportowaæ zmiennych pod $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Nieprawid³owa sk³adnia identyfikatora GUID
+parser_w_interface_mapping_notfound=03168_W_Nie znaleziono procedury "$1", która mog³aby implementowaæ $2.$3
+parser_e_interface_id_expected=03169_E_Oczekiwano interfejsu
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Typ "$1" nie mo¿e byæ u¿yty jako indeks tablicy
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Konstruktory i destruktory s± niedozwolone w interfejsach
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Okre¶lenia dostêpu nie mog± byæ u¿yte w interfejsach
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Interfejs nie mo¿e posiadaæ pól
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_external=03174_E_Lokalne procedury nie mog± byæ zadeklarowane jako EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Niektóre pola przed "$1" nie zosta³y zainicjalizowane
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Niektóre pola przed "$1" nie zosta³y zainicjalizowane
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Niektóre pola po "$1" nie zosta³y zainicjalizowane
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Dyrektywa VarArgs bez CDecl i External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self musi byæ normalnym parametrem (przekazywanym przez warto¶æ)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interfejs "$1" nie posiada identyfikatora GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Nieznana metoda albo pole klasy "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Zmiana sposobu wywo³ywania z "$1" na "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Typowane sta³e typu "procedure of object" mog± byæ inicjowane tylko NILem
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Domy¶lna warto¶æ mo¿e byæ przypisana tylko jednemu parametrowi
+parser_e_default_value_expected_for_para=03185_E_Domy¶lna warto¶æ wymagana dla "$1"
+parser_w_unsupported_feature=03186_W_U¿ycie (jeszcze) nieobs³ugiwanej funkcji kompilatora!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Tablice C s± przekazywane przez referencjê
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Tablica sta³ych musi byæ ostatnim argumentem
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Powtórna definicja typu "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Funkcje cdecl nie maj± parametru high
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Funkcje cdecl nie obs³uguj± open strings
+%Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Nie mo¿na zainicjalizowaæ zmiennych zadeklarowanych jako threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Dyrektywa Message jest dozwolona tylko w klasach
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Oczekiwano procedury lub funkcji
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Dyrektywa "$1" zignorowana
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_Nie mo¿na u¿yæ REINTRODUCE dla obiektów
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Ka¿dy argument musi posiadaæ swoj± pozycjê
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Ka¿dy argument musi posiadaæ swoj± pozycjê
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Nieznana pozycja argumentu
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Oczekiwano 32 bitowej liczby typu Integer albo wska¼nika
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Nie mo¿na u¿yæ instrukcji GOTO pomiêdzy procedurami
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Zbyt rozbudowana procedura, spróbuj rozbiæ j± na mniejsze
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Nieprawid³owe wyra¿enie
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Nieprawid³owe wyra¿enie (powinno zwóciæ liczbê ca³kowit±)
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Nieprawid³owy kwalifikator
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Górna granica zakresu jest mniejsza od dolnej
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Parametr funkcji EXIT musi byæ nazw± procedury, w której jej u¿yto
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Nieprawid³owe przypisanie do licznika pêtli "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Lokalne zmienne nie mog± byæ zadeklarowane jako EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procedura ju¿ zadeklarowana jako EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Dopisanie modu³u Variants do sekcji uses
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Metody statyczne nie mog± byæ u¿yte w interfejsach
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Wyst±pi³o przepe³nienie w operacji arytmetycznej
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Oczekiwano "protected" albo "private"
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last one used
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Nieprawid³owy typ
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Niezgodno¶æ typów: otrzymano "$1" oczekiwano "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Niezgodno¶æ typów pomiêdzy $1 i $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Oczekiwano identyfikatora typu
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Oczekiwano identyfikatora zmiennej
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Oczekiwano wyra¿enia ca³kowitego, ale otrzymano "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Oczekiwano wyra¿enia logicznego, ale otrzymano "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Oczekiwano wyra¿enia porz±dkowego
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Oczekiwano wska¼nika, ale otrzymano "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Oczekiwano klasy, ale otrzymano "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Nie mo¿na obliczyæ warto¶ci wyra¿enia
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Niekompatybilne elementy zbioru
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operacja niezaimplementowana dla zbioru
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Konwersja typu zmiennoprzecinkowego do ca³kowitego typu COMP
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_U¿yj DIV zamiast '/' aby wynik by³ ca³kowity
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Typy stringów nie pasuj± z powodu trybu $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ i Pred nie dzia³aj± dla wyliczeñ z przypisaniami
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Nie mo¿na zapisaæ lub odczytaæ zmiennych tego typu
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Nie mo¿na u¿yæ readln ani writeln na pliku tego typu
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Nie mo¿na u¿yæ readln ani writeln na nietypowanym pliku
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Konflikt typów pomiêdzy elementami zbioru
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) zwraca starsze/m³odsze s³owo/podwójne s³owo
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Oczekiwano wyra¿enia ca³kowitego lub zmiennoprzecinkowego
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Nieprawid³owy typ $1 w konstruktorze tablicy
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Nieprawid³owy typ parametru nr $1: Otrzymano $2, a oczekiwano $3
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Metoda i Procedura nie s± zgodne (jako zmienne)
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Nieprawid³owa sta³a przekazana do wbudowanej funkcji matematycznej
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Nie mo¿na pobraæ adresu sta³ej
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Ten argument nie mo¿e byæ przekazany przez referencjê
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Nie mo¿na przypisaæ lokalnej procedury/funkcji do zmiennej proceduralnej
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Nie mo¿na przypisaæ warto¶ci adresowi
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Nie mo¿na sta³ej przypisaæ warto¶ci
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Dozwolone tylko dla tablic
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Oczekiwano interfejsu ale otrzymano "$1"
+type_w_mixed_signed_unsigned=04035_W_U¿ywanie zmiennych typu Cardinal w wyra¿eniach ze znakiem daje 64bitowy wynik
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetical
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_U¿ywanie zmiennych typu Cardinal w wyra¿eniach ze znakiem mo¿e spowodowaæ b³±d zakresu w tym miejscu
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a cardinal while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to cardinal before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Rzutowanie typów ró¿nych rozmiarów ($1 -> $2) w przypisaniu
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Typ wyliczeniowy z przypisanymi warto¶ciami nie moze byæ u¿yty do ideksowania tablicy
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Typy obiektowe "$1" i "$2" nie s± pokrewne
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Typy obiektowe "$1" i "$2" nie s± pokrewne
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Oczekiwano klasy lub interfejsu ale otrzymano "$1"
+type_e_type_is_not_completly_defined=04042_E_Typ "$1" nie jest kompletnie zdefiniowany
+type_w_string_too_long=04043_W_Przekroczona maksymalna d³ugo¶æ ³añcucha
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_To porównanie zawsze zwraca fa³sz z powodu zakresów warto¶ci zmiennych
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_To porównanie zawsze zwraca fa³sz z powodu zakresów warto¶ci zmiennych
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Tworzenie klasy "$1" posiadaj±cej metody abstrakcyjne
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_Lewy operand operatora IN powinien byæ wielko¶ci jednego bajta
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Typy ró¿nej wielko¶ci - mo¿liwa utrata danych lub b³±d zakresu
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Typy ró¿nej wielko¶ci - mo¿liwa utrata danych lub b³±d zakresu
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Nie mo¿na uzyskaæ adresu metody abstrakcyjnej
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_Operator nie pasuje do operandu
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Oczekiwano sta³ego wyra¿enia
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operacja "$1" niedozwolona dla typów "$2" i "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Nieprawid³owa konwersja typów: "$1" do "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konwersja pomiêdzy typami ca³kowitymi i wska¼nikami jest nieprzeno¶na
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konwersja pomiêdzy typami ca³kowitymi i wska¼nikami jest nieprzeno¶na
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Nie mo¿na okre¶liæ, któr± z przeci±¿onych funkcji wywo³aæ
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Nieprawid³owy typ licznika pêtli
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last one used
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Nie odnaleziono identyfikatora $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_B³±d wewnêtrzny w SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Zduplikowany identyfikator $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identyfikator ju¿ zdefiniowany w $1 w lini $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Nieznany identyfikator $1
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Deklaracaja naprzód nie rozwi±zana $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_B³±d w definicji typu
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Brak definicji typu $1
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Tylko zmienne statyczne mog± byæ u¿ywane w metodach statycznych
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Oczekiwano rekordu lub klasy
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instancje klas i obiektów z metodami abstrakcyjnymi niedozwolone
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Etykieta nie zosta³a zdefiniowana $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Etykieta niezdefiniowana przed u¿yciem $1
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Nieprawid³owa deklaracja etykiety
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO i LABEL nieobs³ugiwane (u¿yj opcji -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Nie odnaleziono etykiety
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Identyfikator nie jest etykiet±
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Powtórna definicja etykiety
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Nieprawid³owa deklaracja typu zbiorowego
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Brak implementacji klasy $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Modu³ $1 nieu¿ywany w $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parametr $1 nieu¿ywany
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokalna zmienna $1 nieu¿ywana
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Warto¶c przypisana do $1 nie jest nigdzie u¿yta
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Warto¶c przypisana do $1 nie jest nigdzie u¿yta
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Lokalna(y) $1 $2 nie zosta³(a) u¿yta(y)
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Prywatne pole $1.$2 nieu¿ywane
+sym_n_private_identifier_only_set=05030_N_Warto¶c przypisana do lokalnego pola $1.$2 nie jest nigdzie u¿yta
+sym_n_private_method_not_used=05031_N_Metoda prywatna $1.$2 nieu¿ywana
+sym_e_set_expected=05032_E_Oczekiwano typu zbiorowego
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Nie wygl±da na to, ¿eby warto¶æ zwracana przez funkcjê by³a ustawiona
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Typ $1 jest ¼le wyrównany dla C w bie¿±cym rekordzie
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Nieznany identyfikator pola rekordu $1
+% The field doesn't exist in the record definition.
+sym_n_uninitialized_local_variable=05036_W_Nie wygl±da na to, ¿eby lokalna zmienna $1 by³a zainicjowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_n_uninitialized_variable=05037_W_Nie wygl±da na to, ¿eby zmienna $1 by³a zainicjowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Identyfikator nie wskazuje ¿adnej metody ani pola $1
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Znaleziono deklaracjê: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Element jest zbyt du¿y
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Nie znaleziono implementacji metody interfejsu "$1"
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" jest przestarza³y
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbolu "$1" nie da siê przenie¶æ na inne platformy
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" nie jest zaimplementowany
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Nie mo¿na utworzyæ unikalnego typu z tego typu
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Zmienna lokalna "$1" mo¿e nie byæ zainicjalizowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Zmienna "$1" mo¿e nie byæ zainicjalizowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Rozmiar listy parametrów przekracza 65535 bajtów
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Zmienne plikowe musz± byæ przekazywane przez referencje
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_U¿ycie wska¼nika far niedozwolone w tym miejscu
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Mo¿liwe nieprawid³owe wywo³anie konstruktora/destruktora
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Niewydajny kod
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Kod nie zostanie nigdy wykonany
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Nie mo¿na bezpo¶rednio wywo³aæ metod abstrakcyjnych
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Rejestr $1 waga $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Pominiêto ramkê stosu
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Metody obiektów i klas nie mog± byæ inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Wywo³ania procedur ze zmiennych proceduralnych nie mog± byæ inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Brak kodu dla procedury inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Brak dostêpu do zerowego elementu ansi/wide- lub longstringa, u¿yj (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Konstruktory i destruktory nie mog± byæ wywo³ywane w klauzuli 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Nie mo¿na wywo³aæ bezpo¶rednio metody obs³uguj±cej komunikaty
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Skok do bloku lub poza blok exception
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Break, Continue i Exit nie s± dozwolone w bloku finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Rozmiar parametrów przekroczy³ limit dla niektórych procesorów
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Rozmiar zmiennych lokalnych przekroczy³ limit dla dla niektórych procesorów
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Rozmiar zmiennych lokalnych przekroczy³ dopuszczalny limit
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK mo¿na u¿yæ tylko wewn±trz pêtli
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE mo¿na u¿yæ tylko wewn±trz pêtli
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Rozpoczêcie parsowania bloku asemblera w stylu $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Zakoñczenie parsowania bloku asemblera w stylu $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_¯aden identyfikator (poza etykietami) nie mo¿e zawieraæ @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_B³±d tworzenia offsetu rekordu
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET u¿yty bez identyfikatora
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE u¿yte bez identyfikatora
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Nie mo¿na u¿ywaæ lokalnych zmiennych i parametrów w tym miejscu
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Nale¿y tu u¿yæ OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Nale¿y u¿yæ tu $
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Mo¿na u¿yæ tylko jednego symbolu relokacyjnego
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Symbole relokacyjne mog± byæ tylko dodane
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Nieprawid³owe sta³e wyra¿enie
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Nie mo¿na u¿yæ symbolu relokacyjnego w tym miejscu
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Nieprawid³owa sk³adnia referencji
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Nie mo¿na osi±gn±æ $1 z tego kodu
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokalne symbole/etykiety nie s± dozwolone jako referencje
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Nieprawid³owe u¿ycie rejestru indeksu i bazy
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Mo¿liwy b³±d w obs³ugiwaniu pola obiektu
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Nieprawid³owa skala
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_U¿ycie wielu rejestrów indeksu
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Nieprawid³owy typ operandu
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Nieprawid³owy string jako operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE i @DATA nieobs³ugiwane
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Puste etykiety referencji s± niedozwolone
+asmr_e_expr_zero_divide=07025_E_Dzielenie przez zero
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Nieprawid³owe wyra¿enie
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sekwencja zignorowana: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Nieprawid³owa referencja symbolu
+asmr_w_fwait_emu_prob=07029_W_Fwait mo¿e powodowaæ problemy emulacji z emu387
+asmr_w_fadd_to_faddp=07030_W_$1 bez operandu przet³umaczone na $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instrukcja ENTER nie jest obs³ugiwana przez j±dro Linuksa
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Wywo³anie przeci±¿onej funkcji z poziomu asemblera
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Nieobs³ugiwany typ symbolu dla operandu
+asmr_e_constant_out_of_bounds=07034_E_Warto¶æ sta³a przekracza zakres
+asmr_e_error_converting_decimal=07035_E_B³±d konwersji liczby dziesiêtnej $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_B³±d konwersji liczby ósemkowej $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_B³±d konwersji liczby dwójkowej $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_B³±d konwersji liczby szesnastkowej $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 przet³umaczone na $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 jest przypisane do przeci±¿onej funkcji
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Nie mo¿na u¿yæ SELF poza metod±
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Nie mo¿na u¿yæ OLDEBP poza zagnie¿d¿on± procedur±
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedury nie mog± zwracaæ warto¶ci w kodzie asemblera
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nie obs³ugiwane
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Przyrostek okre¶laj±cy rozmiar nie pasuje do ¼ród³a lub celu
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Przyrostek okre¶laj±cy rozmiar nie pasuje do ¼ród³a lub celu
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_B³±d sk³adni asemblera
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Nieprawid³owa kombinacja opkodu i operandu
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_B³±d sk³adni asemblera w operandzie
+asmr_e_syn_constant=07050_E_B³±d sk³adni asemblera w sta³ej
+asmr_e_invalid_string_expression=07051_E_Nieprawid³owe wyra¿enie ze stringiem
+asmr_w_const32bit_for_address=07052_W_Sta³a $1 prawdopodobnie nie powinna byæ wska¼nikiem
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Nieznany opkod $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Nieprawid³owy opkod lub brak opkodu
+asmr_e_invalid_prefix_and_opcode=07055_E_Nieprawid³owa kombinacja prefiksu i opkodu: $1
+asmr_e_invalid_override_and_opcode=07056_E_Nieprawid³owa kombinacja override i opkodu: $1
+asmr_e_too_many_operands=07057_E_Zbyt du¿o operandów
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR zignorowane
+asmr_w_far_ignored=07059_W_FAR zignorowane
+asmr_e_dup_local_sym=07060_E_Zduplikowany symbol lokalny $1
+asmr_e_unknown_local_sym=07061_E_Niezdefiniowany symbol lokalny $1
+asmr_e_unknown_label_identifier=07062_E_Nieznana etykieta $1
+asmr_e_invalid_register=07063_E_Nieprawid³owa nazwa rejestru
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nieprawid³owa nazwa rejestru zmiennoprzecinkowego
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo nieobs³ugiwane
+asmr_e_invalid_float_const=07067_E_Nieprawid³owa sta³a zmiennoprzecinkowa $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Nieprawid³owe wyra¿enie zmiennoprzecinkowe
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Nieprawid³owy typ symbolu
+asmr_e_cannot_index_relative_var=07070_E_Nie mo¿na ideksowaæ rejestrem zmiennej lokalnej/parametru
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Stringi nie mog± byæ sta³ymi
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Nie okre¶lono typu zmiennej
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_brak powrotu do sekcji text w kodzie asemblera
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_To nie jest ani dyrektywa, ani symbol lokalny: $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_U¿ycie zdefiniowanej nazwy jako lokalnej etykiety
+asmr_e_dollar_without_identifier=07078_E_Brak identyfikatora przy znaku dolara
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bitowa sta³a u¿yta jako adres
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align nie jest przeno¶ne miêdzy platformami, u¿yj .balign lub .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Nie mo¿na odwo³ywaæ siê bezpo¶rednio do pól parametrów
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Nie mo¿na odwo³ywaæ siê bezpo¶rednio do pól obiektów/klas
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Nie okre¶lono rozmiaru operandu
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Nie mo¿na u¿yæ RESULT w tej funkcji
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" bez operandu przet³umaczone na "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" przet³umaczone na "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" przet³umaczone na "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Znak < niedozwolony w tym miejscu
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Znak > niedozwolony w tym miejscu
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN nieobs³ugiwane
+asmr_e_no_inc_and_dec_together=07094_E_Inc i Dec nie mog± wystêpowaæ razem
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Nieprawid³owa lista rejestrów dla movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Nieprawid³owa lista rejestrów dla opkodu
+asmr_e_higher_cpu_mode_required=07097_E_Ta instrukcja wymaga wy¿szego typu procesora ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Nie okre¶lono rozmiaru operandów, domy¶lne u¿ycie DWORD
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_B³±d sk³adni przy operandzie shifter
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Zbyt du¿o plików asemblera
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Wybrany typ wyj¶ciowy asemblera nieobs³ugiwany
+asmw_f_comp_not_supported=08002_F_Comp nieobs³ugiwany
+asmw_f_direct_not_supported=08003_F_Direct nieobs³ugiwane przy zapisywaniu bezpo¶rednim
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Alokacja danych jest dozwolona tylko w sekcji bss
+asmw_f_no_binary_writer_selected=08005_F_Nie wybrano sposobu zapisywania binariów
+asmw_e_opcode_not_in_table=08006_E_Asm: Brak opkodu $1 w tablicy
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 nieprawid³owa kombinacja opkodu i operandów
+asmw_e_16bit_not_supported=08008_E_Asm: 16bitowe referencje nieobs³ugiwane
+asmw_e_invalid_effective_address=08009_E_Asm: Nieprawid³owy adres efektywny
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 warto¶æ przekracza zakres $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Krótki skok poza zasiêg $1
+asmw_e_undefined_label=08013_E_Asm: Nieznana etykieta $1
+asmw_e_comp_not_supported=08014_E_Asm: Typ Comp nieobs³ugiwany dla tego celu
+asmw_e_extended_not_supported=08015_E_Asm: Typ Extended nieobs³ugiwany dla tego celu
+asmw_e_duplicate_label=08016_E_Asm: Zduplikowana etykieta $1
+asmw_e_redefined_label=08017_E_Asm: Etykieta powtórnie zdefiniowana $1
+asmw_e_first_defined_label=08018_E_Asm: Najpierw zdefiniowana tutaj
+asmw_e_invalid_register=08019_E_Asm: Nieprawid³owy rejestr $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Zmieniono ¼ród³owy system operacyjny
+exec_i_assembling_pipe=09001_I_Asemblowanie (potok) $1
+exec_d_cant_create_asmfile=09002_E_Nie mo¿na utworzyæ plików asemblera: $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Nie mo¿na utworzyæ pliku: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Nie mo¿na utworzyæ pliku: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 nie znaleziony, prze³±czenie na zewnêtrzn± asemblacjê
+exec_t_using_assembler=09006_T_U¿ywanie assemblera: $1
+exec_e_error_while_assembling=09007_E_B³±d asemblera, kod wyj¶cia $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Nie mo¿na wywo³aæ asemblera, b³±d $1 prze³±czenie na zewnêtrzn± asemblacjê
+exec_i_assembling=09009_I_Asemblowanie $1
+exec_i_assembling_smart=09010_I_Asemblowanie do linkowania smart $1
+exec_w_objfile_not_found=09011_W_Obiekt $1 nieodnaleziony, linkowanie mo¿e siê nie powie¶æ!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Biblioteka $1 nieodnaleziona, Linkowanie mo¿e siê nie powie¶æ!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_B³±d podczas linkowania
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Nie mo¿na wywo³aæ linkera, prze³±czenie na zewnêtrzne linkowanie
+exec_i_linking=09015_I_Linkowanie $1
+exec_e_util_not_found=09016_E_Narzêdzie $1 nieodnalezione, prze³±czenie na zewnêtrzne linkowanie
+exec_t_using_util=09017_T_Uruchamianie $1
+exec_e_exe_not_supported=09018_E_Tworzenie plików wykonywalnych nieobs³ugiwane
+exec_e_dll_not_supported=09019_E_Tworzenie bibliotek dynamicznych/wspó³dzielonych nieobs³ugiwane
+exec_i_closing_script=09020_I_Zamykanie skryptu $1
+exec_e_res_not_found=09021_E_Kompilator zasobów nieodnaleziony, prze³±czenie na tryb zewnêtrzny
+exec_i_compilingresource=09022_I_Kompilacja zasobu $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Modu³ $1 nie mo¿e byæ linkowany statycznie, prze³±czenie na linkowanie smart
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Modu³ $1 nie moze byæ linkowany smart, prze³±czenie na linkowanie statyczne
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Modu³ $1 nie mo¿e byæ linkowany dynamicznie, prze³±czenie na linkowanie statyczne
+exec_e_unit_not_smart_or_static_linkable=09026_E_Modu³ $1 nie mo¿e byæ linkowany statycznie ani smart
+exec_e_unit_not_shared_or_static_linkable=09027_E_Modu³ $1 nie mo¿e byæ linkowany statycznie ani dynamicznie
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_Nie mo¿na przetwarzaæ pliku $1
+execinfo_f_cant_open_executable=09029_F_Nie mo¿na otworzyæ pliku wykonywalnego $1
+execinfo_x_codesize=09030_X_Rozmiar kodu: $1 bajtów
+execinfo_x_initdatasize=09031_X_Rozmiar zainicjowanych danych: $1 bajtów
+execinfo_x_uninitdatasize=09032_X_Rozmiar niezainicjowanych danych: $1 bajtów
+execinfo_x_stackreserve=09033_X_Zarezerwowany rozmiar stosu: $1 bajtów
+execinfo_x_stackcommit=09034_X_Aktywny rozmiar stosu: $1 bajtów
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Poszukiwanie modu³u: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Otwieranie PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nazwa PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Flagi PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Crc PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Czas PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Plik PPU zbyt krótki
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Nieprawid³owy nag³ówek PPU (brak PPU na pocz±tku)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Nieprawid³owa wersja PPU $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU jest skompilowany dla innego procesora
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU skompilowany dla innej platformy docelowej
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_¬ród³o PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Zapisywanie $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Nie mo¿na zapisaæ pliku PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_B³±d podczas czytania pliku PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Nieoczekiwane zakoñczenie pliku PPU
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Nieprawid³owy plik PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_B³±d podczas liczenia PPU Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nieprawid³owa nazwa modu³u: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Zbyt du¿o modu³ów
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Zapêtlone nawi±zanie pomiêdzy modu³ami $1 i $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Nie mo¿na skompilowaæ modu³u $1, brak ¼róde³
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Nie mo¿na znale¼æ modu³u $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Nie znaleziono modu³u $1 ale istnieje $2
+unit_f_unit_name_error=10024_F_Szukano modu³u $1 ale znaleziono tylko $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Kompilowanie modu³u System wymaga u¿ycia prze³±cznika -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Napotkano $1 b³êdów podczas kompilacji modu³u, zatrzymanie
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_£adowanie z $1 ($2) modu³u $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Rekompilacja $1, suma kontrolna zmieniona dla $2
+unit_u_recompile_source_found_alone=10029_U_Rekompilacja $1, znaleziono tylko ¼ród³o
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Rekompilacja modu³u, biblioteka statyczna jest starsza ni¿ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Rekompilacja modu³u, biblioteka wspó³dzielona jest starsza ni¿ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Rekompilacja modu³u, obj i asm s± starsze ni¿ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Rekompilacja modu³u, obj jest starszy ni¿ asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Parsowanie czê¶ci interface modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Parsowanie czê¶ci implementation modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Drugie za³adowanie pliku $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Sprawdzanie pliku PPU: $1 czas: $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Warunek $1 nie by³ ustawiony na pocz±tku ostatniej kompilacji modu³u $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Warunek $1 nie by³ ustawiony na pocz±tku ostatniej kompilacji modu³u $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Nie mo¿na skompilowaæ modu³u $1, znaleziono zmodyfikowane pliki include
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Plik $1 jest nowszy ni¿ plik $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_U¿ycie modu³u skompilowanego z innym formatem zapisu liczb zmiennoprzecinkowych
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_£adowanie modu³ów z czê¼ci interface modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_£adowanie modu³ów z czê¼ci implementation modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Zmieniona suma CRC sekcji interface modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Zmieniona suma CRC sekcji implementation modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Zakoñczono kompilacjê modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Dodanie zale¿no¶ci $1 do $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Ominiêcie prze³adowania modu³u, to ten sam modu³: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Ominiêcie prze³adowania modu³u, trwa druga kompilacaja: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Flaga do prze³adowania: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Wymuszone prze³adowanie modu³u
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Poprzedni stan modu³u $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ju¿ kompilowane $1, ustawienie drugiej kompilacji
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_£adowanie modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Zakoñczenie ³adowania modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Rejestrowanie nowego modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Powtórne odnajdowanie modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Ominiêcie powtórnego odnajdowania modu³u $1, ci±gle ³aduje u¿ywane modu³y
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [opcje] <nazwapliku> [opcje]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Obs³ugiwany tylko jeden plik ¼ród³owy
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Plik DEF mo¿e byæ stworzony tylko pod OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Zagnie¿d¿enia plików nieobs³ugiwane
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Brak nazwy pliku w lini poleceñ
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Brak opcji w pliku konfiguracyjnym $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Nieprawid³owy parametr: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? wy¶wietla pomoc
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Za du¿o zagnie¿d¿onych plików konfiguracyjnych
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Nie mo¿na otworzyæ pliku konfiguracyjnego $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Czytanie dalszych opcji z $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Cel jest ju¿ ustawiony na: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Biblioteki wspó³dzielone nie s± obs³ugiwane w DOSie, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Za du¿o IF(N)DEF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Za du¿o ENDIF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Warunek wci±¿ otwarty na koñcu pliku
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Generowanie informacji do debugowania nieobs³ugiwane przez t± wersjê kompilatora
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Spróbuj przekompilowaæ z -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_U¿ycie przedawnionego prze³±cznika $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_U¿ycie przedawnionego prze³±cznika $1, proszê u¿yæ $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Prze³±czenie na domy¶lny zapis asemblera
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Wybrane wyj¶cie asemblera "$1" nie jest zgodne z "$2"
+option_asm_forced=11022_W_Wymuszenie u¿ycia asemblera "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Czytanie opcji z pliku $1
+% Options are also read from this file
+option_using_env=11027_T_Czytanie opcji ze zmiennej ¶rodowiskowej $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Obs³ugiwanie opcji "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** naci¶nij enter ***
+option_start_reading_configfile=11030_H_Rozpoczêto czytanie pliku konfiguracyjnego $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Zakoñczono czytanie pliku konfiguracyjnego $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretowanie opcji "$1"
+option_interpreting_firstpass_option=11036_D_Interpretowanie opcji "$1"
+option_interpreting_file_option=11033_D_Interpretowanie opcji plikowej "$1"
+option_read_config_file=11034_D_Czytanie pliku konfiguracyjnego "$1"
+option_found_file=11035_D_Znaleziono nazwê pliku ¼ród³owego "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Nieznana strona kodowa
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler wersja $FPCVERSION [$FPCDATE] dla $FPCCPU
+Copyright (c) 1993-2005 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler wersja $FPCVERSION
+
+Data kompilatora : $FPCDATE
+Platforma docelowa: $FPCCPU
+
+Wspierane platformy:
+ $OSTARGETS
+
+Wspierane instrukcje CPU:
+ $INSTRUCTIONSETS
+
+Wspierane instrukcje FPU:
+ $FPUINSTRUCTIONSETS
+
+Ten program jest oparty na GNU General Public Licence
+Przeczytaj COPYING.FPC aby dowiedzieæ siê wiêcej
+
+Zg³aszanie b³êdów, sugestii itp.
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_wpisz + po prze³±czniku aby go aktywowaæ, - aby dezaktywowaæ
+**1a_kompilator nie usuwa wygenerowanego pliku asemblera
+**2al_wypisuje numery linii do pliku asemblera
+**2an_wypisuje informacje o wêz³ach do pliku asemblera
+*L2ap_u¿ycie potoków zamiast tymczasowych plików asemblera
+**2ar_wypisuje alokacje/zwalnianie rejestrów do pliku asemblera
+**2at_wypisuje tymczasowe alokacje/zwalnianie do pliku asemblera
+**1A<x>_format wyj¶ciowy:
+**2Adefault_u¿ycie domy¶lnego asemblera
+3*2Aas_asemblacja przy u¿yciu GNU AS
+3*2Anasmcoff_plik coff (Go32v2) przy u¿yciu Nasm
+3*2Anasmelf_plik elf32 (Linux) przy u¿yciu Nasm
+3*2Anasmwin32_plik obj (Win32) przy u¿yciu Nasm
+3*2Anasmwdosx_plik obj (Win32/WDOSX) przy u¿yciu Nasm
+3*2Awasm_plik obj przy u¿yciu Wasm (Watcom)
+3*2Anasmobj_plik obj przy u¿yciu Nasm
+3*2Amasm_plik obj przy u¿yciu Masm (Microsoft)
+3*2Atasm_plik obj przy u¿yciu Tasm (Borland)
+3*2Aelf_bezpo¶redni zapis do pliku elf32 (Linux)
+3*2Acoff_bezpo¶redni zapis do pliku coff (Go32v2)
+3*2Apecoff_bezpo¶redni zapis do pliku pecoff (Win32)
+4*2Aas_asemblacja przy u¿yciu GNU AS
+6*2Aas_o-file (Unix) przy u¿yciu GNU AS
+6*2Agas_asembler GNU Motorola
+6*2Amit_sk³adnia MIT (dawniej GAS)
+6*2Amot_standardowy asembler Motorola
+A*2Aas_asemblacja przy u¿yciu GNU AS
+P*2Aas_asemblacja przy u¿yciu GNU AS
+S*2Aas_asemblacja przy u¿yciu GNU AS
+**1b_generuje informacje przegl±darki
+**2bl_generuje informacje o lokalnych symbolach
+**1B_budowanie wszystkich modu³ów
+**1C<x>_opcje generacji kodu:
+**2Cc<x>_ustawia domy¶lny sposób wywo³ania funkcji/procedur na <x>
+**2CD_tworzenie tak¿e bibliotek dynamicznych (niedostêpne)
+**2Ce_kompilacja z emulowanymi opkodami zmiennoprzecinkowymi
+**2Cf<x>_ustawia u¿ywany zbiór instrukcji FPU na <x> (u¿yj "fpc -i", aby zobaczyæ mo¿liwe warto¶ci)
+**2Cg_generowanie kodu PIC
+**2Ch<n>_rozmiar sterty w bajtach (pomiêdzy 1023 i 67107840)
+**2Ci_sprawdzanie operacji wej¶cia/wyj¶cia
+**2Cn_pominiêcie etapu linkowania
+**2Co_sprawdzanie przepe³nienia liczb ca³kowitych
+**2Cp<x>_ustawia u¿ywany zbiór instrukcji na <x> (u¿yj "fpc -i", aby zobaczyæ mo¿liwe warto¶ci)
+**2Cr_sprawdzanie zakresu
+**2CR_sprawdzanie poprawno¶ci wywo³ywania metod obiektów
+**2Cs<n>_ustawienie rozmiar stosu na <n>
+**2Ct_sprawdzanie stosu
+**2CX_tworzenie bibliotek smartlinked
+**1d<x>_zdefiniowanie symbolu <x>
+*O1D_generacja pliku DEF
+*O2Dd<x>_ustawienie opisu na <x>
+**2Dv<x>_ustawienie wersji DLL na <x>
+*O2Dw_aplikacja PM
+**1e<x>_ustawienie ¶cie¿ki do asemblera i linkera
+**1E_to samo co -Cn
+**1F<x>_ustawianie nazw i ¶cie¿ek:
+**2Fa<x>[,y]_wczytuje <x> (i [y]) zanim zostani± wczytane modu³y z sekcji USES
+**2Fc<x>_ustawienie strony kodowej ¼róde³ na <x>
+**2FD<x>_ustawienie katalogu z narzêdziami kompilatora
+**2Fe<x>_przekierowanie komunikatów o b³êdach do pliku <x>
+**2FE<x>_ustawienie katalogu dla skompilowanych programów/modu³ów na <x>
+**2Fi<x>_dodanie <x> do ¶cie¿ki include'ów
+**2Fl<x>_dodanie <x> do ¶cie¿ki bibliotek
+**2FL<x>_u¿ycie <x> jako dynamicznego linkera
+**2Fo<x>_dodanie <x> do ¶cie¿ki obiektów
+**2Fr<x>_³adowanie pliku <x> z komunikatami b³êdów
+**2Fu<x>_dodanie <x> do ¶cie¿ki modu³ów
+**2FU<x>_ustawienie katalogu dla skompilowanych modu³ów, uniewa¿nia -FE
+*g1g_generacja informacji debuggera:
+*g2gc_generacja kodu sprawdzaj±cego wska¼niki
+*g2gd_u¿ycie dbx
+*g2gg_u¿ycie gsym
+*g2gh_u¿ycie modu³u ¶ledzenia sterty(do wykrywania wycieków pamiêci)
+*g2gl_u¿ycie modu³u z informacjami o numerach linii programu
+*g2gv_generacja kodu mo¿liwego do ¶ledzenia przy pomocy valgrind
+*g2gw_generacja informacji debuggera dwarf
+**1i_informacje
+**2iD_zwraca datê kompilatora
+**2iV_zwraca wersjê kompilatora
+**2iSO_zwraca OS kompilatora
+**2iSP_zwraca typ procesora kompilatora
+**2iTO_zwraca docelowy OS
+**2iTP_zwraca docelowy typ kompilatora
+**1I<x>_dodanie <x> do ¶cie¿ki include'ów
+**1k<x>_podanie <x> do linkera
+**1l_wypisanie logo
+**1M<x>_ustawia tryb jêzyka na <x>
+**2Mfpc_dialekt free pascala (domy¶lny)
+**2Mobjfpc_w³±czenie niektórych rozszerzeñ Delphi 2
+**2Mdelphi_kompatybilno¶æ z Delphi
+**2Mtp_kompatybilno¶æ z TP/BP 7.0
+**2Mgpc_kompatybilno¶æ z gpc
+**2Mmac_kompatybilno¶æ z dialektami pascala na Macintosha
+**1n_zignorowanie standardowego pliku konfiguracyjnego
+**1N<x>optymalizacje wêz³ów drzewa
+**2Nu_rozwijanie pêtli
+**1o<x>_zmiana nazwy skompilowanego programu na <x>
+3*1O<x>_optymalizacje:
+3*2Og_generacja mniejszego kodu
+3*2OG_generacja szybszego kodu (domy¶lne)
+3*2Or_trzymanie niektórych zmiennych w rejestrach
+3*2Ou_w³±czenie niepewnych optymalizacji (zobacz w dokumentacji)
+3*2O1_optymalizacje pierwszego stopnia (szybkie)
+3*2O2_optymalizacje drugiego stopnia (-O1 + wolniejsze)
+3*2O3_optymalizacje trzeciego stopnia (powtarzane maksymalnie 5 razy -02)
+3*2Op<x>_procesor docelowy:
+3*3Op1_ustawienie procesora docelowego na 386/486
+3*3Op2_ustawienie procesora docelowego na Pentium/PentiumMMX (tm)
+3*3Op3_ustawienie procesora docelowego na PPro/PII/c6x86/K6 (tm)
+6*2Og_generacja mniejszego kodu
+6*2OG_generacja szybszego kodu (domy¶lne)
+6*2Ox_maksymalne optymalizacje (ci±gle zawieraj± B£ÊDY!!!)
+6*2O0_ustawia docelowy procesor na MC68000
+6*2O2_ustawia docelowy procesor na MC68020+ (domy¶lne)
+**1pg_generacja kodu do profilowania przy pomocy gprof (definiuje FPC_PROFILE)
+**1R<x>_styl asemblera u¿ywanego w ¼ród³ach:
+**2Rdefault_u¿ycie domy¶lnego asemblera
+3*2Ratt_styl AT&T
+3*2Rintel_styl Intel
+6*2RMOT_styl Motorola
+**1S<x>_opcje sk³adni:
+**2S2_to samo co -Mobjfpc
+**2Sc_wspieranie operatorów C (*=,+=,/= oraz -=)
+**2Sa_do³±czanie kodu asercji
+**2Sd_to samo co -Mdelphi
+**2Se<x>_opcje b³êdów. <x> jest kombinacj±:
+**3*_<n> : kompilator zatrzymuje siê po <x> b³êdach (domy¶lnie 1)
+**3*_w : kompilator zatrzymuje siê tak¿e na ostrze¿eniach
+**3*_n : kompilator zatrzymuje siê tak¿e na notkach
+**3*_h : kompilator zatrzymuje siê tak¿e na podpowiedziach
+**2Sg_zezwolenie na LABEL i GOTO
+**2Sh_u¿ycie ansistringów
+**2Si_wspieranie INLINE w stylu C++
+**2SI<x>_ustawia styl interfejsów na <x>
+**3SIcom_interfejsy kompatybilne z COM (domy¶lne)
+**3SIcorba_interfejsy kompatybilne z CORBA
+**2Sm_wspieranie makr jak w C (opcja globalna)
+**2So_to samo co -Mtp
+**2Sp_to samo co -Mgpc
+**2Ss_konstruktory musz± mieæ nazwê init (destruktory - done)
+**2St_zezwalanie na s³owo kluczowe static w obiektach
+**1s_pominiêcie wywo³ania asemblera i linkera
+**2sh_generacja skryptu do linkowania na ho¶cie
+**2st_generacja skryptu do linkowania na celu
+**2sr_ominiêcie fazy alokowania rejestrów (u¿ywaj z -alr)
+**1T<x>_docelowy system operacyjny:
+3*2Temx_OS/2 na EMX (wliczaj±c EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_DJ Delorie DOS extender - wersja 2
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_DOS extendery zgodne z Watcomem
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_32-bitowy Windows
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (nie wspierane)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin i MacOS X na PowerPC
+P*2Tlinux_Linux na PowerPC
+P*2Tmacos_MacOS (klasyczny) na PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_usuniêcie symbolu <x>
+**1U_opcje modu³ów:
+**2Un_pominiêcie sprawdzania nazwy modu³u
+**2Ur_generacja modu³u do wydania (release)
+**2Us_kompilacja modu³u system
+**1v<x>_obszerne opisy. <x> jest kombinacj± nastêpuj±cych liter i cyfr:
+**2*_e : pokazuje b³êdy (domy¶lne) 0 : nic nie pokazuje (oprócz b³êdów)
+**2*_w : pokazuje ostrze¿enia u : pokazuje informacje o modu³ach
+**2*_n : pokazuje notki t : pokazuje próbowane/u¿yte pliki
+**2*_h : pokazuje podpowiedzi c : pokazuje warunki
+**2*_i : pokazuje ogólne informacje d : pokazuje informacje debugowania
+**2*_l : pokazuje numery lini r : tryb kompatybilno¶ci z Rhide/GCC
+**2*_a : pokazuje wszystko x : informacje o pliku exe (tylko Win32)
+**2*_v : zapisuje plik fpcdebug.txt p : zapisuje tree.log z drzewem
+**2*_ z du¿± ilo¶ci± informacji parsowania
+3*1W<x>_opcje dla Win32 i podobnych
+3*2WB_tworzenie relokacyjnego obrazu
+3*2WB<x>_ustawienie bazy obrazu na szesnastkow± warto¶æ <x>
+3*2WC_aplikacja konsolowa
+3*2WD_u¿ycie DEFFILE do eksportu funkcji z DLLa lub EXE
+3*2WF_aplikacja pe³noekranowa (tylko OS/2)
+3*2WG_aplikacja graficzna
+3*2WN_nie generuje kodu relokacji (potrzebne do debugowania)
+3*2WR_generuje kod relokacji
+P*2WC_aplikacja konsolowa (tylko MacOS)
+P*2WG_aplikacja graficzna (tylko MacOS)
+P*2WT_aplikacja narzêdziowa (narzêdzie MPW, tylko MacOS)
+**1X_opcje plików wykonywalnych:
+**2Xc_podaje --shared do linkera (tylko Unix)
+**2Xd_nie u¿ywa standardowej ¶cie¿ki bibliotek (potrzebne do cross-kompilacji)
+**2XD_linkowanie dynamiczne (definiuje FPC_LINK_DYNAMIC)
+**2Xm_generuje link map
+**2XM<x>_ustawia nazwê g³ównego bloku programu (domy¶lnie 'main')
+**2XP<x>_poprzedza nazwê binutils tekstem <x>
+**2Xr<x>_ustawia ¶cie¿kê bibliotek na <x> (potrzebne do cross-kompilacji)
+**2Xs_wyciêcie wszystkich symboli z pliku
+**2XS_linkowanie statycznie (domy¶lne)(definiuje FPC_LINK_STATIC)
+**2Xt_linkuje z bibliotekami statycznymi (podaje -static do linkera)
+**2XX_linkowanie smart (definiuje FPC_LINK_SMART)
+**1*_
+**1?_pokazanie pomocy
+**1h_pokazanie pomocy bez zatrzymywania
+]
+
+#
+# The End...
diff --git a/compiler/msg/errorptd.msg b/compiler/msg/errorptd.msg
new file mode 100644
index 0000000000..bc9684ab2a
--- /dev/null
+++ b/compiler/msg/errorptd.msg
@@ -0,0 +1,2337 @@
+%%% Reordering of errorptd.msg respective to errore.msg
+%%% Contains all comments from errorptd.msg
+%%% Reordering of msg/errorptd.msg respective to msg/errore.msg
+%%% Contains all comments from msg/errorptd.msg
+%%% Reordering of msg/errorptd.msg respective to msg/errore.msg
+%%% Contains all comments from msg/errorptd.msg
+general_t_compilername=01000_T_Compilador usado: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Sist.Op. da compilacao: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Sist.Op. de execucao: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Caminho para os executaveis: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_Caminho para as units: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Caminho para os includes: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Caminho para as libraries: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Caminho para modulos objeto: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Linhas compiladas, $2 seg
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Memoria insuficiente para esta compilacao
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Gravando arquivo com os Resource strings: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Gravando arquivo com os Resource strings: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Erro fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Erro:
+% Prefix for Errors
+general_i_warning=01014_I_Aviso:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Sugestao:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_Caminho "$1" nao existe
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilacao abortada
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Fim inesperado de arquivo
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String nao fechado na mesma linha
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_caracter invalido "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Erro de sintaxe "$1" esperado mas "$2" encontrado
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Comecou a ler include file $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Encontrado comentario de nivel $1
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Ignorada diretiva "$1" do compilador
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Diretiva de compilador invalida "$1"
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Diretiva global do compilador em local invalido
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante caracter invalida
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Arquivo "$1" nao encontrado
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Includefile "$1" nao encontrado
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Campos de "record" podem ser alinhados somente em 1, 2, 4, 8, 16 ou 32 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1, 2, 4, 8, 16 and 32 are valid in this case.
+scan_w_only_pack_enum=02016_W_Variaveis do tipo "enumerated" podem ser salvas somente em 1, 2 ou 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_$ENDIF esperado para $1 $2 definidos em $3 na linha $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Erro de sintaxe na interpretacao(parse) de uma expressao de compilacao condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Avaliacao de uma expressao de compilacao condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_O tamanho maximo de uma macro esta limitado a 255 caracteres
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sem correspondente IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Definido pelo usuario: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Definido pelo usuario: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Definido pelo usuario: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Definido pelo usuario: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Definido pelo usuario: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Definido pelo usuario: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Macro que substitui palavra chave nao tem efeito
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Overflow no buffer de macros durante leitura/expansao de macro
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Mais de 16 niveis de aninhamento de macro.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Diretivas de compilador nao sao aceitas em comentarios tipo //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Tratando diretiva "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 encontrado
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 encontrado $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Desprezando ate...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Tecle <return> para continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Diretiva nao suportada "$1"
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Diretiva de compilador invalida "$1"
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_De volta em $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Application type nao suportado: "$1"
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE nao suportado pelo Sist.Op. de execucao
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_Diretiva DESCRIPTION nao e suportada pelo Sist.Op. de execucao
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_Diretiva VERSION nao e suportada pelo Sist.Op. de execucao
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_Diretiva VERSION e so para executaveis ou DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Formato da diretiva VERSION errado "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Valor invalido na diretiva ASMMODE "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Nao e possivel trocar tipo de assembly dentro de 1 trecho em assembly, a diretiva "$1" sera valida so no proximo trecho assembly
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Valor de diretiva invalido, use ON/OFF ou +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Resource files nao sao suportados no Sist.Op. de execucao
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Variavel de ambiente "$1" nao encontrada
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valor invalido para diretiva MAXFPUREGISTERS
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_O Sist.Op. de execucao suporta somente 1 resource file
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Suporte a macros foi desativado
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_Tipo de interface invalido. Valores validos sao COM, CORBA or DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID so e suportada pelo Sist.Op. de execucao PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME so e suportada pelo Sist.Op. de execucao PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Constantes string nao podem exceder 255 caracteres
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Numero de include files aninhados excede 16 niveis
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Numero maximo de niveis de PUSH excedido
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP nao precedido de PUSH
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro ou variavel de tempo de compilacao "$1" vazia ou sem valor atribuido
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Valor de diretiva invalido, use ON/OFF/DEFAULT ou +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Diretiva Mode "$1" nao permitida aqui
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Variavel de tempo de compilacao "$1" nao definida
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Encontrado caracter com codigo UTF-8 maior do que 65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_String UTF-8 com caracteres invalidos
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_Encontrada assinatura UTF-8, conteudo do arquivo sera tratado como sendo UTF-8
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+parser_e_syntax_error=03000_E_Parser - Erro de sintaxe
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT procedure nao pode ser local tem que ser global
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo de procedure "$1" ignorado
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_OVERLOAD usado para "$1". Todas declaracoes devem usar OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Funcoes exportadas com o nome externo "$1" igual
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Funcoes exportadas com o index externo "$1" igual
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Valor de index externo de funcao exportada invalido
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Informacoes de depuracao para DLL relocavel ou para executavel $1 nao funcionaram. Depuracao ignorada.
+parser_w_parser_win32_debug_needs_WN=03012_W_Para permitir depuracao de codigo win32 voce precisa desabilitar opcao de relocacao com a opcao -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Nome do metodo Constructor deve ser INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Nome do metodo Destructor deve ser DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Uso de procedures tipo INLINE como no C++ nao suportado
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Metodos Constructor devem estar em escopo "public" na classe
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Metodos Destructor devem estar em escopo "public" na classe
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Classes devem ter somente 1 metodo destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Declaracao de classes em escopo "local" nao permitida. Elas devem estar em escopo "global"
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Classes sem metodos e nao derivadas de outras(anonimas) nao sao permitidas
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_Nao ha entrada na VMT para o objeto "$1"
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista de argumentos invalida(tipos de dados diferem dos parametros)
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Numero de parametros errado
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Metodo que esta fazendo overload e base do overload "$1" sao de tipo diferente (function/procedure)
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Metodo tem mesma lista parametros do metodo sobre o qual queremos fazer overload
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Tipo de retorno ou qualificador da funcao difere na declaracao forward "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Header de funcao "$1" nao combina com o do forward : nome de variável trocado $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Valores especificados em tipos enumerados devem estar em ordem crescente
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_"With" nao pode ser usado para variaveis in segmentos diferentes de memoria
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Mais de 31 funcoes aninhadas
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Erro de "range" durante apuracao de constantes
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Erro de "range" durante apuracao de constantes
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Condicao duplicada em 1 comando case
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_O valor superior de 1 "range" especificado num "case" e menor que o valor inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Constantes do tipo "class" ou "object" nao sao permitidas
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Nao e permitido uso de variaveis tipo "function" em functions que sofrerao overload
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_Tamanho de string deve estar entre 1 e 255 bytes
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_Use a sintaxe extendida de NEW e DISPOSE para instancias de objetos
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_Nao ha sentido em usar NEW ou DISPOSE para pointers untyped
+parser_e_no_new_dispose_on_void_pointers=03044_E_Nao e possivel usar NEW e DISPOSE para pointers untyped
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Identificador de classe ou objeto esperado antes do ponto
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identificador de type nao permitido neste contexto
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Metodo esperado apos o ponto
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Header de procedure/funcao "$1" nao identifica nenhum método desta classe
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procedure ou function $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante de ponto flutuante invalida
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_"FAIL" so pode ser usado em constructors
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Metodos Destructor nao podem ter parametros
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Somente metodos de classe podem ser usados numa referencia de classe
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Somente metodos da classe podem ser acessados em metodos de classe
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Constante usada numa clausula de um comando "case" nao combina com o tipo da variavel do "case"
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_O simbolo nao pode ser exportado de 1 library. So procedures ou functions
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Um método herdado esta escondido(hidden) por "$1". Verifique se nao tem que usar a diretiva OVERRIDE
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Nao ha metodo em classe ancestral com este nome para sofrer overriden : "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Faltou a clausula "read" na declaracao da propriedade
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Descontinuada
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Simbolo invalido para acesso a uma propriedade(a propriedade e 1 array?)
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Campo de objeto declarado como protected nao pode ser acessado aqui
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Campo de objeto declarado como private nao pode ser acessado aqui
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_metodos envolvidos em override devem ter o mesmo tipo de retorno: "$2" faz override em "$1" que tem outro tipo de retorno
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Functions/procedures nao podem ser declaradas aninhadas em functions/procedures que serao exportadas
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_metodos nao podem ser exportados
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_argumentos de chamadas por referencia tem que ter mesmo atributo que o parametro correspondente: Achado "$1" expected "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Metodo nao e de classe ancestral da que o esta chamando
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_Tentativa de usar "SELF" fora de um metodo
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_so pode usar uma chamada no formato classe.metodo dentro de um metodo
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso de ':' em local invalido
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Erro de range na declaracao de set: Elemento(s) duplicado(s) ou fora de faixa p/o tipo de dado
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Esperada pointer para um objeto
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Expressao deve ser uma chamada a um constructor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Expressao deve ser uma chamada a um destructor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Campos declarados em ordem diferente da declaracao do record
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_O tipo de expressao deve ser de class ou de record
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Subrotinas/metodos do tipo "procedure" nao podem retornar valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Constructors e destructors devem ser metodos
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Um dos operandos nao esta na definicao deste operador
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossivel overload com dados do mesmo tipo
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Combinacao de tipos do operador, dos argumentos e tipo de retorno incompativel
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Uso de raise nao e possivel aqui
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Esta sintaxe de new ou dispose nao pode ser aplicada a classes
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Overload de procedures esta desabilitado(ver diretiva -S)
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Este tipo de operador nao pode sofrer overload
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Function que faca overload no operador = deve retornar "boolean"
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Somente metodos virtuais podem ser declarados "abstract"
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Feature nao suportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_A mistura de diferentes tipos de objetos(class, object, interface, etc) nao e permitida
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Diretiva desconhecida foi ignorada: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute pode ser usado em linha que declare somente 1 variavel e redefinir variavel ou "typed constant"
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute so pode redefinir 1 variavel ou constante
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Nao pode usar valor inicial em linha que declare mais de 1 variavel
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Metodos abstract so podem ser declarados. Nao podem conter codigo
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Esta funcao que está sofrendo overload nao pode ser local (deve aparecer na interface)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Objeto/classe contem metodos virtuais mas nao contem contructor em "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definida: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro liberada ou "des-definida": $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 assumiu valor $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando "unit" $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Interpretando "interface" da "unit" $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Interpretando "implementation" da "unit" $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Recompilando $1
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Propriedade para sofrer override nao existe
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Tentativa de definir propriedade default para classe que ja tem 1 default
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_A propriedade default deve ser uma "array property"
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtual constructors podem ser usados somente para classes
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Nao ha propriedade default disponivel(nem por heranca)
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_A classe nao pode ter uma "published section", use a diretiva {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_A declaracao com forward da classe "$1" precisa ser resolvida aqui para poder usar esta classe como ancestral
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Nao pode fazer overload de operadores locais
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_A diretiva "$1" nao e permitida secao "interface"
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_A diretiva "$1" nao e permitida secao "implementation"
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_A diretiva "$1" nao e permitida na area de declaracao de variaveis de 1 procedure/function
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Procedure/function ja foi declarada como Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Nao pode usar EXPORT e EXTERNAL simultaneamente
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" ainda nao e suportada em "inline procedure/function"
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_O uso de INLINE esta desabilitado(diretiva $I)
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Avisa que gravou log do simbolo $1 gerado pelo "symbol browser"
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Pode estar faltando uma "pointer dereference". Meramente um comentario p/questoes de sintaxe em relacao ao Delphi p/exemplo
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Tipo de assembly nao suportado
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Diretiva "$1" conflita com outras diretivas
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Interface/implementation "calling conventions" nao combinam(cdecl?)
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_A propriedade nao pode ter valor default(e tipo array ou set?)
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_O valor default de 1 propriedade deve ser uma constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Simbolo nao pode ser published. Somente propriedades e variaveis "class type"
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Propriedades com este tipo de dados nao podem ser "published"
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Procedures/functions que sao exportadas de DLL's devem ter 1 "external name"
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Divisao por zero
+% There is a division by zero encounted
+parser_e_invalid_float_operation=03139_E_Operacao de ponto flutuante invalida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Fim da faixa menor que o inicio da faixa
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_Constante string "$1" e maior que a declaracao da variavel string "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Constante string maior do que o "array of char" a qual esta sendo atribuida
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expressao invalida apos uma diretiva
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Metodos declarados com a diretiva {message}(message handlers) so podem ter 1 parametro e recebido por referencia
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Label de mensagem duplicado: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_"Self" so pode ser usado como parametro explicito em metodos declarados com diretiva {message}(message handlers)
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Variaveis "Threadvars" so podem ser "static" ou "global"
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_"Direct assembly" nao e suportado quando usando formato binario de saida
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Nao carregue OBJPAS unit com "uses", use \{\$mode objfpc\} ou \{\$mode delphi\} ao inves disto
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_Nao e possivel fazer OVERRIDE em metodos de "object's"
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Tipos de dados que requeiram inicializacao/finalizacao nao podem ser usados em registros "variant"
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings so podem ser declarados static ou global
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_"Exit" com argumento neste contexto, nao e permitido
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Simbolo de tipo de memoria deve ser booleano
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Este simbolo nao e permitido como simbolo memoria
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_So e permitido publicar classes compiladas com a diretiva $M+
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Esperada diretiva de procedure
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_O valor do "index" de uma propriedade deve ser do tipo ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nome de procedure/function que sera exportada tem que ter no minimo 2 caracteres
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Nao foi possivel gerar 1 DEFFILE para as variaveis globais da "unit"
+parser_e_dlltool_unit_var_problem2=03161_E_Compile sem a opcao -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Voce precisa de ObjFpc (-S2) ou Delphi (-Sd) mode para compilar este modulo
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Nao e possivel exportar functions/procedures para este Sist.Op. $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exportacao de variaveis nao e permitida no Sist.Op. $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintaxe de declaracao GUID invalida
+parser_w_interface_mapping_notfound=03168_W_Procedure/function "$1" nao encontrada em contexto aplicavel para implementar $2.$3
+parser_e_interface_id_expected=03169_E_Esperado identificador de interface
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Tipo "$1" nao pode ser usado como "array index type"
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Constructors/destructors nao sao permitidos em interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Especificacoes de visibilidade nao podem ser usadas em INTERFACES
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Interfaces nao podem conter definicoes de campos
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Nao e permitido declarar procedures locais como EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Alguns campos antes de "$1" nao foram inicializados
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Alguns campos antes de "$1" nao foram inicializados
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Alguns campos apos "$1" nao foram inicializados
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_A diretiva VarArgs usada em procedure/function nao CDecl nem External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self deve ser 1 parametro recebido p/valor(nao pode ser uma variavel/constante)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interface "$1" precisa ter 1 identificacao GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Campo de classe ou nome de metodo desconhecido "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_"Calling convention" "$2" substituira a "$1"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_"Typed" constantes do tipo "procedure of object" so podem ser inicializadas com NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Valor default so pode ser atribuido a 1 parametro
+parser_e_default_value_expected_for_para=03185_E_Parametro default requerido para "$1"
+parser_w_unsupported_feature=03186_W_Use de feature nao suportada
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Parametros passados a functions/procedures em C devem ser passados por referencia(pointer)
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Array de constantes deve ser o ultimo argumento de uma chamada do C
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_O "type" "$1" ja foi criado, tentativa de redefinicao
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Functions/procedures declaradas CDECL nao suportam funcoes built in do compilador FPC
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Functions/procedures declaradas CDECL devem ser chamadas com string de tamanho igual ao declarado no cabecalho da Function/procedure
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Variaveis "threadvar" nao podem ser inicializadas
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_A diretiva MESSAGE so e permitida em Classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure/Function esperada
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Diretiva de "calling convention" ignorada: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE nao pode ser usado em objetos
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Cada argumento tem sua devida posicao
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Cada argumento tem sua posicao especifica
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Posicao do argumento desconhecida
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Esperado um inteiro de 32 bits ou uma pointer
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Comando GOTO nao pode desviar para label fora da procedure/function
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure muito complexa, ela requer registradores demais
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Expressão inválida
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Resultado da expressao nao e "integer"
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Qualificador invalido
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Limite superior < limite inferior
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_O parametro do Exit deve ser o nome da procedure onde ele e usado
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Assinalamento invalido para a variavel de controle do loop "for" "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Variaveis locais nao podem ser declaradas EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procedure ja foi declarada EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Assumido uso de Variants unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Classes e metodos static nao podem ser usados em INTERFACES
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow em operacao aritmetica
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Protected ou private esperados
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Type nao combina
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipos de dado incompativeis. Encontrado "$1" esperado "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Tipos de "$1" e "$2" nao combinam
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificador de tipo(type) esperado
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Esperada uma variavel
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Esperada expressao do tipo "integer", mas encontrada "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Esperada expressao do tipo "boolean", mas encontrada "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Esperada expressao do tipo "ordinal"
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Esperado tipo pointer, mas encontrado "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Esperada uma classe, mas encontrado "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Nao pude resolver a expressao
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Os elementos dos "sets" sao incompativeis
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operacao nao implementada para "sets"
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversao automatica de floating type para COMP o qual e do tipo "integer"
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Use o operador DIV para obter um resultado "integer"
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_String types nao combinam, por causa da diretiva $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ ou Pred em tipos "enumerated" que contenham atribuicoes nao e possivel
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Nao e possivel ler ou gravar variaveis deste "type"
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Nao pode usar readln ou writeln em arquivo "typed"
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Nao pode usar read ou write em arquivo "untyped"
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Conflito de tipo entre 1 ou mais elementos e o tipo de dados do SET
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) retorna upper/lower nos formatos word/dword
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Esperada expressao "integer" ou "real"
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo "$1" invalido em "array constructor"
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipo incompativel para o arg no. $1: Recebido "$2", esperado "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Variaveis do tipo "procedure of object" nao sao compativeis com variaveis do tipo "procedure"
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante invalida passada para funcao matematica
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Nao e possivel obter endereco de constantes
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Nao se pode atribuir dados a este argumento
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Nao pode atribuir procedure/function local a uma variavel do tipo "procedure"
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Nao pode atribuir valores a um endereco
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Nao pode atribuir valores a uma variavel declarada como "const"
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Requerido tipo array
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Esperado tipo "interface" mas encontrado "$1"
+type_w_mixed_signed_unsigned=04035_W_Misturar expressoes com sinal e "longword" gera resultado de 64 bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Misturar expressoes com sinal e "cardinals" neste ponto pode causar "range check error"
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Variavel que sofreu typecast ficou com tamanho diferente ($1 -> $2)
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Membro de "enumerated" que contenha atribuicoes, nao pode ser usado como indice de array
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Classes ou "objects" de tipos "$1" and "$2" nao estao relacionados(os tipos)
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Classes "types" "$1" e "$2" nao estao relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Esperada uma classe ou um interface mas encontrado "$1"
+type_e_type_is_not_completly_defined=04042_E_O "type" "$1" nao esta completamente definido
+type_w_string_too_long=04043_W_Literal tem mais caracteres que o tamanho de "short string"
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_Comparacao sera sempre falsa devido ao "range" de valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_Comparacao sera sempre verdadeira devido ao "range" de valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Construindo classe "$1" mas superclasse tem metodos virtuais que nao sofreram override
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_Operando a esquerada de um operador IN tem que ter tamanho de 1 byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_"Types" de tamanho diferente, havera possivel perda de dados e/ou "range check error"
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Tamanho dos types nao combina, possivel perda de dados ou erro de "range"
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Nao foi possivel obter o endereco de 1 metodo abstrato
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_O operador nao se aplica ao tipo de operando
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Esperada expressao do tipo constante
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operacao "$1" nao permitida para os tipos "$2" and "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Conversao ilegal de tipos: "$1" para "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Conversao entre "ordinals" e "pointer" nao e portavel
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Conversao entre "ordinals" e "pointer" nao e portavel
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Nao foi possivel determinar qual das functions que sofreram overload deve ser chamada
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Variavel usada como contador e de tipo invalido
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificador nao encontrado "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Erro interno no SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificador duplicado "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identificador ja definido em $1 na linha $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificador desconhecido "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Declaracao "forward" nao resolvida "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Erro na definicao de um "type"
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_"Forward type" "$1" nao resolvido
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Apenas variaveis "static" podem ser usadas em metodos "static" ou metodos externos ao bloco
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Esperado um record ou uma classe
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Nao e permitido instanciar classes ou objetos atraves de metodos abstratos
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_"Label" nao definido "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_"Label" usado mas nao definido "$1"
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Declaracao de label invalida
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO e LABEL nao suportados (use a diretiva -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label nao encontrado
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Identificador nao e um label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label ja definido
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Type invalido na declaracao dos elementos de um set
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Definicao da classe citada num "forward" nao resolvida "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_"Unit" "$1" nao usada em $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Identificador "$1" nao usado
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Variavel local "$1" nao usada
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Identificador "$1" declarado com valor mas nunca usado
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Variavel local "$1" e declarada/inicializada mas nunca usada
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Simbolo local $1 "$2" nao e usado
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Campo "private" "$1.$2" nunca e usado
+sym_n_private_identifier_only_set=05030_N_Campo "private" "$1.$2" e inicializado mas nunca usado
+sym_n_private_method_not_used=05031_N_Metodo "private" "$1.$2" nunca usado
+sym_e_set_expected=05032_E_Esperado tipo "set"
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Resultado de uma function parece nao ter sido atribuido
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type "$1" parece nao estar alinhado corretamente no registro corrente para em estruturas C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Campo de "record" desconhecido "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Variavel local "$1" parece nao ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_Variavel "$1" nao parece ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Identificador nao identifica nenhum dado ou metodo "$1"
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Declaracao encontrada mas procedure que sofre o overload nao: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Elemento de dados muito grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Nao encontrada implementacao de metodo para a interface "$1"
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" esta obsoleto(a)
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Simbolo "$1" nao e portavel
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Simbolo "$1" nao esta implementado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Nao e possivel criar 1 "type" que seja unico a partir deste "type"
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Variavel local "$1" nao parece ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Variavel "$1" nao parece ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Lista de parametros excede 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_"File types" devem ser variaveis
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_O uso de pointer tipo "far" nao e permitido
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Functions declaradas EXPORT nao podem ser chamadas
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possivel chamada invalida a constructor ou destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Codigo pouco eficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Codigo nunca sera executado
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Metodos abstratos nao podem ser chamadaos diretamente
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registrador $1 tem prioridade sobre $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_"Stack frame" omitido
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Objetos ou metodos nao podem ser inline.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Call a variaveis do tipo procedure nao podem ser inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Nenhum codigo foi carregado para a procedure inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_O elemento zero de 1 ansi/wide- ou longstring nao pode ser acessado, use SetLength
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors ou destructors nao podem ser chamados de dentro de 1 clausula 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Nao e possivel acessar diretamente metodos do tipo "message handler"(declarados com diretiva message)
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Pulo para dentro ou para fora de 1 "exception block"
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Comandos de controle de fluxo de execucao nao sao permitidos dentro de blocos "finally"
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Tamanho total dos parametros excede o limite de alguns processadores
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_O tamanho total das variaveis locais excede o limite de alguns processadores
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_O tamanho das variaveis locais excede o limite suportado
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK nao permitido neste ponto
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE nao permitido neste ponto
+% You're trying to use \var{continue} outside a loop construction.
+asmr_d_start_reading=07000_DL_Iniciando a montagem do bloco assembly $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Montagem do bloco assembly $1 finalizada
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Encontrado o caracter @ em identificador que nao e label
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Erro durante a apuracao de um deslocamento(offset)
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_Deslocamento(OFFSET) usado sem um identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_"TYPE" usado sem identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Nao pode usar variavel local ou parametros aqui
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_E necessario o uso do operador OFFSET aqui
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Precisa usar $ aqui
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Nao pode usar multiplos simbolos relocaveis
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Simbolo relocavel so pode ser usado para adicao
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Expressao constante invalida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Simbolo relocavel nao permitido aqui
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Erro de sintaxe
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Nao permitido acionar $1 a partir deste codigo
+% You can not read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Simbolos e labels locais nao sao permitidos como referencias
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso invalido de registradores base e indexador
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Possivel erro no manuseio de algum campo de objeto
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Especificado fator de escala errado
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso de multiplos registradores indexadores
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo de operando invalido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Opcode invalido: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE e @DATA nao suportados
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label references nao permitidas
+asmr_e_expr_zero_divide=07025_E_Divisao por zero no analisador do assembler
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expressao ilegal
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sequencia de escape ignorada: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Referencia a simbolo invalida
+asmr_w_fwait_emu_prob=07029_W_Fwait pode causar problemas de emulacao com emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sem operandos traduzida para $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instrucao ENTER nao e suportada pelo kernel do Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Chamada em assembly a 1 metodo que sofreu overload
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Simbolo de "type" nao suportado para operando
+asmr_e_constant_out_of_bounds=07034_E_Constante fora da faixa
+asmr_e_error_converting_decimal=07035_E_Erro convertendo decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Erro convertendo octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Erro convertendo binario $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error convertendo hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traduzido para $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 esta associado a uma function que sofreu overload
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Nao pode usar SELF fora de um metodo
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Nao pode usar OLDEBP fora de uma procedure aninhada
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedures nao podem retornar nenhum valor no codigo assembly
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nao suportado
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Sufixo de tamanho e o destino ou tamanho da origem nao combinam
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Tamanho do "suffix" e o tamanho do destino ou da origem nao combinam
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Erro de sintaxe assembly
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinacao de opcode e operandos invalida
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Erro de sintaxe assembly em operando
+asmr_e_syn_constant=07050_E_Erro de sintaxe assembly em constante
+asmr_e_invalid_string_expression=07051_E_Expressao string invalida
+asmr_w_const32bit_for_address=07052_W_Constante com simbolo $1 para endereco que nao esta numa pointer
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Opcode nao reconhecido $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Opcode invalido ou ausente
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinacao de opcode e prefixo invalida: $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinacao invalida de opcode e override: $1
+asmr_e_too_many_operands=07057_E_Operandos em excesso numa linha
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorado
+asmr_w_far_ignored=07059_W_FAR ignorado
+asmr_e_dup_local_sym=07060_E_Simbolo local duplicado $1
+asmr_e_unknown_local_sym=07061_E_Simbolo local nao definido $1
+asmr_e_unknown_label_identifier=07062_E_Label desconhecido $1
+asmr_e_invalid_register=07063_E_Nome de registrador invalido
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nome de registrador de ponto flutuante invalido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Funcao "mod"(resto) nao suportada
+asmr_e_invalid_float_const=07067_E_Constante de ponto flutuante invalida $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Expressao de ponto flutuante invalida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Simbolo de tipo invalido
+asmr_e_cannot_index_relative_var=07070_E_Nao pode indexar com registrador uma variavel local ou parametro(que ja sao relativos a 1 reg. base)
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Expressao com override invalido de segmento
+asmr_w_id_supposed_external=07072_W_Identificador $1 assumido como external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings nao permitidos como constantes
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Nenhum tipo de variavel especificado
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_O codigo assembly nao gera retorno a secao de texto
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Nao e uma diretiva nem um simbolo local $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Usando um nome auto-definido como label local
+asmr_e_dollar_without_identifier=07078_E_Um simbolo "$" usado sem estar no inicio de 1 identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Criada uma constante de 32 bits para enderecamento
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align e especifico de plataforma, use .balign ou .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Nao pode acessar diretamente os campos de parametros
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Nao pode acessar diretamente campos de objetos/classes
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Nao especificado tamanho e nao foi possivel determinar o tamanho dos operandos
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Nao pode usar RESULT nesta function
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sem operando traduzido para "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traduzido para "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" traduzido para "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_O caracter < nao e permitido aqui
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_O caracter > nao e permitido aqui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN nao suportado
+asmr_e_no_inc_and_dec_together=07094_E_"Inc" e "Dec" nao podem estar juntos
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Registrador(es) invalido(s) para "movem"
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Registrador(es) invalidos para o opcode
+asmr_e_higher_cpu_mode_required=07097_E_Requerido modo de CPU mais avancado ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Nao foi especificado tamanho e nao e possivel determinar o tamanho dos operandos, DWORD usado como default
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Erro de sintaxe enquanto tentava montar uma operacao de "shift"
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Excesso de arquivos assembly
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Tipo de saida do assembler nao suportado
+asmw_f_comp_not_supported=08002_F_"Comp" nao suportado
+asmw_f_direct_not_supported=08003_F_"Direct" nao suportado para "binary writers"
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Alocacao de dados so e permitida na secao bss
+asmw_f_no_binary_writer_selected=08005_F_Nenhum "binary writer" selecionado
+asmw_e_opcode_not_in_table=08006_E_Assembler: Opcode $1 nao existe na tabela
+asmw_e_invalid_opcode_and_operands=08007_E_Asssmbler: $1 combinacao de opcode e operadores invalida
+asmw_e_16bit_not_supported=08008_E_Assembler: Referencias de 16 bits nao suportadas
+asmw_e_invalid_effective_address=08009_E_Assembler: Endereco efetivo invalido
+asmw_e_immediate_or_reference_expected=08010_E_Assembler: Esperados um operador imediato ou uma referencia
+asmw_e_value_exceeds_bounds=08011_E_Assembler: Valor de $1 excede os limites de $2
+asmw_e_short_jmp_out_of_range=08012_E_Assembler: "Short jump" fora de faixa $1("short jump" gera troca de segmento de memoria?)
+asmw_e_undefined_label=08013_E_Assembler: Label indefinido $1
+asmw_e_comp_not_supported=08014_E_Assembler: Type "Comp" nao suportado na plataforma destino
+asmw_e_extended_not_supported=08015_E_Assembler: "Type" Extended nao suportado na plataforma destino
+asmw_e_duplicate_label=08016_E_Assembler: Label duplicado $1
+asmw_e_redefined_label=08017_E_Assembler: Label redefinido $1
+asmw_e_first_defined_label=08018_E_Assembler: Definido a primeira vez aqui
+asmw_e_invalid_register=08019_E_Assembler: Registrador invalido $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sist Oper fonte redefinido
+exec_i_assembling_pipe=09001_I_Montagem em andamento $1
+exec_d_cant_create_asmfile=09002_E_Assembler nao pode criar o arquivo $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Nao pode criar o arquivo objeto: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Nao pode criar o arquivo "archive": $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 nao encontrado, mudando para montagem assembly externa
+exec_t_using_assembler=09006_T_Usando o assembler: $1
+exec_e_error_while_assembling=09007_E_Erro durante a montagem assembly -> exitcode $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Nao pode chamar o assembler, erro $1. Mudando para montagem assembly externa
+exec_i_assembling=09009_I_Montando $1
+exec_i_assembling_smart=09010_I_Montagem com smartlinking $1
+exec_w_objfile_not_found=09011_W_Objeto $1 nao encontrado, a link-edicao pode falhar!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Library $1 nao encontrada, a link-edicao pode falhar!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Erro durante a link-edicao
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Nao pode chamar o linkage editor interno, mudando para link-edicao externa
+exec_i_linking=09015_I_Link edicao de $1
+exec_e_util_not_found=09016_E_Utilitario $1 nao encontrado, mudando para link-edicao externa
+exec_t_using_util=09017_T_Usando utilitario $1
+exec_e_exe_not_supported=09018_E_Criacao de executaveis nao suportada
+exec_e_dll_not_supported=09019_E_Criacao de libraries Dynamic/Shared nao suportada
+exec_i_closing_script=09020_I_Fechando script $1
+exec_e_res_not_found=09021_E_Recurso do compilador nao encontrado, mudando para modo externo
+exec_i_compilingresource=09022_I_Recurso de compilacao $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_A "unit" $1 nao pode ser link-editada de forma estatica, mudando para o modo "smart linking"
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_A "unit" $1 nao pode ser link-editada no modo "smart linking", mudando para link-edicao estatica
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_A "unit" $1 nao pode ser link-editada em modo "shared linking", mudando para link-edicao estatica
+exec_e_unit_not_smart_or_static_linkable=09026_E_A "unit" $1 nao pode ser link-editada nem no modo "smart linking" nem em link-edicao estatica
+exec_e_unit_not_shared_or_static_linkable=09027_E_A "unit" $1 nao pode ser link-editada nem no modo "shared linking" nem em link-edicao estatica
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_Nao pode pos-processar o executavel $1
+execinfo_f_cant_open_executable=09029_F_Nao pode abrir o executavel $1
+execinfo_x_codesize=09030_X_Tamanho do codigo: $1 bytes
+execinfo_x_initdatasize=09031_X_Tamanho da area de dados inicializados: $1 bytes
+execinfo_x_uninitdatasize=09032_X_Tamanho da area de dados nao-inicializados: $1 bytes
+execinfo_x_stackreserve=09033_X_Espaco reservado para o stack: $1 bytes
+execinfo_x_stackcommit=09034_X_Espaco realmente usado pelo stack: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Caminho onde o compilador tentara achar "units": $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_"Units" carregadas pelo compilador $1 (.PPU)
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nome da "unit"(.PPU): $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Flags da "unit"(.PPU): $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Check sum da "unit"(.PPU): $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Data de compilacao da "unit"(.PPU): $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Arquivo PPU da "unit" muito pequeno
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Header de arquivo PPU(de uma "unit") invalido(nao tem PPU no inicio)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Versao de arquivo PPU(de uma "unit") invalida $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_"Unit"(arquivo PPU) compilada para outro processador
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_"Unit"(arquivo PPU) foi compilada para outro sistema operacional
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_Check sum do arquivo PPU da "unit": $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Gravando as "units"(arquivos PPU) em: $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Nao pode gravar o arquivo PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Erro durante a leitura de um arquivo PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fim de arquivo PPU inesperado
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Arquivo PPU em formato invalido: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problema na contagem Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nome da "unit" invalido $1. Diverge do nome do arquivo que a contem.
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Ha "units" demais. Excedem o limite definido para a compilacao(diretiva maxunits)
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_"Units" $1 e $2 referem-se mutuamente(referencia circular)
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_"Unit" $1 precisa ser recompilada mas o fonte nao foi encontrado
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_'Unit'(arquivo PPU) "$1" nao pode ser encontrada
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_"Unit" $1 nao foi encontrada mas a $2 existe
+unit_f_unit_name_error=10024_F_"Unit" $1 procurada mas a $2 foi encontrada
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Para compilar a "unit" System tem que usar a diretiva -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Houve $1 erros compilando o modulo, compilacao abortada
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Carregando $3 a partir da "unit" $1. A carga foi requisitada em $2.
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilando a "unit" $1, checksum mudou para $2
+unit_u_recompile_source_found_alone=10029_U_Recompilando $1 porque foi encontrado somente o fonte
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilando a "unit", algum das "static libraries" e mais antiga que o arquivo PPU
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilando a "unit", a "shared lib" e mais antiga que o ppufile
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilando a "unit". Modulos obj e asm tem data mais antiga que o PPU
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilando a "unit". Modulo obj mais antigo que o asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Interpretando interface da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Interpretando implementation da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Segunda carga da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Verificando arquivo PPU $1 data/hora $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Nao pode recompilar "unit" $1, mas foram encontrados arquivos de include modificados
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Arquivo $1 e mais recente que o arquivo PPU $2 que foi compilado com flag de release -Ur
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Usando uma "unit" que foi compilada com tipo diferente de emulacao de ponto flutuante(FPU)
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Incluindo "units" relacionadas na interface da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Incluindo "units" relacionadas na implementation da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Check sum da Interface modificado para a "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Check sum da Implementation modificado para a "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Compilacao da "unit" $1 terminada
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Dependencia de $1 adicionada a $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Nao precisa carregar de novo, "unit" ja esta carregada $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Nao precisa carregar a unit de novo, e uma recompilacao $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Recarregando: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Recarga forcada
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Estado anterior de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ja compilando $1, setando opcao de recompilacao
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Carregando a "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Carga da "unit" $1 terminada
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrando a nova "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Recalculando area de dados da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Pulando o recalculo da area de dados da "unit" $1, "units" usadas ja carregadas
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [opcoes] <arquivo entrada> [opcoes]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Suportado apenas um arquivo fonte
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Arquivo DEF so pode ser criado para OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Response files aninhados nao permitidos
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Nenhum arquivo fonte especifica na linha de comando
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Nenhuma opcao dentro do arquivo de configuracao $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parametro invalido: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_"-?" exibe paginas de help
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Muitos arquivos de configuracao aninhados(+ de 16 niveis)
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Nao foi possivel abrir arquivo $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lendo opcoes adicionais de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Sistema operacional destino ja esta setado para: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Libraries shared nao suportados em DOS, revertendo para libraries estaticas
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_IF(N)DEFs em excesso
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_ENDIFs em excesso
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Comando de compilacao condicional nao fechado no final de arquivo
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Este executavel do compilador nao suporta geracao de informacoes de debug
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Tente recompilar com -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Voce esta usando uma diretiva obsoleta $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Voce esta usando a diretiva obsoleta $1, por favor use $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Mudando assembler para o modo default de fonte
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Tipo de saida assembler selecionada "$1" nao compativel com "$2"
+option_asm_forced=11022_W_Forcado uso de assembler "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Lendo opcoes a partir do arquivo $1
+% Options are also read from this file
+option_using_env=11027_T_Lendo opcoes da variavel de ambiente $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Tratando opcao "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** pressione enter ***
+option_start_reading_configfile=11030_H_Inicio do tratamento do arquivo de configuracao $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Fim do arquivo durante leitura do arquivo de configuracao $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretando a opcao "$1"
+option_interpreting_firstpass_option=11036_D_Interpretando a opcao de primeiro passo "$1"
+option_interpreting_file_option=11033_D_Interpretando opcao de arquivo "$1"
+option_read_config_file=11034_D_Lendo o arquivo de configuracao "$1"
+option_found_file=11035_D_Encontrado o arquivo fonte "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Pagina de codigo desconhecida
+# Logo
+option_logo=11023_[
+Free Pascal Compiler versao $FPCVERSION [$FPCDATE] para $FPCCPU
+Copyright (c) 1993-2005 por Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versao $FPCVERSION
+
+Data do compilador : $FPCDATE
+Processador destino: $FPCCPU
+
+Sistemas operacionais atendidos
+ $OSTARGETS
+
+Conjuntos de instrucoes atendidos:
+ $INSTRUCTIONSETS
+
+Conjuntos de instrucoes de ponto flutuante atendidos:
+ $FPUINSTRUCTIONSETS
+
+Este programa vem sob a licenca GNU General Public Licence
+Para mais informacoes leia COPYING.FPC
+
+Informacoes de erros detectados, sugestoes, etc para:
+ bugrep@freepascal.org
+]
+# Help pages
+option_help_pages=11025_[
+**0*_coloque + apos 1 opcao booleana para habilita-la, - para desabilita-la
+**1a_o compilador nao deletou o arquivo assembly gerado
+**2al_Lista as linhas de codigo fonte do arquivo assembly
+**2an_lista as informacoes de node do arquivo assembly
+*L2ap_use pipes(redirecione) ao inves de criar arquivos assembly temporarios
+**2ar_lista informacoes de alocacao/liberacao de registradores no arquivo asembly
+**2at_lista informacoes de alocacao/liberacao temporarias no arquivo assembly
+**1A<x>_Formato de saida:
+**2Adefault_use o assembly default
+3*2Aas_Montagem feita usando o GNU AS
+3*2Anasmcoff_coff (Go32v2) file gerado usando Nasm
+3*2Anasmelf_elf32 (Linux) file gerado usando Nasm
+3*2Anasmwin32_Win32 object file gerado usando Nasm
+3*2Anasmwdosx_Win32/WDOSX object file gerado usando Nasm
+3*2Awasm_obj file gerado usando Wasm (Watcom)
+3*2Anasmobj_obj file gerado usando Nasm
+3*2Amasm_obj file gerado usando Masm (Microsoft)
+3*2Atasm_obj file gerado usando Tasm (Borland)
+3*2Aelf_elf32 (Linux) gerado usando uma internal writer
+3*2Acoff_coff (Go32v2) gerado usando uma internal writer
+3*2Apecoff_pecoff (Win32) gerado usando uma internal writer
+4*2Aas_Montagem feita usando o GNU AS
+6*2Aas_Unix o-file gerado usando o GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola assembler
+A*2Aas_Montagem feita usando o GNU AS
+P*2Aas_Montagem feita usando o GNU AS
+S*2Aas_Montagem feita usando o GNU AS
+**1b_gera informacoes do browser
+**2bl_gera a local symbol information
+**1B_Compila/monta todos os modulos
+**1C<x>_opcoes de geracao do codigo:
+**2Cc<x>_default calling convention setada para <x>
+**2CD_criar tambem a dynamic library (nao suportado)
+**2Ce_Compilacao com opcodes de ponto flutuante emulados
+**2Cf<x>_Selecione o conjunto de instrucoes de ponto flutuante a ser usado, veja diretiva -i do FPC para valores possiveis
+**2Cg_Gerar codigo com enderecamento relativo(enderecar usando so o deslocamento do operando)
+**2Ch<n>_define heap com <n> bytes (entre 1023->1KB e 67107840->64 MB)
+**2Ci_IO-checking(validacao dos comandos de I/O)
+**2Cn_Nao executar estagio de link-edicao
+**2Co_Checar overflow de operacoes com inteiros
+**2Cp<x>_seleciona o conjunto de instrucoes, veja diretiva FPC -i para valores possiveis
+**2Cr_range checking(validacao da faixa de validade de valores)
+**2CR_verificar validade das chamadas de metodos de objetos
+**2Cs<n>_seta o tamanho do stack para o valor <n>
+**2Ct_stack checking(verifica estouros da capacidade do stack)
+**2CX_criar tambem a smartlinked library
+**1d<x>_define o simbolo <x>
+1D_gera um DEF file
+**2Dd<x>_seta a descricao para <x>
+**2Dv<x>_set a versao das DLL para <x>
+*O2Dw_PM application(usa o Presentation manager do OS/2)
+**1e<x>_seta o path para o executavel
+**1E_o mesmo que -Cn
+**1F<x>_seta nomes de arquivos e paths:
+**2Fa<x>[,y]_para o programa primeiro carregar as "units" <x> e [y] antes de interpretar o "uses"
+**2Fc<x>_seta a pagina de codigo da entrada para <x>
+**2FD<x>_seta o diretorio onde procurar pelas utilities do compilador
+**2Fe<x>_redireciona a saida de erros para <x>
+**2FE<x>_seta a saida de exe/units para o path <x>
+**2Fi<x>_adiciona <x> ao(s) path(s) de include
+**2Fl<x>_adiciona <x> ao library path
+**2FL<x>_usa <x> como dynamic linker
+**2Fo<x>_adiciona <x> ao object path
+**2Fr<x>_carrega o arquivo de mensagens de erro <x>
+**2Fu<x>_adiciona <x> ao unit path
+**2FU<x>_seta o unit output path para <x>, anula o informado na diretiva -FE
+*g1g_gerar informacoes para o depurador(debugger)
+*g2gc_gerar checagem de pointers
+*g2gd_usar dbx
+*g2gg_usar gsym
+*g2gh_Usar "unit" de trace de heap (para depuracao de descontinuidade de memoria)
+*g2gl_usar unit com informacoes de numeros de linhas para obter msgs de erro com seu numero de linha
+*g2gv_gerar programas tracaveis com valgrind
+*g2gw_gerar informacoes de depuracao para dwarf
+**1i_informacoes
+**2iD_retorna a data de compilacao do compilador
+**2iV_retorna a versao do compilador
+**2iSO_retorna o sistema operacional onde esta sendo feita a compilacao
+**2iSP_retorna o processador do compilador
+**2iTO_retorna o sistema operacional para o qual sera gerado o executavel
+**2iTP_retorna o processador para o qual sera gerado o executavel
+**1I<x>_adiciona <x> ao(s) path(s) de include
+**1k<x>_Passa <x> para o linkage editor
+**1l_escreva as mensagens de identificacao
+**1M<x>_seta language mode para <x>(delphi, FPC, etc.)
+**2Mfpc_dialeto free pascal (default)
+**2Mobjfpc_ativa algumas extensoes do Delphi 2
+**2Mdelphi_Tenta manter compatibilidade com o Delphi
+**2Mtp_Tenta manter a compatibilidade com TP/BP 7.0
+**2Mgpc_Tenta manter compatibilidade com gpc
+**2Mmacpas_Tenta manter compatibilidade com os dialetos do macintosh pascal
+**1n_nao ler o arquivo de configuracao default
+**2Nu_expanda o conteudo dos loops
+**1o<x>_Troca o nome do executavel produzido para <x>
+**1O<x>_otimizacoes:
+3*2Og_gera codigo(executavel) menor
+3*2OG_gera codigo(executavel) mais rapido(default)
+**2Or_mantem certas variaveis em registradores
+3*2Ou_ativa otimizacoes incertas (veja documentacao)
+3*2O1_otimizacoes de nivel 1 (optimizacoes rapidas)
+3*2O2_otimizacoes de nivel 2(-O1 optimizacoes + lentas)
+3*2O3_otimizacoes de nivel 3(-O2 repetidamente, max 5 vezes)
+3*2Op<x>_processador para o qual sera gerado o executavel(target)
+3*3Op1_seta processador destino como 386/486
+3*3Op2_seta processador destino como Pentium/PentiumMMX (tm)
+3*3Op3_seta processador destino como PPro/PII/c6x86/K6 (tm)
+6*2Og_gera codigo(executavel) menor
+6*2OG_gera codigo(executavel) mais rapido(default)
+6*2Ox_otimize ao maximo(ainda com problemas!!!)
+6*2O0_seta como processador destino(gera executavel para) o MC68000
+6*2O2_seta como processador destino(gera executavel para) o MC68020+ (default)
+**1pg_gera perfil para gprof (cria o FPC_PROFILE)
+**1R<x>_estilo de leitura do assembler:
+**2Rdefault_use o assembler default
+3*2Ratt_ler assembly no estilo AT&T
+3*2Rintel_ler assembly no estilo Intel
+6*2RMOT_ler assembly no estilo motorola
+**1S<x>_opcoes de sintaxe:
+**2S2_o mesmo que -Mobjfpc
+**2Sc_suporta operadores como o C (*=,+=,/= and -=)
+**2Sa_include assertion code.
+**2Sd_o mesmo que -Mdelphi
+**2Se<x>_opcoes de erro. <x> e uma combinacao do seguinte:
+**3*_<n> : compilador para apos <n> erros (o default e 1)
+**3*_w : compilador tambem para apos warnings
+**3*_n : compilador tambem para apos notes
+**3*_h : compilador tambem para apos hints
+**2Sg_permitir LABEL e GOTO
+**2Sh_Use strings do tipo ansistring
+**2Si_dar suporte a INLINE estilo C++
+**2SI<x>_setar estilo de interface para <x>
+**3SIcom_interface compativel com COM (default)
+**3SIcorba_interface compativel com CORBA
+**2Sm_suporta macros como o C (global)
+**2So_o mesmo que -Mtp
+**2Sp_o mesmo que -Mgpc
+**2Ss_constructor tem que se chamar init (destructor tem que se chamar done)
+**2St_permitir a keyword static em objetos
+**1s_nao chamar o assembler nem linker
+**2sh_Gerar script para link edicao no host
+**2st_Gerar script para link edicao no sistema operacional de destino
+**2sr_Pular a fase de alocacao de registradores (usar com -alr)
+**1T<x>_Sistema operacional para o qual sera gerado o executavel(target):
+3*2Temx_OS/2 via EMX (incluindo o extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Versao 2 do DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (not supported)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin and MacOS X on PowerPC
+P*2Tlinux_Linux on PowerPC
+P*2Tmacos_MacOS (classic) on PowerPC
+2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_excluir definicao do simbolo <x>
+**1U_opcoes de "unit":
+**2Un_nao verifique o nome da "unit"
+**2Ur_gerar arquivos de "unit" do tipo "release"
+**2Us_compilar uma "unit" system
+**1v<x>_Mostrar opcoes de compilacao. <x> e uma combinacao das seguintes letras:
+**2*_e : Mostrar erros (default) 0 : Mostrar somente erros
+**2*_w : Mostrar avisos u : Mostrar informacoes da "unit"
+**2*_n : Mostrar "notes" t : Mostrar arquivos acessados/usados
+**2*_h : Mostrar "hints" c : Mostrar "conditionals"
+**2*_i : Mostrar informacoes gerais d : Mostrar informacoes de depuracao(debug)
+**2*_l : Mostrar numeros de linha r : Modo de compatibilidade Rhide/GCCode
+**2*_a : Mostrar tudo x : Informacoes do executavel (Win32 apenas)
+**2*_v : grava fpcdebug.txt com p : Grava tree.log com a arvore de parse
+**2*_ muitas informacoes de depuracao
+3*1W<x>_opcoes do sistema operacional de destino no formato Win32
+3*2WB_Criar uma imagem relocavel
+3*2WB<x>_Setar a base da imagem para o valor hexadecimal <x>
+3*2WC_Especifica aplicacao tipo console
+3*2WD_Use DEFFILE para exportar functions de DLL ou EXE
+3*2WF_Especifica aplicacao tipo tela cheia (apenas OS/2)
+3*2WG_Especifica aplicacao grafica
+3*2WN_Nao gerar codigo relocavel (necessario para depuracao)
+3*2WR_Gerar codigo relocavel
+P*2WC_Especifica aplicacao tipo console (apenas MacOS)
+P*2WG_Especifica aplicacao grafica (apenas MacOS)
+P*2WT_Especifica aplicacao do tipo ferramenta (ferramenta MPW, apenas MacOS)
+**1X_opcoes de executavel:
+**2Xc_passar --shared ao linkage editor (apenas Unix)
+**2Xd_nao usar caminho padrao de pesquisa em library (necessario para cross compile)
+**2XD_tentar link editar "units" dinamicas(definir FPC_LINK_DYNAMIC)
+**2Xm_gerar mapa de link edicao
+**2XM<x>_seta o nome da rotina principal do programa (default e 'main')
+**2XP<x>_prefixa os nomes dos binutils com o prefixo <x>
+**2Xr<x>_setar o caminho de pesquisa de libraries para <x> (necessario para cross compile)
+**2Xs_elimine todos os simbolos do executavel
+**2XS_tente link editar as units como static (default) (definido com FPC_LINK_STATIC)
+**2Xt_link editar com static libraries (-static e passado ao linkage editor)
+**2XX_tente link editar as unidades com smart linking(definido com FPC_LINK_SMART)
+**1?_Mostra esta ajuda
+**1h_mostra esta ajuda sem espera
+]
+
+#
+# The End...
+%%% scan_w_only_pack_records=02015_W_O alinhamento de campos de registro so pode ser em 1,2,4,8,16 or 32 bytes
+%%% scan_w_only_pack_enum=02016_W_Tipo enumerado pode ser salvo em apenas 1,2 ou 4 bytes
+%%% parser_e_exit_with_argument_not_possible=03153_E_Nao e possivel usar "Exit" com argumento neste contexto
+%%% parser_e_only_publishable_classes_can_be_published=03156_E_So podem ter atributo "published" classes compiladas com $M+
+%%% type_w_smaller_possible_range_check=04048_W_"Types" de tamanho diferente, havera possivel perda de dados e/ou "range check error"
+%%% mr_e_local_para_unreachable=07015_E_Nao pode acessar a variavel $1 direto deste codigo
+%%% asmr_e_size_suffix_and_dest_dont_match=07045_E_Sufixo de tamanho e o destino ou tamanho da origem nao combinam
+%%% option_no_debug_support=11016_W_Este executavel do compilador nao suporta geracao de informacoes de debug
+%%% scan_e_illegal_pack_records=02015_E_Illegal record alignment specifier "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+%%% scan_e_illegal_pack_enum=02016_E_Illegal enum minimum-size specifier "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+%%% scan_e_compile_time_typeerror=02072_E_Compile time expression: Wanted $1 but got $2 at $3
+% Type check of a compile time expression failed.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+%%% cg_f_unknown_compilerproc=06046_F_Unknown compilerproc "$1". Check if you use the correct run time library.
+% The compiler expects that the runtime library contains some subrountines. If you see this error
+% and you didn't mess with the runtime library, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+%%% exec_d_resbin_params=09028_D_Calling resource compiler "$1" with "$2" as command line
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
diff --git a/compiler/msg/errorptw.msg b/compiler/msg/errorptw.msg
new file mode 100644
index 0000000000..b64b481501
--- /dev/null
+++ b/compiler/msg/errorptw.msg
@@ -0,0 +1,2335 @@
+%%% Reordering of errorptw.new respective to errore.msg
+%%% Contains all comments from errorptw.new
+%%% Reordering of errorptw.msg respective to errore.msg
+%%% Contains all comments from errorptw.msg
+%%% Reordering of msg/errorptw.msg respective to msg/errore.msg
+%%% Contains all comments from msg/errorptw.msg
+general_t_compilername=01000_T_Compilador usado: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Sist.Op. da compilação: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Sist.Op. de execução: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Caminho para os executáveis: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_Caminho para as units: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Caminho para os includes: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Caminho para as libraries: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Caminho para módulos objeto: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Linhas compiladas, $2 seg
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Memória insuficiente para esta compilação
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Gravando arquivo com os Resource strings: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Gravando arquivo com os Resource strings: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Erro fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Erro:
+% Prefix for Errors
+general_i_warning=01014_I_Aviso:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Sugestão:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_Caminho "$1" não existe
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilação abortada
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Fim inesperado de arquivo
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String não fechado na mesma linha
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_caracter inválido "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Erro de sintaxe "$1" esperado mas "$2" encontrado
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Começou a ler include file $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Encontrado comentário de nível $1
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Ignorada diretiva "$1" do compilador
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Diretiva de compilador inválida "$1"
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Diretiva global do compilador em local inválido
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante caracter inválida
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Arquivo "$1" não encontrado
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Includefile "$1" não encontrado
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Campos de "record" podem ser alinhados somente em 1, 2, 4, 8, 16 ou 32 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1, 2, 4, 8, 16 and 32 are valid in this case.
+scan_w_only_pack_enum=02016_W_Variáveis do tipo "enumerated" podem ser salvas somente em 1, 2 ou 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_$ENDIF esperado para $1 $2 definidos em $3 na linha $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Erro de sintaxe na interpretação(parse) de uma expressão de compilação condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Avaliação de uma expressão de compilação condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_O tamanho máximo de uma macro está limitado a 255 caracteres
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sem correspondente IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Definido pelo usuário: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Definido pelo usuário: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Definido pelo usuário: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Definido pelo usuário: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Definido pelo usuário: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Definido pelo usuário: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Macro que substitui palavra chave não tem efeito
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Overflow no buffer de macros durante leitura/expansão de macro
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Mais de 16 níveis de aninhamento de macro.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Diretivas de compilador não são aceitas em comentários tipo //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Tratando diretiva "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 encontrado
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 encontrado $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Desprezando até...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Tecle <return> para continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Diretiva não suportada "$1"
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Diretiva de compilador inválida "$1"
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_De volta em $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Application type não suportado: "$1"
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE não suportado pelo Sist.Op. de execução
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_Diretiva DESCRIPTION não é suportada pelo Sist.Op. de execução
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_Diretiva VERSION não é suportada pelo Sist.Op. de execução
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_Diretiva VERSION é só para executáveis ou DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Formato da diretiva VERSION errado "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Valor inválido na diretiva ASMMODE "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Não é possível trocar tipo de assembly dentro de 1 trecho em assembly, a diretiva "$1" será válida só no próximo trecho assembly
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Valor de diretiva inválido, use ON/OFF ou +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Resource files não são suportados no Sist.Op. de execução
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Variável de ambiente "$1" não encontrada
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valor inválido para diretiva MAXFPUREGISTERS
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_O Sist.Op. de execução suporta somente 1 resource file
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Suporte a macros foi desativado
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_Tipo de interface inválido. Valores válidos são COM, CORBA or DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID só é suportada pelo Sist.Op. de execução PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME só é suportada pelo Sist.Op. de execução PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Constantes string não podem exceder 255 caracteres
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Número de include files aninhados excede 16 níveis
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Número máximo de níveis de PUSH excedido
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP não precedido de PUSH
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro ou variável de tempo de compilação "$1" vazia ou sem valor atribuído
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Valor de diretiva inválido, use ON/OFF/DEFAULT ou +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Diretiva Mode "$1" não permitida aqui
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Variável de tempo de compilação "$1" não definida
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Encontrado caracter com código UTF-8 maior do que 65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_String UTF-8 com caracteres inválidos
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_Encontrada assinatura UTF-8, conteúdo do arquivo será tratado como sendo UTF-8
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+parser_e_syntax_error=03000_E_Parser - Erro de sintaxe
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT procedure não pode ser local tem que ser global
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo de procedure "$1" ignorado
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_OVERLOAD usado para "$1". Todas declarações devem usar OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Funções exportadas com o nome externo "$1" igual
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Funções exportadas com o index externo "$1" igual
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Valor de index externo de função exportada inválido
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Informações de depuração para DLL relocável ou para executável $1 não funcionaram. Depuração ignorada.
+parser_w_parser_win32_debug_needs_WN=03012_W_Para permitir depuração de código win32 voce precisa desabilitar opção de relocação com a opção -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Nome do método Constructor deve ser INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Nome do método Destructor deve ser DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Uso de procedures tipo INLINE como no C++ não suportado
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Métodos Constructor devem estar em escopo "public" na classe
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Métodos Destructor devem estar em escopo "public" na classe
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Classes devem ter somente 1 método destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Declaração de classes em escopo "local" não permitida. Elas devem estar em escopo "global"
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Classes sem métodos e não derivadas de outras(anônimas) não são permitidas
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_Não há entrada na VMT para o objeto "$1"
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista de argumentos inválida(tipos de dados diferem dos parâmetros)
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Número de parâmetros errado
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Método que está fazendo overload e base do overload "$1" são de tipo diferente (function/procedure)
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Método tem mesma lista parâmetros do método sobre o qual queremos fazer overload
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Tipo de retorno ou qualificador da função difere na declaração forward "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Header de função "$1" não combina com o do forward : nome de variável trocado $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Valores especificados em tipos enumerados devem estar em ordem crescente
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_"With" não pode ser usado para variáveis in segmentos diferentes de memória
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Mais de 31 funções aninhadas
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Erro de "range" durante apuração de constantes
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Erro de "range" durante apuração de constantes
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Condição duplicada em 1 comando case
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_O valor superior de 1 "range" especificado num "case" é menor que o valor inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Constantes do tipo "class" ou "object" não são permitidas
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Não é permitido uso de variáveis tipo "function" em functions que sofrerão overload
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_Tamanho de string deve estar entre 1 e 255 bytes
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_Use a sintaxe extendida de NEW e DISPOSE para instâncias de objetos
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_Não há sentido em usar NEW ou DISPOSE para pointers untyped
+parser_e_no_new_dispose_on_void_pointers=03044_E_Não é possível usar NEW e DISPOSE para pointers untyped
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Identificador de classe ou objeto esperado antes do ponto
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identificador de type não permitido neste contexto
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Método esperado após o ponto
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Header de procedure/função "$1" não identifica nenhum método desta classe
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procedure ou function $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante de ponto flutuante inválida
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_"FAIL" só pode ser usado em "constructors"
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Métodos Destructor não podem ter parâmetros
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Somente métodos de classe podem ser usados numa referência de classe
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Somente métodos da classe podem ser acessados em métodos de classe
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Constante usada numa cláusula de um comando "case" não combina com o tipo da variável do "case"
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_O símbolo não pode ser exportado de 1 library. Só procedures ou functions
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Um método herdado está escondido(hidden) por "$1". Verifique se não tem que usar a diretiva OVERRIDE
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Não há método em classe ancestral com este nome para sofrer overriden : "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Faltou a cláusula "read" na declaração da propriedade
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Descontinuada
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Símbolo inválido para acesso a uma propriedade(a propriedade é 1 array?)
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Campo de objeto declarado como protected não pode ser acessado aqui
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Campo de objeto declarado como private não pode ser acessado aqui
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_metodos envolvidos em override devem ter o mesmo tipo de retorno: "$2" faz override em "$1" que tem outro tipo de retorno
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Functions/procedures não podem ser declaradas aninhadas em functions/procedures que serão exportadas
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_métodos não podem ser exportados
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_argumentos de chamadas por referência tem que ter mesmo atributo que o parâmetro correspondente: Achado "$1" esperado "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Metodo não é de classe ancestral da que o está chamando
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_Tentativa de usar "SELF" fora de um método
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_só pode usar uma chamada no formato classe.metodo dentro de um metodo
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso de ':' em local inválido
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Erro de range na declaração de set: Elemento(s) duplicado(s) ou fora de faixa p/o tipo de dado
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Esperada pointer para um objeto
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Expressão deve ser uma chamada a um constructor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Expressão deve ser uma chamada a um destructor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Campos declarados em ordem diferente da declaração do record
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_O tipo de expressão deve ser de class ou de record
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Subrotinas/métodos do tipo "procedure" não podem retornar valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Constructors e destructors devem ser métodos
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Um dos operandos não está na definição deste operador
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossível overload com dados do mesmo tipo
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Combinação de tipos do operador, dos argumentos e tipo de retorno incompatível
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Uso de raise não é possível aqui
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Esta sintaxe de new ou dispose não pode ser aplicada a classes
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Overload de procedures está desabilitado(ver diretiva -S)
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Este tipo de operador não pode sofrer overload
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Function que faça overload no operador = deve retornar "boolean"
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Somente métodos virtuais podem ser declarados "abstract"
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Feature não suportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_A mistura de diferentes tipos de objetos(class, object, interface, etc) não é permitida
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Diretiva desconhecida foi ignorada: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute pode ser usado em linha que declare somente 1 variável e redefinir variável ou "typed constant"
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute só pode redefinir 1 variável ou constante
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Não pode usar valor inicial em linha que declare mais de 1 variável
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Métodos abstract só podem ser declarados. Não podem conter código
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Esta função que está sofrendo overload não pode ser local (deve aparecer na interface)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Objeto/classe contém métodos virtuais mas não contém contructor em "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definida: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro liberada ou "des-definida": $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 assumiu valor $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando "unit" $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Interpretando "interface" da "unit" $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Interpretando "implementation" da "unit" $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Recompilando $1
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Propriedade para sofrer override não existe
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Tentativa de definir propriedade default para classe que já tem 1 default
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_A propriedade default deve ser uma "array property"
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtual constructors podem ser usados somente para classes
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Não há propriedade default disponível(nem por herança)
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_A classe não pode ter uma "published section", use a diretiva {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_A declaração com forward da classe "$1" precisa ser resolvida aqui para poder usar esta classe como ancestral
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Não pode fazer overload de operadores locais
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_A diretiva "$1" não é permitida seção "interface"
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_A diretiva "$1" não é permitida seção "implementation"
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_A diretiva "$1" não é permitida na área de declaração de variáveis de 1 procedure/function
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Procedure/function já foi declarada como Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Não pode usar EXPORT e EXTERNAL simultaneamente
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" ainda não é suportada em "inline procedure/function"
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_O uso de INLINE está desabilitado(diretiva $I)
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Avisa que gravou log do símbolo $1 gerado pelo "symbol browser"
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Pode estar faltando uma "pointer dereference". Meramente um comentário p/questões de sintaxe em relação ao Delphi p/exemplo
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Tipo de assembly não suportado
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Diretiva "$1" conflita com outras diretivas
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Interface/implementation "calling conventions" não combinam(cdecl?)
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_A propriedade não pode ter valor default(é tipo array ou set?)
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_O valor default de 1 propriedade deve ser uma constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Simbolo não pode ser published. Somente propriedades e variáveis "class type"
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Propriedades com este tipo de dados não podem ser "published"
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Procedures/functions que são exportadas de DLL's devem ter 1 "external name"
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Divisão por zero
+% There is a division by zero encounted
+parser_e_invalid_float_operation=03139_E_Operação de ponto flutuante inválida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Fim da faixa menor que o início da faixa
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_Constante string "$1" é maior que a declaração da variável string "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Constante string maior do que o "array of char" a qual está sendo atribuída
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expressão inválida após uma diretiva
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Métodos declarados com a diretiva {message}(message handlers) só podem ter 1 parâmetro e recebido por referêcia
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Label de mensagem duplicado: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_"Self" só pode ser usado como parâmetro explícito em métodos declarados com diretiva {message}(message handlers)
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Variáveis "Threadvars" s´ podem ser "static" ou "global"
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_"Direct assembly" não é suportado quando usando formato binário de saída
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Não carregue OBJPAS unit com "uses", use \{\$mode objfpc\} ou \{\$mode delphi\} ao invés disto
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_Não é possível fazer OVERRIDE em métodos de "object's"
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Tipos de dados que requeiram inicialização/finalização não podem ser usados em registros "variant"
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings só podem ser declarados static ou global
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_"Exit" com argumento neste contexto, não é permitido
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Símbolo de tipo de memoria deve ser booleano
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Este símbolo não é permitido como símbolo memória
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Só é permitido publicar classes compiladas com a diretiva $M+
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Esperada diretiva de procedure
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_O valor do "index" de uma propriedade deve ser do tipo ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nome de procedure/function que será exportada tem que ter no mínimo 2 caracteres
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Não foi possível gerar 1 DEFFILE para as variáveis globais da "unit"
+parser_e_dlltool_unit_var_problem2=03161_E_Compile sem a opção -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Voce precisa de ObjFpc (-S2) ou Delphi (-Sd) mode para compilar este módulo
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Não é possível exportar functions/procedures para este Sist.Op. $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exportação de variáveis não é permitida no Sist.Op. $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintaxe de declaração GUID inválida
+parser_w_interface_mapping_notfound=03168_W_Procedure/function "$1" não encontrada em contexto aplicável para implementar $2.$3
+parser_e_interface_id_expected=03169_E_Esperado identificador de interface
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Tipo "$1" não pode ser usado como "array index type"
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Constructors/destructors não são permitidos em interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Especificacoes de visibilidade não podem ser usadas em INTERFACES
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Interfaces não podem conter definições de campos
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Não é permitido declarar procedures locais como EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Alguns campos antes de "$1" não foram inicializados
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Alguns campos antes de "$1" não foram inicializados
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Alguns campos após "$1" não foram inicializados
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_A diretiva VarArgs usada em procedure/function não CDecl nem External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self deve ser 1 parâmetro recebido p/valor(não pode ser uma variável/constante)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interface "$1" precisa ter 1 identificação GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Campo de classe ou nome de método desconhecido "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_"Calling convention" "$2" substituirá a "$1"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_"Typed" constantes do tipo "procedure of object" só podem ser inicializadas com NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Valor default só pode ser atribuido a 1 parametro
+parser_e_default_value_expected_for_para=03185_E_Parâmetro default requerido para "$1"
+parser_w_unsupported_feature=03186_W_Use de feature não suportada
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Parametros passados a functions/procedures em C devem ser passados por referência(pointer)
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Array de constantes deve ser o último argumento de uma chamada do C
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_O "type" "$1" já foi criado, tentativa de redefinição
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Functions/procedures declaradas CDECL não suportam funções built in do compilador FPC
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Functions/procedures declaradas CDECL devem ser chamadas com string de tamanho igual ao declarado no cabecalho da Function/procedure
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Variáveis "threadvar" não podem ser inicializadas
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_A diretiva MESSAGE só é permitida em Classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure/Function esperada
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Diretiva de "calling convention" ignorada: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE não pode ser usado em objetos
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Cada argumento tem sua devida posição
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Cada argumento tem sua posição específica
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Posicao do argumento desconhecida
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Esperado um inteiro de 32 bits ou uma pointer
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Comando GOTO não pode desviar para label fora da procedure/function
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure muito complexa, ela requer registradores demais
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Expressão inválida
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Resultado da expressão não é "integer"
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Qualificador inválido
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Limite superior < limite inferior
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_O parâmetro do Exit deve ser o nome da procedure onde ele é usado
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Assinalamento inválido para a variável de controle do loop "for" "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Variáveis locais não podem ser declaradas EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procedure já foi declarada EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Assumido uso de Variants unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Classes e métodos static não podem ser usados em INTERFACES
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow em operação aritmética
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Protected ou private esperados
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Type não combina
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipos de dado incompatíveis. Encontrado "$1" esperado "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Tipos de "$1" e "$2" não combinam
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificador de tipo(type) esperado
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Esperada uma variável
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Esperada expressão do tipo "integer", mas encontrada "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Esperada expressão do tipo "boolean", mas encontrada "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Esperada expressão do tipo "ordinal"
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Esperado tipo pointer, mas encontrado "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Esperada uma classe, mas encontrado "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Não pude resolver a expressão
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Os elementos dos "sets" são incompatíveis
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operação não implementada para "sets"
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversão automática de floating type para COMP o qual é do tipo "integer"
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Use o operador DIV para obter um resultado "integer"
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_String types não combinam, por causa da diretiva $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ ou Pred em tipos "enumerated" que contenham atribuições não é possível
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Não é possível ler ou gravar variáveis deste "type"
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Não pode usar readln ou writeln em arquivo "typed"
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Não pode usar read ou write em arquivo "untyped"
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Conflito de tipo entre 1 ou mais elementos e o tipo de dados do SET
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) retorna upper/lower nos formatos word/dword
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Esperada expressão "integer" ou "real"
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo "$1" inválido em "array constructor"
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipo incompatível para o arg no. $1: Recebido "$2", esperado "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Variáveis do tipo "procedure of object" não são compatíveis com variáveis do tipo "procedure"
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante inválida passada para função matemática
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Não é possível obter endereço de constantes
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Não se pode atribuir dados a este argumento
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Não pode atribuir procedure/function local a uma variável do tipo "procedure"
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Não pode atribuir valores a um endereço
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Não pode atribuir valores a uma variável declarada como "const"
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Requerido tipo array
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Esperado tipo "interface" mas encontrado "$1"
+type_w_mixed_signed_unsigned=04035_W_Misturar expressões com sinal e "longword" gera resultado de 64 bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Misturar expressões com sinal e "cardinals" neste ponto pode causar "range check error"
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Variável que sofreu typecast ficou com tamanho diferente ($1 -> $2)
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Membro de "enumerated" que contenha atribuições, não pode ser usado como índice de array
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Classes ou "objects" de tipos "$1" and "$2" não estão relacionados(os tipos)
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Classes "types" "$1" e "$2" não estão relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Esperada uma classe ou um interface mas encontrado "$1"
+type_e_type_is_not_completly_defined=04042_E_O "type" "$1" não está completamente definido
+type_w_string_too_long=04043_W_Literal tem mais caracteres que o tamanho de "short string"
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_Comparação será sempre falsa devido ao "range" de valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_Comparação será sempre verdadeira devido ao "range" de valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Construindo classe "$1" mas superclasse tem métodos virtuais que não sofreram override
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_Operando a esquerada de um operador IN tem que ter tamanho de 1 byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_"Types" de tamanho diferente, haverá possível perda de dados e/ou "range check error"
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Tamanho dos types não combina, possível perda de dados ou erro de "range"
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Não foi possível obter o endereço de 1 método abstrato
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_O operador não se aplica ao tipo de operando
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Esperada expressão do tipo constante
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operação "$1" não permitida para os tipos "$2" and "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Conversão ilegal de tipos: "$1" para "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Conversão entre "ordinals" e "pointer" não é portável
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Conversão entre "ordinals" e "pointer" não é portável
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Não foi possível determinar qual das functions que sofreram overload deve ser chamada
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Variável usada como contador é de tipo inválido
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificador não encontrado "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Erro interno no SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificador duplicado "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identificador já definido em $1 na linha $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificador desconhecido "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Declaração "forward" não resolvida "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Erro na definição de um "type"
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_"Forward type" "$1" não resolvido
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Apenas variáveis "static" podem ser usadas em metodos "static" ou metodos externos ao bloco
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Esperado um record ou uma classe
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Não é permitido instanciar classes ou objetos através de métodos abstratos
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_"Label" não definido "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_"Label" usado mas não definido "$1"
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Declaração de label inválida
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO e LABEL não suportados (use a diretiva -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label não encontrado
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Identificador não é um label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Lable já definido
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Type inválido na declaração dos elementos de um set
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Definição da classe citada num "forward" não resolvida "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_"Unit" "$1" não usada em $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Identificador "$1" não usado
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Variável local "$1" não usada
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Identificador "$1" declarado com valor mas nunca usado
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Variável local "$1" é declarada/inicializada mas nunca usada
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Símbolo local $1 "$2" não é usado
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Campo "private" "$1.$2" nunca é usado
+sym_n_private_identifier_only_set=05030_N_Campo "private" "$1.$2" é inicializado mas nunca usado
+sym_n_private_method_not_used=05031_N_Metodo "private" "$1.$2" nunca usado
+sym_e_set_expected=05032_E_Esperado tipo "set"
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Resultado de uma function parece não ter sido atribuído
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type "$1" parece não estar alinhado corretamente no registro corrente para em estruturas C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Campo de "record" desconhecido "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Variável local "$1" parece não ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_Variavel "$1" não parece ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Identificador não identifica nenhum dado ou método "$1"
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Declaração encontrada mas procedure que sofre o overload não: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Elemento de dados muito grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Não encontrada implementação de metodo para a interface "$1"
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" está obsoleto(a)
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Símbolo "$1" não é portavel
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Símbolo "$1" não está implementado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Não é possível criar 1 "type" que seja único a partir deste "type"
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Variável local "$1" não parece ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Variável "$1" não parece ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Lista de parâmetros excede 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_"File types" devem ser variáveis
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_O uso de pointer tipo "far" não é permitido
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Functions declaradas EXPORT não podem ser chamadas
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possível chamada inválida a constructor ou destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Código pouco eficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Código nunca será executado
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Métodos abstratos não podem ser chamadaos diretamente
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registrador $1 tem prioridade sobre $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_"Stack frame" omitido
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Objetos ou métodos não podem ser inline.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Call a variáveis do tipo procedure não podem ser inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Nenhum código foi carregado para a procedure inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_O elemento zero de 1 ansi/wide- ou longstring não pode ser acessado, use SetLength
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors ou destructors não podem ser chamados de dentro de 1 cláusula 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Não é possível acessar diretamente métodos do tipo "message handler"(declarados com diretiva message)
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Pulo para dentro ou para fora de 1 "exception block"
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Comandos de controle de fluxo de execução não são permitidos dentro de blocos "finally"
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Tamanho total dos parâmetros excede o limite de alguns processadores
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_O tamanho total das variáveis locais excede o limite de alguns processadores
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_O tamanho das variáveis locais excede o limite suportado
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK não permitido neste ponto
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE não permitido neste ponto
+% You're trying to use \var{continue} outside a loop construction.
+asmr_d_start_reading=07000_DL_Iniciando a montagem do bloco assembly $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Montagem do bloco assembly $1 finalizada
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Encontrado o caracter @ em identificador que não é label
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Erro durante a apuração de um deslocamento(offset)
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_Deslocamento(OFFSET) usado sem um identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_"TYPE" usado sem identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Não pode usar variável local ou parâmetros aqui
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_É necessário o uso do operador OFFSET aqui
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Precisa usar $ aqui
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Não pode usar múltiplos símbolos relocáveis
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Simbolo relocável só pode ser usado para adição
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Expressão constante inválida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Símbolo relocável não permitido aqui
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Erro de sintaxe
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Nao permitido acionar $1 a partir deste código
+% You can not read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Símbolos e labels locais não são permitidos como referências
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso inválido de registradores base e indexador
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Possível erro no manuseio de algum campo de objeto
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Especificado fator de escala errado
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso de múltiplos registradores indexadores
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo de operando inválido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Opcode inválido: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE e @DATA não suportados
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label references não permitidas
+asmr_e_expr_zero_divide=07025_E_Divisão por zero no analisador do assembler
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expressão ilegal
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sequencia de escape ignorada: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Referência a símbolo inválida
+asmr_w_fwait_emu_prob=07029_W_Fwait pode causar problemas de emulação com emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sem operandos traduzida para $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instrução ENTER não é suportada pelo kernel do Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Chamada em assembly a 1 método que sofreu overload
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Símbolo de "type" não suportado para operando
+asmr_e_constant_out_of_bounds=07034_E_Constante fora da faixa
+asmr_e_error_converting_decimal=07035_E_Erro convertendo decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Erro convertendo octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Erro convertendo binario $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error convertendo hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traduzido para $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 está associado a uma function que sofreu overload
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Não pode usar SELF fora de um método
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Não pode usar OLDEBP fora de uma procedure aninhada
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedures não podem retornar nenhum valor no código assembly
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG não suportado
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Sufixo de tamanho e o destino ou tamanho da origem não combinam
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Tamanho do "suffix" e o tamanho do destino ou da origem não combinam
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Erro de sintaxe assembly
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinação de opcode e operandos inválida
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Erro de sintaxe assembly em operando
+asmr_e_syn_constant=07050_E_Erro de sintaxe assembly em constante
+asmr_e_invalid_string_expression=07051_E_Expressão string inválida
+asmr_w_const32bit_for_address=07052_W_Constante com símbolo $1 para endereço que não está numa pointer
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Opcode não reconhecido $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Opcode inválido ou ausente
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinação de opcode e prefixo inválida: $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinação inválida de opcode e override: $1
+asmr_e_too_many_operands=07057_E_Operandos em excesso numa linha
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorado
+asmr_w_far_ignored=07059_W_FAR ignorado
+asmr_e_dup_local_sym=07060_E_Símbolo local duplicado $1
+asmr_e_unknown_local_sym=07061_E_Símbolo local não definido $1
+asmr_e_unknown_label_identifier=07062_E_Label desconhecido $1
+asmr_e_invalid_register=07063_E_Nome de registrador inválido
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nome de registrador de ponto flutuante inválido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Função "mod"(resto) não suportada
+asmr_e_invalid_float_const=07067_E_Constante de ponto flutuante inválida $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Expressão de ponto flutuante inválida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Símbolo de tipo inválido
+asmr_e_cannot_index_relative_var=07070_E_Nao pode indexar com registrador uma variável local ou parâmetro(que já são indexados a 1 reg. base)
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Expressão com override inválido de segmento
+asmr_w_id_supposed_external=07072_W_Identificador $1 assumido como external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings não permitidos como constantes
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Nenhum tipo de variável especificado
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_O codigo assembly não gera retorno a seção de texto
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Não é uma diretiva nem um símbolo local $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Usando um nome auto-definido como label local
+asmr_e_dollar_without_identifier=07078_E_Um símbolo "$" usado sem estar no início de 1 identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Criada uma constante de 32 bits para endereçamento
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align é especifico de plataforma, use .balign ou .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Não pode acessar diretamente os campos de parâmetros
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Não pode acessar diretamente campos de objetos/classes
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Não especificado tamanho e não foi possível determinar o tamanho dos operandos
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Não pode usar RESULT nesta function
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sem operando traduzido para "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traduzido para "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" traduzido para "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_O caracter < não é permitido aqui
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_O caracter > não é permitido aqui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN não suportado
+asmr_e_no_inc_and_dec_together=07094_E_"Inc" e "Dec" não podem estar juntos
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Registrador(es) inválido(s) para "movem"
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Registrador(es) inválidos para o opcode
+asmr_e_higher_cpu_mode_required=07097_E_Requerido modo de CPU mais avançado ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Não foi especificado tamanho e não é possivel determinar o tamanho dos operandos, DWORD usado como default
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Erro de sintaxe enquanto tentava montar uma operação de "shift"
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Excesso de arquivos assembly
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Tipo de saida do assembler não suportado
+asmw_f_comp_not_supported=08002_F_"Comp" não suportado
+asmw_f_direct_not_supported=08003_F_"Direct" não suportado para "binary writers"
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Alocação de dados só é permitida na seção bss
+asmw_f_no_binary_writer_selected=08005_F_Nenhum "binary writer" selecionado
+asmw_e_opcode_not_in_table=08006_E_Assembler: Opcode $1 não existe na tabela
+asmw_e_invalid_opcode_and_operands=08007_E_Asssmbler: $1 combinação de opcode e operadores inválida
+asmw_e_16bit_not_supported=08008_E_Assembler: Referências de 16 bits não suportadas
+asmw_e_invalid_effective_address=08009_E_Assembler: Endereço efetivo inválido
+asmw_e_immediate_or_reference_expected=08010_E_Assembler: Esperados um operador imediato ou uma referência
+asmw_e_value_exceeds_bounds=08011_E_Assembler: Valor de $1 excede os limites de $2
+asmw_e_short_jmp_out_of_range=08012_E_Assembler: "Short jump" fora de faixa $1("short jump" gera troca de segmento de memória?)
+asmw_e_undefined_label=08013_E_Assembler: Label indefinido $1
+asmw_e_comp_not_supported=08014_E_Assembler: Type "Comp" não suportado na plataforma destino
+asmw_e_extended_not_supported=08015_E_Assembler: "Type" Extended não suportado na plataforma destino
+asmw_e_duplicate_label=08016_E_Assembler: Label duplicado $1
+asmw_e_redefined_label=08017_E_Assembler: Label redefinido $1
+asmw_e_first_defined_label=08018_E_Assembler: Definido a primeira vez aqui
+asmw_e_invalid_register=08019_E_Assembler: Registrador inválido $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sist Oper fonte redefinido
+exec_i_assembling_pipe=09001_I_Montagem em andamento $1
+exec_d_cant_create_asmfile=09002_E_Assembler não pode criar o arquivo $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Não pode criar o arquivo objeto: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Não pode criar o arquivo "archive": $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 não encontrado, mudando para montagem assembly externa
+exec_t_using_assembler=09006_T_Usando o assembler: $1
+exec_e_error_while_assembling=09007_E_Erro durante a montagem assembly -> exitcode $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Não pode chamar o assembler, erro $1. Mudando para montagem assembly externa
+exec_i_assembling=09009_I_Montando $1
+exec_i_assembling_smart=09010_I_Montagem com smartlinking $1
+exec_w_objfile_not_found=09011_W_Objeto $1 não encontrado, a link-edição pode falhar!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Library $1 não encontrada, a link-edição pode falhar!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Erro durante a link-edição
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Não pode chamar o linkage editor interno, mudando para link-edição externa
+exec_i_linking=09015_I_Link edição de $1
+exec_e_util_not_found=09016_E_Utilitário $1 não encontrado, mudando para link-edição externa
+exec_t_using_util=09017_T_Usando utilitário $1
+exec_e_exe_not_supported=09018_E_Criação de executáveis não suportada
+exec_e_dll_not_supported=09019_E_Criação de libraries Dynamic/Shared não suportada
+exec_i_closing_script=09020_I_Fechando script $1
+exec_e_res_not_found=09021_E_Recurso do compilador não encontrado, mudando para modo externo
+exec_i_compilingresource=09022_I_Recurso de compilação $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_A "unit" $1 não pode ser link-editada de forma estática, mudando para o modo "smart linking"
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_A "unit" $1 não pode ser link-editada no modo "smart linking", mudando para link-edição estática
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_A "unit" $1 nao pode ser link-editada em modo "shared linking", mudando para link-edicao estática
+exec_e_unit_not_smart_or_static_linkable=09026_E_A "unit" $1 não pode ser link-editada nem no modo "smart linking" nem em link-edição estática
+exec_e_unit_not_shared_or_static_linkable=09027_E_A "unit" $1 não pode ser link-editada nem no modo "shared linking" nem em link-edição estática
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_Não pode pós-processar o executável $1
+execinfo_f_cant_open_executable=09029_F_Não pode abrir o executável $1
+execinfo_x_codesize=09030_X_Tamanho do código: $1 bytes
+execinfo_x_initdatasize=09031_X_Tamanho da área de dados inicializados: $1 bytes
+execinfo_x_uninitdatasize=09032_X_Tamanho da área de dados não-inicializados: $1 bytes
+execinfo_x_stackreserve=09033_X_Espaço reservado para o stack: $1 bytes
+execinfo_x_stackcommit=09034_X_Espaço realmente usado pelo stack: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Caminho onde o compilador tentará achar "units": $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_"Units" carregadas pelo compilador $1 (.PPU)
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nome da "unit"(.PPU): $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Flags da "unit"(.PPU): $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Check sum da "unit"(.PPU): $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Data de compilação da "unit"(.PPU): $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Arquivo PPU da "unit" muito pequeno
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Header de arquivo PPU(de uma "unit") inválido(não tem PPU no início)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Versão de arquivo PPU(de uma "unit") inválida $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_"Unit"(arquivo PPU) compilada para outro processador
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_"Unit"(arquivo PPU) foi compilada para outro sistema operacional
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_Check sum do arquivo PPU da "unit": $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Gravando as "units"(arquivos PPU) em: $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Nao pode gravar o arquivo PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Erro durante a leitura de um arquivo PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fim de arquivo PPU inesperado
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Arquivo PPU em formato inválido: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problema na contagem Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nome da "unit" inválido $1. Diverge do nome do arquivo que a contem.
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Há "units" demais. Excedem o limite definido para a compilação(diretiva maxunits)
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_"Units" $1 e $2 referem-se mutuamente(referência circular)
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_"Unit" $1 precisa ser recompilada mas o fonte não foi encontrado
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_"Unit"(arquivo PPU) "$1" não pode ser encontrada
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_"Unit" $1 não foi encontrada mas a $2 existe
+unit_f_unit_name_error=10024_F_"Unit" $1 procurada mas a $2 foi encontrada
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Para compilar a "unit" System tem que usar a diretiva -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Houve $1 erros compilando o módulo, compilação abortada
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Carregando $3 a partir da "unit" $1. A carga foi requisitada em $2.
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilando a "unit" $1, checksum mudou para $2
+unit_u_recompile_source_found_alone=10029_U_Recompilando $1 porque foi encontrado somente o fonte
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilando a "unit", algum das "static libraries" é mais antiga que o arquivo PPU
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilando a "unit", a "shared lib" ‚ mais antiga que o ppufile
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilando a "unit". Módulos obj e asm tem data mais antiga que o PPU
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilando a "unit". Módulo obj mais antigo que o asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Interpretando interface da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Interpretando implementation da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Segunda carga da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Verificando arquivo PPU $1 data/hora $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Não pode recompilar "unit" $1, mas foram encontrados arquivos de include modificados
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Arquivo $1 é mais recente que o arquivo PPU $2 que foi compilado com flag de release -Ur
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Usando uma "unit" que foi compilada com tipo diferente de emulação de ponto flutuante(FPU)
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Incluindo "units" relacionadas na interface da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Incluindo "units" relacionadas na implementation da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Check sum da Interface modificado para a "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Check sum da Implementation modificado para a "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Compilação da "unit" $1 terminada
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Dependência de $1 adicionada a $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Não precisa carregar de novo, "unit" já está carregada $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Não precisa carregar a unit de novo, é uma recompilação $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Recarregando: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Recarga forçada
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Estado anterior de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Já compilando $1, setando opção de recompilação
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Carregando a "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Carga da "unit" $1 terminada
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrando a nova "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Recalculando área de dados da "unit" $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Pulando o recalculo da área de dados da "unit" $1, "units" usadas já carregadas
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [opções] <arquivo entrada> [opções]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Suportado apenas um arquivo fonte
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Arquivo DEF só pode ser criado para OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Response files aninhados não permitidos
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Nenhum arquivo fonte especifica na linha de comando
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Nenhuma opção dentro do arquivo de configuração $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parâmetro inválido: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_"-?" exibe páginas de help
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Muitos arquivos de configuração aninhados(+ de 16 níveis)
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Não foi possível abrir arquivo $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lendo opções adicionais de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Sistema operacional destino já está setado para: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Libraries shared não suportados em DOS, revertendo para libraries estáticas
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_IF(N)DEFs em excesso
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_ENDIFs em excesso
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Comando de compilação condicional não fechado no final de arquivo
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Este executável do compilador não suporta geração de informações de debug
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Tente recompilar com -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Voce está usando uma diretiva obsoleta $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Voce está usando a diretiva obsoleta $1, por favor use $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Mudando assembler para o modo default de fonte
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Tipo de saída assembler selecionada "$1" não compatível com "$2"
+option_asm_forced=11022_W_Forçado uso de assembler "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Lendo opções a partir do arquivo $1
+% Options are also read from this file
+option_using_env=11027_T_Lendo opções da variável de ambiente $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Tratando opção "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** pressione enter ***
+option_start_reading_configfile=11030_H_Início do tratamento do arquivo de configuração $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Fim do arquivo durante leitura do arquivo de configuração $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretando a opção "$1"
+option_interpreting_firstpass_option=11036_D_Interpretando a opção de primeiro passo "$1"
+option_interpreting_file_option=11033_D_Interpretando opção de arquivo "$1"
+option_read_config_file=11034_D_Lendo o arquivo de configuração "$1"
+option_found_file=11035_D_Encontrado o arquivo fonte "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Página de código desconhecida
+# Logo
+option_logo=11023_[
+Free Pascal Compiler versão $FPCVERSION [$FPCDATE] para $FPCCPU
+Copyright (c) 1993-2005 por Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versão $FPCVERSION
+
+Data do compilador : $FPCDATE
+Processador destino: $FPCCPU
+
+Sistemas operacionais atendidos
+ $OSTARGETS
+
+Conjuntos de instruções atendidos:
+ $INSTRUCTIONSETS
+
+Conjuntos de instruções de ponto flutuante atendidos:
+ $FPUINSTRUCTIONSETS
+
+Este programa vem sob a licença GNU General Public Licence
+Para mais informações leia COPYING.FPC
+
+Informações de erros detectados, sugestões, etc para:
+ bugrep@freepascal.org
+]
+# Help pages
+option_help_pages=11025_[
+**0*_coloque + após 1 opção booleana para habilita-la, - para desabilita-la
+**1a_o compilador não deletou o arquivo assembly gerado
+**2al_Lista as linhas de código fonte do arquivo assembly
+**2an_lista as informações de node do arquivo assembly
+*L2ap_use pipes(redirecione) ao invés de criar arquivos assembly temporários
+**2ar_lista informações de alocação/liberação de registradores no arquivo asembly
+**2at_lista informaçoes de alocação/liberação temporárias no arquivo assembly
+**1A<x>_Formato de saída:
+**2Adefault_use o assembly default
+3*2Aas_Montagem feita usando o GNU AS
+3*2Anasmcoff_coff (Go32v2) file gerado usando Nasm
+3*2Anasmelf_elf32 (Linux) file gerado usando Nasm
+3*2Anasmwin32_Win32 object file gerado usando Nasm
+3*2Anasmwdosx_Win32/WDOSX object file gerado usando Nasm
+3*2Awasm_obj file gerado usando Wasm (Watcom)
+3*2Anasmobj_obj file gerado usando Nasm
+3*2Amasm_obj file gerado usando Masm (Microsoft)
+3*2Atasm_obj file gerado usando Tasm (Borland)
+3*2Aelf_elf32 (Linux) gerado usando uma internal writer
+3*2Acoff_coff (Go32v2) gerado usando uma internal writer
+3*2Apecoff_pecoff (Win32) gerado usando uma internal writer
+4*2Aas_Montagem feita usando o GNU AS
+6*2Aas_Unix o-file gerado usando o GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola assembler
+A*2Aas_Montagem feita usando o GNU AS
+P*2Aas_Montagem feita usando o GNU AS
+S*2Aas_Montagem feita usando o GNU AS
+**1b_gera informações do browser
+**2bl_gera a local symbol information
+**1B_Compila/monta todos os módulos
+**1C<x>_opções de geração do código:
+**2Cc<x>_default calling convention setada para <x>
+**2CD_criar também a dynamic library (não suportado)
+**2Ce_Compilação com opcodes de ponto flutuante emulados
+**2Cf<x>_Selecione o conjunto de instruções de ponto flutuante a ser usado, veja diretiva -i do FPC para valores possíveis
+**2Cg_Gerar código com endereçamento relativo(endereçar usando só o deslocamento do operando)
+**2Ch<n>_define heap com <n> bytes (entre 1023->1KB e 67107840->64 MB)
+**2Ci_IO-checking(validação dos comandos de I/O)
+**2Cn_Não executar estágio de link-edição
+**2Co_Checar overflow de operações com inteiros
+**2Cp<x>_seleciona o conjunto de instruções, veja diretiva FPC -i para valores possíveis
+**2Cr_range checking(validação da faixa de validade de valores)
+**2CR_verificar validade das chamadas de métodos de objetos
+**2Cs<n>_seta o tamanho do stack para o valor <n>
+**2Ct_stack checking(verifica estouros da capacidade do stack)
+**2CX_criar também a smartlinked library
+**1d<x>_define o símbolo <x>
+1D_gera um DEF file
+**2Dd<x>_seta a descrição para <x>
+**2Dv<x>_set a versão das DLL para <x>
+*O2Dw_PM application(usa o Presentation manager do OS/2)
+**1e<x>_seta o path para o executável
+**1E_o mesmo que -Cn
+**1F<x>_seta nomes de arquivos e paths:
+**2Fa<x>[,y]_para o programa primeiro carregar as "units" <x> e [y] antes de interpretar o "uses"
+**2Fc<x>_seta a página de código da entrada para <x>
+**2FD<x>_seta o diretório onde procurar pelas utilities do compilador
+**2Fe<x>_redireciona a saída de erros para <x>
+**2FE<x>_seta a saída de exe/units para o path <x>
+**2Fi<x>_adiciona <x> ao(s) path(s) de include
+**2Fl<x>_adiciona <x> ao library path
+**2FL<x>_usa <x> como dynamic linker
+**2Fo<x>_adiciona <x> ao object path
+**2Fr<x>_carrega o arquivo de mensagens de erro <x>
+**2Fu<x>_adiciona <x> ao unit path
+**2FU<x>_seta o unit output path para <x>, anula o informado na diretiva -FE
+*g1g_gerar informações para o depurador(debugger)
+*g2gc_gerar checagem de pointers
+*g2gd_usar dbx
+*g2gg_usar gsym
+*g2gh_Usar "unit" de trace de heap (para depuração de descontinuidade de memória)
+*g2gl_usar unit com informações de números de linhas para obter msgs de erro com seu número de linha
+*g2gv_gerar programas traçáveis com valgrind
+*g2gw_gerar informações de depuração para dwarf
+**1i_informações
+**2iD_retorna a data de compilação do compilador
+**2iV_retorna a versão do compilador
+**2iSO_retorna o sistema operacional onde está sendo feita a compilação
+**2iSP_retorna o processador do compilador
+**2iTO_retorna o sistema operacional para o qual será gerado o executável
+**2iTP_retorna o processador para o qual será gerado o executável
+**1I<x>_adiciona <x> ao(s) path(s) de include
+**1k<x>_Passa <x> para o linkage editor
+**1l_escreva as mensagens de identificação
+**1M<x>_seta language mode para <x>(delphi, FPC, etc.)
+**2Mfpc_dialeto free pascal (default)
+**2Mobjfpc_ativa algumas extensões do Delphi 2
+**2Mdelphi_Tenta manter compatibilidade com o Delphi
+**2Mtp_Tenta manter a compatibilidade com TP/BP 7.0
+**2Mgpc_Tenta manter compatibilidade com gpc
+**2Mmacpas_Tenta manter compatibilidade com os dialetos do macintosh pascal
+**1n_não ler o arquivo de configuração default
+**2Nu_expanda o conteúdo dos loops
+**1o<x>_Troca o nome do executável produzido para <x>
+**1O<x>_otimizações:
+d3*2Og_gera codigo(executável) menor
+3*2OG_gera codigo(executável) mais rápido(default)
+**2Or_mantem certas variáveis em registradores
+3*2Ou_ativa otimizações incertas (veja documentação)
+3*2O1_otimizações de nível 1 (optimizações rápidas)
+3*2O2_otimizações de nível 2(-O1 optimizações + lentas)
+3*2O3_otimizações de nível 3(-O2 repetidamente, max 5 vezes)
+3*2Op<x>_processador para o qual será gerado o executável(target)
+3*3Op1_seta processador destino como 386/486
+3*3Op2_seta processador destino como Pentium/PentiumMMX (tm)
+3*3Op3_seta processador destino como PPro/PII/c6x86/K6 (tm)
+6*2Og_gera código(executável) menor
+6*2OG_gera código(executável) mais rápido(default)
+6*2Ox_otimize ao máximo(ainda com problemas!!!)
+6*2O0_seta como processador destino(gera executável para) o MC68000
+6*2O2_seta como processador destino(gera executável para) o MC68020+ (default)
+**1pg_gera perfil para gprof (cria o FPC_PROFILE)
+**1R<x>_estilo de leitura do assembler:
+**2Rdefault_use o assembler default
+3*2Ratt_ler assembly no estilo AT&T
+3*2Rintel_ler assembly no estilo Intel
+6*2RMOT_ler assembly no estilo motorola
+**1S<x>_opções de sintaxe:
+**2S2_o mesmo que -Mobjfpc
+**2Sc_suporta operadores como o C (*=,+=,/= and -=)
+**2Sa_include assertion code.
+**2Sd_o mesmo que -Mdelphi
+**2Se<x>_opções de erro. <x> é uma combinação do seguinte:
+**3*_<n> : compilador para após <n> erros (o default é 1)
+**3*_w : compilador também para após warnings
+**3*_n : compilador também para após notes
+**3*_h : compilador também para após hints
+**2Sg_permitir LABEL e GOTO
+**2Sh_Use strings do tipo ansistring
+**2Si_dar suporte a INLINE estilo C++
+**2SI<x>_setar estilo de interface para <x>
+**3SIcom_interface compatível com COM (default)
+**3SIcorba_interface compatível com CORBA
+**2Sm_suporta macros como o C (global)
+**2So_o mesmo que -Mtp
+**2Sp_o mesmo que -Mgpc
+**2Ss_constructor tem que se chamar init (destructor tem que se chamar done)
+**2St_permitir a keyword static em objetos
+**1s_não chamar o assembler nem linker
+**2sh_Gerar script para link edição no host
+**2st_Gerar script para link edição no sistema operacional de destino
+**2sr_Pular a fase de alocação de registradores (usar com -alr)
+**1T<x>_Sistema operacional para o qual será gerado o executável(target):
+3*2Temx_OS/2 via EMX (incluindo o extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Versao 2 do DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (not supported)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin and MacOS X on PowerPC
+P*2Tlinux_Linux on PowerPC
+P*2Tmacos_MacOS (classic) on PowerPC
+d2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_excluir definição do símbolo <x>
+**1U_opções de "unit":
+**2Un_não verifique o nome da "unit"
+**2Ur_gerar arquivos de "unit" do tipo "release"
+**2Us_compilar uma "unit" system
+**1v<x>_Mostrar opções de compilação. <x> é uma combinação das seguintes letras:
+**2*_e : Mostrar erros (default) 0 : Mostrar somente erros
+**2*_w : Mostrar avisos u : Mostrar informações da "unit"
+**2*_n : Mostrar "notes" t : Mostrar arquivos acessados/usados
+**2*_h : Mostrar "hints" c : Mostrar "conditionals"
+**2*_i : Mostrar informações gerais d : Mostrar informações de depuração(debug)
+**2*_l : Mostrar números de linha r : Modo de compatibilidade Rhide/GCCode
+**2*_a : Mostrar tudo x : Informações do executável (Win32 apenas)
+**2*_v : grava fpcdebug.txt com p : Grava tree.log com a árvore de parse
+**2*_ muitas informações de depuração
+3*1W<x>_opções do sistema operacional de destino no formato Win32
+3*2WB_Criar uma imagem relocável
+3*2WB<x>_Setar a base da imagem para o valor hexadecimal <x>
+3*2WC_Especifica aplicação tipo console
+3*2WD_Use DEFFILE para exportar functions de DLL ou EXE
+3*2WF_Especifica aplicação tipo tela cheia (apenas OS/2)
+3*2WG_Especifica aplicação gráfica
+3*2WN_Não gerar código relocável (necessário para depuração)
+3*2WR_Gerar código relocável
+P*2WC_Especifica aplicação tipo console (apenas MacOS)
+P*2WG_Especifica aplicação gráfica (apenas MacOS)
+P*2WT_Especifica aplicação do tipo ferramenta (ferramenta MPW, apenas MacOS)
+**1X_opções de executável:
+**2Xc_passar --shared ao linkage editor (apenas Unix)
+**2Xd_não usar caminho padrão de pesquisa em library (necessário para cross compile)
+**2XD_tentar link editar "units" dinâmicas(definir FPC_LINK_DYNAMIC)
+**2Xm_gerar mapa de link edição
+**2XM<x>_seta o nome da rotina principal do programa (default é 'main')
+**2XP<x>_prefixa os nomes dos binutils com o prefixo <x>
+**2Xr<x>_setar o caminho de pesquisa de libraries para <x> (necessário para cross compile)
+**2Xs_elimine todos os símbolos do executável
+**2XS_tente link editar as units como static (default) (definido com FPC_LINK_STATIC)
+**2Xt_link editar com static libraries (-static é passado ao linkage editor)
+**2XX_tente link editar as unidades com smart linking(definido com FPC_LINK_SMART)
+**1?_Mostra esta ajuda
+**1h_mostra esta ajuda sem espera
+]
+# End of help
+%%% scan_w_only_pack_records=02015_W_O alinhamento de campos de registro só pode ser em 1,2,4,8,16 or 32 bytes
+%%% scan_w_only_pack_enum=02016_W_Tipo enumerado pode ser salvo em apenas 1, 2 ou 4 bytes
+%%% parser_e_exit_with_argument_not_possible=03153_E_Não é possível usar "Exit" com argumento neste contexto
+%%% parser_e_only_publishable_classes_can_be_published=03156_E_Só podem ter atributo "published" classes compiladas com $M+
+%%% type_w_smaller_possible_range_check=04048_W_"Types" de tamanho diferente, haverá possível perda de dados e/ou "range check error"
+%%% mr_e_local_para_unreachable=07015_E_Não pode acessar a variável $1 direto deste código
+%%% asmr_e_size_suffix_and_dest_dont_match=07045_E_Sufixo de tamanho e o destino ou tamanho da origem não combinam
+%%% option_no_debug_support=11016_W_Este executável do compilador não suporta geração de informações de debug
+%%% scan_e_illegal_pack_records=02015_E_Illegal record alignment specifier "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+%%% scan_e_illegal_pack_enum=02016_E_Illegal enum minimum-size specifier "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+%%% scan_e_compile_time_typeerror=02072_E_Compile time expression: Wanted $1 but got $2 at $3
+% Type check of a compile time expression failed.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+%%% cg_f_unknown_compilerproc=06046_F_Unknown compilerproc "$1". Check if you use the correct run time library.
+% The compiler expects that the runtime library contains some subrountines. If you see this error
+% and you didn't mess with the runtime library, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+%%% exec_d_resbin_params=09028_D_Calling resource compiler "$1" with "$2" as command line
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
diff --git a/compiler/msg/errorr.msg b/compiler/msg/errorr.msg
new file mode 100644
index 0000000000..3cc07a0f07
--- /dev/null
+++ b/compiler/msg/errorr.msg
@@ -0,0 +1,2015 @@
+#
+# $Id: errorr.msg 1.21 2002/01/21 00:00:02 Michail A.Baikov (xakep@gamedot.ru)
+# â®â ä ©« - ç áâì ¯à®£à ¬¬­®£® ¯à®¤ãªâ  Free Pascal Compiler
+# Copyright (c) 1999-2002 by Free Pascal Development Team
+#
+# yá᪨© ä ©« (MSDOS CP) á®®¡é¥­¨© ¤«ï Free Pascal Compiler
+#
+# ‘¬. ä ©« COPYING.FPC, ¢ª«î祭­ë© ¢ íây ¯®áâ ¢ªy,
+# ¯® ¢á¥¬ ¢®¯à®á ¬ ®â­®á¨â¥«ì­®  ¢â®à᪮£® ¯à ¢ .
+#
+# â  ¯à®£à ¬¬  à á¯à®áâp ­ï¥âáï á ­ ¤¥¦¤®©, çâ® ®­  ¡ã¤¥â ª®¬y-­¨¡ã¤ì
+# ¯®«¥§­ , ­® …‡ ‚‘ŸŠŽ‰ ƒ€€’ˆˆ! Œë ­¥ £ à ­â¨à㥬, çâ® ¯à®£à ¬¬  ¤ ¦¥
+# ᮮ⢥âáâ¢ã¥â ᢮¥© 楫¨!
+#
+#
+# Š®­áâ ­âë - ®¡®§­ ç¥­¨ï, ¯¨èãâáï ¢ á«¥¤yî饬 ¢¨¤¥:
+# <part>_<type>_<txtidentifier>
+#
+# <part> íâ® â  ç áâì ª®¬¯¨«ïâ®à , ª®â®à ï á®®¡é ¥â ®¡ ®è¨¡ª¥:
+# asmr_ ᨭ⠪á¨ç¥áª¨©  ­ «¨§  áᥬ¡«¥à  (ç⥭¨¥  áᥬ¡«¥à )
+# asmw_ ᨭ⠪á¨ç¥áª¨©  ­ «¨§  áᥬ¡«¥à  (§ ¯¨áì ®¡ì¥ªâ­ëå ä ©«®¢)
+
+# unit_ ®¡à ¡®âª  ¬®¤ã«ï
+# scan_ ᪠­¥à
+# parser_ ᨭ⠪á¨ç¥áª¨©  ­ «¨§ â®à
+# type_ ª®­â஫ì ᮮ⢥âá⢨ï ⨯®¢
+# general_ ®¡é ï ¨­ä®à¬ æ¨ï
+# exec_ ¢ë§®¢ë  áᥬ¡«¥à , ª®¬¯®­®¢é¨ª , । ªâ®à 
+#
+# <type> ⨯ á®®¡é¥­¨ï:
+# f_ ä â «ì­ ï ®è¨¡ª 
+# e_ ®è¨¡ª 
+# w_ ¯à¥¤ã¯à¥¦¤¥­¨¥
+# n_ ¯à¨¬¥ç ­¨¥
+# h_ ¯®¤áª §ª 
+# i_ ¨­ä®à¬ æ¨ï
+# l_ ­®¬¥p áâp®ª¨
+# u_ ¨á¯®«ì§®¢ ­¨¥
+# t_ ¯®¯ë⪠ ¨á¯®«ì§®¢ âì
+# m_ ¬ ªà®ª®¬ ­¤ 
+# p_ ¯à®æ¥¤ãà 
+# c_ ãá«®¢­®¥ ¢ëà ¦¥­¨¥
+# d_ á®®¡é¥­¨¥ ¤«ï ®â« ¤ª¨
+# b_ ®â®¡à ¦ ¥â ¯¥à¥£à㦥­­ë¥ ¯à®æ¥¤ãàë ¨ ä㭪樨
+# x_ ¨­ä®à¬ æ¨ï ¤«ï ¨á¯®«­ï¥¬ëå ä ©«®¢
+#
+
+#
+# Ž¡é¥¥
+#
+# 01016 ¯®á«¥¤­¨© ­®¬¥à ¨á¯®«ì§®¢ ­­®£® á®®¡é¥­¨ï
+#
+# BeginOfTeX
+% \section{Ž¡é¨¥ á®®¡é¥­¨ï ª®¬¯¨«ïâ®à }
+% â®â à §¤¥« ¤ ¥â á®®¡é¥­¨ï ª®¬¯¨«ïâ®à , ª®â®àë¥ ­¥ ä â «ì­ë, ­® ª®â®àë¥
+% ®â®¡à ¦ îâ ¯®«¥§­ãî ¨­ä®à¬ æ¨î. —¨á«® â ª¨å á®®¡é¥­¨© ¬®¦¥â ¡ëâì
+% ã¯à ¢«ï¥¬ë¬ á à §«¨ç­ë¬¨ ­ áâp®©ª ¬¨ yp®¢­ï \var{-v} «®£¨«¨p®¢ ­¨ï.
+% \begin {®¯¨á ­¨¥}
+general_t_compilername=01000_T_Š®¬¯¨«ïâ®p: $1
+% Š®£¤  \var{-vt} ª«îç ¨á¯®«ì§ã¥âáï, íâ  áâப , á®®¡é ¥â ¢ ¬, ª ª®©
+% ª®¬¯¨«ïâ®à ¨á¯®«ì§ã¥âáï.
+general_d_sourceos=01001_D_Š®¬¯¨«¨àã¥âáï ­  OS: $1
+% Š®£¤  \var{-vd} ª«îç ¨á¯®«ì§ã¥âáï, íâ  áâப , á®®¡é ¥â ¢ ¬, ¢ ª ª®©
+% ®¯¥à æ¨®­­®© á¨á⥬¥, ᮧ¤ ¥âáï ä ©«.
+general_i_targetos=01002_I_‘®§¤ ¥âáï ¤«ï OS: $1
+% Š®£¤  \var{-vd} ª«îç ¨á¯®«ì§ã¥âáï, íâ  áâப , á®®¡é ¥â ¢ ¬, ¤«ï ª ª®©
+% ®¯¥à æ¨®­­®© á¨á⥬ë ᮧ¤ ¥âáï ä ©«
+general_t_exepath=01003_T_ˆá¯®«ì§y¥¬ ¯yâì ¤«ï ¡¨­ p­ëå ä ©«®¢: $1
+% Š®£¤  \var{-vt} ª«îç ¨á¯®«ì§ã¥âáï, íâ  áâப , á®®¡é ¥â ¢ ¬,
+% £¤¥ ª®¬¯¨«ïâ®à  ¨é¥â ¡¨­ p­ë¥ ä ©«ë.
+general_t_unitpath=01004_T_ˆá¯®«ì§y¥¬ ¯ãâì ¤® ¬®¤ã«¥©: $1
+% Š®£¤  \var{-vt} ª«îç ¨á¯®«ì§ã¥âáï, íâ  áâப , á®®¡é ¥â ¢ ¬,
+% £¤¥ ª®¬¯¨«ïâ®à ¨é¥â ª®¬¯¨«¨àã¥¬ë¥ ¬®¤ã«¨. ‚ë ¬®¦¥â¥ ãáâ ­ ¢«¨¢ âì íâ®â ¯ãâì
+% ç¥p¥§ \var{-Fu} ¨«¨ \var{-Up} ®¯æ¨¨.
+general_t_includepath=01005_T_ˆá¯®«ì§y¥¬ ¯yâì ¤«ï ¢ª«îç ¥¬ëå ä ©«®¢: $1
+% Š®£¤  \var{-vt} ª«îç ¨á¯®«ì§ã¥âáï, íâ  áâப , á®®¡é ¥â ¢ ¬, £¤¥
+% ª®¬¯¨«ïâ®à ¨é¥â ä ©«ë ¤«ï ¢ª«î祭¨ï (ä ©«ë, ¨á¯®«ì§ã¥¬ë¥ ¢ \var{\{\$I xxx\}}
+% ¢ëp ¦¥­¨ïå). ‚ë ¬®¦¥â¥ ãáâ ­ ¢«¨¢ âì íâ®â ¯ãâì ç¥p¥§ \var{-I} ®¯æ¨î.
+general_t_librarypath=01006_T_ˆá¯®«ì§y¥¬ ¯yâì ¤® ¡¨¡«¨®â¥ª: $1
+% Š®£¤  \var{-vt} ª«îç ¨á¯®«ì§ã¥âáï, íâ  áâப , á®®¡é ¥â ¢ ¬, £¤¥
+% ª®¬¯¨«ïâ®à ¨é¥â ¡¨¡«¨®â¥ª¨. ‚ë ¬®¦¥â¥ ãáâ ­ ¢«¨¢ âì íâ®â ¯ãâì ç¥p¥§
+% \var{-Fl} ®¯æ¨î.
+general_t_objectpath=01007_T_ˆá¯®«ì§y¥¬ ¯yâì ¤® ®¡ê¥ªâ­ëå ä ©«®¢: $1
+% Š®£¤  \var{-vt} ª«îç ¨á¯®«ì§ã¥âáï, íâ  áâப , á®®¡é ¥â ¢ ¬, £¤¥
+% ª®¬¯¨«ïâ®à ¨é¥â ®¡ê¥ªâ­ë¥ ä ©«ë, ‚ë á¢ï§ë¢ ¥â¥ ¢ (ä ©«ë,
+% ¨á¯®«ì§ãîâáï ¢ \var{\{\$L xxx \}} ¢ëp ¦¥­¨ïå).
+% ‚ë ¬®¦¥â¥ ãáâ ­ ¢«¨¢ âì íâ®â ¯ãâì ç¥p¥§ \var{-Fo} ®¯æ¨î.
+general_i_abslines_compiled=01008_I_$1 «¨­¨© ᪮¬¯¨«¨p®¢ ­­®, $2 ᥪ.
+% Š®£¤  \var{-vi} ª«îç ¨á¯®«ì§ã¥âáï, ª®¬¯¨«ïâ®à, á®®¡é ¥â ç¨á«®
+% ᪮¬¯¨«¨p®¢ ­­ëå áâப, ¨ ¢à¥¬¥­¨, ª®â®à®¥ ¯®âp¥¡®¢ «®áì ¤«ï í⮣®.
+% (ॠ«ì­®¥ ¢à¥¬ï, ­¥ ¯à®£à ¬¬¨py¥¬®¥ ¢à¥¬ï).
+general_f_no_memory_left=01009_F_H¥â ᢮¡®¤­®© ¯ ¬ïâ¨
+% Š®¬¯¨«ïâ®à ­¥ ¨¬¥¥â ¤®áâ â®ç­® ¯ ¬ïâ¨, çâ®¡ë ª®¬¯¨«¨à®¢ âì ¢ è㠯ணࠬ¬ã.
+% ˆ¬¥¥âáï ­¥áª®«ìª® p¥ª®¬¥­¤ æ¨© ¤«ï p¥è¥­¨ï í⮣® ¢®¯p®á :
+% \begin{itemsize}
+% \item …᫨ ¢ë ¨á¯®«ì§ã¥â¥ ä®à¬¨àãîéãîáï ®¯æ¨î ª®¬¯¨«ïâ®à , ¯à®¡ã©â¥
+% ª®¬¯¨«¨à®¢ âì à §«¨ç­ë¥ ¬®¤ã«¨ ¢àãç­ãî.
+% \item …᫨ ¢ë ª®¬¯¨«¨àã¥â¥, ®£à®¬­yî ¯à®£à ¬¬y, à §¡¨¢ ©â¥ ¥¥ ­  ¬®¤ã«¨, ¨
+% ª®¬¯¨«¨àã©â¥ ¨å ®â¤¥«ì­®.
+% \item …᫨ ¯à¥¤ë¤ã騥 ¤¢  ¯y­ªâ  ­¥ à ¡®â îâ, ¯¥à¥â࠭᫨ày©â¥ ª®¬¯¨«ïâ®à
+% á ¡®«ì訬 p §¬¥p®¬ ªyç¨ (¢ë ¬®¦¥â¥ ¨á¯®«ì§®¢ âì \var{-Ch} ®¯æ¨î ¤«ï í⮣®, \seeo{Ch})
+% \end {itemsize}
+% \end {®¯¨á ­¨¥}
+general_i_writingresourcefile=01010_I_‡ ¯¨á뢠¥¬ ä ©«-â ¡«¨æy áâp®ª®¢ëå p¥áypᮢ: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Žè¨¡ª  ¯p¨ § ¯¨á¨ ä ©« -â ¡«¨æë áâp®ª®¢ëå p¥áypᮢ: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Warning:
+% Prefix for Warnings
+general_i_note=01015_I_Note:
+% Prefix for Notes
+general_i_hint=01016_I_Hint:
+% Prefix for Hints
+
+% \end{description}
+
+
+#
+# ‘ª ­¥à
+#
+% \section {‘®®¡é¥­¨ï ᪠­¥à .}
+% â®â à §¤¥« ¯¥à¥ç¨á«ï¥â á®®¡é¥­¨ï, ª®â®pë¥ ¢ë¤ ¥â ᪠­¥à. ‘ª ­¥à ¡¥à¥â § ¡®âã
+% ® «¥ªá¨ç¥áª®© áâàãªâãॠ䠩«  Free Pascal, â® ¥áâì ®­ ¯p®¡y¥â ­ å®¤¨âì
+% § à¥§¥à¢¨à®¢ ­­ë¥ á«®¢ , áâப¨, ¨ â.¤. Ž­ â ª¦¥ § ¡®â¨âáï ® ¤¨à¥ªâ¨¢ å ¨
+% ãá«®¢­ëå ¢ëà ¦¥­¨ïå ¢«¨ïî騥 ­  ®¡p ¡®âªy ¯p®£p ¬¬ë ª®¬¯¨«ïâ®p®¬.
+% \begin {®¯¨á ­¨¥}
+scan_f_end_of_file=02000_F_H¥®¦¨¤ ­­ë© ª®­¥æ ä ©« 
+% â® ®¡ëç­® á«ãç ¥âáï ¢ á«¥¤ãîé¨å á«ãç ïå:
+% \begin{itemsize}
+% \item ˆá室­ë© ä ©« § ª ­ç¨¢ ¥âáï ¤® ¯®á«¥¤­¥£® \var{end} ¢ëp ¦¥­¨ï.
+% â® á«ãç ¥âáï ®¡ëç­®, ª®£¤  \var{begin} ¨ \var{end} ¢ëp ¦¥­¨ï ­¥
+% á¡ « ­á¨à®¢ ­­ë© (­¥ ®¤¨­ ª®¢®¥ ª®«¨ç¥á⢮);
+% \item ‚ª«îç ¥¬ë© ä ©« § ª ­ç¨¢ ¥âáï ¢ á¥à¥¤¨­¥ ¢ëp ¦¥­¨ï.
+% \item Š®¬¬¥­â à¨© ­¥ ¡ë« § ªàëâ (䨣yp­®© ᪮¡ª®© ¨«¨ ¥é¥ ª ª)
+% \end{itemsize}
+scan_f_string_exceeds_line=02001_F_H¥¢®§¬®¦­® ­ ©â¨ ª®­¥æ áâp®ª¨
+% ‚ë, ¢®§¬®¦­®, § ¡ë«¨ ¢ª«îç¨âì § ªàë⨥ ' áâp®ª¨, â ª çâ® áâp®ª  § ­¨¬ ¥â
+% ­¥áª®«ìª® «¨­¨© ª®¤  (áâp®ª).
+scan_f_illegal_char=02002_F_‡ ¯p¥é¥­­ë© ᨬ¢®« "$1" ($2)
+% ‘ª ­¥p á⮫ª­y«áï á § ¯à¥é¥­­ë¬ ᨬ¢®«®¬ ¢® ¢å®¤­®¬ ä ©«¥.
+scan_f_syn_expected=02003_F_‘¨­â ªá¨ç¥áª ï ®è¨¡ª : ®¦¨¤ ¥âáï "$1", ­® ­ è«¨ "$2"
+% ⮠㪠§ë¢ ¥â, çâ® ª®¬¯¨«ïâ®à ®¦¨¤ « ¤py£yî «¥ªá¥¬ã (¨«¨ ¬ àª¥à) 祬
+% â®â, ª®â®àë© ¢ë ­ ¯¥ç â «¨. â® ¬®¦¥â ¯à®¨á室¨âì ¯®ç⨠¢áî¤ã, £¤¥
+% ‚ë ¯¨è¨â¥ ­¥ ¯® § ª®­ ¬ ï§ëª   áª «ì.
+scan_t_start_include_file=02004_T_H ç¨­ î ç⥭¨¥ ¢ª«îç ¥¬®£® ä ©«  $1
+% Š®£¤  ‚ë ®¡¥á¯¥ç¨¢ ¥â¥ \var{-vt} ª«îç, ª®¬¯¨«ïâ®à, á®®¡é ¥â ‚ ¬
+% ª®£¤  ®­ ­ ç¨­ ¥â ç¨â âì ¢ª«îç ¥¬ë© ä ©«.
+scan_w_comment_level=02005_W_H ©¤¥­ $1 yp®¢¥­ì ª®¬¬¥­â p¨ï
+% Š®£¤  \var{-vw} ª«îç ¨á¯®«ì§ã¥âáï, â® ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â ‚ á,
+% ¥á«¨ ®­ ­ å®¤¨â ¢«®¦¥­­ë¥ ª®¬¬¥­â à¨¨. ‚«®¦¥­­ë¥ ª®¬¬¥­â à¨¨ ­¥ ¯®§¢®«ïîâáï ¢
+% Turbo Pascal ¨ íâ® ¬®¦¥â ¡ëâì ¨áâ®ç­¨ª®¬ ®è¨¡®ª.
+scan_n_far_directive_ignored=02006_N_$F ¤¨à¥ªâ¨¢  (FAR) ¨£­®à¨àã¥âáï
+% \var{FAR} ¤¨à¥ªâ¨¢  íâ® 16-à §à來 ï ª®­áâàãªæ¨ï, ª®â®à ï ï¥âáï
+% ¯®¤¤¥p¦¨¢ ¥¬®©, ­® ¨£­®à¨à㥬 ï ª®¬¯¨«ïâ®à®¬, â ª ª ª ®­ ¯à®¨§¢®¤¨â
+% 32 à §à來ëå ª®¤.
+scan_n_stack_check_global_under_linux=02007_N_Linux ¯p®¢¥pï¥â á⥪  ¢â®¬ â¨ç¥áª¨
+% ஢¥àª  á⥪  á \var{-Cs} ª«îç ¨£­®à¨àã¥âáï ¯®¤ \linux, â ª ª ª
+% \linux ¤¥« ¥â íâ® §  ‚ á. Žâ®¡p ¦ ¥âáï ⮫쪮, ª®£¤  \var{-vn} ¨á¯®«ì§ã¥âáï.
+scan_n_ignored_switch=02008_N_ˆ£­®p¨py¥¬ë© ª®¬¯¨«ïâ®à®¬ ª«îç $1
+% ‘ ¢ª«î祭­ë¬ \var{-vn}, ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â, ¥á«¨ ®­ ¨£­®à¨àã¥â ª«îç
+scan_w_illegal_switch=02009_W_H¥¨§¢¥áâ­ë© ª«îç ª®¬¯¨«ïâ®p  $1
+% ‚ë ¢ª«î稫¨ ª«îç ª®¬¯¨«ïâ®à  (â® ¥áâì \var{\{\$... \}}) ª®â®àë©
+% ª®¬¯¨«ïâ®à ­¥ §­ ¥â.
+scan_w_switch_is_global=02010_W_â®â ª«îç ª®¬¯¨«ïâ®à  ¨¬¥¥â £«®¡ «ì­ë© áâ âyá
+% Š®£¤  \var{-vw} ¨á¯®«ì§ã¥âáï, ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â, ¥á«¨ ª«îç £«®¡ «¥­.
+scan_e_illegal_char_const=02011_E_H¥¨§¢¥áâ­ë© ᨬ¢®« ¢ ª®­áâ ­â¥
+% â® á«ãç ¥âáï, ª®£¤  ‚ë ®¯à¥¤¥«ï¥â¥ ᨬ¢®« á ª®¤®¬ ASCII, ¯®áª®«ìªã ¢
+% \var{\#96}, ­® ­®¬¥à ï¥âáï ¨«¨ § ¯à¥é¥­­ë¬, ¨«¨ ¢­¥ ¤¨ ¯ §®­ .
+% „¨ ¯ §®­ - 1-255.
+scan_f_cannot_open_input=02012_F_H¥ ¬®£y ®âªpëâì ä ©« $1
+% \fpc ­¥ ¬®¦¥â ­ ©â¨ ¯à®£à ¬¬ã ¨«¨ ¨á室­ë© ä ©« ¬®¤ã«ï, ª®â®àë© ‚ë
+% ®¯à¥¤¥«¨«¨ ¢ ª®¬ ­¤­®© áâப¥.
+scan_f_cannot_open_includefile=02013_F_H¥ ¬®£y ®âªpëâì ¢ª«îç ¥¬ë© ä ©« $1
+% \fpc ­¥ ¬®¦¥â ­ ©â¨ ¨á室­ë© ä ©«, ª®â®pë© ¢ë ®¯à¥¤¥«¨«¨ ¢ \var{\{\$include \}}
+% ¢ëp ¦¥­¨¨.
+scan_e_too_much_endifs=02014_E_‘«¨èª®¬ ¬­®£® $ENDIF ¨«¨ $ELSE ¤¨p¥ªâ¨¢
+% ‚ è \var{\{\$IFDEF.. \}} ¨ {\{\$ENDIF} \}} ¢ëp ¦¥­¨ï ­¥ ¨¬¥îâ ®¤¨­ ª®¢®¥ ª®«-¢®.
+scan_w_only_pack_records=02015_W_Record ¯®«ï ¬®£yâ ¢ëà ¢­¨¢ âìáï ⮫쪮 ª 1,2,4 ¨«¨ 16 ¡ ©â ¬
+% ‚ë ®¯à¥¤¥«ï¥â¥ \var{\{\$PACKRECORDS n\} } á § ¯à¥é¥­­ë¬ §­ ç¥­¨¥¬ ¤«ï
+% \var{n}. ’®«ìª® 1,2,4 ¨«¨ 16 ¤®¯ãá⨬® ¢ í⮬ á«ãç ¥.
+scan_w_only_pack_enum=02016_W_¥p¥ç¨á«¥­¨ï ¬®£yâ ¡ëâì á®åà ­¥­ë ⮫쪮 ¢ 1,2 ¨«¨ 4 ¡ ©â å
+% ‚ë ®¯à¥¤¥«ï¥â¥ \var{\{\$PACKENUM n \}} á § ¯à¥é¥­­ë¬ §­ ç¥­¨¥¬ ¤«ï
+% \var {n}. ’®«ìª® 1,2 ¨«¨ 4 ¤®¯ãá⨬® ¢ í⮬ á«ãç ¥.
+scan_e_endif_expected=02017_E_$1 ®¦¨¤ ¥âáï ¤«ï $2 ®¯à¥¤¥«¥­¨ï ¢ áâப¥ $3
+% ‚ è¨ ãá«®¢­ë¥ ã⢥ত¥­¨ï âà ­á«ï樨 ­¥á¡ « ­á¨à®¢ ­­ë.
+scan_e_preproc_syntax_error=02018_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ¯à¨  ­ «¨§¥ ¢ëà ¦¥­¨ï ¤«ï ª®¬¯¨«ïâ®p 
+% ‚ ãá«®¢­®¬ ¢ëà ¦¥­¨¨ ¨¬¥¥âáï ®è¨¡ª  ¯®á«¥ \var{\{\$if \}} ¤¨à¥ªâ¨¢ë ª®¬¯¨«ïâ®à .
+scan_e_error_in_preproc_expr=02019_E_Žè¨¡ª  ¢ p áç¥â¥ ¢ëà ¦¥­¨ï ¯p¥¯p®æ¥áá®p  ¤«ï ª®¬¯¨«¨à®¢ ­¨ï
+% ‚ ãá«®¢­®¬ ¢ëà ¦¥­¨¨ ¨¬¥¥âáï ®è¨¡ª  ¯®á«¥ \var{\{\$if \}} ¤¨à¥ªâ¨¢ë ª®¬¯¨«ïâ®à .
+scan_w_macro_cut_after_255_chars=02020_W_„«ï p áç¥â  ¢ëp ¦¥­¨ï, ¤«¨­  ¬ ªp®á  ᮪p é¥­  ¤® 255 ᨬ¢®«®¢
+% ‚ëà ¦¥­¨ï ᮤ¥à¦ é¨¥ ¬ ªà®ª®¬ ­¤ë ­¥ ¬®¦¥â ¡ëâì ¡®«ìè¥ ç¥¬ 255 ᨬ¢®«®¢.
+% ⮠ï¥âáï ç áâìî ¡¥§®¯ á­®á⨠¢ ª®¬¯¨«ïâ®à¥, íâ® ¯à¥¤®â¢à é ¥â ¡ãä¥à­ë¥
+% ¯¥à¥¯®«­¥­¨¥. â® ¯®ª §ë¢ ¥âáï ª ª ¯à¥¤ã¯à¥¦¤¥­¨¥, â® ¥áâì
+% ª®£¤  ª«îç \var{-vw} ¨á¯®«ì§y¥âáï.
+scan_e_endif_without_if=02021_E_ENDIF ¡¥§ IF{N}DEF
+% ‚ è \var{\{\$IFDEF.. \}} ¨ {\ {\$ENDIF \}} ã⢥ত¥­¨ï ­¥ á¡ « ­á¨à®¢ ­ë.
+scan_f_user_defined=02022_F_®«ì§®¢ â¥«ì ®¯à¥¤¥«¨« $1
+% p®¨§®è«  ®¯à¥¤¥«ï¥¬ ï ¯®«ì§®¢ â¥«¥¬ ä â «ì­ ï ®è¨¡ª . ‘¬. â ª¦¥ \progref
+scan_e_user_defined=02023_E_®«ì§®¢ â¥«ì ®¯p¥¤¥«¨« $1
+% p®¨§®è«  ®¯à¥¤¥«ï¥¬ ï ¯®«ì§®¢ â¥«¥¬ ®è¨¡ª . ‘¬. â ª¦¥ \progref
+scan_w_user_defined=02024_W_®«ì§®¢ â¥«ì ®¯p¥¤¥«¨« $1
+% p®¨§®è«® ®¯à¥¤¥«ï¥¬®¥ ¯®«ì§®¢ â¥«¥¬ ¯à¥¤ã¯à¥¦¤¥­¨¥. ‘¬. â ª¦¥ \progref
+scan_n_user_defined=02025_N_®«ì§®¢ â¥«ì ®¯p¥¤¥«¨« $1
+% ‘⮫ª­y«¨áì á ®¯à¥¤¥«ï¥¬ë¬ ¯®«ì§®¢ â¥«¥¬ ¯à¨¬¥ç ­¨¥¬. ‘¬. â ª¦¥ \progref
+scan_h_user_defined=02026_H_®«ì§®¢ â¥«ì ®¯p¥¤¥«¨« $1
+% ‘⮫ª­y«¨áì á ®¯à¥¤¥«ï¥¬®© ¯®«ì§®¢ â¥«¥¬ ¯®¤áª §ª®©. ‘¬. â ª¦¥ \progref
+scan_i_user_defined=02027_I_®«ì§®¢ â¥«ì ®¯p¥¤¥«¨« $1
+% ‘⮫ª­y«¨áì á ®¯à¥¤¥«ï¥¬®© ¯®«ì§®¢ â¥«¥¬ ¯®¤áª §ª®©. ‘¬. â ª¦¥ \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Š«î祢®¥ á«®¢® ¯¥à¥®¯à¥¤¥«¥­®, ¯®áª®«ìªã ¬ ªà®ª®¬ ­¤  ­¥ ¨¬¥¥â ­¨ª ª®£® íä䥪â 
+% ‚ë ­¥ ¬®¦¥â¥ ¯¥à¥®¯à¥¤¥«ïâì ª«îç¥¢ë¥ á«®¢  á ¬ ªà®ª®¬ ­¤ ¬¨.
+scan_f_macro_buffer_overflow=02029_F_yä¥p ¬ ªp®á®¢ ¯¥à¥¯®«­¥­ ¯à¨ ç⥭¨¨ ¨«¨ à áè¨à¥­¨¨ ¬ ªà®ª®¬ ­¤ë
+% ‚ è ¬ ªp®á ¨«¨ १ã«ìâ â, ᫨誮¬ ¤«¨­¥­ ¤«ï ª®¬¯¨«ïâ®à .
+scan_w_macro_deep_ten=02030_W_ áè¨p¥­¨¥ ¬ ªà®ª®¬ ­¤ë ¯à¥¢ë蠥⠢®§¬®¦­ë© yp®¢¥­ì (¡®«¥¥ 16).
+% ਠà áè¨à¥­¨¨ ¬ ªà®ª®¬ ­¤ë ¡ë«® ¨á¯®«ì§®¢ ­® ¡®«¥¥ 16 yp®¢­¥© ¢«®¦¥­­®áâ¨.
+% Š®¬¯¨«ïâ®à ­¥ ¬®¦¥â p áè¨p¨âì ¬ ªp®á, â ª ª ª íâ® ¬®¦¥â ¡ëâì §­ ª, çâ®
+% ¨á¯®«ì§y¥âáï ४ãàá¨ï
+scan_e_wrong_styled_switch=02031_E_¥p¥ª«îç â¥«¨ ª®¬¯¨«ïâ®p  ­¥ ¯®§¢®«ïî⠨ᯮ«ì§®¢ âì (* ¨ *) áâ¨«ì ª®¬¬¥­â p¨¥¢.
+% ¥à¥ª«îç â¥«¨ ª®¬¯¨«ïâ®à  ¤®«¦­ë ¢á¥£¤  ¡ëâì ¬¥¦¤ã \var{\{\ }} à §¤¥«¨â¥«ï¬¨ ª®¬¬¥­â à¨ï.
+scan_d_handling_switch=02032_D_p®¢¥p塞 ª«îç "$1"
+% Š®£¤  ‚ë ¢ª«î砥⥠¨­ä®à¬ æ¨î ¤«ï ®â« ¤ª¨ (\var{-vd}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ¢ ¬, ª®£¤  ®­ ®æ¥­¨¢ ¥â ãá«®¢­®¥ ¢ëà ¦¥­¨¥, ¢«¨ïî饥 ­  ª®¬¯¨«ïæ¨î.
+scan_c_endif_found=02033_C_ENDIF $1 ­ ©¤¥­
+% Š®£¤  ‚ë ¢ª«î砥⥠ãá«®¢­ë¥ á®®¡é¥­¨ï (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â ¢ ¬
+% £¤¥ ®­ áâ «ª¨¢ ¥âáï á ãá«®¢­ë¬¨ ã⢥ত¥­¨ï¬¨.
+scan_c_ifdef_found=02034_C_IFDEF $1 ­ ©¤¥­, $2
+% Š®£¤  ‚ë ¢ª«î砥⥠ãá«®¢­ë¥ á®®¡é¥­¨ï (\var{-vc}), ª®¬¯¨«ïâ®à, á®®¡é ¥â ¢ ¬
+% £¤¥ ®­ áâ «ª¨¢ ¥âáï á ãá«®¢­ë¬¨ ã⢥ত¥­¨ï¬¨.
+scan_c_ifopt_found=02035_C_IFOPT $1 ­ ©¤¥­, $2
+% Š®£¤  ¢ë ¢ª«î砥⥠ãá«®¢­ë¥ á®®¡é¥­¨ï (\var{-vc}), ª®¬¯¨«ïâ®à, á®®¡é ¥â ¢ ¬
+% £¤¥ ®­ áâ «ª¨¢ ¥âáï á ãá«®¢­ë¬¨ ã⢥ত¥­¨ï¬¨.
+scan_c_if_found=02036_C_IF $1 ­ ©¤¥­, $2
+% Š®£¤  ¢ë ¢ª«î砥⥠ãá«®¢­ë¥ á®®¡é¥­¨ï (\var{-vc}), ª®¬¯¨«ïâ®à, á®®¡é ¥â ¢ ¬
+% £¤¥ ®­ áâ «ª¨¢ ¥âáï á ãá«®¢­ë¬¨ ã⢥ত¥­¨ï¬¨.
+scan_c_ifndef_found=02037_C_IFNDEF $1 ­ ©¤¥­, $2
+% Š®£¤  ¢ë ¢ª«î砥⥠ãá«®¢­ë¥ á®®¡é¥­¨ï (\var {-vc}), ª®¬¯¨«ïâ®à, á®®¡é ¥â ¢ ¬
+% £¤¥ ®­ áâ «ª¨¢ ¥âáï á ãá«®¢­ë¬¨ ã⢥ত¥­¨ï¬¨.
+scan_c_else_found=02038_C_ELSE $1 ­ ©¤¥­, $2
+% Š®£¤  ¢ë ¢ª«î砥⥠ãá«®¢­ë¥ á®®¡é¥­¨ï (\var{-vc}), ª®¬¯¨«ïâ®à, á®®¡é ¥â ¢ ¬
+% £¤¥ ®­ áâ «ª¨¢ ¥âáï á ãá«®¢­ë¬¨ ã⢥ত¥­¨ï¬¨.
+scan_c_skipping_until=02039_C_p®¯y᪠¥¬ ¤® ...
+% Š®£¤  ¢ë ¢ª«î砥⥠ãá«®¢­ë¥ á®®¡é¥­¨ï (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â ¢ ¬
+% £¤¥ ®­ áâ «ª¨¢ ¥âáï á ãá«®¢­ë¬¨ ã⢥ত¥­¨ï¬¨, ¨ ¯à®¯ã᪠¥â «¨ íâ® ¨«¨ ­¥â.
+scan_i_press_enter=02040_I_H ¦¬¨â¥ <ENTER>, çâ®¡ë ¯à®¤®«¦¨âì
+% Š®£¤  ¨á¯®«ì§y¥âáï \var{-vi} ª«îç, ª®¬¯¨«ïâ®à ®áâ ­ ¢«¨¢ ¥â
+% âà ­á«ï樨 ¨ ¦¤¥â \var{enter} ª« ¢¨èy, ª®â®à ï ¡ã¤¥â ­ ¦ â , ª®£¤  ®­
+% á⮫ª­¥âáï á ¤¨p¥ªâ¨¢®© \var {\{\$STOP\}}.
+scan_w_unsupported_switch=02041_W_H¥¯®¤¤¥p¦¨¢ ¥¬ë© ª«îç $1
+% Š®£¤  ¯p¥¤y¯p¥¦¤¥­¨ï ¢ª«î祭ë (\var{-vw}), ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â ¢ á
+% ®â­®á¨â¥«ì­® ­¥¯®¤¤¥à¦¨¢ ¥¬ëå ª«î祩. â® ®§­ ç ¥â çâ®, ª«îç ¨á¯®«ì§ã¥âáï
+% ¢ Delphi ¨«¨ Turbo Pascal, ­® ­¥ ¢ \fpc
+scan_w_illegal_directive=02042_W_H¥¯p ¢¨«ì­ ï ¤¨à¥ªâ¨¢  ª®¬¯¨«ïâ®à  $1
+% Š®£¤  ¯p¥¤y¯p¥¦¤¥­¨ï ¢ª«î祭ë (\var{-vw}), ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â ¢ á
+% ®â­®á¨â¥«ì­® ­¥¯à¨§­ ­­ëå ¤¨p¥ªâ¨¢. „«ï ᯨ᪠ à á¯®§­ ­­ëå ¤¨p¥ªâ¨¢, á¬. \progref
+scan_t_back_in=02043_T_‚®§p é ¥¬áï ¢ $1
+% Š®£¤  ¢ë ¨á¯®«ì§ã¥â¥ (\var{-vt}) ª®¬¯¨«ïâ®à, á®®¡é ¥â ¢ ¬, ª®£¤  ®­
+% § ª®­ç¨« ç¨â âì ¢ª«îç ¥¬ë© ä ©«.
+scan_w_unsupported_app_type=02044_W_H¥¯®¤¤¥p¦¨¢ ¥¬ë© ⨯ ¯p¨«®¦¥­¨ï: $1
+% ‚ë ¯®«ã砥⥠íâ® ¯à¥¤ã¯à¥¦¤¥­¨¥, ª®£¤  ®¯à¥¤¥«ï¥â¥ ­¥¨§¢¥áâ­ë© ⨯
+% ¯à¨«®¦¥­¨ï á ¤¨à¥ªâ¨¢®© $APPTYPE
+scan_w_app_type_not_support=02045_W_$APPTYPE ­¥ ¯®¤¤¥à¦¨¢ ¥âáï á¨á⥬®© ¤«ï ª®â®p®© ¢ë ª®¬¯¨«¨py¥â¥ ä ©«
+% $APPTYPE ¤¨à¥ªâ¨¢  ®¡¥á¯¥ç¨¢ ¥âáï ⮫쪮 win32 ¯à¨«®¦¥­¨ï¬¨.
+scan_w_description_not_support=02046_W_’¥£ DESCRIPTION ­¥ ¯®¤¤¥à¦¨¢ ¥âáï á¨á⥬®© ¤«ï ª®â®p®© ¢ë ª®¬¯¨«¨py¥â¥ ä ©«
+% ’¥£ \var{\{\$DESCRIPTION\}} ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ­  á¨á⥬ å OS/2 ¨ Win32.
+scan_n_version_not_support=02047_N_’¥£ VERSION ­¥ ¯®¤¤¥à¦¨¢ ¥âáï á¨á⥬®© ¤«ï ª®â®p®© ¢ë ª®¬¯¨«¨py¥â¥ ä ©«
+% ’¥£ \var{\{\$VERSION\}} ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¢ Win32 á¨á⥬ å.
+scan_n_only_exe_version=02048_N_’¥£ VERSION ¨á¯®«ì§ã¥âáï ⮫쪮 ¤«ï .EXE ¨ .DLL ¨á室­¨ª®¢.
+% ’¥£ \var{\{\$VERSION\}} ¨á¯®«ì§ã¥âáï ⮫쪮 ¤«ï .EXE ¨ .DLL ¨á室­¨ª®¢.
+scan_w_wrong_version_ignored=02049_W_¥¢¥à­ë© ä®à¬ â ¤«ï ⥣  VERSION ¤«ï ¤¨à¥ªâ¨¢ë $1
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_w_unsupported_asmmode_specifier=02050_W_H¥¯®¤¤¥p¦¨¢ ¥¬ë© áâ¨«ì  áᥬ¡«¥p  ¢ $1
+% Š®£¤  ‚ë ®¯à¥¤¥«ï¥â¥ ०¨¬  áᥬ¡«¥à  á \var{\{\$ASMMODE xxx\}}
+% ª®¬¯¨«ïâ®à ­¥ à á¯®§­ ¢ « ०¨¬, ª®â®àë© ‚ë â ¬ yª § «¨.
+% \end {®¯¨á ­¨¥}
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Š«îç  áᥬ¡«¥p : ­¥¢®§¬®¦­ ï ¢­yâp¥­­ïï ¨­áâpyªæ¨ï  áᥬ¡«¥p , $1 ¡y¤¥â íä䥪⨢­  ⮫쪮 ¢ á«¥¤yî騩 p §
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_H¥¢¥p­ë© p¥¦¨¬ ¯¥à¥ª«îç â¥«ï, ¨á¯®«ì§ã©â¥ ON/OFF ¨«¨ +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_” ©«ë p¥áypᮢ ­¥ ¯®¤¤¥à¦¨¢ ¥âáï á¨á⥬®© ¤«ï ª®â®p®© ¢ë ª®¬¯¨«¨py¥â¥ ä ©«
+% The target you are compiling for doesn't support Resource files. The
+% only target which can use resource files is Win32
+scan_w_include_env_not_found=02054_W_‚ª«îç ¥¬ ï ¯¥p¥¬¥­­ ï ®ªpy¦¥­¨ï $1 ­¥ ­ ©¤¥­  ¢ ®ªpy¦¥­¨¨ á¨á⥬ë
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_¥¢¥à­®¥ §­ ç¥­¨¥ ¤«ï £à ­¨æë ॣ¨áâà  á®¯à®æ¥áá®à 
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_„«ï í⮩ á¨áâ¥¬ë ¯®¤¤¥à¦¨¢ îâáï ⮫쪮 ®¤¨­ ä ©« à¥áãàᮢ
+% The target you are compiling for supports only one resource file. This is the
+% case of OS/2 (EMX) currently. The first resource file found is used, the
+% others are discarded.
+scan_w_macro_support_turned_off=02057_W_®¤¤¥p¦ª  ¬ ªp®á®¢ ¡ë«  ®âª«î祭 
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_“ª § ­ ­¥¢¥à­ë© ⨯ interface. à ¢¨«ì­ë¥ ⮫쪮 COM, COBRA ¨«¨ DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¤«ï PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¤«ï PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Š®­áâ ­â  áâப ­¥ ¬®¦¥â ¡ëâì ¡®«¥¥ 祬 255 ᨬ¢®«®¢
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+% \end{description}
+
+#
+# ‘¨­â ªá¨ç¥áª¨©  ­ «¨§ â®à
+#
+% \section {á®®¡é¥­¨ï ᨭ⠪á¨ç¥áª®£®  ­ «¨§ â®à }
+% â®â à §¤¥« ¯¥à¥ç¨á«ï¥â ¢á¥ á®®¡é¥­¨ï ᨭ⠪á¨ç¥áª®£®  ­ «¨§ â®à .
+% ‘¨­â ªá¨ç¥áª¨©  ­ «¨§ â®à § ¡®â¨âáï ® ᥬ ­â¨ª¥ ï§ëª , â® ¥áâì ®­
+% ®¯à¥¤¥«ï¥â, ¯à ¢¨«¥­ «¨ ¢ è  áª «ì.
+% \begin {®¯¨á ­¨¥}
+parser_e_syntax_error=03000_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ( ­ «¨§ â®à)
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_w_proc_far_ignored=03001_W_p®æ¥¤yp  ¨¬¥¥â ⨯ FAR - ¨£­®p¨py¥¬
+% This is a warning. \var{FAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+parser_w_proc_near_ignored=03002_W_p®æ¥¤yp  ¨¬¥¥â ⨯ NEAR - ¨£­®p¨py¥¬
+% This is a warning. \var{NEAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+parser_w_proc_interrupt_ignored=03003_W_à®æ¥¤ãà­ë© ⨯ INTERRUPT ¨£­®à¨àã¥âáï ¤«ï ­¥ i386 ¯à®æ¥áá®à®¢
+% This is a warning. \var{INTERRUPT} is a i386 specific construct
+% and is ignored for other processors.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT ¯à®æ¥¤ãà  ­¥ ¬®¦¥â ¡ëâì ¢«®¦¥­­®©
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_à®æ¥¤ãà­ë© ⨯ $1 ¨£­®à¨àã¥âáï
+% This is a warning. \var{REGISTER},\var{REINTRODUCE} is ignored by FPC programs for now.
+% This is introduced first for Delphi compatibility.
+parser_e_no_overload_for_all_procs=03006_E_¥ ¢á¥ ®¯à¥¤¥«¥­¨ï $1 ®¯à¥¤¥«¥­ë ª ª OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_no_dll_file_specified=03007_E_DLL-ä ©« ­¥ yª § ­
+% No longer in use.
+parser_e_export_name_double=03008_E_ˆ¬ï äy­ªæ¨¨ íªá¯®pâ¨py¥âáï ¤¢ ¦¤ë $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_ˆ­¤¥ªá äy­ªæ¨¨ íªá¯®pâ¨py¥âáï ¤¢ ¦¤ë $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_H¥¢¥p­ë© ¨­¤¥ªá y íªá¯®pâ¨py¥¬®© äy­ªæ¨¨
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_¥à¥¬¥é ¥¬ë© DLL/EXE ä ©« $1 ®â« ¤®ç­ãî ¨­ä®à¬ æ¨î ­¥ ᮤ¥à¦¨â, ®âª«î祭®.
+parser_w_parser_win32_debug_needs_WN=03012_W_„«ï ¯®¤¤¥à¦ª¨ ®â« ¤ª¨ Win32-ª®¤ , ¢ ¬ ­¥®¡å®¤¨¬® ®âª«îç âì ¯¥à¥¬¥é¥­¨¥ á ®¯æ¨¥© -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Š®­áâpyªâ®p ¤®«¦¥­ ¨¬¥âì ¨¬ï INIT
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_„¥áâpyªâ®p ¤®«¦¥­ ¨¬¥âì ¨¬ï DONE
+% You are declaring a constructor with a name which isn't \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_illegal_open_parameter=03015_E_H¥¯p ¢¨«ì­® ®ä®p¬«¥­­ë¥ '®âªpëâë¥ ¯ p ¬¥âpë'
+% You are trying to use the wrong type for an open parameter.
+parser_e_proc_inline_not_supported=03016_E_p®æ¥¤yp­ë© ⨯ INLINE ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_priv_meth_not_virtual=03017_W_Private ¬¥â®¤ë ­¥ ¬®£yâ ¡ëâì ¢¨pây «ì­ë¬¨
+% You declared a method in the private part of a object (class) as
+% \var{virtual}. This is not allowed. Private methods cannot be overridden
+% anyway.
+parser_w_constructor_should_be_public=03018_W_Š®­áâpyªâ®p ¤®«¦¥­ ¡ëâì public
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_„¥áâpyªâ®p ¤®«¦¥­ ¡ëâì public
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Š« áá ¬®¦¥â ¨¬¥âì ⮫쪮 ®¤¨­ ¤¥áâpyªâ®p
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Ž¯p¥¤¥«¥­¨ï «®ª «ì­ëå ª« áᮢ ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Ž¯p¥¤¥«¥­¨ï ­¥¨§¢¥áâ­ëå ª« áᮢ ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_object_has_no_vmt=03023_E_Ž¡ê¥ªâ $1 ­¥ ï¥âáï â ¡«¨æ¥© VMT
+parser_e_illegal_parameter_list=03024_E_H¥¢¥p­ë© ᯨ᮪ ¯ p ¬¥âp®¢
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_type=03025_E_H¥¯p ¢¨«ì­® ®¯p¥¤¥«¥­ ⨯ ¯ p ¬¥âp  ¤«ï  p£y¬¥­â  $1
+% There is an error in the parameter list of the function or procedure.
+% The compiler cannot determine the error more accurate than this.
+parser_e_wrong_parameter_size=03026_E_H¥¯p ¢¨«ì­® ®¯p¥¤¥«¥­® ª®«¨ç¥á⢮ ¯ p ¬¥âp®¢
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_¥à¥£à㦥­­ë© ¨¤¥­â¨ä¨ª â®p $1 ­¥ ï¥âáï äy­ªæ¨¥©
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it isn't a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_¥à¥£à㦥­­ë¥ äy­ªæ¨¨ ¤®«¦­ë ¨¬¥âì â®â-¦¥ ᯨ᮪ ¯ p ¬¥âp®¢
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_‡ £®«®¢®ª äy­ªæ¨¨ ­¥ ᮮ⢥âáâ¢y¥â ¯p¥¤ë¤y饬y ®¯p¥¤¥«¥­¨î ¢ forward $1
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_‡ £®«®¢®ª äy­ªæ¨¨ $1 ­¥ ᮮ⢥âáâ¢y¥â ¯p¥¤ë¤y饬y ®¯p¥¤¥«¥­¨î ¢ forward : ¨¬¥­  ¯¥p¥¬¥­­ëå ¨§¬¥­¥­ë $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_‡­ ç¥­¨ï ¢ ⨯ å ¯¥à¥ç¨á«¥­¨ï ¤®«¦­ë ¡ëâì ¢®§à áâ î騬¨
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_n_interface_name_diff_implementation_name=03032_N_Interface ¨ Implementation ¨¬¥­  p §­ë¥ $1 => $2
+% This note warns you if the implementation and interface names of a
+% functions are different, but they have the same mangled name. This
+% is important when using overloaded functions (but should produce no error).
+parser_e_no_with_for_variable_in_other_segments=03033_E_With ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ¢ ¯¥p¥¬¥­­ëå ª®â®pë¥ ­ å®¤ïâáï ¢ p §«¨ç­ëå ᥣ¬¥­â å
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Š®«¨ç¥á⢮ ¢«®¦¥­¨© ¢ äy­ªæ¨¨ ᫨誮¬ ¬­®£® (¡®«¥¥ 31)
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Žè¨¡ª  ¢ë室  ¨§ ¤®¯yá⨬®£® ¤¨ ¯ §®­  ¯p¨ p áç¥â¥ ª®­áâ ­â
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Žè¨¡ª  ¢ë室  ¨§ ¤®¯yá⨬®£® ¤¨ ¯ §®­  ¯p¨ p áç¥â¥ ª®­áâ ­â
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_®¢â®p­ ï ¬¥âª  CASE
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_‚¥på­ïï £p ­¨æ  ¤¨ ¯ §®­  ¬¥­ìè¥ ç¥¬ ­¨¦­ïï
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_’¨¯¨§¨p®¢ ­­ë¥ ª®­áâ ­âë ª« áᮢ ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_¥à¥¬¥­­ë¥ ¯¥à¥£à㦥­­ëå ä㭪権 ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_„«¨­  áâp®ª¨ ¤®«¦­  ¡ëâì ¢ ¤¨ ¯ §®­¥ 1 .. 255
+% The length of a string in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+% (This is not true for \var{Longstrings} and \var{AnsiStrings}.
+parser_w_use_extended_syntax_for_objects=03042_W_ˆá¯®«ì§®¢ ­¨¥ p áè¨p¥­­®£® ᨭ⠪á¨á  NEW ¨ DISPOSE ¤«ï ¨­á⠭権 ®¡ê¥ªâ®¢
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_ˆá¯®«ì§®¢ ­¨¥ NEW ¨ DISPOSE ¤«ï ­¥â¨¯¨§¨p®¢ ­­ëå yª § â¥«¥©, ¡¥áá¬ëá«¥­­®
+parser_e_no_new_dispose_on_void_pointers=03044_E_ˆá¯®«ì§®¢ ­¨¥ NEW ¨ DISPOSE ¤«ï ­¥â¨¯¨§¨p®¢ ­­ëå yª § â¥«¥©, ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Ž¦¨¤ ¥âáï ¨¤¥­â¨ä¨ª â®p ª« áá 
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_ˆ¤¥­â¨ä¨ª â®p ⨯  §¤¥áì ­¥y¬¥á⥭
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Ž¦¨¤ ¥âáï ¨¤¥­â¨ä¨ª â®p ¬¥â®¤ 
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_‡ £®«®¢®ª äy­ªæ¨¨ ­¥ ᮤ¥p¦¨â ­¥ ®¤­®£® ¨§ ¬¥â®¤®¢ ®¡ê¥ªâ  $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_p_procedure_start=03049_P_p®æ¥¤yp /”y­ªæ¨ï $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_H¥¢¥p­ ï ª®­áâ ­â  á ¯« ¢ î饩 § ¯ï⮩
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL ¬®¦¥â ¨á¯®«ì§®¢ âáï ⮫쪮 ¢ ª®­áâpyªâ®p å
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_„¥áâpyªâ®pë ­¥ ¬®£yâ ¨¬¥âì ¯ p ¬¥âp®¢
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_’®«ìª® ¬¥â®¤ë ª« áá  ¬®£ãâ ááë« âìáï ­  ª« áá
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_’®«ìª® ª ¬¥â®¤ ¬ ª« áá  ¬®¦­® ®¡à é âìáï ¢ ¬¥â®¤ å ª« áá 
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_’¨¯ ª®­áâ ­âë ¨ ⨯ ¢ëp ¦¥­¨ï ¢ CASE ­¥ ᮢ¯ ¤ îâ
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_‘¨¬¢®« ­¥ ¬®¦¥â íªá¯®àâ¨à®¢ âìáï ¨§ ¡¨¡«¨®â¥ª¨
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_“­ á«¥¤®¢ ­­ë© ¬¥â®¤ áªpëâ $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_¥ ¨¬¥¥âáï ­¨ª ª®£® ¬¥â®¤  ¢ ª« áᥠ¯à¥¤ª , ª®â®àë© ­ã¦­® ¯¥p¥®¯p¥¤¥«¨âì: $1
+% You try to \var{override} a virtual method of a parent class that doesn't
+% exist.
+parser_e_no_procedure_to_access_property=03059_E_¨ª ª®© í«¥¬¥­â ­¥ ®¡¥á¯¥ç¨¢ ¥â ®¡à é¥­¨ï ª ᢮©á⢠¬ ª« áá 
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_‘®åà ­¥­­ ï ¤¨à¥ªâ¨¢  ᢮©á⢠¥áâì, ­® ¥é¥ ­¥ p¥ «¨§®¢ ­ 
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_H¥¢¥p­ë© ᨬ¢®« ¤«ï ¤®áâ㯠 ª ᢮©áâ¢y
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_H¥¢®§¬®¦­® ®¡à â¨âìáï ª protected ¯®«î ®¡ê¥ªâ 
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_H¥¢®§¬®¦­® ®¡à â¨âìáï ª private ¯®«î ®¡ê¥ªâ 
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_w_overloaded_are_not_both_virtual=03064_W_¥à¥£à㦥­­ë¥ ¬¥â®¤ë ¢¨pây «ì­ëå ¬¥â®¤®¢, ¤®«¦­ë ¡ëâì ⮦¥ ¢¨pây «ì­ë¬¨: $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+parser_w_overloaded_are_not_both_non_virtual=03065_W_¥à¥£à㦥­­ë© ¬¥â®¤ H… ¢¨àâã «ì­®£® ¬¥â®¤  ¤®«¦¥­ ¡ëâì ⮦¥ H… ¢¨àâã «ì­ë¬: $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+parser_e_overridden_methods_not_same_ret=03066_E_¥à¥®¯à¥¤¥«¥­­ë¥ ¬¥â®¤ë ¤®«¦­ë ¨¬¥âì â®â-¦¥ á ¬ë© â¨¯ ¢®§¢à é ¥¬®£® §­ ç¥­¨ï: "$2" ¯¥à¥®¯à¥¤¥«¥­ "$1" ª®â®àë© ¢®§¢à é ¥â ¤à㣮© ⨯
+% If you declare oerridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_EXPORT äy­ªæ¨¨ ­¥ ¬®£yâ ¡ëâì ¢«®¦¥­­ë¬¨
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Œ¥â®¤ë ­¥ ¬®£yâ íªá¯®pâ¨p®¢ âìáï
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_‚맮¢ á ¯¥à¥¬¥­­ë¬¨ ¯ à ¬¥âà ¬¨ ¤®«¦¥­ ᮮ⢥âá⢮¢ âì â®ç­®: ®«ã祭® "$1", ®¦¨¤ ¥âáï "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_„ ­­ë© ª« áá ­¥ ï¥âáï த¨â¥«ì᪨¬ ª« áᮬ ⥪ã饣® ª« áá 
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF p §p¥è ¥âáï ⮫쪮 ¢ ¬¥â®¤ å
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Œ¥â®¤ë ¬®£yâ ¢ë§ë¢ âìáï ⮫쪮 ¢ ¤py£¨å ¬¥â®¤ å ­ ¯pï¬yî á ¨¤¥­â¨ä¨ª â®p®¬ ⨯  ª« áá 
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_H¥¯p ¢¨«ì­®¥ ¨á¯®«ì§®¢ ­¨¥ ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Žè¨¡ª  ¯à®¢¥àª¨ ¯à¨­ ¤«¥¦­®á⨠ª ¤¨ ¯ §®­ã ¢ ª®­áâàãªâ®à¥ ­ ¡®à  ¨«¨ ¤¢®©­®¬ í«¥¬¥­â¥ ­ ¡®à 
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Ž¦¨¤ ¥âáï yª § â¥«ì ­  ®¡ê¥ªâ
+% You specified an illegal type in a \var{New} statement.
+% The extended synax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_‚ëp ¦¥­¨¥ ¤®«¦­® ¢ë§ë¢ âì ª®­áâpyªâ®p
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_‚ëp ¦¥­¨¥ ¤®«¦­® ¢ë§ë¢ âì ¤¥áâpyªâ®p
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_H¥¢¥p­ë© ¯®p冷ª í«¥¬¥­â®¢ ⨯  RECORD
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_’¨¯ ¢ëp ¦¥­¨ï ¤®«¦­® ¡ëâì CLASS ¨«¨ RECORD
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_p®æ¥¤ypë ­¥ ¬®£yâ ¢®§¢p é âì §­ ç¥­¨ï
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Š®­áâpyªâ®pë ¨ ¤¥áâpyªâ®pë ¤®«¦­ë ¡ëâì ¬¥â®¤ ¬¨
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Ž¯¥p â®p ­¥ ¯¥p¥£py¦¥­
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_¥à¥£à㦥­­®¥ á¢ï§ë¢ ­¨¥ ­¥¢®§¬®¦­® á ®¤¨­ ª®¢ë¬¨ ⨯ ¬¨ ¤ ­­ëå
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_¥à¥£à㧪  ®¯¥à â®à  ­¥¢®§¬®¦­ 
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_RERAISE §¤¥áì ­¥¢®§¬®¦¥­
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_ áè¨p¥­­ë© ᨭ⠪á¨á NEW ¨ DISPOSE ¤«ï ª« áá  ­¥¤®¯yá⨬®
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_asm_incomp_with_function_return=03087_E_€áᥬ¡«¥p ­¥á®¢¬¥á⨬ á ⨯®¬, ª®â®p®¥ ¢®§p é ¥â äy­ªæ¨ï
+% You're trying to implement a \var{assembler} function, but the return type
+% of the function doesn't allow that.
+parser_e_procedure_overloading_is_off=03088_E_p®æ¥¤yp­ ï ¯¥à¥£à㧪  ®âª«î祭 
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_¥¢®§¬®¦­® ¯à¥®¡à §¨âì íâ®â ®¯¥à â®à ¢ ¯¥à¥£à㦥­­ë© ®¯¥à â®à
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_‘à ¢­¨â¥«ì­ë© ®¯¥à â®à ¤®«¦¥­ ¢®§¢à â¨âì ¡ã«¥¢® §­ ç¥­¨¥
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_’®«ìª® ¢¨àâã «ì­ë¥ ¬¥â®¤ë ¬®£ãâ ¡ëâì  ¡áâà ªâ­ë
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_ˆá¯®«ì§®¢ ­¨¥ ¯®ª  ­¥¯®¤¤¥à¦¨¢ ¥¬®© ®á®¡¥­­®á⨠ª®¬¯¨«ïâ®à 
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_‘¬¥è¨¢ âì Š‹€‘‘› ¨ Žš…Š’› ­¥ ¯®§¢®«ï¥âáï
+% You cannot derive \var{objects} and \var{classes} intertwined . That is,
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_¥¨§¢¥áâ­ ï ¤¨à¥ªâ¨¢  ¯à®æ¥¤ãàë, $1 ¨£­®à¨ày¥âáï
+% The procedure direcive you secified is unknown. Recognised procedure
+% directives are \var{cdecl}, \var{stdcall}, \var{popstack}, \var{pascal}
+% \var{register}, \var{export}.
+parser_e_absolute_only_one_var=03095_E_ABSOLUTE ¬®¦¥â ¡ëâì á¢ï§ ­  ⮫쪮 á Ž„HŽ‰ ¯¥p¥¬¥­­®©
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE ¬®¦¥â ¡ëâì á¢ï§ ­  ⮫쪮 á ¯¥p¥¬¥­­®© ¨«¨ ª®­á⠭⮩
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_’®«ìª® Ž„H€ ¯¥p¥¬¥­­ ï ¬®¦¥â ¡ëâì ¨­¨æ¨ «¨§¨p®¢ ­ 
+% You cannot specify more than one variable with a initial value
+% in Delphi syntax.
+parser_e_abstract_no_definition=03098_E_€¡áâà ªâ­ë¥ ¬¥â®¤ë ­¥ ¤®«¦­ë ¨¬¥âì ®¯à¥¤¥«¥­¨¥ (â® ¥áâì ¨¬¥âì ⥫®)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_â  ¯¥à¥£à㦥­­ ï äã­ªæ¨ï ­¥ ¬®¦¥â ¡ëâì «®ª «ì­®©, ¨ ¤®«¦­  íªá¯®àâ¨à®¢ âìáï
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_‚¨àâã «ì­ë¥ ¬¥â®¤ë ¨á¯®«ì§ãîâáï ¡¥§ ª®­áâàãªâ®à  ¢ $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_m_macro_defined=03101_M_Ž¯p¥¤¥«¥­ ¬ ªp®á: $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+parser_m_macro_undefined=03102_M_Œ ªp®á ­¥®¯p¥¤¥«¥­: $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+parser_m_macro_set_to=03103_M_Œ ªp®á $1 yáâ ­®¢«¥­ ¢ $2
+% When \var{-vm} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Š®¬¯¨«¨p®¢ ­¨¥ $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_U_€­ «¨§¨à㥬 ¨­â¥à䥩á­ãî ç áâì ¬®¤y«ï $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_U_€­ «¨§¨à㥬 ॠ«¨§ æ¨®­­ãî ç áâì ¬®¤y«ï $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_D_®¢â®à­®¥ ª®¬¯¨«¨à®¢ ­¨¥ $1
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_paras_allowed=03108_E_‘¢®©á⢠ ¬ áᨢ  ¢ í⮩ â®çª¥ ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% You cannot use array properties at that point in the source.
+parser_e_no_property_found_to_override=03109_E_H¥â ­¨ª ª¨å ᢮©á⢠¤«ï ¯¥p¥®¯p¥¤¥«¥­¨ï
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_’®«ìª® ®¤­® § ¤ ­­®¥ ¯®-㬮«ç ­¨î ᢮©á⢮ p §p¥è ¥âáï, ­ ©¤¥­® y­ á«¥¤®¢ ­­®¥, § ¤ ­­®¥ ¯® y¬®«ç ­¨î, ᢮©á⢮ ¢ ª« áᥠ$1
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_‡ ¤ ­­®¥ ¯®-㬮«ç ­¨î ᢮©á⢮ ¤®«¦­® ¡ëâì ᢮©á⢮¬ ¬ áᨢ 
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_‚¨pây «ì­ë¥ ª®­áâpyªâ®pë ¯®¤¤¥p¦¨¢ îâáï ⮫쪮 ¢ ª« áᮢëå ¬®¤¥«ïå ®¡ê¥ªâ 
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_H¥â ᢮©áâ¢
+% You try to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Š« áá ­¥ ¬®¦¥â ¨¬¥âì PUBLISHED à §¤¥«, ¨á¯®«ì§y©â¥ ª«îç {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_FORWARD ®¯p¥¤¥«¥­¨¥ ª« áá  $1 ¤®«¦­® ¡ëâì ॠ«¨§®¢ ­® §¤¥áì, çâ®¡ë ¨á¯®«ì§®¢ âì ª« áá ª ª ¯à¥¤®ª
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_‹®ª «ì­ë¥ ®¯¥p â®pë ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_p®æ¥¤yp­ ï ¤¨p¥ªâ¨¢  $1 ­¥ p §p¥è¥­  ¢ ¨­â¥à䥩᭮© ç á⨠¬®¤ã«ï
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_p®æ¥¤yp­ ï ¤¨p¥ªâ¨¢  $1 ­¥ p §p¥è¥­  ¢ ॠ«¨§ æ¨®­­®© ç á⨠¬®¤ã«ï
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_p®æ¥¤yp­ ï ¤¨p¥ªâ¨¢  $1 ­¥ p §p¥è¥­  ¢ PROCVAR ®¯p¥¤¥«¥­¨¨
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_”ã­ªæ¨ï $1 㦥 ®¡ê¥­  ª ª PUBLIC ¨«¨ FORWARD
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_H¥«ì§ï ¨á¯®«ì§®¢ âì EXPORT ¨ EXTERNAL ¢¬¥áâ¥
+% These two procedure directives are mutually exclusive
+parser_e_name_keyword_expected=03122_E_Ž¦¨¤ ¥âáï ª«î祢®¥ á«®¢® NAME
+% The definition of an external variable needs a \var{name} clause.
+parser_w_not_supported_for_inline=03123_W_$1 ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ¢­yâp¨ INLINE ¯p®æ¥¤ypë/äy­ªæ¨¨
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_‚ª«î祭¨¥ INLINE ®âª«î祭®
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_‡ ¯¨á뢠¥¬ «®£ ¡p y§¥p  $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Œ®¦¥â ¡ëâì ®âáyâáâ¢y¥â p §ë¬¥­®¢ ­­ë© yª § â¥«ì
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_‚ë¡p ­­ë© á⨫ì ç⥭¨ï  áᥬ¡«¥p  ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_p®æ¥¤yp­ ï ¤¨p¥ªâ¨¢  $1 ª®­ä«¨ªây¥â á ¤py£¨¬¨ ¤¨p¥ªâ¨¢ ¬¨
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_‘®£« è¥­¨¥ ® ¢ë§®¢¥ ¯p®æ¥¤ypë/äy­ªæ¨¨ ­¥ ᮮ⢥âáâ¢ã¥â yª § ­­®¬y ¢ëè¥ ¢ FORWARD
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_register_calling_not_supported=03130_E_‚맮¢ p¥£¨áâp®¢ ("FAST CALL") ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% The \var{register} calling convention, i.e., arguments are passed in
+% registers instead of on the stack is not supported. Arguments are always
+% passed on the stack.
+parser_e_property_cant_have_a_default_value=03131_E_‘¢®©á⢮ ­¥ ¬®¦¥â ¨¬¥âì §­ ç¥­¨¥ ¯® y¬®«ç ­¨î
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_‡­ ç¥­¨¥ ¯® y¬®«ç ­¨î y ᢮©á⢠ ¤®«¦­® ¡ëâì ª®­á⠭⮩
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_‘¨¬¢®« ­¥ ¬®¦¥â ¡ëâì PUBLISHED, ⮫쪮 ª« áá
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_â®â ¢¨¤ ᢮©á⢠ ­¥ ¬®¦¥â ¡ëâì PUBLISHED
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_w_empty_import_name=03135_W_“ª § ­­®¥ ¨¬ï ¨¬¯®àâ  ¯yáâ®
+% Both index and name for the import are 0 or empty
+parser_e_empty_import_name=03136_W_’ॡã¥âáï ¨¬ï ¨¬¯®àâ 
+% Some targets need a name for the imported procedure or a cdecl specifier
+parser_e_used_proc_name_changed=03137_E_‚­ãâ७­¥¥ ¨¬ï ä㭪樨, ¨§¬¥­¥­­® ¯®á«¥ ¨á¯®«ì§®¢ ­¨ï ä㭪樨
+% This is an internal error; please report any occurrences of this error
+% to the \fpc team.
+parser_e_division_by_zero=03138_E_„¥«¥­¨¥ ­  ­®«ì
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_H¥¯p ¢¨«ì­ ï ®¯¥p æ¨ï á ¯« ¢ î饩 § ¯ï⮩
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_‚¥på­ïï £p ­¨æ  ¤¨ ¯ §®­  ¬¥­ìè¥, 祬 ­¨¦­ïï £p ­¨æ 
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_‘âப  "$1" ¡®«ìè¥ ç¥¬ $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_‘âப®¢ ï ¤«¨­  ¡®«ìè¥, 祬 ¤«¨­  ¬ áᨢ  ᨬ¢®«®¢
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_H¥¢¥p­®¥ ¢ëp ¦¥­¨¥ ¯®á«¥ ¤¨p¥ªâ¨¢ë á®®¡é¥­¨ï
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Ž¡p ¡®â稪¨ á®®¡é¥­¨© ¬®£yâ ¡p âì ⮫쪮 ®¤¨­ § ¯p®á ¢ áá뫮筮¬ ¯ p ¬¥âp¥
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_®¢â®p­®¥ ®¯p¥¤¥«¥­¨¥ ¬¥âª¨ á®®¡é¥­¨ï: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_SELF ¬®¦¥â ¡ëâì ⮫쪮 ª ª ï¢­ë© ¯ à ¬¥âà ¢ ®¡à ¡®â稪 å á®®¡é¥­¨ï
+% The self parameter can be passed only explicitly in a method which
+% is declared as message method handler.
+parser_e_threadvars_only_sg=03147_E_¥p¥¬¥­­ë¥ âp¥©¤®¢ ¬®£yâ ¡ëâì ⮫쪮 áâ â¨ç¥áª¨¬¨ ¨«¨ £«®¡ «ì­ë¬¨
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_àאַ© áâ¨«ì  áᥬ¡«¥p  ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ä®p¬ â®¬ ¢ë室­®£® ä ©« 
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_H¥ § £py¦ ©â¥ OBJPAS ¬®¤y«ì, ¨á¯®«ì§y©â¥ {$mode objfpc} ¨«¨ {$mode delphi} ¢¬¥áâ® í⮣®
+% You're trying to load the ObjPas unit manual from a uses clause. This is
+% not a good idea to do, you can better use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automaticly
+parser_e_no_object_override=03150_E_¥p¥®¯p¥¤¥«¥­¨¥ ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­­® ¢ ®¡ê¥ªâ å
+% Override isn't support for objects, use VIRTUAL instead to override
+% a method of an anchestor object
+parser_e_cant_use_inittable_here=03151_E_’¨¯ ¤ ­­ëå, ª®â®pë© âp¥¡y¥â INITILIZATION/FINALIZATION ­¥ ¬®¦¥â ¨á¯®«ì§®¢ âìáï ¢ p §«¨ç­ëå § ¯¨áïå
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_‘âப®¢ë¥ à¥áãàáë ¬®£ãâì ¡ëâì ⮫쪮 áâ â¨ç¥áª¨¬¨ ¨«¨ £«®¡ «ì­ë¬¨
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_à®æ¥¤ãà  Exit á  à£ã¬¥­â®¬ §¤¥áì ­¥¤®¯ãá⨬ 
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_’¨¯ á®å࠭塞®£® ᨬ¢®«  ¤®«¦¥­ ¡ëâì boolean
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_â®â ⨯ ᨬ¢®«  ­¥ ¬®¦¥â ¡ëâì á®åp ­¥­ ¢ í⮬ ᢮©á⢥
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_’®«ìª® ª« áá, ª®â®pë© ª®¬¯¨«¨py¥âáï ¢ $M+ p¥¦¨¬¥ ¬®¦¥â ¡ëâì published
+% In the published section of a class can be only class as fields used which
+% are compiled in $M+ or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Ž¦¨¤ ¥âáï ¯p®æ¥¤yp­ ï ¤¨p¥ªâ¨¢ 
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_‡­ ç¥­¨¥ ᢮©á⢠ ¨­¤¥ªá  ¤®«¦­® ¡ëâì ®¡ëç­®£® ⨯ 
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_ˆ¬ï ¯p®æ¥¤ypë ᫨誮¬ ª®p®âª®¥ ¤«ï íªá¯®pâ 
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Žâáãâáâ¢ãîé ï DEFFILE § ¯¨áì ¬®¦¥â ¡ëâì ᮧ¤ ­  ¤«ï £«®¡ «ì­ëå ¯¥à¥¬¥­­ëå ¬®¤ã«ï
+parser_e_dlltool_unit_var_problem2=03161_E_Š®¬¯¨«¨à®¢ ­¨¥ ¡¥§ -WD ®¯æ¨¨
+parser_f_need_objfpc_or_delphi_mode=03162_F_‚ ¬ ­¥®¡å®¤¨¬ ObjFpc (-S2) ¨«¨ Delphi (-Sd) p¥¦¨¬ ᮢ¬¥á⨬®á⨠¤«ï ª®¬¯¨«ï樨 í⮣® ¬®¤y«ï
+% You need to use {$mode objfpc} or {$mode delphi} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_H¥ ¬®£y íªá¯®pâ¨p®¢ âì á í⨬ ¨­¤¥ªá®¬ ¯®¤ $1
+% Exporting of functions or procedures with a specified index is not
+% support on all targets. The only platforms currently supporting
+% export with index are OS/2 and Win32.
+parser_e_no_export_of_variables_for_target=03164_E_ªá¯®pâ¨p®¢ ­¨¥ ¯¥p¥¬¥­­ëå ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ¯®¤ $1
+% Exporting of variables is not support on all targets. The only platform
+% currently supporting export of variables is Win32.
+parser_e_improper_guid_syntax=03165_E_¥¯®¤å®¤ï騩 GUID ᨭ⠪á¨á
+parser_f_interface_cant_have_variables=03166_F_Interface ­¥ ¬®¦¥â ¨¬¥âì ¯¥à¥¬¥­­ëå
+parser_f_interface_cant_have_constr_or_destr=03167_F_Interface ­¥ ¬®¦¥â ¨¬¥âì ª®­áâàãªâ®à  ¨«¨ destructor
+parser_w_interface_mapping_notfound=03168_W_à®æ¥¤ãà  ­ §¢ ­­ ï "$1" ­¥ ­ ©¤¥­  ¯®¤å®¤ï饩 ¤«ï ॠ«¨§ æ¨¨ $2.$3
+parser_e_interface_id_expected=03169_E_’ॡã¥âáï inteface
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_’¨¯ "$1" ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ª ª ¨­¤¥ªá ¬ áᨢ 
+% Types like DWord or Int64 aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Con- ¨ destructor ­¥ ¯®§¢®«ïîâáï ¢ interface
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_‘¯¥æ¨ä¨ª â®àë ¤®áâ㯠 ­¥ ¬®£ã⠨ᯮ«ì§®¢ âìáï ¢ INTERFACES
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Interface ­¥ ¬®¦¥â ¨¬¥âì ¯®«¥©, ⮫쪮 ¬¥â®¤ë
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_external=03174_E_¥ ¬®£ã ®¯à¥¤¥«¨âì «®ª «ì­ãî ¯à®æ¥¤ãàã ª ª EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance on errors very high
+parser_w_skipped_fields_before=03175_W_¥ª®â®àë¥ ¯®«ï, ­ å®¤ï騥áï ¯¥à¥¤ "$1" ­¥ ¡ë«¨ ¨­¨æ¨ «¨§¨à®¢ ­ë
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_¥ª®â®àë¥ ¯®«ï, ­ å®¤ï騥áï ¯¥à¥¤ "$1" ­¥ ¡ë«¨ ¨­¨æ¨ «¨§¨à®¢ ­ë
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_h_skipped_fields_after=03177_H_¥ª®â®àë¥ ¯®«ï, ­ å®¤ï騥áï ¯¥à¥¤ "$1" ­¥ ¡ë«¨ ¨­¨æ¨ «¨§¨à®¢ ­ë
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically), but the the
+% compiler gives a hint because it can be the source of a problem.
+parser_e_varargs_need_cdecl_and_external=03178_E_VarArgs ¤¨à¥ªâ¨¢  ¡¥§ CDecl ¨ External
+% The varargs directive can only be used with procedures or functions
+% that are declared with CDecl and External directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self ¤®«¦¥­ ¡ëâì ­®à¬ «ì­ë¬ (call-by-value) ¯ à ¬¥â஬
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_ˆ­â¥à䥩á "$1" ­¥ ¨¬¥¥â ¨¤¥­â¨ä¨ª â®à  interface
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_¥¨§¢¥áâ­ë© ¯®«¥ ª« áá  ¨«¨ ¬¥â®¤  "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_¥à¥®¯à¥¤¥«¥­¨¥ ᮣ« è¥­¨ï ® ¢ë§®¢ å ¬¥¦¤ã "$1" ¨ "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_’¨¯¨§¨à®¢ ­­ ï ª®­áâ ­â  (⨯ procedure ¨«¨ object) ¬®¦¥â ¡ëâì ¨­¨æ¨ «¨§¨à®¢ ­­  ⮫쪮 ¢ NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+% \end{description}
+
+#
+# p®¢¥pª  ⨯®¢
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_H¥¯p ¢¨«ì­ë© ⨯
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_H¥á®¢¬¥á⨬®áâì ⨯®¢: ¯®«y稫¨ $1,   ®¦¨¤ «¨ $2
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_H¥á®®â¢¥âá⢨¥ ⨯®¢ ¬¥¦¤y $1 ¨ $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Ž¦¨¤ ¥âáï ¢ëà ¦¥­¨¥ ⨯  TYPE
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Ž¦¨¤ ¥âáï ¢ëà ¦¥­¨¥ ⨯  VAR
+% This happens when you pass a constant to a \var{Inc} var or \var{Dec}
+% procedure. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Ž¦¨¤ ¥âáï ¢ëp ¦¥­¨¥ ⨯  INTEGER, ­® ¯®«ã稫¨ "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Ž¦¨¤ ¥âáï ¢ëà ¦¥­¨¥ ⨯  BOOLEAN, ­® ¯®«ã稫¨ "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Ž¦¨¤ ¥âáï ¢ëp ¦¥­¨¥ â ª®£®-¦¥ ⨯ 
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Ž¦¨¤ ¥âáï ⨯ POINTER, ­® ¯®«ã稫¨ "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Ž¦¨¤ ¥âáï ⨯ CLASS, ­® ¯®«ã稫¨ "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_varid_or_typeid_expected=04010_E_Ž¦¨¤ ¥âáï ¯¥p¥¬¥­­ ï ¨«¨ ¨¤¥­â¨ä¨ª â®p
+% The argument to the \var{High} or \var{Low} function is not a variable
+% nor a type identifier.
+type_e_cant_eval_constant_expr=04011_E_H¥¢®§¬®¦­® p áç¨â âì §­ ç¥­¨¥ ª®­áâ ­âë
+% No longer in use.
+type_e_set_element_are_not_comp=04012_E_“áâ ­®¢ª  í«¥¬¥­â®¢ ¬ áᨢ  ­¥¢®§¬®¦­ 
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Ž¯¥p æ¨ï ­¥ p¥ «¨§®¢ ­  ¤«ï ­ ¡®p®¢ §­ ç¥­¨©
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_€¢â®¬ â¨ç¥áª®¥ ¯p¥®¡p §®¢ ­¨¥ ⨯®¢ ¨§ REAL ¢ COMP, ª®â®pë© ï¢«ï¥âáï ç¨á«®¬ ⨯  INTEGER
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_ˆá¯®«ì§y©â¥ DIV ¢¬¥áâ® í⮣®, ¤«ï ¯®«y祭¨ï 楫®ç¨á«¥­­®£® p¥§y«ìâ â 
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_‘âp®ª®¢ë¥ ⨯ë p §­ë¥ ¨§-§  $V+ p¥¦¨¬ 
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_SUCC ¨«¨ PRED ­  ¯¥p¥ç¨á«¥­¨ïå á ­ §­ ç¥­¨ï¬¨ ­¥¢®§¬®¦­ë
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_H¥¢®§¬®¦­® ¯p®ç¥áâì ¨«¨ § ¯¨á âì ¯¥p¥¬¥­­yî í⮣® ⨯ 
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% booleans, reals, pchars and strings can be read from/written to a text file.
+type_e_no_readln_writeln_for_typed_file=04019_E_¥¢®§¬®¦­® ¨á¯®«ì§®¢ âì Readln ¨«¨ Writeln ­  ⨯¨§¨à®¢ ­­®¬ ä ©«¥
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_¥¢®§¬®¦­® ¨á¯®«ì§®¢ âì Read ¨«¨ Write ­  ­¥â¨¯¨§¨à®¢ ­­®¬ ä ©«¥
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Žè¨¡ª  ⨯®¢ ¬¥¦¤y í«¥¬¥­â ¬¨ ­ ¡®p 
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_LO/HI (LONGINT/DWORD) ¢®§¢p é îâ áâ p襥/¬« ¤è¥¥ á«®¢®
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Ž¦¨¤ ¥âáï ¢ëp ¦¥­¨¥ ⨯  INTEGER ¨«¨ REAL
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_H¥¢¥p­ë© ⨯ "$1" ¢ ¬ áᨢ¥ ª®­áâpyªâ®p 
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_H¥á®¢¬¥á⨬®áâì ⨯®¢ ¢  p£y¬¥­â¥ # $1: ®«ã稫¨ "$2", ­® ®¦¨¤ ¥âáï "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Œ¥â®¤ (¯¥p¥¬¥­­ ï) ¨ p®æ¥¤yp  (¯¥p¥¬¥­­ ï) ­¥ ᮢ¬¥á⨬ë
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_‡ ¯p¥é¥­­ ï ª®­áâ ­â , ¡ë«  ¯¥p¥¤ ­  ª ¢­yâp¥­­¥© ¬ â¥¬ â¨ç¥áª®© äy­ªæ¨¨
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_H¥ ¬®£y ¯®«yç¨âì  ¤p¥á ª®­áâ ­âë
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_€à£ã¬¥­â ­¥ ¬®¦¥â ¡ëâì á¢ï§ ­ á
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_¥¬®£ã á¢ï§ âì «®ª «ì­ãî ¯à®æ¥¤ãàã/äã­ªæ¨î á ¯à®æ¥¤ãà­®© ¯¥à¥¬¥­­®©
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_H¥ ¬®£y ¯®¤¢ï§ âì §­ ç¥­¨¥ ª  ¤p¥áy
+% It's not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_H¥ ¬®£y ¯®¤¢ï§ âì §­ ç¥­¨¥ ª ª®­áâ ­â¥
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing make the parameter value or var.
+type_e_array_required=04033_E_’p¥¡y¥âáï ⨯ array
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_âॡã¥âáï ⨯ interface, ­® ¯®«ã稫¨ "$1"
+type_w_mixed_signed_unsigned=04035_W_‘¬¥è¨¢ ­¨¥ §­ ª®¢ëå ¢ëà ¦¥­¨© ¨ cardinal ⨯  ¤ ¥â 64bit १ã«ìâ â
+% If you divide (or calculate the modulus of) a signed expression by a cardinal (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetical
+% expression (+, -, *, div, mod) in which both signed numbers and cardinals appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetics. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_‘¬¥è¨¢ ­¨¥ §­ ª®¢ëå ¢ëà ¦¥­¨© ¨ cardinal ⨯  ¬®¦¥â ¤ âì ®è¨¡ªã ¢ë室  §  ¤¨ ¯ §®­
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a cardinal while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to cardinal before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_ਢ¥¤¥­¨¥ ⨯  ¨§ $1 ¢ $2 ­¥¢®§¬®¦­® ¯à¨ ¯à¨á¢ ¨¢ ­¨¨, â ª ª ª ®¯¥à ­¤ë ¨¬¥îâ à §­ë© à §¬¥à
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+% \end{description}
+
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_ˆ¤¥­â¨ä¨ª â®p ­¥ ­ ©¤¥­ $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_‚­yâp¥­­ïï ®è¨¡ª  ¢ SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_„¢®©­®© ¨¤¥­â¨ä¨ª â®p $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_ˆ¤¥­â¨ä¨ª â®p y¦¥ ®¯p¥¤¥«¥­ ¢ $1 (áâp®ª  $2)
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_H¥¨§¢¥áâ­ë© ¨¤¥­â¨ä¨ª â®p $1
+% The identifier encountered hasn't been declared, or is used outside the
+% scope where it's defined.
+sym_e_forward_not_resolved=05005_E_FORWARD ­¥ ­ ©¤¥­ $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_f_id_already_typed=05006_F_ˆ¤¥­â¨ä¨ª â®p y¦¥ ®¯p¥¤¥«¥­ ª ª ⨯
+% You are trying to redefine a type.
+sym_e_error_in_type_def=05007_E_Žè¨¡ª  ¢ ®¯p¥¤¥«¥­¨¨ ⨯ 
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_type_id_not_defined=05008_E_’¨¯ ¨¤¥­â¨ä¨ª â®p  ­¥ ®¯p¥¤¥«¥­
+% The type identifier has not been defined yet.
+sym_e_forward_type_not_resolved=05009_E_FORWARD ⨯ ­¥ ­ ©¤¥­ $1
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_’®«ìª® áâ â¨ç¥áª¨¥ ¯¥à¥¬¥­­ë¥ ¬®£ã⠨ᯮ«ì§®¢ âìáï ¢ áâ â¨ç¥áª¨å ¨«¨ ¢­¥è­¨å ¬¥â®¤ å
+% A static method of an object can only access static variables.
+sym_e_invalid_call_tvarsymmangledname=05011_E_H¥¢¥p­ë© ¢ë§®¢ tvarsym.mangledname()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_f_type_must_be_rec_or_class=05012_F_Ž¦¨¤ ¥âáï ⨯ RECORD ¨«¨ CLASS
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Ž¡p §æë ª« áᮢ ¨«¨ ®¡ê¥ªâ®¢ á  ¡áâp ªâ­ë¬ ¬¥â®¤®¬ ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Œ¥âª  ­¥ ®¯p¥¤¥«¥­  $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Œ¥âª  $1 ¨á¯®«ì§ã¥âáï, ­® ­¥®¯à¥¤¥«¥­ 
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_H¥¢¥p­®¥ ®¯à¥¤¥«¥­¨¥ ¬¥âª¨
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO ¨ LABEL ­¥ ¯®¤¤¥p¦¨¢ îâáï (¨á¯®«ì§y©â¥ ª«îç -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Œ¥âª  ­¥ ­ ©¤¥­ 
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_â®â ¨¤¥­â¨ä¨ª â®p ­¥ ¬¥âª 
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_®¢â®p­®¥ ®¯p¥¤¥«¥­¨¥ ¬¥âª¨
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_¥¢¥p­®¥ ®¡ê¥­¨¥ ⨯  í«¥¬¥­â®¢ ­ ¡®à 
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_FORWARD ®¯p¥¤¥«¥­¨¥ ª« áá  ­¥ ®¡­ py¦¥­® $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Œ®¤ã«ì $1 ­¥ ¨á¯®«ì§ã¥âáï ¢ $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_ p ¬¥âp ­¥ ¨á¯®«ì§y¥âáï $1
+% This is a warning. The identifier was declared (locally or globally) but
+% wasn't used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_‹®ª «ì­ ï ¯¥p¥¬¥­­ ï ­¥ ¨á¯®«ì§y¥âáï $1
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_‡­ ç¥­¨¥ ¯ à ¬¥âà  $1 á¢ï§ ­  á 祬-â®, ­® ­¥ ¨á¯®«ì§ã¥âáï
+% This is a warning. The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_‹®ª «ì­ ï ¯¥à¥¬¥­­ ï $1 á¢ï§ ­  á 祬-â®, ­® ­¥ ¨á¯®«ì§ã¥âáï
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_‹®ª «ì­ë© ᨬ¢®« $1 $2 ­¥¨á¯®«ì§ã¥âáï
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Private ¯®«¥ $1.$2 ­¥¨á¯®«ì§ã¥âáï
+sym_n_private_identifier_only_set=05030_N_Private ¯®«¥ $1.$2 á¢ï§ ­  á 祬-â®, ­® ­¥ ¨á¯®«ì§ã¥âáï
+sym_n_private_method_not_used=05031_N_Private ¬¥â®¤ $1.$2 ­¥¨á¯®«ì§ã¥âáï
+
+
+sym_e_set_expected=05032_E_Ž¦¨¤ ¥âáï yáâ ­®¢ª  ⨯ 
+% The variable or expression isn't of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_¥§y«ìâ â äy­ªæ¨¨ ª ¦¥âáï ­¥ yáâ ­®¢«¥­
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_’¨¯ $1 ­¥ª®à४⭮ ¢ë஢­¥­ ¢ ⥪ã饩 § ¯¨á¨ C ï§ëª 
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_H¥¨§¢¥áâ­®¥ ¯®«¥ ¢ § ¯¨á¨ $1
+% The field doesn't exist in the record definition.
+sym_n_uninitialized_local_variable=05036_W_‹®ª «ì­ ï ¯¥p¥¬¥­­ ï $1 ª ¦¥âáï ­¥ ¨­¨æ¨ «¨§¨p®¢ ­ 
+sym_n_uninitialized_variable=05037_W_¥p¥¬¥­­ ï $1 ª ¦¥âáï ­¥ ¨­¨æ¨ «¨§¨p®¢ ­ 
+% These messages are displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% wasn't initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_ˆ¤¥­â¨ä¨ª â®p ­¥ yª §ë¢ ¥â ­¨ ­  ª ª®© í«¥¬¥­â $1
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the class you are trying to create. The procedure you specified
+% does not exist.
+sym_b_param_list=05039_B_H ©¤¥­® ®¯p¥¤¥«¥­¨¥: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_‘¥£¬¥­â ¤ ­­ëå ᫨誮¬ ¡®«ì让 (¬ ªá. 2GB)
+% You get this when you declare an array whose size exceeds the 2GB limit.
+% \end{description}
+
+
+#
+# Codegenerator
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_break_not_allowed=06000_E_BREAK ­¥ p §p¥è¥­®
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06001_E_CONTINUE ­¥ p §p¥è¥­®
+% You're trying to use \var{continue} outside a loop construction.
+cg_e_too_complex_expr=06002_E_‚ëp ¦¥­¨¥ ᫨誮¬ á«®¦­®¥ - ¯¥p¥¯®«­¥­¨¥ á⥪  FPU
+% Your expression is too long for the compiler. You should try dividing the
+% construct over multiple assignments.
+cg_e_illegal_expression=06003_E_H¥¯p ¢¨«ì­®¥ ¢ëp ¦¥­¨¥
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+cg_e_invalid_integer=06004_E_H¥¯p ¢¨«ì­®¥ 楫®ç¨á«¥­­®¥ ¢ëp ¦¥­¨¥
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+cg_e_invalid_qualifier=06005_E_H¥¤¥©á⢨⥫ì­ë© ᯥæ¨ä¨ª â®p
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+cg_e_upper_lower_than_lower=06006_E_‚¥på­¨© ¯p¥¤¥« ¤¨ ¯ §®­  ¬¥­ìè¥ ­¨¦­¥£® ¯p¥¤¥« .
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+cg_e_illegal_count_var=06007_E_H¥¢¥p­ ï ¯¥à¥¬¥­­ ï-áç¥â稪
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+cg_e_cant_choose_overload_function=06008_E_¥ ¬®£ã ®¯à¥¤¥«¨âì, ªâ® '¯¥à¥£à㦠«' äã­ªæ¨î, çâ®¡ë ¥¥ ¢ë§¢ âì
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+cg_e_parasize_too_big=06009_E_ §¬¥p ᯨ᪠ ¯ p ¬¥âp®¢ ¯p¥¢ëᨫ ¤®¯yáâ¨¬ë© ¯p¥¤¥« ¢ 65535 ¡ ©â (64kb)
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_illegal_type_conversion=06010_E_H¥¯p ¢¨«ì­®¥ ¯p¥®¡p §®¢ ­¨¥ ⨯®¢
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+cg_d_pointer_to_longint_conv_not_portable=06011_D_Š®­¢¥pâ æ¨ï ¬¥¦¤y ORDINAL ¨ POINTER ­¥¢®§¬®¦­  ¨§-§  ®âáãâáâ¢¨ï ¯®¤¤¥à¦ª¨ ã ¯« âä®à¬ë
+% If you typecast a pointer to a longint, this code will not compile
+% on a machine using 64bit for pointer storage.
+cg_e_file_must_call_by_reference=06012_E_” ©«®¢ë¥ â¨¯ë ¤®«¦­ë ¡ëâì ¯¥p¥¬¥­­ë¬¨
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_ˆá¯®«ì§®¢ ­¨¥ FAR yª § â¥«ï §¤¥áì ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_var_must_be_reference=06014_E_H¥¯p ¢¨«ì­ë© ¢ë§®¢ ¯ p ¬¥âp  ¯® áá뫪¥
+% You are trying to pass a constant or an expression to a procedure that
+% requires a \var{var} parameter. Only variables can be passed as a \var{var}
+% parameter.
+cg_e_dont_call_exported_direct=06015_E_ˆá¯®«ì§®¢ ­¨¥ EXPORT ®¯p¥¤¥«ï¥â, çâ® íâ  äy­ªæ¨ï ­¥ ¬®¦¥â §¤¥áì ¢ë§ë¢ âìáï
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_‚®§¬®¦­® ­¥¯p ¢¨«ì­ë© ¢ë§®¢ ª®­áâpyªâ®p  ¨«¨ ¤¥áâpyªâ®p  (­¥ ᮮ⢥âáâ¢y¥â ⥪y饬y ª®­â¥ªáây)
+% No longer in use.
+cg_n_inefficient_code=06017_N_H¥íä䥪⨢­ë© ª®¤
+% You construction seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_H¥¤®á⨦¨¬ë© ª®¤
+% You specified a loop which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_stackframe_with_esp=06019_E_‚맮¢ ¯p®æ¥¤ypë á STACKFRAME ESP/SP
+% The compiler encountered a procedure or function call inside a
+% procedure that uses a \var{ESP/SP} stackframe. Normally, when a call is
+% done the procedure needs a \var{EBP} stackframe.
+cg_e_cant_call_abstract_method=06020_E_€¡áâp ªâ­ë¥ ¬¥â®¤ë ­¥ ¬®£yâ ¢ë§ë¢ âìáï ­ ¯pï¬yî
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_f_internal_error_in_getfloatreg=06021_F_‚­yâp¥­­ïï ®è¨¡ª  ¢ getfloatreg(), p á¯p¥¤¥«¥­¨¥ ¯p®¢ «¥­®!
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_f_unknown_float_type=06022_F_H¥¨§¢¥áâ­ë© ⨯ ¯« ¢ î饩 § ¯ï⮩
+% The compiler cannot determine the kind of float that occurs in an expression.
+cg_f_secondvecn_base_defined_twice=06023_F_SecondVecn() ¡ §  ®¯p¥¤¥«¥­  ¤¢ ¦¤ë
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_f_extended_cg68k_not_supported=06024_F_ áè¨p¥­¨ï cg68k ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% The \var{extended} type is not supported on the m68k platform.
+cg_f_32bit_not_supported_in_68000=06025_F_¥§§­ ª®¢ë¥ 32-¡¨â­ë¥ ç¨á«  ­¥ ¯®¤¤¥p¦¨¢ îâáï ¢ MC680x0 p¥¦¨¬¥
+% The cardinal is not supported on the m68k platform.
+cg_f_internal_error_in_secondinline=06026_F_‚­yâp¥­­ïï ®è¨¡ª  ¢ secondinline()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_d_register_weight=06027_D_¥£¨áâp $1 ¢¥á¨â $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_e_stacklimit_in_local_routine=06028_E_‹¨¬¨â á⥪  ¢ «®ª «ì­®© ¯®¤¯p®£p ¬¬¥ ¨áç¥p¯ ­
+% Your code requires a too big stack. Some operating systems pose limits
+% on the stack size. You should use less variables or try ro put large
+% variables on the heap.
+cg_d_stackframe_omited=06029_D_STACK FRAME ®¯y饭ë
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_‚ ®¡ê¥ªâ å ¨«¨ ª« áá å ­¥«ì§ï ¨á¯®«ì§®¢ âì INLINE
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_‚ ¢ë§®¢ å PROCVAR ­¥«ì§ï ¨á¯®«ì§®¢ âì INLINE
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_H¥â ª®¤  ¢ INLINE
+% The compiler couldn't store code for the inline procedure.
+cg_e_no_call_to_interrupt=06034_E_àאַ© ¢ë§®¢ ¯à®æ¥¤ãàë-¯à¥à뢠­¨ï $1 ­¥¢®§¬®¦¥­
+% You can not call an interrupt procedure directly from FPC code
+cg_e_can_access_element_zero=06035_E_Hy«¥¢®© í«¥¬¥­â ¤«¨­­®© áâp®ª¨ ­¥¤®áây¯¥­, ¨á¯®«ì§y©â¥ ¢¬¥áâ® í⮣® SETLENGTH ¨«¨ LENGTH
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_include_not_implemented=06036_E_‚ª«î祭¨ï ¨ ¨áª«î祭¨ï ­¥ ¯®¤¤¥p¦¨¢ îâáï ¢ CASE
+% \var{include} and \var{exclude} are only partially
+% implemented for \var{i386} processors
+% and not at all for \var{m68k} processors.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Š®­áâpyªâ®pë ¨«¨ ¤¥áâpyªâ®pë ­¥ ¬®£yâ ¢ë§ë¢ âìáï ¢­yâp¨ 'WITH' ¯p¥¤«®¦¥­¨©
+% Inside a \var{With} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_H¥«ì§ï ¢ë§ë¢ âì ¬¥â®¤ ®¡p ¡®â稪  ᮡë⨩ ­¥¯®áp¥¤á⢥­­®
+% A message method handler method can't be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_¥à¥å®¤ §  ¢­¥è­îî áâ®à®­ã ¢ exception ¡«®ª¥
+% It isn't allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+% \end{description}
+cg_e_control_flow_outside_finally=06040_E_Š®­â஫¨àãî騥 ¢ëà ¦¥­¨ï (break,continue ¨ exit) ¢ ¡«®ª¥ finally - ­¥¤®¯ãá⨬ë
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+# EndOfTeX
+
+#
+# Assembler reader
+#
+asmr_d_start_reading=07000_D_H ç¨­ ¥¬ ç¨â âì $1 áâ¨«ì  áᥬ¡«¥p 
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_D_Š®­¥æ ç⥭¨ï $1 áâ¨«ï  áᥬ¡«¥p 
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_—â®-â®, ­® ­¥ ¬¥âª , ᮤ¥p¦¨â @
+% A identifier which isn't a label can't contain a @.
+asmr_w_override_op_not_supported=07003_W_¥p¥®¯p¥¤¥«¥­­ë¥ ®¯¥p â®pë ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% The Override operator is not supported
+asmr_e_building_record_offset=07004_E_Žè¨¡ª  ¯®áâp®¥­¨ï ᬥ饭¨ï ¢ § ¯¨á¨
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET ¨á¯®«ì§y¥âáï ¡¥§ ¨¤¥­â¨ä¨ª â®p 
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE ¨á¯®«ì§y¥âáï ¡¥§ ¨¤¥­â¨ä¨ª â®p 
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_H¥ ¬®£y §¤¥áì ¨á¯®«ì§®¢ âì «®ª «ì­ë¥ ¯¥p¥¬¥­­ë¥ ¨«¨ ¯ p ¬¥âpë
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the %ebp register so the
+% address can't be get directly.
+asmr_e_need_offset=07008_E_‡¤¥áì ­¥®¡å®¤¨¬® ¨á¯®«ì§®¢ âì OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_‡¤¥áì ­¥®¡å®¤¨¬® ¨á¯®«ì§®¢ âì §­ ª ¤®«« à  ('$')
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_H¥ ¬®£y ¨á¯®«ì§®¢ âì ¬­®¦¥á⢥­­ë¥ ¯¥p¥¬¥é ¥¬ë¥ ᨬ¢®«ë
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_¥p¥¬¥é ¥¬ë© ᨬ¢®« ¬®¦¥â ¡ëâì ⮫쪮 ¤®¡ ¢«¥­
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_H¥¯p ¢¨«ì­®¥ ¢ëp ¦¥­¨¥ ¢ ª®­áâ ­â¥
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_¥p¥¬¥é ¥¬ë¥ ᨬ¢®«ë §¤¥áì ­¥ p §p¥è¥­ë
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_H¥¢¥p­ë© ᨭ⠪á¨á áá뫪¨
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_‚ë ­¥ ¬®¦¥â¥ ¤®áâ¨çì $1 ¨§ í⮣® ª®¤ 
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_‹®ª «ì­ë¥ ᨬ¢®«ë ¨«¨ ¬¥âª¨ ­¥«ì§ï ¨á¯®«ì§®¢ âì ª ª áá뫪¨
+% ‚ë ­¥ ¬®¦¥â¥ ¨á¯®«ì§®¢ âì «®ª «ì­ë¥ ᨬ¢®«ë ¨«¨ ¬¥âª¨ ª ª áá뫪¨
+asmr_e_wrong_base_index=07017_E_H¥¢¥p­ ï ¡ §  ¨ ¨­¤¥ªá ¢ ¨á¯®«ì§®¢ ­¨¨ p¥£¨áâp 
+% There is an error with the base and index register
+asmr_w_possible_object_field_bug=07018_W_‚®§¬®¦­ ï ®è¨¡ª  ¢ ã¯à ¢«¥­¨¨ ¯®«ï ®¡ê¥ªâ 
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_H¥¢¥p­ë© ¬ èâ ¡ ä ªâ®p  (?ª®íää¨æ¨¥­â ‹ ¬¥? :-&)
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Œ­®¦¥á⢥­­®¥ ¨á¯®«ì§®¢ ­¨¥ ¨­¤¥ªá  p¥£¨áâp 
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_H¥¢¥p­ë© ⨯ ®¯¥p ­¤ 
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_H¥¢¥p­ ï áâp®ª , ª ª ®¯¥p ­¤ ª®¤  ®¯¥p æ¨¨: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE ¨ @DATA ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_yáâë¥ áá뫪¨ ¬¥â®ª ­¥ p §p¥è¥­ë
+asmr_e_expr_zero_divide=07025_E_„¥«¥­¨¥ ­  ­®«ì ¢ ¢ëà ¦¥­¨¨
+asmr_e_expr_illegal=07026_E_¥¢¥à­®¥ ¢ëà ¦¥­¨¥
+asmr_e_escape_seq_ignored=07027_E_Esc-¯®á«¥¤®¢ â¥«ì­®áâì ¨£­®p¨py¥âáï: $1
+asmr_e_invalid_symbol_ref=07028_E_H¥¢¥p­ ï áá뫪  ­  ᨬ¢®«
+asmr_w_fwait_emu_prob=07029_W_FWAIT ¬®¦¥â ¢ë§¢ âì ¯p®¡«¥¬ë í¬y«ï樨 á EMU387
+asmr_w_fadd_to_faddp=07030_W_$1 ¡¥§ ®¯¥à ­¤  â࠭᫨àã¥âáï ¢ $1P
+asmr_w_enter_not_supported_by_linux=07031_W_ENTER ¨­áâàãªæ¨ï ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¢ Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_‚맮¢ ¯¥p¥£py¦¥­­®© äy­ªæ¨¨ ¢  áᥬ¡«¥p¥
+asmr_e_unsupported_symbol_type=07033_E_H¥ ¯®¤¤¥p¦¨¢ ¥¬ë© ⨯ ᨬ¢®«  ¢ ®¯¥p ­¤¥
+asmr_e_constant_out_of_bounds=07034_E_®áâ®ï­­®¥ §­ ç¥­¨¥ ¢­¥ £p ­¨æ
+asmr_e_error_converting_decimal=07035_E_Žè¨¡ª  ¯p¨ ¯p¥®¡p §®¢ ­¨¨ ¤¥áïâ¨ç­®£® ç¨á«  $1
+asmr_e_error_converting_octal=07036_E_Žè¨¡ª  ¯p¨ ¯p¥®¡p §®¢ ­¨¨ ¢®á¬¥p¨ç­®£® ç¨á«  $1
+asmr_e_error_converting_binary=07037_E_Žè¨¡ª  ¯p¨ ¯p¥®¡p §®¢ ­¨¨ ¤¢®¨ç­®£® ç¨á«  $1
+asmr_e_error_converting_hexadecimal=07038_E_Žè¨¡ª  ¯p¨ ¯p¥®¡p §®¢ ­¨¨ è¥áâ­ ¤æ â¥p¨ç­®£® ç¨á«  $1
+asmr_h_direct_global_to_mangled=07039_H_$1 ¯p¥®¡p §®¢ ­® ¢ $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 á¢ï§ ­ á ¯¥p¥£py¦¥­­®© äy­ªæ¨¥©
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_H¥ ¬®£y ¨á¯®«ì§®¢ âì SELF ¢­¥ ¬¥â®¤ 
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_H¥ ¬®£y ¨á¯®«ì§®¢ âì __OLDEBP ¢­¥ ¢«®¦¥­­®© ¯p®æ¥¤ypë
+asmr_e_void_function=07043_W_”y­ªæ¨ï ª®â®p ï ®¯p¥¤¥«¥­  ª ª '­¥ ¢®§p é îé ï §­ ç¥­¨©' ­¥ ¬®¦¥â ¨å ¢®§¢p é âì
+asmr_e_SEG_not_supported=07044_E_SEG ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmr_e_size_suffix_and_dest_dont_match=07045_E_‘yä䨪á p §¬¥p  ¨  ¤p¥á â ¨«¨ ¨á室­ë© p §¬¥p ­¥ ᮮ⢥âáâ¢yîâ
+asmr_w_size_suffix_and_dest_dont_match=07046_W_‘yä䨪á p §¬¥p  ¨  ¤p¥á â ¨«¨ ¨á室­ë© p §¬¥p ­¥ ᮮ⢥âáâ¢yîâ
+asmr_e_syntax_error=07047_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ¯à¨  áᥬ¡«¨à®¢ ­¨¨
+asmr_e_invalid_opcode_and_operand=07048_E_H¥¢¥p­ ï ª®¬¡¨­ æ¨ï ª®¤  ®¯¥p æ¨¨ ¨ ®¯¥p ­¤®¢
+asmr_e_syn_operand=07049_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ¢ ®¯¥p ­¤¥ ¯à¨  áᥬ¡«¨à®¢ ­¨¨
+asmr_e_syn_constant=07050_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ¢ ª®­á⠭⥠¯à¨  áᥬ¡«¨à®¢ ­¨¨
+asmr_e_invalid_string_expression=07051_E_H¥¢¥p­®¥ áâp®ª®¢®¥ ¢ëp ¦¥­¨¥
+asmr_w_const32bit_for_address=07052_W_ª®­áâ ­â  á ᨬ¢®«®¬ $1 ­¥ ¤«ï 32bit  ¤à¥á 
+asmr_e_unknown_opcode=07053_E_¥¨§¢¥áâ­ë© opcode $1
+asmr_e_invalid_or_missing_opcode=07054_E_H¥¢¥p­ ï ¨«¨ ¯p®¯y饭­ ï ª®¬ ­¤ 
+asmr_e_invalid_prefix_and_opcode=07055_E_H¥¢¥p­ ï ª®¬¡¨­ æ¨ï ¯p¥ä¨ªá  ¨ ª®¬ ­¤ë: $1
+asmr_e_invalid_override_and_opcode=07056_E_H¥¢¥p­ ï ª®¬¡¨­ æ¨ï ¯¥p¥®¯p¥¤¥«¥­¨ï ¨ ª®¬ ­¤ë: $1
+asmr_e_too_many_operands=07057_E_‘«¨èª®¬ ¬­®£® ®¯¥p ­¤®¢ ¢ áâp®ª¥
+asmr_w_near_ignored=07058_W_„¨à¥ªâ¨¢  NEAR ¨£­®p¨pã¥âáï
+asmr_w_far_ignored=07059_W_„¨à¥ªâ¨¢  FAR ¨£­®p¨pã¥âáï
+asmr_e_dup_local_sym=07060_E_®¢â®p­®¥ ®¯p¥¤¥«¥­¨¥ «®ª «ì­®£® ᨬ¢®«  $1
+asmr_e_unknown_local_sym=07061_E_H¥¨§¢¥áâ­ë© «®ª «ì­ë© ᨬ¢®« $1
+asmr_e_unknown_label_identifier=07062_E_H¥¨§¢¥áâ­ ï ¬¥âª  ¨¤¥­â¨ä¨ª â®p  $1
+asmr_e_invalid_register=07063_E_¥¯à ¢¨«ì­®¥ ¨¬ï ॣ¨áâà 
+asmr_e_invalid_fpu_register=07064_E_H¥¯p ¢¨«ì­®¥ ¨¬ï p¥£¨áâp  ¤«ï ®¯¥p æ¨¨ á ¯« ¢ î饩 § ¯ï⮩
+asmr_e_nor_not_supported=07065_E_NOR ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmr_w_modulo_not_supported=07066_W_MODULO ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmr_e_invalid_float_const=07067_E_H¥¢¥p­ ï ª®­áâ ­â  (¯« ¢ îé ï § ¯ïâ ï): $1
+asmr_e_invalid_float_expr=07068_E_H¥¢¥p­®¥ ¢ëp ¦¥­¨¥ (¯« ¢ îé ï ®¯¥p æ¨ï)
+asmr_e_wrong_sym_type=07069_E_H¥¢¥p­ë© ⨯ ᨬ¢®« 
+asmr_e_cannot_index_relative_var=07070_E_H¥ ¬®£y ¨­¤¥ªá¨p®¢ âì «®ª «ì­yî ¯¥p¥¬¥­­yî ¨«¨ ¯ p ¬¥âp á p¥£¨áâp®¬
+asmr_e_invalid_seg_override=07071_E_H¥¢¥p­®¥ ¢ëp ¦¥­¨¥ ¯¥p¥®¯p¥¤¥«¥­­®£® ᥣ¬¥­â 
+asmr_w_id_supposed_external=07072_W_ˆ¤¥­â¨ä¨ª â®p $1, ¯p¥¤¯®«®¦¨¬ çâ® ®­ ¢­¥è­¨©
+asmr_e_string_not_allowed_as_const=07073_E_H¥«ì§ï ¨á¯®«ì§®¢ âì áâp®ª¨ ª ª ª®­áâ ­âë
+asmr_e_no_var_type_specified=07074_’¨¯ ¯¥p¥¬¥­­®© ­¥ yª § ­
+asmr_w_assembler_code_not_returned_to_text=07075_E_€áᥬ¡«¥p᪨© ª®¤ ­¥ ¢®§¢p é ¥âáï ¢ TEXT ᥣ¬¥­â
+asmr_e_not_directive_or_local_symbol=07076_E_$1 ­¥ ¤¨p¥ªâ¨¢  ¨ ­¥ «®ª «ì­ë© ᨬ¢®«
+asmr_w_using_defined_as_local=07077_E_ˆá¯®«ì§®¢ ­¨¥ ®¯p¥¤¥«¥­­®£® ¨¬¥­¨ ª ª «®ª «ì­ ï ¬¥âª 
+asmr_e_dollar_without_identifier=07078_E_‘¨¬¢®« '$' ¨á¯®«ì§y¥âáï ¡¥§ ¨¤¥­â¨ä¨ª â®p 
+asmr_w_32bit_const_for_address=07079_W_32-¡¨â­ ï ª®­áâ ­â  á®§¤ ¥âáï ¤«ï  ¤p¥á 
+asmr_n_align_is_target_specific=07080_N_.ALIGN ¨á¯®«ì§y¥âáï ᯥ樠«ì­® ¤«ï yª § ­¨ï ¯« âä®p¬ë, ¨á¯®«ì§y©â¥ .BALIGN ¨«¨ .P2ALIGN
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_H¥â ¤®áây¯  ª ¯®«î ¯ p ¬¥âp  ­ ¯pï¬yî, ¨á¯®«ì§y©â¥ p¥£¨áâpë
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_H¥â ¤®áây¯  ª ¯®«ï¬ ®¡ê¥ªâ®¢/ª« áᮢ ­ ¯pï¬yî, ¨á¯®«ì§y©â¥ p¥£¨áâpë
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_H¥ § ¤ ­ p §¬¥p ¨ ­¥¢®§¬®¦­® ®¯p¥¤¥«¨âì p §¬¥p ®¯¥p ­¤®¢
+% You should specify explicitly a size for the reference, because
+% compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_H¥ ¬®£y ¨á¯®«ì§®¢ âì RESULT ¢ í⮩ äy­ªæ¨¨
+asmr_h_RESULT_is_reg=07085_H_RESULT íâ® p¥£¨áâp $1
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" ¡¥§ ®¯¥à ­¤  â࠭᫨àã¥âáï ¢ "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" â࠭᫨àã¥âáï ¢ "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" â࠭᫨àã¥âáï ¢ "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_‘¨¬¢®« < §¤¥áì ­¥ à §à¥è¥­
+asmr_e_invalid_char_greater=07090_E_‘¨¬¢®« > §¤¥áì ­¥ à §à¥è¥­
+asmr_w_xdef_not_supported=07091_W_XDEF ­¥ ¯®¤¤¥à¦¨¢ ¥âáï
+asmr_e_invalid_global_def=07092_E_¥¢¥à­ë© ᨭ⠪á¨á XDEF
+asmr_w_align_not_supported=07093_W_ALIGN ­¥ ¯®¤¤¥à¦¨¢ ¥âáï
+asmr_e_no_inc_and_dec_together=07094_E_Inc ¨ Dec ­¥ ¬®£ãâ ¡ëâì ¢¬¥áâ¥
+asmr_e_invalid_reg_list_in_movem=07095_E_¥¢¥à­ë© reglist ¢ movem
+asmr_e_invalid_reg_list_for_opcode=07096_E_¥¢¥à­ë© reglist ¤«ï opcode
+asmr_e_68020_mode_required=07097_E_’ॡã¥âáï 68020 ०¨¬
+
+#
+# Assembler/binary writers
+#
+asmw_f_too_many_asm_files=08000_F_‘«¨èª®¬ ¬­®£® ä ©«®¢ ¤«ï  áᥬ¡«¨p®¢ ­¨ï
+asmw_f_assembler_output_not_supported=08001_F_‚ë¡p ­­ë© ⨯  áᥬ¡«¥p  ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmw_f_comp_not_supported=08002_F_COMP ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmw_f_direct_not_supported=08003_F_àאַ©  áᥬ¡«¥p §¤¥áì ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmw_e_alloc_data_only_in_bss=08004_E_ á¯p¥¤¥«¥­¨¥ ¤ ­­ëå ¢ ¯ ¬ï⨠¢®§¬®¦­® ⮫쪮 ¢ BSS ᥪ樨
+asmw_f_no_binary_writer_selected=08005_F_¥ ¢ë¡à ­ áâ¨«ì  áᥬ¡«¨à®¢ ­¨ï
+asmw_e_opcode_not_in_table=08006_E_Asm: Š®¬ ­¤ë $1 ­¥â ¢ ᯨ᪥ ª®¬ ­¤
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 ­¥¢¥p­ ï ª®¬¡¨­ æ¨ï ®¯¥p ­¤®¢ ¢ ª®¬ ­¤¥
+asmw_e_16bit_not_supported=08008_E_Asm: 16-¡¨â­ë¥ áá뫪¨ ­¥ ¯®¤¤¥p¦¨¢ îâáï
+asmw_e_invalid_effective_address=08009_E_Asm: H¥¢¥p­ë© íä䥪⨢­ë©(?)  ¤p¥á
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Ž¦¨¤ ¥âáï IMMEDIATE ¨«¨ áá뫪 
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 §­ ç¥­¨¥ ¢ëè«® §  £p ­¨æë $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: SHORT JUMP ¢ë襫 §  £p ­¨æë ¤¨ ¯®§®­  $1
+asmw_e_undefined_label=08013_E_Asm: ¥®¯à¥¤¥«¥­­ ï ¬¥âª  $1
+asmw_e_comp_not_supported=08014_E_Asm: ’¨¯ Comp ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¯®¤ í⮩ ¯« âä®à¬®©
+asmw_e_extended_not_supported=08015_E_Asm: ’¨¯ Extend ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¯®¤ í⮩ ¯« âä®à¬®©
+asmw_e_duplicate_label=08016_E_Asm: ®¢â®à­ ï ¬¥âª  $1
+
+#
+# Executing linker/assembler
+#
+exec_w_source_os_redefined=09000_W_ˆá室­ ï ®¯¥p æ¨®­­ ï á¨á⥬  ¯¥p¥®¯p¥¤¥«¥­ 
+exec_i_assembling_pipe=09001_I_€áᥬ¡«¨py¥¬ (pipe) $1
+exec_d_cant_create_asmfile=09002_E_H¥ ¬®£y ᮧ¤ âì ä ©«  áᬥ¡«¥p : $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_objectfile=09003_E_¥ ¬®£ã ᮧ¤ âì ®¡ê¥ªâ­ë© ä ©«: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_archivefile=09004_E_¥ ¬®£ã ᮧ¤ âì  à娢­ë© ä ©«: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_assembler_not_found=09005_E_€áᥬ¡«¥p $1 ­¥ ­ ©¤¥­, ¨á¯®«ì§y¥¬ ¢¬¥áâ® ­¥£® ¢­¥è­¨©  áᥬ¡«¥p
+exec_t_using_assembler=09006_T_ˆá¯®«ì§y¥¬  áᥬ¡«¥p: $1
+exec_e_error_while_assembling=09007_E_Žè¨¡ª  ¯p¨  áᥬ¡«¨p®¢ ­¨¨ $1
+exec_e_cant_call_assembler=09008_E_H¥ ¬®£y ¢ë§¢ âì  áᥬ¡«¥p, ®è¨¡ª  $1. ˆá¯®«ì§y¥¬ ¢¬¥áâ® ­¥£® ¢­¥è­¨©  áᥬ¡«¥p
+exec_i_assembling=09009_I_€áᥬ¡«¨p®¢ ­¨¥ $1
+exec_i_assembling_smart=09010_I_ˆ­â¥«¥ªây «ì­®¥  áᥬ¡«¨p®¢ ­¨¥ $1
+exec_w_objfile_not_found=09011_W_Ž¡ê¥ªâ­ë© ä ©« $1 ­¥ ­ ©¤¥­, ª®¬¯®­®¢ª  ¬®¦¥â ¡ëâì ­¥y¤ ç­®© !
+exec_w_libfile_not_found=09012_W_¨¡«¨®â¥ª  $1 ­¥ ­ ©¤¥­ , ª®¬¯®­®¢ª  ¬®¦¥â ¡ëâì ­¥y¤ ç­®© !
+exec_e_error_while_linking=09013_E_Žè¨¡ª  ¯p¨ ª®¬¯®­®¢ª¥
+exec_e_cant_call_linker=09014_E_H¥ ¬®£y ¢ë§¢ âì ª®¬¯®­®¢é¨ª, ¨á¯®«ì§y¥¬ ¢¬¥áâ® ­¥£® ¢­¥è­¨© ª®¬¯®­®¢é¨ª
+exec_i_linking=09015_I_Š®¬¯®­®¢ª  $1
+exec_e_util_not_found=09016_E_“⨫¨â  $1 ­¥ ­ ©¤¥­ , ¯¥p¥ª«îç ¥¬áï ­  ¢­¥è­îî «¨­ª®¢ªy
+exec_t_using_util=09017_T_ˆá¯®«ì§ã¥¬ ¢­¥è­îî ã⨫¨âã $1
+exec_e_exe_not_supported=09018_E_‘®§¤ ­¨¥ ¨á¯®«­ï¥¬ëå ä ©«®¢ ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+exec_e_dll_not_supported=09019_E_‘®§¤ ­¨¥ ¤¨­ ¬¨ç¥áª¨å ¡¨¡«¨®â¥ª (DLL) ­¥ ¯®¤¤¥p¦¨¢ îâáï
+exec_i_closing_script=09020_I_‡ ªp뢠¥¬ áªp¨¯â $1
+exec_e_res_not_found=09021_E_Š®¬¯¨«ïâ®p p¥áypᮢ ­¥ ­ ©¤¥­, ¯¥p¥ª«îç ¥¬áï ­  ¢­¥è­¨© ª®¬¯¨«ïâ®à à¥áãàᮢ
+exec_i_compilingresource=09022_I_Š®¬¯¨«¨py¥¬ p¥áypá $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᮡp ­ ¢ p¥¦¨¬¥ static, ¢ª«îç ¥¬ smart á¡®pªy
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᮡp ­ ¢ p¥¦¨¬¥ smart, ¢ª«îç ¥¬ static á¡®pªy
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᮡp ­ ¢ p¥¦¨¬¥ shared, ¢ª«îç ¥¬ static á¡®pªy
+exec_e_unit_not_smart_or_static_linkable=09026_E_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᮡp ­ ¢ p¥¦¨¬ å smart ¨«¨ static
+exec_e_unit_not_shared_or_static_linkable=09027_E_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᮡp ­ ¢ p¥¦¨¬ å shared ¨«¨ static
+
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_H¥ ¬®¦¥¬ ¨á¯®«­¨âì ¨á¯®«­ï¥¬ë© ¬®¤y«ì $1
+execinfo_f_cant_open_executable=09029_F_H¥ ¬®£y ®âªpëâì ¨á¯®«­ï¥¬ë© ¬®¤y«ì $1
+execinfo_x_codesize=09030_X_ §¬¥p ª®¤ : $1 ¡ ©â
+execinfo_x_initdatasize=09031_X_ §¬¥p ¨­¨æ¨ «¨§¨pyî饩 ç áâ¨: $1 ¡ ©â
+execinfo_x_uninitdatasize=09032_X_ §¬¥p ¤¥-¨­¨æ¨ «¨§¨pyî饩 ç áâ¨: $1 ¡ ©â
+execinfo_x_stackreserve=09033_X_‡ p¥§¥p¢¨p®¢ ­­® á⥪ : $1 ¡ ©â
+execinfo_x_stackcommit=09034_X_ˆá¯®«ì§®¢ ­® á⥪ : $1 ¡ ©â
+
+# Unit loading
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_®¨áª ¬®¤y«¥©: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU § £py¦ ¥âáï $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU ¨¬ï: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU ä« £¨: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU ¢p¥¬ï: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_PPU ä ©« ᫨誮¬ ª®p®âª¨©
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_H¥¢¥p­ë© § £®«®¢®ª PPU (­¥â PPU ¬¥âª¨ ¢­ ç «¥)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_H¥¢¥p­ ï ¢¥pá¨ï PPU ä ©«  $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU ä ©« ®âª®¬¯¨«¨p®¢ ­ ¤«ï ¤py£®£® ¯p®æ¥áá®p 
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU ä ©« ®âª®¬¯¨«¨p®¢ ­ ¤«ï ¤py£®© OS
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU ¨áâ®ç­¨ª: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_‡ ¯¨á뢠¥¬ $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_H¥ ¬®£y § ¯¨á âì PPU-ä ©«
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_—¨â ¥¬ PPU-ä ©«
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_¥®¦¨¤ ­­ë© ª®­¥æ y PPU-ä ©« 
+% Unexpected end of file.
+unit_f_ppu_invalid_entry=10016_F_H¥¯p ¢¨«ì­ë© ¢å®¤ ¢ PPU-ä ©«: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU DBX COUNT ¯p®¡«¥¬ 
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_H¥¢¥p­®¥ ¨¬ï ¬®¤y«ï: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_‘«¨èª®¬ ¬­®£® ¬®¤y«¥©
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Špy£®¢ ï áá뫪  ¬®¤y«ï ¬¥¦¤y $1 ¨ $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_H¥ ¬®£y ®âª®¬¯¨«¨p®¢ âì ¬®¤y«ì $1. H¥ ¬®£y ­ ©â¨ ¨á室­¨ª®¢.
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_H¥ ¬®£y ­ ©â¨ PPU ä ©« $1.
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Œ®¤ã«ì $1 ­¥ ­ ©¤¥­, ­® $2 áãé¥áâ¢ã¥â
+unit_f_unit_name_error=10024_F_Œ®¤ã«ì $1 ¨áª «¨, ­® ­ è«¨ ¬®¤ã«ì $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_’p¥¡y¥âáï ª®¬¯¨«¨p®¢ ­¨¥ á¨á⥬­®£® ¬®¤y«ï. ˆá¯®«ì§y©â¥ ª«îç -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Ž¡­ py¦¥­® $1 ®è¨¡®ª ¯p¨ ª®¬¯¨«¨p®¢ ­¨¨ ¬®¤y«ï, ®áâ ­ ¢«¨¢ ¥¬áï
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_‡ £py§ª  ¨§ $1 ($2) ¬®¤y«ì $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_¥p¥ª®¬¯¨«¨p®¢ ­¨¥ $1, ª®­âp®«ì­ ï áy¬¬  y $2 ¨§¬¥­¥­ 
+unit_u_recompile_source_found_alone=10029_U_¥p¥ª®¬¯¨«¨p®¢ ­¨¥ $1, â ª ª ª ­ ©¤¥­ë ⮫쪮 ¨á室­¨ª¨
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_¥p¥ª®¬¯¨«¨p®¢ ­¨¥ ¬®¤y«ï, â ª ª ª ¡¨¡«¨®â¥ª  (static) áâ pè¥ ç¥¬ ppu-ä ©«
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_¥p¥ª®¬¯¨«¨p®¢ ­¨¥ ¬®¤y«ï, â ª ª ª ¡¨¡«¨®â¥ª  (shared) áâ pè¥ ç¥¬ ppu-ä ©«
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_¥p¥ª®¬¯¨«¨p®¢ ­¨¥ ¬®¤y«ï, â ª ª ª .as ¨ .obj ä ©« áâ pè¥ ç¥¬ ppu-ä ©«
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_¥p¥ª®¬¯¨«¨p®¢ ­¨¥ ¬®¤y«ï, â ª ª ª .obj ä ©« áâ pè¥ ç¥¬ .as ä ©«
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_start_parse_interface=10034_U_€­ «¨§¨à㥬 ¨­â¥p䥩á­ãî ç áâì $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_start_parse_implementation=10035_U_€­ «¨§¨à㥬 p¥ «¨§ æ¨®­­ãî ç áâì $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_‚â®p ï § £py§ª  ¤«ï ¬®¤y«ï $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU ¯p®¢¥pª  ä ©«  $1 ¢p¥¬ï $2
+unit_h_cond_not_set_in_last_compile=10038_H_“á«®¢­®¥ ¢ëp ¦¥­¨¥ $1 ­¥ ¡ë«® yáâ ­®¢«¥­® ¯p¨ ¯®á«¥¤­¥© ª®¬¯¨«ï樨 $2
+% when recompilation of an unit is required the compiler will check that
+% the same conditionals are set for the recompiliation. The compiler has
+% found a conditional that currently is defined, but was not used the last
+% time the unit was compiled.
+unit_h_cond_set_in_last_compile=10039_H_“á«®¢­®¥ ¢ëp ¦¥­¨¥ $1 ¡ë«® yáâ ­®¢«¥­® ¯p¨ ¯®á«¥¤­¥© ª®¬¯¨«ï樨 $2
+% when recompilation of an unit is required the compiler will check that
+% the same conditionals are set for the recompiliation. The compiler has
+% found a conditional that was used the last time the unit was compiled, but
+% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_ ©¤¥­ ¬®¤ã«ì $1 âॡãî騩 ᡮન, ­® ­¥ª®â®àë¥ ¢ª«îç ¥¬ë¥ ä ©«ë ­¥ ­ ©¤¥­ë
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_” ©« $1 ­®¢¥¥ 祬 ä ©« $2 ($2 á ä« £®¬ Release PPU)
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+% \end{description}
+
+#
+# Options
+#
+option_usage=11000_$1 [®¯æ¨¨] <ä ©«> [®¯æ¨¨]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_®¤¤¥p¦¨¢ ¥âáï ⮫쪮 ®¤¨­ ä ©« ¤«ï ª®¬¯¨«ï樨
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF ä ©« ¬®¦¥â ᮧ¤ ¢ âìáï ⮫쪮 ¯®¤ OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_‚«®¦¥­­ë¥ ä ©«ë ®â¢¥â  ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_ˆ¬ï ä ©«  ¤«ï ª®¬¯¨«ï樨 ¢ ª®¬ ­¤­®© áâp®ª¥ ­¥ ®¡­ à㦥­®
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Ž¯æ¨ï ª®¬¯¨«ïâ®à  $1 ¢­ãâਠª®­ä¨£ãà æ¨®­­®£® ä ©«  ­¥ ®¡­ à㦥­ 
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_H¥¢¥p­ë© ¯ p ¬¥âp: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? ¢ë¢¥á⨠áâp ­¨æë ¯®¬®é¨
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_‘«¨èª®¬ ¬­®£® ¢«®¦¥­­ëå ª®­ä¨£yp æ¨®­­ëå ä ©«®¢
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_H¥ ¬®£y ®âªpëâì ä ©« $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_—⥭¨¥ ¤ «ì­¥©è¨å ¯ p ¬¥âp®¢ ¨§ $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_TARGET yáâ ­®¢«¥­ ¤¢ ¦¤ë ¢: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_SHARED ¡¨¡«¨®â¥ª¨ ­¥ ¯®¤¤¥p¦¨¢ îâáï ¢ GO32* ¯p¨«®¦¥­¨ïå, ¤¥« ¥¬ ¨å STATIC
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_‘«¨èª®¬ ¬­®£® $IFDEF ¨«¨ $IFNDEF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_‘«¨èª®¬ ¬­®£® $ENDIF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Žâªpë⨥ yá«®¢­®£® ¢ëp ¦¥­¨ï ¢ ª®­æ¥ ä ©« 
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_ƒ¥­¥p æ¨ï ¨­ä®p¬ æ¨¨ ¤«ï ®â« ¤ª¨ ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ¢ í⮬ ¨á¯®«­ï¥¬®¬ ä ©«¥
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_®¯p®¡y©â¥ ®âª®¬¯¨«¨p®¢ âì á ®¯æ¨¥© -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_‚ë ¨á¯®«ì§y©â¥ yáâ p¥¢è¨© ª«îç $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_‚ë ¨á¯®«ì§y¥â¥ yáâ p¥¢è¨© ª«îç $1, ¯®¦ «y©áâ  ¨á¯®«ì§y©â¥ ¢¬¥áâ® ­¥£® ª«îç $2
+% â® ¯à¥¤ã¯à¥¦¤ ¥â ‚ á, ª®£¤  ‚ë ¨á¯®«ì§ã¥â¥ ª«îç, ª®â®àë© ¡®«ìè¥ ­¥
+% ¯®¤¤¥à¦¨¢ ¥âáï. ‚ë ¤®«¦­ë ¨á¯®«ì§®¢ âì ¢â®à®© ª«îç ¢¬¥áâ® í⮣®.
+% ¥ª®¬¥­¤ã¥âáï, § ¬¥­¨âì ª«îç, çâ®¡ë ¯à¥®¤®«¥âì ¯à®¡«¥¬ë ¢ ¡ã¤ã饬,
+% ª®£¤  ª«îç, yª § ­­ë© ¢ ¬¨ ¬®¦¥â ¨§¬¥­ïâìáï ¨ ¨¬¥âì ¤py£®¥ §­ ç¥­¨¥.
+option_switch_bin_to_src_assembler=11020_N_¥p¥ª«îç ¥¬  áᥬ¡«¥p ¢  áᥬ¡«¥p § ¤ ­­ë© ¯® y¬®«ç ­¨î
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_‚¨¤ ¢ë¡à ­­®£® áâ¨«ï  áᥬ¡«¥à  "$1" ­¥ ᮢ¬¥á⨬ á "$2"
+option_asm_forced=11022_W_Š ᮦ «¥­¨î, ¨á¯®«ì§ã¥¬ áâ¨«ì  áᥬ¡«¥à  "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_—¨â î ®¯æ¨¨ ¨§ ä ©«  $1
+% Options are also read from this file
+option_using_env=11027_T_—¨â î ®¯æ¨¨ ¨§ ®ªà㦥­¨ï $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Ž¡à ¡®âª  ®¯æ¨¨ "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** ­ ¦¬¨â¥ enter ***
+
+#
+# ‹®£® (®¯æ¨ï -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCVER [$FPCDATE] for $FPCTARGET [Russian Edition]
+Copyright (c) 1993-2002 by Florian Klaempfl
+]
+
+#
+# ˆ­ä®p¬ æ¨ï (®¯æ¨ï -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVER
+
+Compiler Date : $FPCDATE
+Compiler Target: $FPCTARGET
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs, suggestions and etc to:
+ bugrep@freepascal.org, russia@freepascal.org
+]
+
+#
+# ‘âà ­¨æë ‘¯à ¢ª¨ (®¯æ¨ï -? ˆ -h)
+#
+# Ž¡à â¨âì ¢­¨¬ ­¨¥: Hy¬¥p æ¨î ­¥ ¬¥­ïâì!
+#
+option_help_pages=11025_[
+**0*_¤¥« © '+', çâ®¡ë ¢ª«îç¨âì ª«îç, ¨ '-' çâ®¡ë ®âª«îç¨âì ¥£®
+**1a_ª®¬¯¨«ïâ®à ­¥ ¡y¤¥â 㤠«ïâì ᣥ­¥à¨à®¢ ­­ë©  áᥬ¡«¥à᪨© ä ©«
+**2al_¢ë¢®¤¨âì ­®¬¥p  áâப ¢  áᥬ¡«¨p®¢ ­­­®¬ ä ©«¥
+**2ar_¢ë¢®¤¨âì ¨­ä®p¬ æ¨î ® ᯨ᪥ § ­ïâëå/®á¢®¡®¦¤¥­­ëå p¥£¨áâp®¢ ¢  áᥬ¡«¥p᪨© ä ©«
+**2at_¢ë¢®¤¨âì ¨­ä®p¬ æ¨î ® ᯨ᪥ § ­ïâëå/®á¢®¡®¦¤¥­­ëå ¢p¥¬¥­­ëå ¯¥p¥¬¥­­ëå ¢  áᥬ¡«¥p᪨© ä ©«
+**1b_£¥­¥p¨p®¢ âì ¨­ä®p¬ æ¨î ¤«ï ¡p y§¥p  (IDE)
+**2bl_â ª¦¥ £¥­¥p¨p¨âì ¨­ä®p¬ æ¨î ® «®ª «ì­ëå ᨬ¢®« å
+**1B_¯¥p¥ª®¬¯¨«¨p®¢ âì ¢á¥ ¬®¤y«¨
+**1C<x>_®¯æ¨¨ £¥­¥p â®p  ª®¤ 
+3*2CD_â ª¦¥ ᮧ¤ âì ¤¨­ ¬¨ç¥áªyî ¡¨¡«¨®â¥ªy (­¥ ¯®¤¤¥p¦¨¢ ¥âáï)
+**2Ch<n>_<n> ¡ ©â ªyç¨ (¬¥¦¤ã 1023 ¨ 67107840)
+**2Ci_¯p®¢¥pª  ¢¢®¤ -¢ë¢®¤ 
+**2Cn_¯p®¯yáâ¨âì áâ ¤¨î «¨­ª®¢ª¨ ¬®¤y«ï
+**2Co_¯p®¢¥pïâì ¯¥à¥¯®«­¥­¨¥ ¢ 楫®ç¨á«¥­­ëå ®¯¥à æ¨ïå
+**2Cr_¯p®¢¥pª  ¤¨ ¯ §®­ 
+**2Cs<n>_yáâ ­®¢¨âì p §¬¥p á⥪  ¤® <n>
+**2Ct_¯à®¢¥àª  á⥪ 
+3*2CX_â ª¦¥ ᮧ¤ âì smartlink ¢¥pá¨î
+**1d<x>_®¯p¥¤¥«¨âì ᨬ¢®« <x>
+*O1D_ᮧ¤ âì DEF-ä ©«
+*O2Dd<x>_yáâ ­®¢¨âì ®¯¨á ­¨¥ ¢ <x>
+*O2Dw_PM ¯à¨«®¦¥­¨¥
+**1e<x>_yáâ ­®¢¨âì ¯yâì ¤«ï ¨á¯®«­ï¥¬ëå ä ©«®¢
+**1E_⮦¥, çâ® ¨ -Cn
+**1F<x>_yáâ ­®¢¨âì ¨¬¥­  ä ©«®¢ ¨ ¯ãâ¨
+**2FD<x>_yáâ ­®¢¨âì ¯y⨠¤® ª â «®£®¢, £¤¥ ¨áª âì ã⨫¨âë
+**2Fe<x>_¯¥p¥­ ¯p ¢¨âì ¢ë¢®¤ ®è¨¡®ª ¢ <x>
+**2Fi<x>_¤®¡ ¢¨âì <x> ª ¯yâï¬ ¤® ¢ª«îç ¥¬ëå ä ©«®¢
+**2Fl<x>_¤®¡ ¢¨âì <x> ª ¯yâï¬ ¤® ä ©«®¢ ¡¨¡«¨®â¥ª
+*L2FL<x>_¨á¯®«ì§®¢ âì <x> ª ª ¤¨­ ¬¨ç¥áª¨© ª®¬¯®­®¢é¨ª
+**2Fo<x>_¤®¡ ¢¨âì <x> ª ¯yâï¬ ¤® ®¡ê¥ªâ­ëå ä ©«®¢
+**2Fr<x>_§ £py§¨âì ä ©« á®®¡é¥­¨© ®¡ ®è¨¡ª å <x>
+**2Fu<x>_¤®¡ ¢¨âì <x> ª ¯ã⨠¤® ¬®¤ã«¥©
+**2FU<x>_yáâ ­®¢¨âì ¯yâì ¤® ¬®¤y«¥© ª ª <x>, ®â¬¥­ï¥â -FE
+*g1g_ᮧ¤ ¢ âì ¨­ä®à¬ æ¨î ¤«ï ®â« ¤ç¨ª 
+*g2gg_¨á¯®«ì§®¢ âì GSYM
+*g2gd_¨á¯®«ì§®¢ âì DBX
+*g2gh_¨á¯®«ì§®¢ âì ¬®¤y«ì á«¥¦¥­¨ï §  ªã祩 (¤«ï ®â« ¤ª¨ yâ¥ç¥ª ¯ ¬ïâ¨)
+*g2gl_¨á¯®«ì§®¢ âì «¨­¨¨ ¢ ¨­ä®p¬ æ¨®­­®¬ ¬®¤y«¥ ¤«ï ¡®«ì襩 ¨­ä®p¬ æ¨¨ ¯p¨ ®â« ¤ª¥
+*g2gc_£¥­¥à¨à®¢ âì ¯à®¢¥àª¨ ¤«ï 㪠§ â¥«¥©
+**1i_¨­ä®p¬ æ¨ï
+**2iD_¢®§¢p é ¥â ¤ ây ª®¬¯¨«ïâ®p 
+**2iV_¢®§p é ¥â ¢¥pá¨î ª®¬¯¨«ïâ®à 
+**2iSO_¢®§¢p é ¥â ⨯ OS, ­  ª®â®p®© ¡ë« ᮧ¤ ­  ¯p®£p ¬¬ 
+**2iSP_¢®§¢p é ¥â ⨯ ¯p®æ¥áá®p , ­  ª®â®p®¬ ¡ë«  ᮧ¤ ­  ¯p®£p ¬¬ 
+**2iTO_¢®§¢p é ¥â ⨯ OS, ¤«ï ª®â®p®© ¡ë«  ᮧ¤ ­  ¯p®£p ¬¬ 
+**2iTP_¢®§¢p é ¥â ⨯ ¯p®æ¥áá®p , ¤«ï ª®â®p®£® ¡ë«  ᮧ¤ ­  ¯p®£p ¬¬ 
+**1I<x>_¤®¡ ¢«ï¥â <x> ¢ ¯y⨠¤® ¢ª«îç ¥¬ëå ä ©«®¢
+**1k<x>_¯p®å®¤ <x> ª®¬¯®­®¢é¨ªy
+**1l_§ ¯¨á뢠âì ¢ ¯p®£p ¬¬y «®£®â¨¯ fpc
+**1n_­¥ ç¨â âì áâ ­¤ pâ­ë© ä ©« ª®­ä¨£ãà æ¨¨
+**1o<x>_¨§¬¥­¨âì ¨¬ï ¯à®£à ¬¬ë, ­  <x>
+**1pg_£¥­¥p æ¨ï ¯à®ä¨«¨àãî饣® ª®¤  ¤«ï GPROF (®¯p¥¤¥«ï¥â FPC_PROFILE)
+*L1P_¨á¯®«ì§®¢ âì ä ©«ë ¢ ¯ ¬ï⨠(pipes) ¢¬¥áâ® ¢à¥¬¥­­ëå ä ©«®¢  áᥬ¡«¥à 
+**1S_ᨭ⠪á¨ç¥áª¨¥ ®¯æ¨¨
+**2S2_ª«îç ¢ª«î祭¨ï ­¥ª®â®pëå p áè¨p¥­¨© Delphi 2
+**2Sc_¯®¤¤¥p¦¨¢ âì ®¯¥à â®àë, ¯®å®¦¨¥ ­  ®¯¥p â®pë ¢ C (*=,+=,/= ¨ -=)
+**2sa_¢ª«îç âì ª®­â஫¨àãî騩 ª®¤
+**2Sd_p¥¦¨¬ Delphi-ᮢ¬¥á⨬®áâ¨
+**2Se<x>_ª®¬¯¨«ïâ®p ®áâ ­ ¢«¨¢ ¥âáï ¯®á«¥ <x> ®è¨¡ª¨ (¯® 㬮«ç ­¨î ¯®á«¥ 1 ®è¨¡ª¨)
+**2Sg_¯®¤¤¥p¦¨¢ âì LABEL ¨ GOTO
+**2Sh_¨á¯®«ì§®¢ âì ANSI áâp®ª¨
+**2Si_¯®¤¤¥p¦¨¢ âì á⨫ì INLINE ï§ëª  C++
+**2Sm_¯®¤¤¥p¦¨¢ âì ¬ ªà®ª®¬ ­¤ë ¯®¤®¡­® C (£«®¡ «ì­®)
+**2So_p¥¦¨¬ TP/BP 7.0 ᮢ¬¥á⨬®áâ¨
+**2Sp_p¥¦¨¬ GPC ᮢ¬¥á⨬®áâ¨
+**2Ss_ª®­áâpyªâ®p ¤®«¦¥­ ¨¬¥âì ¨¬ï init (¤¥áâpyªâ®p ¤®«¦¥­ ¨¬¥âì ¨¬ï done)
+**2St_¯®¤¤¥p¦ª  áâ â¨ç¥áª¨å ª«î祢ëå á«®¢ ¢ ®¡ê¥ªâ å
+**1s_­¥ ¢ë§ë¢ âì  áᥬ¡«¥à ¨ ª®¬¯®­®¢é¨ª ¯p¨ p ¡®â¥ (⮫쪮 á -a)
+**1u<x>_y¤ «ï¥â ®¯p¥¤¥«¥­¨¥ ᨬ¢®«  <x>
+**1U_®¯æ¨¨ ¬®¤y«¥©
+**2Un_­¥ ¯p®¢¥pïâì ᮮ⢥âá⢨¥ ¨¬¥­¨ ¬®¤y«ï ¨ ¨¬¥­¨ ä ©«  ¬®¤y«ï
+**2Us_᪮¬¯¨«¨p®¢ âì £« ¢­ë© ¬®¤y«ì (system)
+**1v<x>_¯®¤p®¡­®áâì <x> íâ® ª®¬¡¨­ æ¨ï á«¥¤yîé¨å ᨬ¢®«®¢:
+**2*_e : ‚ᥠ®è¨¡ª¨ (¯® 㬮«ç ­¨î) d: ˆ­ä®à¬ æ¨ï ¤«ï ®â« ¤ª¨
+**2*_w : ।ã¯à¥¦¤¥­¨ï u: ˆ­ä®à¬ æ¨î ¬®¤ã«ï
+**2*_n : ਬ¥ç ­¨ï t: ஡®¢ ­­ë¥/¨á¯®«ì§®¢ ­­ë¥ ä ©«ë
+**2*_h : ®¤áª §ª¨ m: Ž¯à¥¤¥«¥­­ë¥ ¬ ªà®ª®¬ ­¤ë
+**2*_i : Ž¡é ï ¨­ä®à¬ æ¨ï p: Š®¬¯¨«¨àã¥¬ë¥ ¯à®æ¥¤ãàë
+**2*_l : H®¬¥p  «¨­¨© c: “á«®¢­ë¥ ¢ëà ¦¥­¨ï
+**2*_a : ‚ᥠ¯®ª §ë¢ âì 0: H¨ç¥£® ­¥ á®®¡é âì, ªp®¬¥ ®è¨¡®ª
+**2*_b : ®ª § âì ¢áî ¯p®æ¥¤ypy, r: Rhide/GCC ०¨¬ ᮢ¬¥á⨬®áâ¨
+**2*_ ¥á«¨ ®è¨¡ª  ¯p®¨á室¨â x: ˆ­ä®à¬ æ¨ï ® ä ©«¥ (⮫쪮 Win32)
+**2*_ ¨¬¥­­® ¢ ­¥©
+**1X_®¯æ¨¨ ¢ë¯®«­¥­¨ï
+*L2Xc_«¨­ª®¢ âì á ¡¨¡«¨®â¥ª®© ï§ëª  C
+**2Xs_®ç¨áâ¨âì ¢á¥ á¨¬¢®«ì­ë¥ ¨¬¥­  ¨§ ¯p®£p ¬¬ë
+**2XD_«¨­ª®¢ âì ¤¨­ ¬¨ç¥áª¨¥ ¡¨¡«¨®â¥ª¨ (®¯p¥¤¥«ï¥â FPC_LINK_DYNAMIC)
+**2XS_«¨­ª®¢ âì áâ â¨ç¥áª¨¥ ¡¨¡«¨®â¥ª¨ (®¯p¥¤¥«ï¥â FPC_LINK_STATIC)
+**2XX_«¨­ª®¢ âì smart-¡¨¡«¨®â¥ª¨ (®¯p¥¤¥«ï¥â FPC_LINK_SMART)
+**0*_Ž¯æ¨¨ ᯥæ¨ä¨ç­ë¥ ¤«ï ¯p®æ¥áá®p®¢:
+3*1A<x>_ä®à¬ â ¢ë¢®¤ 
+3*2Aas_ä ©«, ¨á¯®«ì§ãî騩 GNU
+3*2Aasaout_ä ©«, ¨á¯®«ì§ãî騩 GNU for aout (Go32v1)
+3*2Anasmcoff_coff (Go32v2) ä ©«, ¨á¯®«ì§ãî騩 Nasm
+3*2Anasmelf_elf32 (Linux) ä ©«, ¨á¯®«ì§ãî騩 Nasm
+3*2Anasmobj_obj ä ©«, ¨á¯®«ì§ãî騩 Nasm
+3*2Amasm_obj ¨á¯®«ì§yî騩 Masm (Microsoft)
+3*2Atasm_obj ¨á¯®«ì§yî騩 Tasm (Borland)
+3*2Acoff_coff (Go32v2) ¨á¯®«ì§ãï ¢áâ஥­­ë©  áᥬ¡«¥à
+3*2Apecoff_pecoff (Win32) ¨á¯®«ì§ãï ¢áâ஥­­ë©  áᥬ¡«¥à
+3*1R<x>_á⨫ì ç⥭¨ï  áᥬ¡«¥p 
+3*2Ratt_ç¨â âì ª ª  áᥬ¡«¥à ¢ á⨫¥ AT&T
+3*2Rintel_ç¨â âì ª ª  áᥬ¡«¥à ¢ á⨫¥ Intel
+3*2Rdirect_⥪áâ  áᥬ¡«¥à  ¯¥p¥¤ ¢ âì ­¥¯®á।á⢥­­®  áᥬ¡«¥ày
+3*1O<x>_â¨¯ë ®¯â¨¬¨§ æ¨©
+3*2Og_£¥­¥p¨p®¢ âì ¬¥­ì訩 ª®¤
+3*2OG_£¥­¥p¨p®¢ âì ¡ëáâpë© ª®¤ (¯® y¬®«ç ­¨î)
+3*2Or_á®åp ­ïâì ­¥ª®â®àë¥ ¯¥à¥¬¥­­ë¥ ¢ ॣ¨áâp å
+3*2Ou_¢ª«îç¨âì ­¥®¯à¥¤¥«¥­­ë¥ ®¯â¨¬¨§ æ¨¨ (á¬. ¤®ªã¬¥­â æ¨î)
+3*2O1_yp®¢¥­ì 1 ®¯â¨¬¨§ æ¨¨ (¡ëáâàë¥ ®¯â¨¬¨§ æ¨¨)
+3*2O2_yp®¢¥­ì 2 ®¯â¨¬¨§ æ¨¨ (-O1 + ¡®«¥¥ ¬¥¤«¥­­ë¥ ®¯â¨¬¨§ æ¨¨)
+3*2O3_yp®¢¥­ì 3 ®¯â¨¬¨§ æ¨¨ (â®â ¦¥ á ¬ë© ª ª -O2u)
+3*2Op_⨯ ¯à®æ¥áá®à , ¤«ï ª®â®p®£® ¯p®¨á室¨â ª®¬¯¨«ïæ¨ï:
+3*3Op1_¤«ï ¯à®æ¥áá®à  386/486
+3*3Op2_¤«ï ¯à®æ¥áá®à Pentium/PentiumMMX (tm)
+3*3Op3_¯à®æ¥áá®à Pentium PRO/Pentium II/Cyrix 6X86/AMD K6 (tm)
+3*1T<x>_⨯ ®¯¥à æ¨®­­ ï á¨á⥬ë, ¤«ï ª®â®p®© ¯p®¨á室¨â ª®¬¯¨«ïæ¨ï:
+3*2TGO32V2_version 2 (DJ Delorie à áè¨à¨â¥«ì DOS)
+3*2TLINUX_Linux
+3*2TOS2_OS/2 / eComStation
+3*2TWIN32_Windows 32 Bit
+3*1W<x>_Win32 ®¯æ¨¨
+3*1WB<x>_ “áâ ­®¢ª  Image ¡ §ë ¢ è¥áâ­ ¤æ¥â¨à¨ç­®¥ <x> §­ ç¥­¨¥
+3*1WC_ Ž¯à¥¤¥«¨âì, çâ® íâ® ¡ã¤¥â ª®­á®«ì­®¥ ¯à¨«®¦¥­¨¥
+3*1WD_ ˆá¯®«ì§®¢ âì DEFFILE ¤«ï íªá¯®àâ¨à®¢ ­­ëå ä㭪権 DLL ¨«¨ EXE
+3*1WG_ Ž¯à¥¤¥«¨âì, çâ® íâ® ¡ã¤¥â GUI ¯à¨«®¦¥­¨¥
+3*1WN_ ¥ £¥­¥à¨à®¢ âì ¯¥à¥¬¥é ¥¬ë© ª®¤ (­¥®¡å®¤¨¬® ¤«ï ®â« ¤ª¨)
+3*1WR_ ƒ¥­¥à¨à®¢ âì ¯¥à¥¬¥é ¥¬ë© ª®¤
+6*1A<x>_ä®à¬ â  áᥬ¡«¥p 
+6*2Ao_Unix o-ä ©«, ¨á¯®«ì§ãî騩 GNU  áᥬ¡«¥p
+6*2Agas_GNU  áᥬ¡«¥à ä¨à¬ë Motorola
+6*2Amit_MIT ᨭ⠪á¨á (áâ àë© GAS)
+6*2Amot_áâ ­¤ pâ­ë©  áᥬ¡«¥p ä¨à¬ë Motorola
+6*1O_®¯â¨¬¨§ æ¨¨
+6*2Oa_¢ª«î砥⠮¯â¨¬¨§ â®p
+6*2Og_£¥­¥p¨p®¢ âì ¬¥­ì訩 ª®¤
+6*2OG_£¥­¥p¨p®¢ âì ¡ëáâpë© ª®¤ (¯® 㬮«ç ­¨î)
+6*2Ox_¬ ªá¨¬ «ì­ ï ®¯â¨¬¨§ æ¨ï (¥áâì ®è¨¡ª¨!)
+6*2O2_¤«ï ¯à®æ¥áá®à  MC68020+
+6*1R<x>_á⨫ì ç⥭¨ï  áᥬ¡«¥p 
+6*2RMOT_ç¨â âì ª ª Motorola- áᥬ¡«¥p
+6*1T<x>_®¯¥à æ¨®­­ ï á¨á⥬  ¤«ï ª®â®p®© ª®¬¯¨«¨py¥âáï ä ©«
+6*2TAMIGA_Commodore ‚Œ ä¨à¬ë Commodore
+6*2TATARI_Atari ST/STe/TT
+6*2TMACOS_Macintosh m68k
+6*2TLINUX_Linux-68k
+**1*_
+**1?_¯®ª § âì íây á¯à ¢ªy
+**1h_¯®ª § âì íây á¯à ¢ªy, ¡¥§ ®¦¨¤ ­¨ï <enter>
+]
+#
+# The End
diff --git a/compiler/msg/errorrw.msg b/compiler/msg/errorrw.msg
new file mode 100644
index 0000000000..ebbdeddbc0
--- /dev/null
+++ b/compiler/msg/errorrw.msg
@@ -0,0 +1,2015 @@
+#
+# $Id: errorr.msg 1.21 2002/01/21 00:00:02 Michail A.Baikov (xakep@gamedot.ru)
+# Ýòîò ôàéë - ÷àñòü ïðîãðàììíîãî ïðîäóêòà Free Pascal Compiler
+# Copyright (c) 1999-2002 by Free Pascal Development Team
+#
+# Ðyññêèé ôàéë (Windows CP1251) ñîîáùåíèé äëÿ Free Pascal Compiler
+#
+# Ñì. ôàéë COPYING.FPC, âêëþ÷åííûé â ýòy ïîñòàâêy,
+# ïî âñåì âîïðîñàì îòíîñèòåëüíî àâòîðñêîãî ïðàâà.
+#
+# Ýòà ïðîãðàììà ðàñïðîñòpàíÿåòñÿ ñ íàäåæäîé, ÷òî îíà áóäåò êîìy-íèáóäü
+# ïîëåçíà, íî ÁÅÇ ÂÑßÊÎÉ ÃÀÐÀÍÒÈÈ! Ìû íå ãàðàíòèðóåì, ÷òî ïðîãðàììà äàæå
+# ñîîòâåòñòâóåò ñâîåé öåëè!
+#
+#
+# Êîíñòàíòû - îáîçíà÷åíèÿ, ïèøóòñÿ â ñëåäyþùåì âèäå:
+# <part>_<type>_<txtidentifier>
+#
+# <part> ýòî òà ÷àñòü êîìïèëÿòîðà, êîòîðàÿ ñîîáùàåò îá îøèáêå:
+# asmr_ ñèíòàêñè÷åñêèé àíàëèç àññåìáëåðà (÷òåíèå àññåìáëåðà)
+# asmw_ ñèíòàêñè÷åñêèé àíàëèç àññåìáëåðà (çàïèñü îáüåêòíûõ ôàéëîâ)
+
+# unit_ îáðàáîòêà ìîäóëÿ
+# scan_ ñêàíåð
+# parser_ ñèíòàêñè÷åñêèé àíàëèçàòîð
+# type_ êîíòðîëü ñîîòâåòñòâèÿ òèïîâ
+# general_ îáùàÿ èíôîðìàöèÿ
+# exec_ âûçîâû àññåìáëåðà, êîìïîíîâùèêà, ðåäàêòîðà
+#
+# <type> òèï ñîîáùåíèÿ:
+# f_ ôàòàëüíàÿ îøèáêà
+# e_ îøèáêà
+# w_ ïðåäóïðåæäåíèå
+# n_ ïðèìå÷àíèå
+# h_ ïîäñêàçêà
+# i_ èíôîðìàöèÿ
+# l_ íîìåp ñòpîêè
+# u_ èñïîëüçîâàíèå
+# t_ ïîïûòêà èñïîëüçîâàòü
+# m_ ìàêðîêîìàíäà
+# p_ ïðîöåäóðà
+# c_ óñëîâíîå âûðàæåíèå
+# d_ ñîîáùåíèå äëÿ îòëàäêè
+# b_ îòîáðàæàåò ïåðåãðóæåííûå ïðîöåäóðû è ôóíêöèè
+# x_ èíôîðìàöèÿ äëÿ èñïîëíÿåìûõ ôàéëîâ
+#
+
+#
+# Îáùåå
+#
+# 01016 ïîñëåäíèé íîìåð èñïîëüçîâàííîãî ñîîáùåíèÿ
+#
+# BeginOfTeX
+% \section{Îáùèå ñîîáùåíèÿ êîìïèëÿòîðà}
+% Ýòîò ðàçäåë äàåò ñîîáùåíèÿ êîìïèëÿòîðà, êîòîðûå íå ôàòàëüíû, íî êîòîðûå
+% îòîáðàæàþò ïîëåçíóþ èíôîðìàöèþ. ×èñëî òàêèõ ñîîáùåíèé ìîæåò áûòü
+% óïðàâëÿåìûì ñ ðàçëè÷íûìè íàñòpîéêàìè ypîâíÿ \var{-v} ëîãèëèpîâàíèÿ.
+% \begin {îïèñàíèå}
+general_t_compilername=01000_T_Êîìïèëÿòîp: $1
+% Êîãäà \var{-vt} êëþ÷ èñïîëüçóåòñÿ, ýòà ñòðîêà, ñîîáùàåò âàì, êàêîé
+% êîìïèëÿòîð èñïîëüçóåòñÿ.
+general_d_sourceos=01001_D_Êîìïèëèðóåòñÿ íà OS: $1
+% Êîãäà \var{-vd} êëþ÷ èñïîëüçóåòñÿ, ýòà ñòðîêà, ñîîáùàåò âàì, â êàêîé
+% îïåðàöèîííîé ñèñòåìå, ñîçäàåòñÿ ôàéë.
+general_i_targetos=01002_I_Ñîçäàåòñÿ äëÿ OS: $1
+% Êîãäà \var{-vd} êëþ÷ èñïîëüçóåòñÿ, ýòà ñòðîêà, ñîîáùàåò âàì, äëÿ êàêîé
+% îïåðàöèîííîé ñèñòåìû ñîçäàåòñÿ ôàéë
+general_t_exepath=01003_T_Èñïîëüçyåì ïyòü äëÿ áèíàpíûõ ôàéëîâ: $1
+% Êîãäà \var{-vt} êëþ÷ èñïîëüçóåòñÿ, ýòà ñòðîêà, ñîîáùàåò âàì,
+% ãäå êîìïèëÿòîðà èùåò áèíàpíûå ôàéëû.
+general_t_unitpath=01004_T_Èñïîëüçyåì ïóòü äî ìîäóëåé: $1
+% Êîãäà \var{-vt} êëþ÷ èñïîëüçóåòñÿ, ýòà ñòðîêà, ñîîáùàåò âàì,
+% ãäå êîìïèëÿòîð èùåò êîìïèëèðóåìûå ìîäóëè. Âû ìîæåòå óñòàíàâëèâàòü ýòîò ïóòü
+% ÷åpåç \var{-Fu} èëè \var{-Up} îïöèè.
+general_t_includepath=01005_T_Èñïîëüçyåì ïyòü äëÿ âêëþ÷àåìûõ ôàéëîâ: $1
+% Êîãäà \var{-vt} êëþ÷ èñïîëüçóåòñÿ, ýòà ñòðîêà, ñîîáùàåò âàì, ãäå
+% êîìïèëÿòîð èùåò ôàéëû äëÿ âêëþ÷åíèÿ (ôàéëû, èñïîëüçóåìûå â \var{\{\$I xxx\}}
+% âûpàæåíèÿõ). Âû ìîæåòå óñòàíàâëèâàòü ýòîò ïóòü ÷åpåç \var{-I} îïöèþ.
+general_t_librarypath=01006_T_Èñïîëüçyåì ïyòü äî áèáëèîòåê: $1
+% Êîãäà \var{-vt} êëþ÷ èñïîëüçóåòñÿ, ýòà ñòðîêà, ñîîáùàåò âàì, ãäå
+% êîìïèëÿòîð èùåò áèáëèîòåêè. Âû ìîæåòå óñòàíàâëèâàòü ýòîò ïóòü ÷åpåç
+% \var{-Fl} îïöèþ.
+general_t_objectpath=01007_T_Èñïîëüçyåì ïyòü äî îáúåêòíûõ ôàéëîâ: $1
+% Êîãäà \var{-vt} êëþ÷ èñïîëüçóåòñÿ, ýòà ñòðîêà, ñîîáùàåò âàì, ãäå
+% êîìïèëÿòîð èùåò îáúåêòíûå ôàéëû, Âû ñâÿçûâàåòå â (ôàéëû,
+% èñïîëüçóþòñÿ â \var{\{\$L xxx \}} âûpàæåíèÿõ).
+% Âû ìîæåòå óñòàíàâëèâàòü ýòîò ïóòü ÷åpåç \var{-Fo} îïöèþ.
+general_i_abslines_compiled=01008_I_$1 ëèíèé ñêîìïèëèpîâàííî, $2 ñåê.
+% Êîãäà \var{-vi} êëþ÷ èñïîëüçóåòñÿ, êîìïèëÿòîð, ñîîáùàåò ÷èñëî
+% ñêîìïèëèpîâàííûõ ñòðîê, è âðåìåíè, êîòîðîå ïîòpåáîâàëîñü äëÿ ýòîãî.
+% (ðåàëüíîå âðåìÿ, íå ïðîãðàììèpyåìîå âðåìÿ).
+general_f_no_memory_left=01009_F_Håò ñâîáîäíîé ïàìÿòè
+% Êîìïèëÿòîð íå èìååò äîñòàòî÷íî ïàìÿòè, ÷òîáû êîìïèëèðîâàòü âàøó ïðîãðàììó.
+% Èìååòñÿ íåñêîëüêî påêîìåíäàöèé äëÿ påøåíèÿ ýòîãî âîïpîñà:
+% \begin{itemsize}
+% \item Åñëè âû èñïîëüçóåòå ôîðìèðóþùóþñÿ îïöèþ êîìïèëÿòîðà, ïðîáóéòå
+% êîìïèëèðîâàòü ðàçëè÷íûå ìîäóëè âðó÷íóþ.
+% \item Åñëè âû êîìïèëèðóåòå, îãðîìíyþ ïðîãðàììy, ðàçáèâàéòå åå íà ìîäóëè, è
+% êîìïèëèðóéòå èõ îòäåëüíî.
+% \item Åñëè ïðåäûäóùèå äâà ïyíêòà íå ðàáîòàþò, ïåðåòðàíñëèðyéòå êîìïèëÿòîð
+% ñ áîëüøèì pàçìåpîì êy÷è (âû ìîæåòå èñïîëüçîâàòü \var{-Ch} îïöèþ äëÿ ýòîãî, \seeo{Ch})
+% \end {itemsize}
+% \end {îïèñàíèå}
+general_i_writingresourcefile=01010_I_Çàïèñûâàåì ôàéë-òàáëèöy ñòpîêîâûõ påñypñîâ: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Îøèáêà ïpè çàïèñè ôàéëà-òàáëèöû ñòpîêîâûõ påñypñîâ: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Warning:
+% Prefix for Warnings
+general_i_note=01015_I_Note:
+% Prefix for Notes
+general_i_hint=01016_I_Hint:
+% Prefix for Hints
+
+% \end{description}
+
+
+#
+# Ñêàíåð
+#
+% \section {Ñîîáùåíèÿ ñêàíåðà.}
+% Ýòîò ðàçäåë ïåðå÷èñëÿåò ñîîáùåíèÿ, êîòîpûå âûäàåò ñêàíåð. Ñêàíåð áåðåò çàáîòó
+% î ëåêñè÷åñêîé ñòðóêòóðå ôàéëà Free Pascal, òî åñòü îí ïpîáyåò íàõîäèòü
+% çàðåçåðâèðîâàííûå ñëîâà, ñòðîêè, è ò.ä. Îí òàêæå çàáîòèòñÿ î äèðåêòèâàõ è
+% óñëîâíûõ âûðàæåíèÿõ âëèÿþùèå íà îápàáîòêy ïpîãpàììû êîìïèëÿòîpîì.
+% \begin {îïèñàíèå}
+scan_f_end_of_file=02000_F_Håîæèäàííûé êîíåö ôàéëà
+% Ýòî îáû÷íî ñëó÷àåòñÿ â ñëåäóþùèõ ñëó÷àÿõ:
+% \begin{itemsize}
+% \item Èñõîäíûé ôàéë çàêàí÷èâàåòñÿ äî ïîñëåäíåãî \var{end} âûpàæåíèÿ.
+% Ýòî ñëó÷àåòñÿ îáû÷íî, êîãäà \var{begin} è \var{end} âûpàæåíèÿ íå
+% ñáàëàíñèðîâàííûé (íå îäèíàêîâîå êîëè÷åñòâî);
+% \item Âêëþ÷àåìûé ôàéë çàêàí÷èâàåòñÿ â ñåðåäèíå âûpàæåíèÿ.
+% \item Êîììåíòàðèé íå áûë çàêðûò (ôèãypíîé ñêîáêîé èëè åùå êàê)
+% \end{itemsize}
+scan_f_string_exceeds_line=02001_F_Håâîçìîæíî íàéòè êîíåö ñòpîêè
+% Âû, âîçìîæíî, çàáûëè âêëþ÷èòü çàêðûòèå ' ñòpîêè, òàê ÷òî ñòpîêà çàíèìàåò
+% íåñêîëüêî ëèíèé êîäà (ñòpîê).
+scan_f_illegal_char=02002_F_Çàïpåùåííûé ñèìâîë "$1" ($2)
+% Ñêàíåp ñòîëêíyëñÿ ñ çàïðåùåííûì ñèìâîëîì âî âõîäíîì ôàéëå.
+scan_f_syn_expected=02003_F_Ñèíòàêñè÷åñêàÿ îøèáêà: îæèäàåòñÿ "$1", íî íàøëè "$2"
+% Ýòî óêàçûâàåò, ÷òî êîìïèëÿòîð îæèäàë äpyãyþ ëåêñåìó (èëè ìàðêåð) ÷åì
+% òîò, êîòîðûé âû íàïå÷àòàëè. Ýòî ìîæåò ïðîèñõîäèòü ïî÷òè âñþäó, ãäå
+% Âû ïèøèòå íå ïî çàêîíàì ÿçûêà Ïàñêàëü.
+scan_t_start_include_file=02004_T_Hà÷èíàþ ÷òåíèå âêëþ÷àåìîãî ôàéëà $1
+% Êîãäà Âû îáåñïå÷èâàåòå \var{-vt} êëþ÷, êîìïèëÿòîð, ñîîáùàåò Âàì
+% êîãäà îí íà÷èíàåò ÷èòàòü âêëþ÷àåìûé ôàéë.
+scan_w_comment_level=02005_W_Hàéäåí $1 ypîâåíü êîììåíòàpèÿ
+% Êîãäà \var{-vw} êëþ÷ èñïîëüçóåòñÿ, òî êîìïèëÿòîð ïðåäóïðåæäàåò Âàñ,
+% åñëè îí íàõîäèò âëîæåííûå êîììåíòàðèè. Âëîæåííûå êîììåíòàðèè íå ïîçâîëÿþòñÿ â
+% Turbo Pascal è ýòî ìîæåò áûòü èñòî÷íèêîì îøèáîê.
+scan_n_far_directive_ignored=02006_N_$F äèðåêòèâà (FAR) èãíîðèðóåòñÿ
+% \var{FAR} äèðåêòèâà ýòî 16-ðàçðÿäíàÿ êîíñòðóêöèÿ, êîòîðàÿ ÿâëÿåòñÿ
+% ïîääåpæèâàåìîé, íî èãíîðèðóåìàÿ êîìïèëÿòîðîì, òàê êàê îí ïðîèçâîäèò
+% 32 ðàçðÿäíûõ êîä.
+scan_n_stack_check_global_under_linux=02007_N_Linux ïpîâåpÿåò ñòåê àâòîìàòè÷åñêè
+% Ïðîâåðêà ñòåêà ñ \var{-Cs} êëþ÷ èãíîðèðóåòñÿ ïîä \linux, òàê êàê
+% \linux äåëàåò ýòî çà Âàñ. Îòîápàæàåòñÿ òîëüêî, êîãäà \var{-vn} èñïîëüçóåòñÿ.
+scan_n_ignored_switch=02008_N_Èãíîpèpyåìûé êîìïèëÿòîðîì êëþ÷ $1
+% Ñ âêëþ÷åííûì \var{-vn}, êîìïèëÿòîð ïðåäóïðåæäàåò, åñëè îí èãíîðèðóåò êëþ÷
+scan_w_illegal_switch=02009_W_Håèçâåñòíûé êëþ÷ êîìïèëÿòîpà $1
+% Âû âêëþ÷èëè êëþ÷ êîìïèëÿòîðà (òî åñòü \var{\{\$... \}}) êîòîðûé
+% êîìïèëÿòîð íå çíàåò.
+scan_w_switch_is_global=02010_W_Ýòîò êëþ÷ êîìïèëÿòîðà èìååò ãëîáàëüíûé ñòàòyñ
+% Êîãäà \var{-vw} èñïîëüçóåòñÿ, êîìïèëÿòîð ïðåäóïðåæäàåò, åñëè êëþ÷ ãëîáàëåí.
+scan_e_illegal_char_const=02011_E_Håèçâåñòíûé ñèìâîë â êîíñòàíòå
+% Ýòî ñëó÷àåòñÿ, êîãäà Âû îïðåäåëÿåòå ñèìâîë ñ êîäîì ASCII, ïîñêîëüêó â
+% \var{\#96}, íî íîìåð ÿâëÿåòñÿ èëè çàïðåùåííûì, èëè âíå äèàïàçîíà.
+% Äèàïàçîí - 1-255.
+scan_f_cannot_open_input=02012_F_Hå ìîãy îòêpûòü ôàéë $1
+% \fpc íå ìîæåò íàéòè ïðîãðàììó èëè èñõîäíûé ôàéë ìîäóëÿ, êîòîðûé Âû
+% îïðåäåëèëè â êîìàíäíîé ñòðîêå.
+scan_f_cannot_open_includefile=02013_F_Hå ìîãy îòêpûòü âêëþ÷àåìûé ôàéë $1
+% \fpc íå ìîæåò íàéòè èñõîäíûé ôàéë, êîòîpûé âû îïðåäåëèëè â \var{\{\$include \}}
+% âûpàæåíèè.
+scan_e_too_much_endifs=02014_E_Ñëèøêîì ìíîãî $ENDIF èëè $ELSE äèpåêòèâ
+% Âàø \var{\{\$IFDEF.. \}} è {\{\$ENDIF} \}} âûpàæåíèÿ íå èìåþò îäèíàêîâîå êîë-âî.
+scan_w_only_pack_records=02015_W_Record ïîëÿ ìîãyò âûðàâíèâàòüñÿ òîëüêî ê 1,2,4 èëè 16 áàéòàì
+% Âû îïðåäåëÿåòå \var{\{\$PACKRECORDS n\} } ñ çàïðåùåííûì çíà÷åíèåì äëÿ
+% \var{n}. Òîëüêî 1,2,4 èëè 16 äîïóñòèìî â ýòîì ñëó÷àå.
+scan_w_only_pack_enum=02016_W_Ïåpå÷èñëåíèÿ ìîãyò áûòü ñîõðàíåíû òîëüêî â 1,2 èëè 4 áàéòàõ
+% Âû îïðåäåëÿåòå \var{\{\$PACKENUM n \}} ñ çàïðåùåííûì çíà÷åíèåì äëÿ
+% \var {n}. Òîëüêî 1,2 èëè 4 äîïóñòèìî â ýòîì ñëó÷àå.
+scan_e_endif_expected=02017_E_$1 îæèäàåòñÿ äëÿ $2 îïðåäåëåíèÿ â ñòðîêå $3
+% Âàøè óñëîâíûå óòâåðæäåíèÿ òðàíñëÿöèè íåñáàëàíñèðîâàííû.
+scan_e_preproc_syntax_error=02018_E_Ñèíòàêñè÷åñêàÿ îøèáêà ïðè àíàëèçå âûðàæåíèÿ äëÿ êîìïèëÿòîpà
+% Â óñëîâíîì âûðàæåíèè èìååòñÿ îøèáêà ïîñëå \var{\{\$if \}} äèðåêòèâû êîìïèëÿòîðà.
+scan_e_error_in_preproc_expr=02019_E_Îøèáêà â pàñ÷åòå âûðàæåíèÿ ïpåïpîöåññîpà äëÿ êîìïèëèðîâàíèÿ
+% Â óñëîâíîì âûðàæåíèè èìååòñÿ îøèáêà ïîñëå \var{\{\$if \}} äèðåêòèâû êîìïèëÿòîðà.
+scan_w_macro_cut_after_255_chars=02020_W_Äëÿ pàñ÷åòà âûpàæåíèÿ, äëèíà ìàêpîñà ñîêpàùåíà äî 255 ñèìâîëîâ
+% Âûðàæåíèÿ ñîäåðæàùèå ìàêðîêîìàíäû íå ìîæåò áûòü áîëüøå ÷åì 255 ñèìâîëîâ.
+% Ýòî ÿâëÿåòñÿ ÷àñòüþ áåçîïàñíîñòè â êîìïèëÿòîðå, ýòî ïðåäîòâðàùàåò áóôåðíûå
+% ïåðåïîëíåíèå. Ýòî ïîêàçûâàåòñÿ êàê ïðåäóïðåæäåíèå, òî åñòü
+% êîãäà êëþ÷ \var{-vw} èñïîëüçyåòñÿ.
+scan_e_endif_without_if=02021_E_ENDIF áåç IF{N}DEF
+% Âàø \var{\{\$IFDEF.. \}} è {\ {\$ENDIF \}} óòâåðæäåíèÿ íå ñáàëàíñèðîâàíû.
+scan_f_user_defined=02022_F_Ïîëüçîâàòåëü îïðåäåëèë $1
+% Ïpîèçîøëà îïðåäåëÿåìàÿ ïîëüçîâàòåëåì ôàòàëüíàÿ îøèáêà. Ñì. òàêæå \progref
+scan_e_user_defined=02023_E_Ïîëüçîâàòåëü îïpåäåëèë $1
+% Ïpîèçîøëà îïðåäåëÿåìàÿ ïîëüçîâàòåëåì îøèáêà. Ñì. òàêæå \progref
+scan_w_user_defined=02024_W_Ïîëüçîâàòåëü îïpåäåëèë $1
+% Ïpîèçîøëî îïðåäåëÿåìîå ïîëüçîâàòåëåì ïðåäóïðåæäåíèå. Ñì. òàêæå \progref
+scan_n_user_defined=02025_N_Ïîëüçîâàòåëü îïpåäåëèë $1
+% Ñòîëêíyëèñü ñ îïðåäåëÿåìûì ïîëüçîâàòåëåì ïðèìå÷àíèåì. Ñì. òàêæå \progref
+scan_h_user_defined=02026_H_Ïîëüçîâàòåëü îïpåäåëèë $1
+% Ñòîëêíyëèñü ñ îïðåäåëÿåìîé ïîëüçîâàòåëåì ïîäñêàçêîé. Ñì. òàêæå \progref
+scan_i_user_defined=02027_I_Ïîëüçîâàòåëü îïpåäåëèë $1
+% Ñòîëêíyëèñü ñ îïðåäåëÿåìîé ïîëüçîâàòåëåì ïîäñêàçêîé. Ñì. òàêæå \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Êëþ÷åâîå ñëîâî ïåðåîïðåäåëåíî, ïîñêîëüêó ìàêðîêîìàíäà íå èìååò íèêàêîãî ýôôåêòà
+% Âû íå ìîæåòå ïåðåîïðåäåëÿòü êëþ÷åâûå ñëîâà ñ ìàêðîêîìàíäàìè.
+scan_f_macro_buffer_overflow=02029_F_Áyôåp ìàêpîñîâ ïåðåïîëíåí ïðè ÷òåíèè èëè ðàñøèðåíèè ìàêðîêîìàíäû
+% Âàø ìàêpîñ èëè ðåçóëüòàò, ñëèøêîì äëèíåí äëÿ êîìïèëÿòîðà.
+scan_w_macro_deep_ten=02030_W_Ðàñøèpåíèå ìàêðîêîìàíäû ïðåâûøàåò âîçìîæíûé ypîâåíü (áîëåå 16).
+% Ïðè ðàñøèðåíèè ìàêðîêîìàíäû áûëî èñïîëüçîâàíî áîëåå 16 ypîâíåé âëîæåííîñòè.
+% Êîìïèëÿòîð íå ìîæåò pàñøèpèòü ìàêpîñ, òàê êàê ýòî ìîæåò áûòü çíàê, ÷òî
+% èñïîëüçyåòñÿ ðåêóðñèÿ
+scan_e_wrong_styled_switch=02031_E_Ïåpåêëþ÷àòåëè êîìïèëÿòîpà íå ïîçâîëÿþò èñïîëüçîâàòü (* è *) ñòèëü êîììåíòàpèåâ.
+% Ïåðåêëþ÷àòåëè êîìïèëÿòîðà äîëæíû âñåãäà áûòü ìåæäó \var{\{\ }} ðàçäåëèòåëÿìè êîììåíòàðèÿ.
+scan_d_handling_switch=02032_D_Ïpîâåpÿåì êëþ÷ "$1"
+% Êîãäà Âû âêëþ÷àåòå èíôîðìàöèþ äëÿ îòëàäêè (\var{-vd}), êîìïèëÿòîð ñîîáùàåò
+% âàì, êîãäà îí îöåíèâàåò óñëîâíîå âûðàæåíèå, âëèÿþùåå íà êîìïèëÿöèþ.
+scan_c_endif_found=02033_C_ENDIF $1 íàéäåí
+% Êîãäà Âû âêëþ÷àåòå óñëîâíûå ñîîáùåíèÿ (\var{-vc}), êîìïèëÿòîð ñîîáùàåò âàì
+% ãäå îí ñòàëêèâàåòñÿ ñ óñëîâíûìè óòâåðæäåíèÿìè.
+scan_c_ifdef_found=02034_C_IFDEF $1 íàéäåí, $2
+% Êîãäà Âû âêëþ÷àåòå óñëîâíûå ñîîáùåíèÿ (\var{-vc}), êîìïèëÿòîð, ñîîáùàåò âàì
+% ãäå îí ñòàëêèâàåòñÿ ñ óñëîâíûìè óòâåðæäåíèÿìè.
+scan_c_ifopt_found=02035_C_IFOPT $1 íàéäåí, $2
+% Êîãäà âû âêëþ÷àåòå óñëîâíûå ñîîáùåíèÿ (\var{-vc}), êîìïèëÿòîð, ñîîáùàåò âàì
+% ãäå îí ñòàëêèâàåòñÿ ñ óñëîâíûìè óòâåðæäåíèÿìè.
+scan_c_if_found=02036_C_IF $1 íàéäåí, $2
+% Êîãäà âû âêëþ÷àåòå óñëîâíûå ñîîáùåíèÿ (\var{-vc}), êîìïèëÿòîð, ñîîáùàåò âàì
+% ãäå îí ñòàëêèâàåòñÿ ñ óñëîâíûìè óòâåðæäåíèÿìè.
+scan_c_ifndef_found=02037_C_IFNDEF $1 íàéäåí, $2
+% Êîãäà âû âêëþ÷àåòå óñëîâíûå ñîîáùåíèÿ (\var {-vc}), êîìïèëÿòîð, ñîîáùàåò âàì
+% ãäå îí ñòàëêèâàåòñÿ ñ óñëîâíûìè óòâåðæäåíèÿìè.
+scan_c_else_found=02038_C_ELSE $1 íàéäåí, $2
+% Êîãäà âû âêëþ÷àåòå óñëîâíûå ñîîáùåíèÿ (\var{-vc}), êîìïèëÿòîð, ñîîáùàåò âàì
+% ãäå îí ñòàëêèâàåòñÿ ñ óñëîâíûìè óòâåðæäåíèÿìè.
+scan_c_skipping_until=02039_C_Ïpîïyñêàåì äî ...
+% Êîãäà âû âêëþ÷àåòå óñëîâíûå ñîîáùåíèÿ (\var{-vc}), êîìïèëÿòîð ñîîáùàåò âàì
+% ãäå îí ñòàëêèâàåòñÿ ñ óñëîâíûìè óòâåðæäåíèÿìè, è ïðîïóñêàåò ëè ýòî èëè íåò.
+scan_i_press_enter=02040_I_Hàæìèòå <ENTER>, ÷òîáû ïðîäîëæèòü
+% Êîãäà èñïîëüçyåòñÿ \var{-vi} êëþ÷, êîìïèëÿòîð îñòàíàâëèâàåò
+% òðàíñëÿöèè è æäåò \var{enter} êëàâèøy, êîòîðàÿ áóäåò íàæàòà, êîãäà îí
+% ñòîëêíåòñÿ ñ äèpåêòèâîé \var {\{\$STOP\}}.
+scan_w_unsupported_switch=02041_W_Håïîääåpæèâàåìûé êëþ÷ $1
+% Êîãäà ïpåäyïpåæäåíèÿ âêëþ÷åíû (\var{-vw}), êîìïèëÿòîð ïðåäóïðåæäàåò âàñ
+% îòíîñèòåëüíî íåïîääåðæèâàåìûõ êëþ÷åé. Ýòî îçíà÷àåò ÷òî, êëþ÷ èñïîëüçóåòñÿ
+% â Delphi èëè Turbo Pascal, íî íå â \fpc
+scan_w_illegal_directive=02042_W_Håïpàâèëüíàÿ äèðåêòèâà êîìïèëÿòîðà $1
+% Êîãäà ïpåäyïpåæäåíèÿ âêëþ÷åíû (\var{-vw}), êîìïèëÿòîð ïðåäóïðåæäàåò âàñ
+% îòíîñèòåëüíî íåïðèçíàííûõ äèpåêòèâ. Äëÿ ñïèñêà ðàñïîçíàííûõ äèpåêòèâ, ñì. \progref
+scan_t_back_in=02043_T_Âîçpàùàåìñÿ â $1
+% Êîãäà âû èñïîëüçóåòå (\var{-vt}) êîìïèëÿòîð, ñîîáùàåò âàì, êîãäà îí
+% çàêîí÷èë ÷èòàòü âêëþ÷àåìûé ôàéë.
+scan_w_unsupported_app_type=02044_W_Håïîääåpæèâàåìûé òèï ïpèëîæåíèÿ: $1
+% Âû ïîëó÷àåòå ýòî ïðåäóïðåæäåíèå, êîãäà îïðåäåëÿåòå íåèçâåñòíûé òèï
+% ïðèëîæåíèÿ ñ äèðåêòèâîé $APPTYPE
+scan_w_app_type_not_support=02045_W_$APPTYPE íå ïîääåðæèâàåòñÿ ñèñòåìîé äëÿ êîòîpîé âû êîìïèëèpyåòå ôàéë
+% $APPTYPE äèðåêòèâà îáåñïå÷èâàåòñÿ òîëüêî win32 ïðèëîæåíèÿìè.
+scan_w_description_not_support=02046_W_Òåã DESCRIPTION íå ïîääåðæèâàåòñÿ ñèñòåìîé äëÿ êîòîpîé âû êîìïèëèpyåòå ôàéë
+% Òåã \var{\{\$DESCRIPTION\}} ïîääåðæèâàåòñÿ òîëüêî íà ñèñòåìàõ OS/2 è Win32.
+scan_n_version_not_support=02047_N_Òåã VERSION íå ïîääåðæèâàåòñÿ ñèñòåìîé äëÿ êîòîpîé âû êîìïèëèpyåòå ôàéë
+% Òåã \var{\{\$VERSION\}} ïîääåðæèâàåòñÿ òîëüêî â Win32 ñèñòåìàõ.
+scan_n_only_exe_version=02048_N_Òåã VERSION èñïîëüçóåòñÿ òîëüêî äëÿ .EXE è .DLL èñõîäíèêîâ.
+% Òåã \var{\{\$VERSION\}} èñïîëüçóåòñÿ òîëüêî äëÿ .EXE è .DLL èñõîäíèêîâ.
+scan_w_wrong_version_ignored=02049_W_Íåâåðíûé ôîðìàò äëÿ òåãà VERSION äëÿ äèðåêòèâû $1
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_w_unsupported_asmmode_specifier=02050_W_Håïîääåpæèâàåìûé ñòèëü àññåìáëåpà â $1
+% Êîãäà Âû îïðåäåëÿåòå ðåæèì àññåìáëåðà ñ \var{\{\$ASMMODE xxx\}}
+% êîìïèëÿòîð íå ðàñïîçíàâàë ðåæèì, êîòîðûé Âû òàì yêàçàëè.
+% \end {îïèñàíèå}
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Êëþ÷ àññåìáëåpà: íåâîçìîæíàÿ âíyòpåííÿÿ èíñòpyêöèÿ àññåìáëåpà, $1 áyäåò ýôôåêòèâíà òîëüêî â ñëåäyþùèé pàç
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Håâåpíûé påæèì ïåðåêëþ÷àòåëÿ, èñïîëüçóéòå ON/OFF èëè +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Ôàéëû påñypñîâ íå ïîääåðæèâàåòñÿ ñèñòåìîé äëÿ êîòîpîé âû êîìïèëèpyåòå ôàéë
+% The target you are compiling for doesn't support Resource files. The
+% only target which can use resource files is Win32
+scan_w_include_env_not_found=02054_W_Âêëþ÷àåìàÿ ïåpåìåííàÿ îêpyæåíèÿ $1 íå íàéäåíà â îêpyæåíèè ñèñòåìû
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Íåâåðíîå çíà÷åíèå äëÿ ãðàíèöû ðåãèñòðà ñîïðîöåññîðà
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Äëÿ ýòîé ñèñòåìû ïîääåðæèâàþòñÿ òîëüêî îäèí ôàéë ðåñóðñîâ
+% The target you are compiling for supports only one resource file. This is the
+% case of OS/2 (EMX) currently. The first resource file found is used, the
+% others are discarded.
+scan_w_macro_support_turned_off=02057_W_Ïîääåpæêà ìàêpîñîâ áûëà îòêëþ÷åíà
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_Óêàçàí íåâåðíûé òèï interface. Ïðàâèëüíûå òîëüêî COM, COBRA èëè DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID ïîääåðæèâàåòñÿ òîëüêî äëÿ PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME ïîääåðæèâàåòñÿ òîëüêî äëÿ PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Êîíñòàíòà ñòðîê íå ìîæåò áûòü áîëåå ÷åì 255 ñèìâîëîâ
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+% \end{description}
+
+#
+# Ñèíòàêñè÷åñêèé àíàëèçàòîð
+#
+% \section {ñîîáùåíèÿ ñèíòàêñè÷åñêîãî àíàëèçàòîðà}
+% Ýòîò ðàçäåë ïåðå÷èñëÿåò âñå ñîîáùåíèÿ ñèíòàêñè÷åñêîãî àíàëèçàòîðà.
+% Ñèíòàêñè÷åñêèé àíàëèçàòîð çàáîòèòñÿ î ñåìàíòèêå ÿçûêà, òî åñòü îí
+% îïðåäåëÿåò, ïðàâèëåí ëè âàø Ïàñêàëü.
+% \begin {îïèñàíèå}
+parser_e_syntax_error=03000_E_Ñèíòàêñè÷åñêàÿ îøèáêà (àíàëèçàòîð)
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_w_proc_far_ignored=03001_W_Ïpîöåäypà èìååò òèï FAR - èãíîpèpyåì
+% This is a warning. \var{FAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+parser_w_proc_near_ignored=03002_W_Ïpîöåäypà èìååò òèï NEAR - èãíîpèpyåì
+% This is a warning. \var{NEAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+parser_w_proc_interrupt_ignored=03003_W_Ïðîöåäóðíûé òèï INTERRUPT èãíîðèðóåòñÿ äëÿ íå i386 ïðîöåññîðîâ
+% This is a warning. \var{INTERRUPT} is a i386 specific construct
+% and is ignored for other processors.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT ïðîöåäóðà íå ìîæåò áûòü âëîæåííîé
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Ïðîöåäóðíûé òèï $1 èãíîðèðóåòñÿ
+% This is a warning. \var{REGISTER},\var{REINTRODUCE} is ignored by FPC programs for now.
+% This is introduced first for Delphi compatibility.
+parser_e_no_overload_for_all_procs=03006_E_Íå âñå îïðåäåëåíèÿ $1 îïðåäåëåíû êàê OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_no_dll_file_specified=03007_E_DLL-ôàéë íå yêàçàí
+% No longer in use.
+parser_e_export_name_double=03008_E_Èìÿ ôyíêöèè ýêñïîpòèpyåòñÿ äâàæäû $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Èíäåêñ ôyíêöèè ýêñïîpòèpyåòñÿ äâàæäû $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Håâåpíûé èíäåêñ y ýêñïîpòèpyåìîé ôyíêöèè
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Ïåðåìåùàåìûé DLL/EXE ôàéë $1 îòëàäî÷íóþ èíôîðìàöèþ íå ñîäåðæèò, îòêëþ÷åíî.
+parser_w_parser_win32_debug_needs_WN=03012_W_Äëÿ ïîääåðæêè îòëàäêè Win32-êîäà, âàì íåîáõîäèìî îòêëþ÷àòü ïåðåìåùåíèå ñ îïöèåé -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Êîíñòpyêòîp äîëæåí èìåòü èìÿ INIT
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Äåñòpyêòîp äîëæåí èìåòü èìÿ DONE
+% You are declaring a constructor with a name which isn't \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_illegal_open_parameter=03015_E_Håïpàâèëüíî îôîpìëåííûå 'îòêpûòûå ïàpàìåòpû'
+% You are trying to use the wrong type for an open parameter.
+parser_e_proc_inline_not_supported=03016_E_Ïpîöåäypíûé òèï INLINE íå ïîääåpæèâàåòñÿ
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_priv_meth_not_virtual=03017_W_Private ìåòîäû íå ìîãyò áûòü âèpòyàëüíûìè
+% You declared a method in the private part of a object (class) as
+% \var{virtual}. This is not allowed. Private methods cannot be overridden
+% anyway.
+parser_w_constructor_should_be_public=03018_W_Êîíñòpyêòîp äîëæåí áûòü public
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Äåñòpyêòîp äîëæåí áûòü public
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Êëàññ ìîæåò èìåòü òîëüêî îäèí äåñòpyêòîp
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Îïpåäåëåíèÿ ëîêàëüíûõ êëàññîâ íå ïîääåpæèâàåòñÿ
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Îïpåäåëåíèÿ íåèçâåñòíûõ êëàññîâ íå ïîääåpæèâàåòñÿ
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_object_has_no_vmt=03023_E_Îáúåêò $1 íå ÿâëÿåòñÿ òàáëèöåé VMT
+parser_e_illegal_parameter_list=03024_E_Håâåpíûé ñïèñîê ïàpàìåòpîâ
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_type=03025_E_Håïpàâèëüíî îïpåäåëåí òèï ïàpàìåòpà äëÿ àpãyìåíòà $1
+% There is an error in the parameter list of the function or procedure.
+% The compiler cannot determine the error more accurate than this.
+parser_e_wrong_parameter_size=03026_E_Håïpàâèëüíî îïpåäåëåíî êîëè÷åñòâî ïàpàìåòpîâ
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Ïåðåãðóæåííûé èäåíòèôèêàòîp $1 íå ÿâëÿåòñÿ ôyíêöèåé
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it isn't a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Ïåðåãðóæåííûå ôyíêöèè äîëæíû èìåòü òîò-æå ñïèñîê ïàpàìåòpîâ
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Çàãîëîâîê ôyíêöèè íå ñîîòâåòñòâyåò ïpåäûäyùåìy îïpåäåëåíèþ â forward $1
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Çàãîëîâîê ôyíêöèè $1 íå ñîîòâåòñòâyåò ïpåäûäyùåìy îïpåäåëåíèþ â forward : èìåíà ïåpåìåííûõ èçìåíåíû $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Çíà÷åíèÿ â òèïàõ ïåðå÷èñëåíèÿ äîëæíû áûòü âîçðàñòàþùèìè
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_n_interface_name_diff_implementation_name=03032_N_Interface è Implementation èìåíà pàçíûå $1 => $2
+% This note warns you if the implementation and interface names of a
+% functions are different, but they have the same mangled name. This
+% is important when using overloaded functions (but should produce no error).
+parser_e_no_with_for_variable_in_other_segments=03033_E_With íå ìîæåò áûòü èñïîëüçîâàí â ïåpåìåííûõ êîòîpûå íàõîäÿòñÿ â pàçëè÷íûõ ñåãìåíòàõ
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Êîëè÷åñòâî âëîæåíèé â ôyíêöèè ñëèøêîì ìíîãî (áîëåå 31)
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Îøèáêà âûõîäà èç äîïyñòèìîãî äèàïàçîíà ïpè pàñ÷åòå êîíñòàíò
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Îøèáêà âûõîäà èç äîïyñòèìîãî äèàïàçîíà ïpè pàñ÷åòå êîíñòàíò
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Ïîâòîpíàÿ ìåòêà CASE
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Âåpõíÿÿ ãpàíèöà äèàïàçîíà ìåíüøå ÷åì íèæíÿÿ
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Òèïèçèpîâàííûå êîíñòàíòû êëàññîâ íå ïîääåpæèâàþòñÿ
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Ïåðåìåííûå ïåðåãðóæåííûõ ôóíêöèé íå ïîääåpæèâàþòñÿ
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_Äëèíà ñòpîêè äîëæíà áûòü â äèàïàçîíå 1 .. 255
+% The length of a string in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+% (This is not true for \var{Longstrings} and \var{AnsiStrings}.
+parser_w_use_extended_syntax_for_objects=03042_W_Èñïîëüçîâàíèå pàñøèpåííîãî ñèíòàêñèñà NEW è DISPOSE äëÿ èíñòàíöèé îáúåêòîâ
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_Èñïîëüçîâàíèå NEW è DISPOSE äëÿ íåòèïèçèpîâàííûõ yêàçàòåëåé, áåññìûñëåííî
+parser_e_no_new_dispose_on_void_pointers=03044_E_Èñïîëüçîâàíèå NEW è DISPOSE äëÿ íåòèïèçèpîâàííûõ yêàçàòåëåé, íå ïîääåpæèâàåòñÿ
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Îæèäàåòñÿ èäåíòèôèêàòîp êëàññà
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Èäåíòèôèêàòîp òèïà çäåñü íåyìåñòåí
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Îæèäàåòñÿ èäåíòèôèêàòîp ìåòîäà
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Çàãîëîâîê ôyíêöèè íå ñîäåpæèò íå îäíîãî èç ìåòîäîâ îáúåêòà $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_p_procedure_start=03049_P_Ïpîöåäypà/Ôyíêöèÿ $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Håâåpíàÿ êîíñòàíòà ñ ïëàâàþùåé çàïÿòîé
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL ìîæåò èñïîëüçîâàòñÿ òîëüêî â êîíñòpyêòîpàõ
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Äåñòpyêòîpû íå ìîãyò èìåòü ïàpàìåòpîâ
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Òîëüêî ìåòîäû êëàññà ìîãóò ññûëàòüñÿ íà êëàññ
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Òîëüêî ê ìåòîäàì êëàññà ìîæíî îáðàùàòüñÿ â ìåòîäàõ êëàññà
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Òèï êîíñòàíòû è òèï âûpàæåíèÿ â CASE íå ñîâïàäàþò
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Ñèìâîë íå ìîæåò ýêñïîðòèðîâàòüñÿ èç áèáëèîòåêè
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Óíàñëåäîâàííûé ìåòîä ñêpûò $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Íå èìååòñÿ íèêàêîãî ìåòîäà â êëàññå ïðåäêà, êîòîðûé íóæíî ïåpåîïpåäåëèòü: $1
+% You try to \var{override} a virtual method of a parent class that doesn't
+% exist.
+parser_e_no_procedure_to_access_property=03059_E_Íèêàêîé ýëåìåíò íå îáåñïå÷èâàåò îáðàùåíèÿ ê ñâîéñòâàì êëàññà
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Ñîõðàíåííàÿ äèðåêòèâà ñâîéñòâ åñòü, íî åùå íå påàëèçîâàíà
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Håâåpíûé ñèìâîë äëÿ äîñòóïà ê ñâîéñòây
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Håâîçìîæíî îáðàòèòüñÿ ê protected ïîëþ îáúåêòà
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Håâîçìîæíî îáðàòèòüñÿ ê private ïîëþ îáúåêòà
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_w_overloaded_are_not_both_virtual=03064_W_Ïåðåãðóæåííûå ìåòîäû âèpòyàëüíûõ ìåòîäîâ, äîëæíû áûòü òîæå âèpòyàëüíûìè: $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+parser_w_overloaded_are_not_both_non_virtual=03065_W_Ïåðåãðóæåííûé ìåòîä HÅ âèðòóàëüíîãî ìåòîäà äîëæåí áûòü òîæå HÅ âèðòóàëüíûì: $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+parser_e_overridden_methods_not_same_ret=03066_E_Ïåðåîïðåäåëåííûå ìåòîäû äîëæíû èìåòü òîò-æå ñàìûé òèï âîçâðàùàåìîãî çíà÷åíèÿ: "$2" ïåðåîïðåäåëåí "$1" êîòîðûé âîçâðàùàåò äðóãîé òèï
+% If you declare oerridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_EXPORT ôyíêöèè íå ìîãyò áûòü âëîæåííûìè
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Ìåòîäû íå ìîãyò ýêñïîpòèpîâàòüñÿ
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Âûçîâ ñ ïåðåìåííûìè ïàðàìåòðàìè äîëæåí ñîîòâåòñòâîâàòü òî÷íî: Ïîëó÷åíî "$1", îæèäàåòñÿ "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Äàííûé êëàññ íå ÿâëÿåòñÿ ðîäèòåëüñêèì êëàññîì òåêóùåãî êëàññà
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF pàçpåøàåòñÿ òîëüêî â ìåòîäàõ
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Ìåòîäû ìîãyò âûçûâàòüñÿ òîëüêî â äpyãèõ ìåòîäàõ íàïpÿìyþ ñ èäåíòèôèêàòîpîì òèïà êëàññà
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Håïpàâèëüíîå èñïîëüçîâàíèå ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Îøèáêà ïðîâåðêè ïðèíàäëåæíîñòè ê äèàïàçîíó â êîíñòðóêòîðå íàáîðà èëè äâîéíîì ýëåìåíòå íàáîðà
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Îæèäàåòñÿ yêàçàòåëü íà îáúåêò
+% You specified an illegal type in a \var{New} statement.
+% The extended synax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Âûpàæåíèå äîëæíî âûçûâàòü êîíñòpyêòîp
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Âûpàæåíèå äîëæíî âûçûâàòü äåñòpyêòîp
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Håâåpíûé ïîpÿäîê ýëåìåíòîâ òèïà RECORD
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Òèï âûpàæåíèÿ äîëæíî áûòü CLASS èëè RECORD
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Ïpîöåäypû íå ìîãyò âîçâpàùàòü çíà÷åíèÿ
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Êîíñòpyêòîpû è äåñòpyêòîpû äîëæíû áûòü ìåòîäàìè
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Îïåpàòîp íå ïåpåãpyæåí
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Ïåðåãðóæåííîå ñâÿçûâàíèå íåâîçìîæíî ñ îäèíàêîâûìè òèïàìè äàííûõ
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Ïåðåãðóçêà îïåðàòîðà íåâîçìîæíà
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_RERAISE çäåñü íåâîçìîæåí
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Ðàñøèpåííûé ñèíòàêñèñ NEW è DISPOSE äëÿ êëàññà íåäîïyñòèìî
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_asm_incomp_with_function_return=03087_E_Àññåìáëåp íåñîâìåñòèì ñ òèïîì, êîòîpîå âîçpàùàåò ôyíêöèÿ
+% You're trying to implement a \var{assembler} function, but the return type
+% of the function doesn't allow that.
+parser_e_procedure_overloading_is_off=03088_E_Ïpîöåäypíàÿ ïåðåãðóçêà îòêëþ÷åíà
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Íåâîçìîæíî ïðåîáðàçèòü ýòîò îïåðàòîð â ïåðåãðóæåííûé îïåðàòîð
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Ñðàâíèòåëüíûé îïåðàòîð äîëæåí âîçâðàòèòü áóëåâî çíà÷åíèå
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Òîëüêî âèðòóàëüíûå ìåòîäû ìîãóò áûòü àáñòðàêòíû
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Èñïîëüçîâàíèå ïîêà íåïîääåðæèâàåìîé îñîáåííîñòè êîìïèëÿòîðà
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Ñìåøèâàòü ÊËÀÑÑÛ è ÎÁÚÅÊÒÛ íå ïîçâîëÿåòñÿ
+% You cannot derive \var{objects} and \var{classes} intertwined . That is,
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Íåèçâåñòíàÿ äèðåêòèâà ïðîöåäóðû, $1 èãíîðèðyåòñÿ
+% The procedure direcive you secified is unknown. Recognised procedure
+% directives are \var{cdecl}, \var{stdcall}, \var{popstack}, \var{pascal}
+% \var{register}, \var{export}.
+parser_e_absolute_only_one_var=03095_E_ABSOLUTE ìîæåò áûòü ñâÿçàíà òîëüêî ñ ÎÄHÎÉ ïåpåìåííîé
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE ìîæåò áûòü ñâÿçàíà òîëüêî ñ ïåpåìåííîé èëè êîíñòàíòîé
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Òîëüêî ÎÄHÀ ïåpåìåííàÿ ìîæåò áûòü èíèöèàëèçèpîâàíà
+% You cannot specify more than one variable with a initial value
+% in Delphi syntax.
+parser_e_abstract_no_definition=03098_E_Àáñòðàêòíûå ìåòîäû íå äîëæíû èìåòü îïðåäåëåíèå (òî åñòü èìåòü òåëî)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Ýòà ïåðåãðóæåííàÿ ôóíêöèÿ íå ìîæåò áûòü ëîêàëüíîé, è äîëæíà ýêñïîðòèðîâàòüñÿ
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Âèðòóàëüíûå ìåòîäû èñïîëüçóþòñÿ áåç êîíñòðóêòîðà â $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_m_macro_defined=03101_M_Îïpåäåëåí ìàêpîñ: $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+parser_m_macro_undefined=03102_M_Ìàêpîñ íåîïpåäåëåí: $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+parser_m_macro_set_to=03103_M_Ìàêpîñ $1 yñòàíîâëåí â $2
+% When \var{-vm} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Êîìïèëèpîâàíèå $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_U_Àíàëèçèðóåì èíòåðôåéñíóþ ÷àñòü ìîäyëÿ $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_U_Àíàëèçèðóåì ðåàëèçàöèîííóþ ÷àñòü ìîäyëÿ $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_D_Ïîâòîðíîå êîìïèëèðîâàíèå $1
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_paras_allowed=03108_E_Ñâîéñòâà ìàññèâà â ýòîé òî÷êå íå ïîääåpæèâàþòñÿ
+% You cannot use array properties at that point in the source.
+parser_e_no_property_found_to_override=03109_E_Håò íèêàêèõ ñâîéñòâ äëÿ ïåpåîïpåäåëåíèÿ
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Òîëüêî îäíî çàäàííîå ïî-óìîë÷àíèþ ñâîéñòâî pàçpåøàåòñÿ, íàéäåíî yíàñëåäîâàííîå, çàäàííîå ïî yìîë÷àíèþ, ñâîéñòâî â êëàññå $1
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Çàäàííîå ïî-óìîë÷àíèþ ñâîéñòâî äîëæíî áûòü ñâîéñòâîì ìàññèâà
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Âèpòyàëüíûå êîíñòpyêòîpû ïîääåpæèâàþòñÿ òîëüêî â êëàññîâûõ ìîäåëÿõ îáúåêòà
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Håò ñâîéñòâ
+% You try to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Êëàññ íå ìîæåò èìåòü PUBLISHED ðàçäåë, èñïîëüçyéòå êëþ÷ {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_FORWARD îïpåäåëåíèå êëàññà $1 äîëæíî áûòü ðåàëèçîâàíî çäåñü, ÷òîáû èñïîëüçîâàòü êëàññ êàê ïðåäîê
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Ëîêàëüíûå îïåpàòîpû íå ïîääåpæèâàþòñÿ
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Ïpîöåäypíàÿ äèpåêòèâà $1 íå pàçpåøåíà â èíòåðôåéñíîé ÷àñòè ìîäóëÿ
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Ïpîöåäypíàÿ äèpåêòèâà $1 íå pàçpåøåíà â ðåàëèçàöèîííîé ÷àñòè ìîäóëÿ
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Ïpîöåäypíàÿ äèpåêòèâà $1 íå pàçpåøåíà â PROCVAR îïpåäåëåíèè
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Ôóíêöèÿ $1 óæå îáúÿâëåíà êàê PUBLIC èëè FORWARD
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Håëüçÿ èñïîëüçîâàòü EXPORT è EXTERNAL âìåñòå
+% These two procedure directives are mutually exclusive
+parser_e_name_keyword_expected=03122_E_Îæèäàåòñÿ êëþ÷åâîå ñëîâî NAME
+% The definition of an external variable needs a \var{name} clause.
+parser_w_not_supported_for_inline=03123_W_$1 íå ïîääåpæèâàåòñÿ âíyòpè INLINE ïpîöåäypû/ôyíêöèè
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Âêëþ÷åíèå INLINE îòêëþ÷åíî
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Çàïèñûâàåì ëîã ápàyçåpà $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Ìîæåò áûòü îòñyòñòâyåò pàçûìåíîâàííûé yêàçàòåëü
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Âûápàííûé ñòèëü ÷òåíèÿ àññåìáëåpà íå ïîääåpæèâàåòñÿ
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Ïpîöåäypíàÿ äèpåêòèâà $1 êîíôëèêòyåò ñ äpyãèìè äèpåêòèâàìè
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Ñîãëàøåíèå î âûçîâå ïpîöåäypû/ôyíêöèè íå ñîîòâåòñòâóåò yêàçàííîìy âûøå â FORWARD
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_register_calling_not_supported=03130_E_Âûçîâ påãèñòpîâ ("FAST CALL") íå ïîääåpæèâàåòñÿ
+% The \var{register} calling convention, i.e., arguments are passed in
+% registers instead of on the stack is not supported. Arguments are always
+% passed on the stack.
+parser_e_property_cant_have_a_default_value=03131_E_Ñâîéñòâî íå ìîæåò èìåòü çíà÷åíèå ïî yìîë÷àíèþ
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Çíà÷åíèå ïî yìîë÷àíèþ y ñâîéñòâà äîëæíî áûòü êîíñòàíòîé
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Ñèìâîë íå ìîæåò áûòü PUBLISHED, òîëüêî êëàññ
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Ýòîò âèä ñâîéñòâà íå ìîæåò áûòü PUBLISHED
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_w_empty_import_name=03135_W_Óêàçàííîå èìÿ èìïîðòà ïyñòî
+% Both index and name for the import are 0 or empty
+parser_e_empty_import_name=03136_W_Òðåáóåòñÿ èìÿ èìïîðòà
+% Some targets need a name for the imported procedure or a cdecl specifier
+parser_e_used_proc_name_changed=03137_E_Âíóòðåííåå èìÿ ôóíêöèè, èçìåíåííî ïîñëå èñïîëüçîâàíèÿ ôóíêöèè
+% This is an internal error; please report any occurrences of this error
+% to the \fpc team.
+parser_e_division_by_zero=03138_E_Äåëåíèå íà íîëü
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Håïpàâèëüíàÿ îïåpàöèÿ ñ ïëàâàþùåé çàïÿòîé
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Âåpõíÿÿ ãpàíèöà äèàïàçîíà ìåíüøå, ÷åì íèæíÿÿ ãpàíèöà
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_Ñòðîêà "$1" áîëüøå ÷åì $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Ñòðîêîâàÿ äëèíà áîëüøå, ÷åì äëèíà ìàññèâà ñèìâîëîâ
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Håâåpíîå âûpàæåíèå ïîñëå äèpåêòèâû ñîîáùåíèÿ
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Îápàáîò÷èêè ñîîáùåíèé ìîãyò ápàòü òîëüêî îäèí çàïpîñ â ññûëî÷íîì ïàpàìåòpå
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Ïîâòîpíîå îïpåäåëåíèå ìåòêè ñîîáùåíèÿ: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_SELF ìîæåò áûòü òîëüêî êàê ÿâíûé ïàðàìåòð â îáðàáîò÷èêàõ ñîîáùåíèÿ
+% The self parameter can be passed only explicitly in a method which
+% is declared as message method handler.
+parser_e_threadvars_only_sg=03147_E_Ïåpåìåííûå òpåéäîâ ìîãyò áûòü òîëüêî ñòàòè÷åñêèìè èëè ãëîáàëüíûìè
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Ïðÿìîé ñòèëü àññåìáëåpà íå ïîääåpæèâàåòñÿ ôîpìàòîì âûõîäíîãî ôàéëà
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_Hå çàãpyæàéòå OBJPAS ìîäyëü, èñïîëüçyéòå {$mode objfpc} èëè {$mode delphi} âìåñòî ýòîãî
+% You're trying to load the ObjPas unit manual from a uses clause. This is
+% not a good idea to do, you can better use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automaticly
+parser_e_no_object_override=03150_E_Ïåpåîïpåäåëåíèå íå ìîæåò áûòü èñïîëüçîâàííî â îáúåêòàõ
+% Override isn't support for objects, use VIRTUAL instead to override
+% a method of an anchestor object
+parser_e_cant_use_inittable_here=03151_E_Òèï äàííûõ, êîòîpûé òpåáyåò INITILIZATION/FINALIZATION íå ìîæåò èñïîëüçîâàòüñÿ â pàçëè÷íûõ çàïèñÿõ
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Ñòðîêîâûå ðåñóðñû ìîãóòü áûòü òîëüêî ñòàòè÷åñêèìè èëè ãëîáàëüíûìè
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Ïðîöåäóðà Exit ñ àðãóìåíòîì çäåñü íåäîïóñòèìà
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Òèï ñîõðàíÿåìîãî ñèìâîëà äîëæåí áûòü boolean
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Ýòîò òèï ñèìâîëà íå ìîæåò áûòü ñîõpàíåí â ýòîì ñâîéñòâå
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Òîëüêî êëàññ, êîòîpûé êîìïèëèpyåòñÿ â $M+ påæèìå ìîæåò áûòü published
+% In the published section of a class can be only class as fields used which
+% are compiled in $M+ or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Îæèäàåòñÿ ïpîöåäypíàÿ äèpåêòèâà
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Çíà÷åíèå ñâîéñòâà èíäåêñà äîëæíî áûòü îáû÷íîãî òèïà
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Èìÿ ïpîöåäypû ñëèøêîì êîpîòêîå äëÿ ýêñïîpòà
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Îòñóòñòâóþùàÿ DEFFILE çàïèñü ìîæåò áûòü ñîçäàíà äëÿ ãëîáàëüíûõ ïåðåìåííûõ ìîäóëÿ
+parser_e_dlltool_unit_var_problem2=03161_E_Êîìïèëèðîâàíèå áåç -WD îïöèè
+parser_f_need_objfpc_or_delphi_mode=03162_F_Âàì íåîáõîäèì ObjFpc (-S2) èëè Delphi (-Sd) påæèì ñîâìåñòèìîñòè äëÿ êîìïèëÿöèè ýòîãî ìîäyëÿ
+% You need to use {$mode objfpc} or {$mode delphi} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Hå ìîãy ýêñïîpòèpîâàòü ñ ýòèì èíäåêñîì ïîä $1
+% Exporting of functions or procedures with a specified index is not
+% support on all targets. The only platforms currently supporting
+% export with index are OS/2 and Win32.
+parser_e_no_export_of_variables_for_target=03164_E_Ýêñïîpòèpîâàíèå ïåpåìåííûõ íå ïîääåpæèâàåòñÿ ïîä $1
+% Exporting of variables is not support on all targets. The only platform
+% currently supporting export of variables is Win32.
+parser_e_improper_guid_syntax=03165_E_Íåïîäõîäÿùèé GUID ñèíòàêñèñ
+parser_f_interface_cant_have_variables=03166_F_Interface íå ìîæåò èìåòü ïåðåìåííûõ
+parser_f_interface_cant_have_constr_or_destr=03167_F_Interface íå ìîæåò èìåòü êîíñòðóêòîðà èëè destructor
+parser_w_interface_mapping_notfound=03168_W_Ïðîöåäóðà íàçâàííàÿ "$1" íå íàéäåíà ïîäõîäÿùåé äëÿ ðåàëèçàöèè $2.$3
+parser_e_interface_id_expected=03169_E_Òðåáóåòñÿ inteface
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Òèï "$1" íå ìîæåò áûòü èñïîëüçîâàí êàê èíäåêñ ìàññèâà
+% Types like DWord or Int64 aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Con- è destructor íå ïîçâîëÿþòñÿ â interface
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Ñïåöèôèêàòîðû äîñòóïà íå ìîãóò èñïîëüçîâàòüñÿ â INTERFACES
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Interface íå ìîæåò èìåòü ïîëåé, òîëüêî ìåòîäû
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_external=03174_E_Íå ìîãó îïðåäåëèòü ëîêàëüíóþ ïðîöåäóðó êàê EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance on errors very high
+parser_w_skipped_fields_before=03175_W_Íåêîòîðûå ïîëÿ, íàõîäÿùèåñÿ ïåðåä "$1" íå áûëè èíèöèàëèçèðîâàíû
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Íåêîòîðûå ïîëÿ, íàõîäÿùèåñÿ ïåðåä "$1" íå áûëè èíèöèàëèçèðîâàíû
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_h_skipped_fields_after=03177_H_Íåêîòîðûå ïîëÿ, íàõîäÿùèåñÿ ïåðåä "$1" íå áûëè èíèöèàëèçèðîâàíû
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically), but the the
+% compiler gives a hint because it can be the source of a problem.
+parser_e_varargs_need_cdecl_and_external=03178_E_VarArgs äèðåêòèâà áåç CDecl è External
+% The varargs directive can only be used with procedures or functions
+% that are declared with CDecl and External directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self äîëæåí áûòü íîðìàëüíûì (call-by-value) ïàðàìåòðîì
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Èíòåðôåéñ "$1" íå èìååò èäåíòèôèêàòîðà interface
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Íåèçâåñòíûé ïîëå êëàññà èëè ìåòîäà "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Ïåðåîïðåäåëåíèå ñîãëàøåíèÿ î âûçîâàõ ìåæäó "$1" è "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Òèïèçèðîâàííàÿ êîíñòàíòà (òèï procedure èëè object) ìîæåò áûòü èíèöèàëèçèðîâàííà òîëüêî â NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+% \end{description}
+
+#
+# Ïpîâåpêà òèïîâ
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Håïpàâèëüíûé òèï
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Håñîâìåñòèìîñòü òèïîâ: ïîëy÷èëè $1, à îæèäàëè $2
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Håñîîòâåòñòâèå òèïîâ ìåæäy $1 è $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Îæèäàåòñÿ âûðàæåíèå òèïà TYPE
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Îæèäàåòñÿ âûðàæåíèå òèïà VAR
+% This happens when you pass a constant to a \var{Inc} var or \var{Dec}
+% procedure. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Îæèäàåòñÿ âûpàæåíèå òèïà INTEGER, íî ïîëó÷èëè "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Îæèäàåòñÿ âûðàæåíèå òèïà BOOLEAN, íî ïîëó÷èëè "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Îæèäàåòñÿ âûpàæåíèå òàêîãî-æå òèïà
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Îæèäàåòñÿ òèï POINTER, íî ïîëó÷èëè "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Îæèäàåòñÿ òèï CLASS, íî ïîëó÷èëè "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_varid_or_typeid_expected=04010_E_Îæèäàåòñÿ ïåpåìåííàÿ èëè èäåíòèôèêàòîp
+% The argument to the \var{High} or \var{Low} function is not a variable
+% nor a type identifier.
+type_e_cant_eval_constant_expr=04011_E_Håâîçìîæíî pàñ÷èòàòü çíà÷åíèå êîíñòàíòû
+% No longer in use.
+type_e_set_element_are_not_comp=04012_E_Óñòàíîâêà ýëåìåíòîâ ìàññèâà íåâîçìîæíà
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Îïåpàöèÿ íå påàëèçîâàíà äëÿ íàáîpîâ çíà÷åíèé
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Àâòîìàòè÷åñêîå ïpåîápàçîâàíèå òèïîâ èç REAL â COMP, êîòîpûé ÿâëÿåòñÿ ÷èñëîì òèïà INTEGER
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Èñïîëüçyéòå DIV âìåñòî ýòîãî, äëÿ ïîëy÷åíèÿ öåëî÷èñëåííîãî påçyëüòàòà
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Ñòpîêîâûå òèïû pàçíûå èç-çà $V+ påæèìà
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_SUCC èëè PRED íà ïåpå÷èñëåíèÿõ ñ íàçíà÷åíèÿìè íåâîçìîæíû
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Håâîçìîæíî ïpî÷åñòü èëè çàïèñàòü ïåpåìåííyþ ýòîãî òèïà
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% booleans, reals, pchars and strings can be read from/written to a text file.
+type_e_no_readln_writeln_for_typed_file=04019_E_Íåâîçìîæíî èñïîëüçîâàòü Readln èëè Writeln íà òèïèçèðîâàííîì ôàéëå
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Íåâîçìîæíî èñïîëüçîâàòü Read èëè Write íà íåòèïèçèðîâàííîì ôàéëå
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Îøèáêà òèïîâ ìåæäy ýëåìåíòàìè íàáîpà
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_LO/HI (LONGINT/DWORD) âîçâpàùàþò ñòàpøåå/ìëàäøåå ñëîâî
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Îæèäàåòñÿ âûpàæåíèå òèïà INTEGER èëè REAL
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Håâåpíûé òèï "$1" â ìàññèâå êîíñòpyêòîpà
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Håñîâìåñòèìîñòü òèïîâ â àpãyìåíòå # $1: Ïîëó÷èëè "$2", íî îæèäàåòñÿ "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Ìåòîä (ïåpåìåííàÿ) è Ïpîöåäypà (ïåpåìåííàÿ) íå ñîâìåñòèìû
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Çàïpåùåííàÿ êîíñòàíòà, áûëà ïåpåäàíà ê âíyòpåííåé ìàòåìàòè÷åñêîé ôyíêöèè
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Hå ìîãy ïîëy÷èòü àäpåñ êîíñòàíòû
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Àðãóìåíò íå ìîæåò áûòü ñâÿçàí ñ
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Íåìîãó ñâÿçàòü ëîêàëüíóþ ïðîöåäóðó/ôóíêöèþ ñ ïðîöåäóðíîé ïåðåìåííîé
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Hå ìîãy ïîäâÿçàòü çíà÷åíèå ê àäpåñy
+% It's not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Hå ìîãy ïîäâÿçàòü çíà÷åíèå ê êîíñòàíòå
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing make the parameter value or var.
+type_e_array_required=04033_E_Òpåáyåòñÿ òèï array
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_òðåáóåòñÿ òèï interface, íî ïîëó÷èëè "$1"
+type_w_mixed_signed_unsigned=04035_W_Ñìåøèâàíèå çíàêîâûõ âûðàæåíèé è cardinal òèïà äàåò 64bit ðåçóëüòàò
+% If you divide (or calculate the modulus of) a signed expression by a cardinal (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetical
+% expression (+, -, *, div, mod) in which both signed numbers and cardinals appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetics. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Ñìåøèâàíèå çíàêîâûõ âûðàæåíèé è cardinal òèïà ìîæåò äàòü îøèáêó âûõîäà çà äèàïàçîí
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a cardinal while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to cardinal before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Ïðèâåäåíèå òèïà èç $1 â $2 íåâîçìîæíî ïðè ïðèñâàèâàíèè, òàê êàê îïåðàíäû èìåþò ðàçíûé ðàçìåð
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+% \end{description}
+
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Èäåíòèôèêàòîp íå íàéäåí $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Âíyòpåííÿÿ îøèáêà â SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Äâîéíîé èäåíòèôèêàòîp $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Èäåíòèôèêàòîp yæå îïpåäåëåí â $1 (ñòpîêà $2)
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Håèçâåñòíûé èäåíòèôèêàòîp $1
+% The identifier encountered hasn't been declared, or is used outside the
+% scope where it's defined.
+sym_e_forward_not_resolved=05005_E_FORWARD íå íàéäåí $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_f_id_already_typed=05006_F_Èäåíòèôèêàòîp yæå îïpåäåëåí êàê òèï
+% You are trying to redefine a type.
+sym_e_error_in_type_def=05007_E_Îøèáêà â îïpåäåëåíèè òèïà
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_type_id_not_defined=05008_E_Òèï èäåíòèôèêàòîpà íå îïpåäåëåí
+% The type identifier has not been defined yet.
+sym_e_forward_type_not_resolved=05009_E_FORWARD òèï íå íàéäåí $1
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Òîëüêî ñòàòè÷åñêèå ïåðåìåííûå ìîãóò èñïîëüçîâàòüñÿ â ñòàòè÷åñêèõ èëè âíåøíèõ ìåòîäàõ
+% A static method of an object can only access static variables.
+sym_e_invalid_call_tvarsymmangledname=05011_E_Håâåpíûé âûçîâ tvarsym.mangledname()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_f_type_must_be_rec_or_class=05012_F_Îæèäàåòñÿ òèï RECORD èëè CLASS
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Îápàçöû êëàññîâ èëè îáúåêòîâ ñ àáñòpàêòíûì ìåòîäîì íå ïîääåpæèâàþòñÿ
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Ìåòêà íå îïpåäåëåíà $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Ìåòêà $1 èñïîëüçóåòñÿ, íî íåîïðåäåëåíà
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Håâåpíîå îïðåäåëåíèå ìåòêè
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO è LABEL íå ïîääåpæèâàþòñÿ (èñïîëüçyéòå êëþ÷ -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Ìåòêà íå íàéäåíà
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Ýòîò èäåíòèôèêàòîp íå ìåòêà
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Ïîâòîpíîå îïpåäåëåíèå ìåòêè
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Íåâåpíîå îáúÿâëåíèå òèïà ýëåìåíòîâ íàáîðà
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_FORWARD îïpåäåëåíèå êëàññà íå îáíàpyæåíî $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Ìîäóëü $1 íå èñïîëüçóåòñÿ â $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Ïàpàìåòp íå èñïîëüçyåòñÿ $1
+% This is a warning. The identifier was declared (locally or globally) but
+% wasn't used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Ëîêàëüíàÿ ïåpåìåííàÿ íå èñïîëüçyåòñÿ $1
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Çíà÷åíèå ïàðàìåòðà $1 ñâÿçàíà ñ ÷åì-òî, íî íå èñïîëüçóåòñÿ
+% This is a warning. The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Ëîêàëüíàÿ ïåðåìåííàÿ $1 ñâÿçàíà ñ ÷åì-òî, íî íå èñïîëüçóåòñÿ
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Ëîêàëüíûé ñèìâîë $1 $2 íåèñïîëüçóåòñÿ
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Private ïîëå $1.$2 íåèñïîëüçóåòñÿ
+sym_n_private_identifier_only_set=05030_N_Private ïîëå $1.$2 ñâÿçàíà ñ ÷åì-òî, íî íå èñïîëüçóåòñÿ
+sym_n_private_method_not_used=05031_N_Private ìåòîä $1.$2 íåèñïîëüçóåòñÿ
+
+
+sym_e_set_expected=05032_E_Îæèäàåòñÿ yñòàíîâêà òèïà
+% The variable or expression isn't of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Ðåçyëüòàò ôyíêöèè êàæåòñÿ íå yñòàíîâëåí
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Òèï $1 íåêîððåêòíî âûðîâíåí â òåêóùåé çàïèñè C ÿçûêà
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Håèçâåñòíîå ïîëå â çàïèñè $1
+% The field doesn't exist in the record definition.
+sym_n_uninitialized_local_variable=05036_W_Ëîêàëüíàÿ ïåpåìåííàÿ $1 êàæåòñÿ íå èíèöèàëèçèpîâàíà
+sym_n_uninitialized_variable=05037_W_Ïåpåìåííàÿ $1 êàæåòñÿ íå èíèöèàëèçèpîâàíà
+% These messages are displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% wasn't initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Èäåíòèôèêàòîp íå yêàçûâàåò íè íà êàêîé ýëåìåíò $1
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the class you are trying to create. The procedure you specified
+% does not exist.
+sym_b_param_list=05039_B_Hàéäåíî îïpåäåëåíèå: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Ñåãìåíò äàííûõ ñëèøêîì áîëüøîé (ìàêñ. 2GB)
+% You get this when you declare an array whose size exceeds the 2GB limit.
+% \end{description}
+
+
+#
+# Codegenerator
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_break_not_allowed=06000_E_BREAK íå pàçpåøåíî
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06001_E_CONTINUE íå pàçpåøåíî
+% You're trying to use \var{continue} outside a loop construction.
+cg_e_too_complex_expr=06002_E_Âûpàæåíèå ñëèøêîì ñëîæíîå - ïåpåïîëíåíèå ñòåêà FPU
+% Your expression is too long for the compiler. You should try dividing the
+% construct over multiple assignments.
+cg_e_illegal_expression=06003_E_Håïpàâèëüíîå âûpàæåíèå
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+cg_e_invalid_integer=06004_E_Håïpàâèëüíîå öåëî÷èñëåííîå âûpàæåíèå
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+cg_e_invalid_qualifier=06005_E_Håäåéñòâèòåëüíûé ñïåöèôèêàòîp
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+cg_e_upper_lower_than_lower=06006_E_Âåpõíèé ïpåäåë äèàïàçîíà ìåíüøå íèæíåãî ïpåäåëà.
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+cg_e_illegal_count_var=06007_E_Håâåpíàÿ ïåðåìåííàÿ-ñ÷åò÷èê
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+cg_e_cant_choose_overload_function=06008_E_Íå ìîãó îïðåäåëèòü, êòî 'ïåðåãðóæàë' ôóíêöèþ, ÷òîáû åå âûçâàòü
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+cg_e_parasize_too_big=06009_E_Ðàçìåp ñïèñêà ïàpàìåòpîâ ïpåâûñèë äîïyñòèìûé ïpåäåë â 65535 áàéò (64kb)
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_illegal_type_conversion=06010_E_Håïpàâèëüíîå ïpåîápàçîâàíèå òèïîâ
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+cg_d_pointer_to_longint_conv_not_portable=06011_D_Êîíâåpòàöèÿ ìåæäy ORDINAL è POINTER íåâîçìîæíà èç-çà îòñóòñòâèÿ ïîääåðæêè ó ïëàòôîðìû
+% If you typecast a pointer to a longint, this code will not compile
+% on a machine using 64bit for pointer storage.
+cg_e_file_must_call_by_reference=06012_E_Ôàéëîâûå òèïû äîëæíû áûòü ïåpåìåííûìè
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_Èñïîëüçîâàíèå FAR yêàçàòåëÿ çäåñü íå ïîääåpæèâàåòñÿ
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_var_must_be_reference=06014_E_Håïpàâèëüíûé âûçîâ ïàpàìåòpà ïî ññûëêå
+% You are trying to pass a constant or an expression to a procedure that
+% requires a \var{var} parameter. Only variables can be passed as a \var{var}
+% parameter.
+cg_e_dont_call_exported_direct=06015_E_Èñïîëüçîâàíèå EXPORT îïpåäåëÿåò, ÷òî ýòà ôyíêöèÿ íå ìîæåò çäåñü âûçûâàòüñÿ
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Âîçìîæíî íåïpàâèëüíûé âûçîâ êîíñòpyêòîpà èëè äåñòpyêòîpà (íå ñîîòâåòñòâyåò òåêyùåìy êîíòåêñòy)
+% No longer in use.
+cg_n_inefficient_code=06017_N_Håýôôåêòèâíûé êîä
+% You construction seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Håäîñòèæèìûé êîä
+% You specified a loop which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_stackframe_with_esp=06019_E_Âûçîâ ïpîöåäypû ñ STACKFRAME ESP/SP
+% The compiler encountered a procedure or function call inside a
+% procedure that uses a \var{ESP/SP} stackframe. Normally, when a call is
+% done the procedure needs a \var{EBP} stackframe.
+cg_e_cant_call_abstract_method=06020_E_Àáñòpàêòíûå ìåòîäû íå ìîãyò âûçûâàòüñÿ íàïpÿìyþ
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_f_internal_error_in_getfloatreg=06021_F_Âíyòpåííÿÿ îøèáêà â getfloatreg(), pàñïpåäåëåíèå ïpîâàëåíî!
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_f_unknown_float_type=06022_F_Håèçâåñòíûé òèï ïëàâàþùåé çàïÿòîé
+% The compiler cannot determine the kind of float that occurs in an expression.
+cg_f_secondvecn_base_defined_twice=06023_F_SecondVecn() áàçà îïpåäåëåíà äâàæäû
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_f_extended_cg68k_not_supported=06024_F_Ðàñøèpåíèÿ cg68k íå ïîääåpæèâàþòñÿ
+% The \var{extended} type is not supported on the m68k platform.
+cg_f_32bit_not_supported_in_68000=06025_F_Áåççíàêîâûå 32-áèòíûå ÷èñëà íå ïîääåpæèâàþòñÿ â MC680x0 påæèìå
+% The cardinal is not supported on the m68k platform.
+cg_f_internal_error_in_secondinline=06026_F_Âíyòpåííÿÿ îøèáêà â secondinline()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_d_register_weight=06027_D_Ðåãèñòp $1 âåñèò $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_e_stacklimit_in_local_routine=06028_E_Ëèìèò ñòåêà â ëîêàëüíîé ïîäïpîãpàììå èñ÷åpïàí
+% Your code requires a too big stack. Some operating systems pose limits
+% on the stack size. You should use less variables or try ro put large
+% variables on the heap.
+cg_d_stackframe_omited=06029_D_STACK FRAME îïyùåíû
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Â îáúåêòàõ èëè êëàññàõ íåëüçÿ èñïîëüçîâàòü INLINE
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Â âûçîâàõ PROCVAR íåëüçÿ èñïîëüçîâàòü INLINE
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Håò êîäà â INLINE
+% The compiler couldn't store code for the inline procedure.
+cg_e_no_call_to_interrupt=06034_E_Ïðÿìîé âûçîâ ïðîöåäóðû-ïðåðûâàíèÿ $1 íåâîçìîæåí
+% You can not call an interrupt procedure directly from FPC code
+cg_e_can_access_element_zero=06035_E_Hyëåâîé ýëåìåíò äëèííîé ñòpîêè íåäîñòyïåí, èñïîëüçyéòå âìåñòî ýòîãî SETLENGTH èëè LENGTH
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_include_not_implemented=06036_E_Âêëþ÷åíèÿ è èñêëþ÷åíèÿ íå ïîääåpæèâàþòñÿ â CASE
+% \var{include} and \var{exclude} are only partially
+% implemented for \var{i386} processors
+% and not at all for \var{m68k} processors.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Êîíñòpyêòîpû èëè äåñòpyêòîpû íå ìîãyò âûçûâàòüñÿ âíyòpè 'WITH' ïpåäëîæåíèé
+% Inside a \var{With} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Håëüçÿ âûçûâàòü ìåòîä îápàáîò÷èêà ñîáûòèé íåïîñpåäñòâåííî
+% A message method handler method can't be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Ïåðåõîä çà âíåøíþþ ñòîðîíó â exception áëîêå
+% It isn't allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+% \end{description}
+cg_e_control_flow_outside_finally=06040_E_Êîíòðîëèðóþùèå âûðàæåíèÿ (break,continue è exit) â áëîêå finally - íåäîïóñòèìû
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+# EndOfTeX
+
+#
+# Assembler reader
+#
+asmr_d_start_reading=07000_D_Hà÷èíàåì ÷èòàòü $1 ñòèëü àññåìáëåpà
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_D_Êîíåö ÷òåíèÿ $1 ñòèëÿ àññåìáëåpà
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_×òî-òî, íî íå ìåòêà, ñîäåpæèò @
+% A identifier which isn't a label can't contain a @.
+asmr_w_override_op_not_supported=07003_W_Ïåpåîïpåäåëåííûå îïåpàòîpû íå ïîääåpæèâàþòñÿ
+% The Override operator is not supported
+asmr_e_building_record_offset=07004_E_Îøèáêà ïîñòpîåíèÿ ñìåùåíèÿ â çàïèñè
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET èñïîëüçyåòñÿ áåç èäåíòèôèêàòîpà
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE èñïîëüçyåòñÿ áåç èäåíòèôèêàòîpà
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Hå ìîãy çäåñü èñïîëüçîâàòü ëîêàëüíûå ïåpåìåííûå èëè ïàpàìåòpû
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the %ebp register so the
+% address can't be get directly.
+asmr_e_need_offset=07008_E_Çäåñü íåîáõîäèìî èñïîëüçîâàòü OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Çäåñü íåîáõîäèìî èñïîëüçîâàòü çíàê äîëëàðà ('$')
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Hå ìîãy èñïîëüçîâàòü ìíîæåñòâåííûå ïåpåìåùàåìûå ñèìâîëû
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Ïåpåìåùàåìûé ñèìâîë ìîæåò áûòü òîëüêî äîáàâëåí
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Håïpàâèëüíîå âûpàæåíèå â êîíñòàíòå
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Ïåpåìåùàåìûå ñèìâîëû çäåñü íå pàçpåøåíû
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Håâåpíûé ñèíòàêñèñ ññûëêè
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Âû íå ìîæåòå äîñòè÷ü $1 èç ýòîãî êîäà
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Ëîêàëüíûå ñèìâîëû èëè ìåòêè íåëüçÿ èñïîëüçîâàòü êàê ññûëêè
+% Âû íå ìîæåòå èñïîëüçîâàòü ëîêàëüíûå ñèìâîëû èëè ìåòêè êàê ññûëêè
+asmr_e_wrong_base_index=07017_E_Håâåpíàÿ áàçà è èíäåêñ â èñïîëüçîâàíèè påãèñòpà
+% There is an error with the base and index register
+asmr_w_possible_object_field_bug=07018_W_Âîçìîæíàÿ îøèáêà â óïðàâëåíèè ïîëÿ îáúåêòà
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Håâåpíûé ìàøòàá ôàêòîpà (?êîýôôèöèåíò Ëàìå? :-&)
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Ìíîæåñòâåííîå èñïîëüçîâàíèå èíäåêñà påãèñòpà
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Håâåpíûé òèï îïåpàíäà
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Håâåpíàÿ ñòpîêà, êàê îïåpàíä êîäà îïåpàöèè: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE è @DATA íå ïîääåpæèâàþòñÿ
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Ïyñòûå ññûëêè ìåòîê íå pàçpåøåíû
+asmr_e_expr_zero_divide=07025_E_Äåëåíèå íà íîëü â âûðàæåíèè
+asmr_e_expr_illegal=07026_E_Íåâåðíîå âûðàæåíèå
+asmr_e_escape_seq_ignored=07027_E_Esc-ïîñëåäîâàòåëüíîñòü èãíîpèpyåòñÿ: $1
+asmr_e_invalid_symbol_ref=07028_E_Håâåpíàÿ ññûëêà íà ñèìâîë
+asmr_w_fwait_emu_prob=07029_W_FWAIT ìîæåò âûçâàòü ïpîáëåìû ýìyëÿöèè ñ EMU387
+asmr_w_fadd_to_faddp=07030_W_$1 áåç îïåðàíäà òðàíñëèðóåòñÿ â $1P
+asmr_w_enter_not_supported_by_linux=07031_W_ENTER èíñòðóêöèÿ íå ïîääåðæèâàåòñÿ â Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Âûçîâ ïåpåãpyæåííîé ôyíêöèè â àññåìáëåpå
+asmr_e_unsupported_symbol_type=07033_E_Hå ïîääåpæèâàåìûé òèï ñèìâîëà â îïåpàíäå
+asmr_e_constant_out_of_bounds=07034_E_Ïîñòîÿííîå çíà÷åíèå âíå ãpàíèö
+asmr_e_error_converting_decimal=07035_E_Îøèáêà ïpè ïpåîápàçîâàíèè äåñÿòè÷íîãî ÷èñëà $1
+asmr_e_error_converting_octal=07036_E_Îøèáêà ïpè ïpåîápàçîâàíèè âîñìåpè÷íîãî ÷èñëà $1
+asmr_e_error_converting_binary=07037_E_Îøèáêà ïpè ïpåîápàçîâàíèè äâîè÷íîãî ÷èñëà $1
+asmr_e_error_converting_hexadecimal=07038_E_Îøèáêà ïpè ïpåîápàçîâàíèè øåñòíàäöàòåpè÷íîãî ÷èñëà $1
+asmr_h_direct_global_to_mangled=07039_H_$1 ïpåîápàçîâàíî â $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 ñâÿçàí ñ ïåpåãpyæåííîé ôyíêöèåé
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Hå ìîãy èñïîëüçîâàòü SELF âíå ìåòîäà
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Hå ìîãy èñïîëüçîâàòü __OLDEBP âíå âëîæåííîé ïpîöåäypû
+asmr_e_void_function=07043_W_Ôyíêöèÿ êîòîpàÿ îïpåäåëåíà êàê 'íå âîçpàùàþùàÿ çíà÷åíèé' íå ìîæåò èõ âîçâpàùàòü
+asmr_e_SEG_not_supported=07044_E_SEG íå ïîääåpæèâàåòñÿ
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Ñyôôèêñ pàçìåpà è àäpåñàò èëè èñõîäíûé pàçìåp íå ñîîòâåòñòâyþò
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Ñyôôèêñ pàçìåpà è àäpåñàò èëè èñõîäíûé pàçìåp íå ñîîòâåòñòâyþò
+asmr_e_syntax_error=07047_E_Ñèíòàêñè÷åñêàÿ îøèáêà ïðè àññåìáëèðîâàíèè
+asmr_e_invalid_opcode_and_operand=07048_E_Håâåpíàÿ êîìáèíàöèÿ êîäà îïåpàöèè è îïåpàíäîâ
+asmr_e_syn_operand=07049_E_Ñèíòàêñè÷åñêàÿ îøèáêà â îïåpàíäå ïðè àññåìáëèðîâàíèè
+asmr_e_syn_constant=07050_E_Ñèíòàêñè÷åñêàÿ îøèáêà â êîíñòàíòå ïðè àññåìáëèðîâàíèè
+asmr_e_invalid_string_expression=07051_E_Håâåpíîå ñòpîêîâîå âûpàæåíèå
+asmr_w_const32bit_for_address=07052_W_êîíñòàíòà ñ ñèìâîëîì $1 íå äëÿ 32bit àäðåñà
+asmr_e_unknown_opcode=07053_E_Íåèçâåñòíûé opcode $1
+asmr_e_invalid_or_missing_opcode=07054_E_Håâåpíàÿ èëè ïpîïyùåííàÿ êîìàíäà
+asmr_e_invalid_prefix_and_opcode=07055_E_Håâåpíàÿ êîìáèíàöèÿ ïpåôèêñà è êîìàíäû: $1
+asmr_e_invalid_override_and_opcode=07056_E_Håâåpíàÿ êîìáèíàöèÿ ïåpåîïpåäåëåíèÿ è êîìàíäû: $1
+asmr_e_too_many_operands=07057_E_Ñëèøêîì ìíîãî îïåpàíäîâ â ñòpîêå
+asmr_w_near_ignored=07058_W_Äèðåêòèâà NEAR èãíîpèpóåòñÿ
+asmr_w_far_ignored=07059_W_Äèðåêòèâà FAR èãíîpèpóåòñÿ
+asmr_e_dup_local_sym=07060_E_Ïîâòîpíîå îïpåäåëåíèå ëîêàëüíîãî ñèìâîëà $1
+asmr_e_unknown_local_sym=07061_E_Håèçâåñòíûé ëîêàëüíûé ñèìâîë $1
+asmr_e_unknown_label_identifier=07062_E_Håèçâåñòíàÿ ìåòêà èäåíòèôèêàòîpà $1
+asmr_e_invalid_register=07063_E_Íåïðàâèëüíîå èìÿ ðåãèñòðà
+asmr_e_invalid_fpu_register=07064_E_Håïpàâèëüíîå èìÿ påãèñòpà äëÿ îïåpàöèè ñ ïëàâàþùåé çàïÿòîé
+asmr_e_nor_not_supported=07065_E_NOR íå ïîääåpæèâàåòñÿ
+asmr_w_modulo_not_supported=07066_W_MODULO íå ïîääåpæèâàåòñÿ
+asmr_e_invalid_float_const=07067_E_Håâåpíàÿ êîíñòàíòà (ïëàâàþùàÿ çàïÿòàÿ): $1
+asmr_e_invalid_float_expr=07068_E_Håâåpíîå âûpàæåíèå (ïëàâàþùàÿ îïåpàöèÿ)
+asmr_e_wrong_sym_type=07069_E_Håâåpíûé òèï ñèìâîëà
+asmr_e_cannot_index_relative_var=07070_E_Hå ìîãy èíäåêñèpîâàòü ëîêàëüíyþ ïåpåìåííyþ èëè ïàpàìåòp ñ påãèñòpîì
+asmr_e_invalid_seg_override=07071_E_Håâåpíîå âûpàæåíèå ïåpåîïpåäåëåííîãî ñåãìåíòà
+asmr_w_id_supposed_external=07072_W_Èäåíòèôèêàòîp $1, ïpåäïîëîæèì ÷òî îí âíåøíèé
+asmr_e_string_not_allowed_as_const=07073_E_Håëüçÿ èñïîëüçîâàòü ñòpîêè êàê êîíñòàíòû
+asmr_e_no_var_type_specified=07074_Òèï ïåpåìåííîé íå yêàçàí
+asmr_w_assembler_code_not_returned_to_text=07075_E_Àññåìáëåpñêèé êîä íå âîçâpàùàåòñÿ â TEXT ñåãìåíò
+asmr_e_not_directive_or_local_symbol=07076_E_$1 íå äèpåêòèâà è íå ëîêàëüíûé ñèìâîë
+asmr_w_using_defined_as_local=07077_E_Èñïîëüçîâàíèå îïpåäåëåííîãî èìåíè êàê ëîêàëüíàÿ ìåòêà
+asmr_e_dollar_without_identifier=07078_E_Ñèìâîë '$' èñïîëüçyåòñÿ áåç èäåíòèôèêàòîpà
+asmr_w_32bit_const_for_address=07079_W_32-áèòíàÿ êîíñòàíòà ñîçäàåòñÿ äëÿ àäpåñà
+asmr_n_align_is_target_specific=07080_N_.ALIGN èñïîëüçyåòñÿ ñïåöèàëüíî äëÿ yêàçàíèÿ ïëàòôîpìû, èñïîëüçyéòå .BALIGN èëè .P2ALIGN
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Håò äîñòyïà ê ïîëþ ïàpàìåòpà íàïpÿìyþ, èñïîëüçyéòå påãèñòpû
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Håò äîñòyïà ê ïîëÿì îáúåêòîâ/êëàññîâ íàïpÿìyþ, èñïîëüçyéòå påãèñòpû
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Hå çàäàí pàçìåp è íåâîçìîæíî îïpåäåëèòü pàçìåp îïåpàíäîâ
+% You should specify explicitly a size for the reference, because
+% compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Hå ìîãy èñïîëüçîâàòü RESULT â ýòîé ôyíêöèè
+asmr_h_RESULT_is_reg=07085_H_RESULT ýòî påãèñòp $1
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" áåç îïåðàíäà òðàíñëèðóåòñÿ â "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" òðàíñëèðóåòñÿ â "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" òðàíñëèðóåòñÿ â "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Ñèìâîë < çäåñü íå ðàçðåøåí
+asmr_e_invalid_char_greater=07090_E_Ñèìâîë > çäåñü íå ðàçðåøåí
+asmr_w_xdef_not_supported=07091_W_XDEF íå ïîääåðæèâàåòñÿ
+asmr_e_invalid_global_def=07092_E_Íåâåðíûé ñèíòàêñèñ XDEF
+asmr_w_align_not_supported=07093_W_ALIGN íå ïîääåðæèâàåòñÿ
+asmr_e_no_inc_and_dec_together=07094_E_Inc è Dec íå ìîãóò áûòü âìåñòå
+asmr_e_invalid_reg_list_in_movem=07095_E_Íåâåðíûé reglist â movem
+asmr_e_invalid_reg_list_for_opcode=07096_E_Íåâåðíûé reglist äëÿ opcode
+asmr_e_68020_mode_required=07097_E_Òðåáóåòñÿ 68020 ðåæèì
+
+#
+# Assembler/binary writers
+#
+asmw_f_too_many_asm_files=08000_F_Ñëèøêîì ìíîãî ôàéëîâ äëÿ àññåìáëèpîâàíèÿ
+asmw_f_assembler_output_not_supported=08001_F_Âûápàííûé òèï àññåìáëåpà íå ïîääåpæèâàåòñÿ
+asmw_f_comp_not_supported=08002_F_COMP íå ïîääåpæèâàåòñÿ
+asmw_f_direct_not_supported=08003_F_Ïðÿìîé àññåìáëåp çäåñü íå ïîääåpæèâàåòñÿ
+asmw_e_alloc_data_only_in_bss=08004_E_Ðàñïpåäåëåíèå äàííûõ â ïàìÿòè âîçìîæíî òîëüêî â BSS ñåêöèè
+asmw_f_no_binary_writer_selected=08005_F_Íå âûáðàí ñòèëü àññåìáëèðîâàíèÿ
+asmw_e_opcode_not_in_table=08006_E_Asm: Êîìàíäû $1 íåò â ñïèñêå êîìàíä
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 íåâåpíàÿ êîìáèíàöèÿ îïåpàíäîâ â êîìàíäå
+asmw_e_16bit_not_supported=08008_E_Asm: 16-áèòíûå ññûëêè íå ïîääåpæèâàþòñÿ
+asmw_e_invalid_effective_address=08009_E_Asm: Håâåpíûé ýôôåêòèâíûé(?) àäpåñ
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Îæèäàåòñÿ IMMEDIATE èëè ññûëêà
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 çíà÷åíèå âûøëî çà ãpàíèöû $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: SHORT JUMP âûøåë çà ãpàíèöû äèàïîçîíà $1
+asmw_e_undefined_label=08013_E_Asm: Íåîïðåäåëåííàÿ ìåòêà $1
+asmw_e_comp_not_supported=08014_E_Asm: Òèï Comp íå ïîääåðæèâàåòñÿ ïîä ýòîé ïëàòôîðìîé
+asmw_e_extended_not_supported=08015_E_Asm: Òèï Extend íå ïîääåðæèâàåòñÿ ïîä ýòîé ïëàòôîðìîé
+asmw_e_duplicate_label=08016_E_Asm: Ïîâòîðíàÿ ìåòêà $1
+
+#
+# Executing linker/assembler
+#
+exec_w_source_os_redefined=09000_W_Èñõîäíàÿ îïåpàöèîííàÿ ñèñòåìà ïåpåîïpåäåëåíà
+exec_i_assembling_pipe=09001_I_Àññåìáëèpyåì (pipe) $1
+exec_d_cant_create_asmfile=09002_E_Hå ìîãy ñîçäàòü ôàéë àññìåáëåpà: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_objectfile=09003_E_Íå ìîãó ñîçäàòü îáúåêòíûé ôàéë: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_archivefile=09004_E_Íå ìîãó ñîçäàòü àðõèâíûé ôàéë: $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_assembler_not_found=09005_E_Àññåìáëåp $1 íå íàéäåí, èñïîëüçyåì âìåñòî íåãî âíåøíèé àññåìáëåp
+exec_t_using_assembler=09006_T_Èñïîëüçyåì àññåìáëåp: $1
+exec_e_error_while_assembling=09007_E_Îøèáêà ïpè àññåìáëèpîâàíèè $1
+exec_e_cant_call_assembler=09008_E_Hå ìîãy âûçâàòü àññåìáëåp, îøèáêà $1. Èñïîëüçyåì âìåñòî íåãî âíåøíèé àññåìáëåp
+exec_i_assembling=09009_I_Àññåìáëèpîâàíèå $1
+exec_i_assembling_smart=09010_I_Èíòåëåêòyàëüíîå àññåìáëèpîâàíèå $1
+exec_w_objfile_not_found=09011_W_Îáúåêòíûé ôàéë $1 íå íàéäåí, êîìïîíîâêà ìîæåò áûòü íåyäà÷íîé !
+exec_w_libfile_not_found=09012_W_Áèáëèîòåêà $1 íå íàéäåíà, êîìïîíîâêà ìîæåò áûòü íåyäà÷íîé !
+exec_e_error_while_linking=09013_E_Îøèáêà ïpè êîìïîíîâêå
+exec_e_cant_call_linker=09014_E_Hå ìîãy âûçâàòü êîìïîíîâùèê, èñïîëüçyåì âìåñòî íåãî âíåøíèé êîìïîíîâùèê
+exec_i_linking=09015_I_Êîìïîíîâêà $1
+exec_e_util_not_found=09016_E_Óòèëèòà $1 íå íàéäåíà, ïåpåêëþ÷àåìñÿ íà âíåøíþþ ëèíêîâêy
+exec_t_using_util=09017_T_Èñïîëüçóåì âíåøíþþ óòèëèòó $1
+exec_e_exe_not_supported=09018_E_Ñîçäàíèå èñïîëíÿåìûõ ôàéëîâ íå ïîääåpæèâàåòñÿ
+exec_e_dll_not_supported=09019_E_Ñîçäàíèå äèíàìè÷åñêèõ áèáëèîòåê (DLL) íå ïîääåpæèâàþòñÿ
+exec_i_closing_script=09020_I_Çàêpûâàåì ñêpèïò $1
+exec_e_res_not_found=09021_E_Êîìïèëÿòîp påñypñîâ íå íàéäåí, ïåpåêëþ÷àåìñÿ íà âíåøíèé êîìïèëÿòîð ðåñóðñîâ
+exec_i_compilingresource=09022_I_Êîìïèëèpyåì påñypñ $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_ìîäyëü $1 íå ìîæåò áûòü ñîápàí â påæèìå static, âêëþ÷àåì smart ñáîpêy
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_ìîäyëü $1 íå ìîæåò áûòü ñîápàí â påæèìå smart, âêëþ÷àåì static ñáîpêy
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_ìîäyëü $1 íå ìîæåò áûòü ñîápàí â påæèìå shared, âêëþ÷àåì static ñáîpêy
+exec_e_unit_not_smart_or_static_linkable=09026_E_ìîäyëü $1 íå ìîæåò áûòü ñîápàí â påæèìàõ smart èëè static
+exec_e_unit_not_shared_or_static_linkable=09027_E_ìîäyëü $1 íå ìîæåò áûòü ñîápàí â påæèìàõ shared èëè static
+
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_Hå ìîæåì èñïîëíèòü èñïîëíÿåìûé ìîäyëü $1
+execinfo_f_cant_open_executable=09029_F_Hå ìîãy îòêpûòü èñïîëíÿåìûé ìîäyëü $1
+execinfo_x_codesize=09030_X_Ðàçìåp êîäà: $1 áàéò
+execinfo_x_initdatasize=09031_X_Ðàçìåp èíèöèàëèçèpyþùåé ÷àñòè: $1 áàéò
+execinfo_x_uninitdatasize=09032_X_Ðàçìåp äå-èíèöèàëèçèpyþùåé ÷àñòè: $1 áàéò
+execinfo_x_stackreserve=09033_X_Çàpåçåpâèpîâàííî ñòåêà: $1 áàéò
+execinfo_x_stackcommit=09034_X_Èñïîëüçîâàíî ñòåêà: $1 áàéò
+
+# Unit loading
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Ïîèñê ìîäyëåé: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU çàãpyæàåòñÿ $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU èìÿ: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU ôëàãè: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU âpåìÿ: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_PPU ôàéë ñëèøêîì êîpîòêèé
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Håâåpíûé çàãîëîâîê PPU (íåò PPU ìåòêè âíà÷àëå)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Håâåpíàÿ âåpñèÿ PPU ôàéëà $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU ôàéë îòêîìïèëèpîâàí äëÿ äpyãîãî ïpîöåññîpà
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU ôàéë îòêîìïèëèpîâàí äëÿ äpyãîé OS
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU èñòî÷íèê: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Çàïèñûâàåì $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Hå ìîãy çàïèñàòü PPU-ôàéë
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_×èòàåì PPU-ôàéë
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Íåîæèäàííûé êîíåö y PPU-ôàéëà
+% Unexpected end of file.
+unit_f_ppu_invalid_entry=10016_F_Håïpàâèëüíûé âõîä â PPU-ôàéë: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU DBX COUNT ïpîáëåìà
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Håâåpíîå èìÿ ìîäyëÿ: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Ñëèøêîì ìíîãî ìîäyëåé
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Êpyãîâàÿ ññûëêà ìîäyëÿ ìåæäy $1 è $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Hå ìîãy îòêîìïèëèpîâàòü ìîäyëü $1. Hå ìîãy íàéòè èñõîäíèêîâ.
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Hå ìîãy íàéòè PPU ôàéë $1.
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Ìîäóëü $1 íå íàéäåí, íî $2 ñóùåñòâóåò
+unit_f_unit_name_error=10024_F_Ìîäóëü $1 èñêàëè, íî íàøëè ìîäóëü $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Òpåáyåòñÿ êîìïèëèpîâàíèå ñèñòåìíîãî ìîäyëÿ. Èñïîëüçyéòå êëþ÷ -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Îáíàpyæåíî $1 îøèáîê ïpè êîìïèëèpîâàíèè ìîäyëÿ, îñòàíàâëèâàåìñÿ
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Çàãpyçêà èç $1 ($2) ìîäyëü $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Ïåpåêîìïèëèpîâàíèå $1, êîíòpîëüíàÿ ñyììà y $2 èçìåíåíà
+unit_u_recompile_source_found_alone=10029_U_Ïåpåêîìïèëèpîâàíèå $1, òàê êàê íàéäåíû òîëüêî èñõîäíèêè
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Ïåpåêîìïèëèpîâàíèå ìîäyëÿ, òàê êàê áèáëèîòåêà (static) ñòàpøå ÷åì ppu-ôàéë
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Ïåpåêîìïèëèpîâàíèå ìîäyëÿ, òàê êàê áèáëèîòåêà (shared) ñòàpøå ÷åì ppu-ôàéë
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Ïåpåêîìïèëèpîâàíèå ìîäyëÿ, òàê êàê .as è .obj ôàéë ñòàpøå ÷åì ppu-ôàéë
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Ïåpåêîìïèëèpîâàíèå ìîäyëÿ, òàê êàê .obj ôàéë ñòàpøå ÷åì .as ôàéë
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_start_parse_interface=10034_U_Àíàëèçèðóåì èíòåpôåéñíóþ ÷àñòü $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_start_parse_implementation=10035_U_Àíàëèçèðóåì påàëèçàöèîííóþ ÷àñòü $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Âòîpàÿ çàãpyçêà äëÿ ìîäyëÿ $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU ïpîâåpêà ôàéëà $1 âpåìÿ $2
+unit_h_cond_not_set_in_last_compile=10038_H_Óñëîâíîå âûpàæåíèå $1 íå áûëî yñòàíîâëåíî ïpè ïîñëåäíåé êîìïèëÿöèè $2
+% when recompilation of an unit is required the compiler will check that
+% the same conditionals are set for the recompiliation. The compiler has
+% found a conditional that currently is defined, but was not used the last
+% time the unit was compiled.
+unit_h_cond_set_in_last_compile=10039_H_Óñëîâíîå âûpàæåíèå $1 áûëî yñòàíîâëåíî ïpè ïîñëåäíåé êîìïèëÿöèè $2
+% when recompilation of an unit is required the compiler will check that
+% the same conditionals are set for the recompiliation. The compiler has
+% found a conditional that was used the last time the unit was compiled, but
+% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Íàéäåí ìîäóëü $1 òðåáóþùèé ñáîðêè, íî íåêîòîðûå âêëþ÷àåìûå ôàéëû íå íàéäåíû
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Ôàéë $1 íîâåå ÷åì ôàéë $2 ($2 ñ ôëàãîì Release PPU)
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+% \end{description}
+
+#
+# Options
+#
+option_usage=11000_$1 [îïöèè] <ôàéë> [îïöèè]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Ïîääåpæèâàåòñÿ òîëüêî îäèí ôàéë äëÿ êîìïèëÿöèè
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF ôàéë ìîæåò ñîçäàâàòüñÿ òîëüêî ïîä OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Âëîæåííûå ôàéëû îòâåòà íå ïîääåpæèâàþòñÿ
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Èìÿ ôàéëà äëÿ êîìïèëÿöèè â êîìàíäíîé ñòpîêå íå îáíàðóæåíî
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Îïöèÿ êîìïèëÿòîðà $1 âíóòðè êîíôèãóðàöèîííîãî ôàéëà íå îáíàðóæåíà
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Håâåpíûé ïàpàìåòp: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? âûâåñòè ñòpàíèöû ïîìîùè
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Ñëèøêîì ìíîãî âëîæåííûõ êîíôèãypàöèîííûõ ôàéëîâ
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Hå ìîãy îòêpûòü ôàéë $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_×òåíèå äàëüíåéøèõ ïàpàìåòpîâ èç $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_TARGET yñòàíîâëåí äâàæäû â: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_SHARED áèáëèîòåêè íå ïîääåpæèâàþòñÿ â GO32* ïpèëîæåíèÿõ, äåëàåì èõ STATIC
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Ñëèøêîì ìíîãî $IFDEF èëè $IFNDEF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Ñëèøêîì ìíîãî $ENDIF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Îòêpûòèå yñëîâíîãî âûpàæåíèÿ â êîíöå ôàéëà
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Ãåíåpàöèÿ èíôîpìàöèè äëÿ îòëàäêè íå ïîääåpæèâàåòñÿ â ýòîì èñïîëíÿåìîì ôàéëå
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Ïîïpîáyéòå îòêîìïèëèpîâàòü ñ îïöèåé -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Âû èñïîëüçyéòå yñòàpåâøèé êëþ÷ $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Âû èñïîëüçyåòå yñòàpåâøèé êëþ÷ $1, ïîæàëyéñòà èñïîëüçyéòå âìåñòî íåãî êëþ÷ $2
+% Ýòî ïðåäóïðåæäàåò Âàñ, êîãäà Âû èñïîëüçóåòå êëþ÷, êîòîðûé áîëüøå íå
+% ïîääåðæèâàåòñÿ. Âû äîëæíû èñïîëüçîâàòü âòîðîé êëþ÷ âìåñòî ýòîãî.
+% Ðåêîìåíäóåòñÿ, çàìåíèòü êëþ÷, ÷òîáû ïðåîäîëåòü ïðîáëåìû â áóäóùåì,
+% êîãäà êëþ÷, yêàçàííûé âàìè ìîæåò èçìåíÿòüñÿ è èìåòü äpyãîå çíà÷åíèå.
+option_switch_bin_to_src_assembler=11020_N_Ïåpåêëþ÷àåì àññåìáëåp â àññåìáëåp çàäàííûé ïî yìîë÷àíèþ
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Âèä âûáðàííîãî ñòèëÿ àññåìáëåðà "$1" íå ñîâìåñòèì ñ "$2"
+option_asm_forced=11022_W_Ê ñîæàëåíèþ, èñïîëüçóåì ñòèëü àññåìáëåðà "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_×èòàþ îïöèè èç ôàéëà $1
+% Options are also read from this file
+option_using_env=11027_T_×èòàþ îïöèè èç îêðóæåíèÿ $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Îáðàáîòêà îïöèè "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** íàæìèòå enter ***
+
+#
+# Ëîãî (îïöèÿ -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCVER [$FPCDATE] for $FPCTARGET [Russian Edition]
+Copyright (c) 1993-2002 by Florian Klaempfl
+]
+
+#
+# Èíôîpìàöèÿ (îïöèÿ -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVER
+
+Compiler Date : $FPCDATE
+Compiler Target: $FPCTARGET
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs, suggestions and etc to:
+ bugrep@freepascal.org, russia@freepascal.org
+]
+
+#
+# Ñòðàíèöû Ñïðàâêè (îïöèÿ -? È -h)
+#
+# Îáðàòèòü âíèìàíèå: Hyìåpàöèþ íå ìåíÿòü!
+#
+option_help_pages=11025_[
+**0*_äåëàé '+', ÷òîáû âêëþ÷èòü êëþ÷, è '-' ÷òîáû îòêëþ÷èòü åãî
+**1a_êîìïèëÿòîð íå áyäåò óäàëÿòü ñãåíåðèðîâàííûé àññåìáëåðñêèé ôàéë
+**2al_âûâîäèòü íîìåpà ñòðîê â àññåìáëèpîâàíííîì ôàéëå
+**2ar_âûâîäèòü èíôîpìàöèþ î ñïèñêå çàíÿòûõ/îñâîáîæäåííûõ påãèñòpîâ â àññåìáëåpñêèé ôàéë
+**2at_âûâîäèòü èíôîpìàöèþ î ñïèñêå çàíÿòûõ/îñâîáîæäåííûõ âpåìåííûõ ïåpåìåííûõ â àññåìáëåpñêèé ôàéë
+**1b_ãåíåpèpîâàòü èíôîpìàöèþ äëÿ ápàyçåpà (IDE)
+**2bl_òàêæå ãåíåpèpèòü èíôîpìàöèþ î ëîêàëüíûõ ñèìâîëàõ
+**1B_ïåpåêîìïèëèpîâàòü âñå ìîäyëè
+**1C<x>_îïöèè ãåíåpàòîpà êîäà
+3*2CD_òàêæå ñîçäàòü äèíàìè÷åñêyþ áèáëèîòåêy (íå ïîääåpæèâàåòñÿ)
+**2Ch<n>_<n> áàéò êy÷è (ìåæäó 1023 è 67107840)
+**2Ci_ïpîâåpêà ââîäà-âûâîäà
+**2Cn_ïpîïyñòèòü ñòàäèþ ëèíêîâêè ìîäyëÿ
+**2Co_ïpîâåpÿòü ïåðåïîëíåíèå â öåëî÷èñëåííûõ îïåðàöèÿõ
+**2Cr_ïpîâåpêà äèàïàçîíà
+**2Cs<n>_yñòàíîâèòü pàçìåp ñòåêà äî <n>
+**2Ct_ïðîâåðêà ñòåêà
+3*2CX_òàêæå ñîçäàòü smartlink âåpñèþ
+**1d<x>_îïpåäåëèòü ñèìâîë <x>
+*O1D_ñîçäàòü DEF-ôàéë
+*O2Dd<x>_yñòàíîâèòü îïèñàíèå â <x>
+*O2Dw_PM ïðèëîæåíèå
+**1e<x>_yñòàíîâèòü ïyòü äëÿ èñïîëíÿåìûõ ôàéëîâ
+**1E_òîæå, ÷òî è -Cn
+**1F<x>_yñòàíîâèòü èìåíà ôàéëîâ è ïóòè
+**2FD<x>_yñòàíîâèòü ïyòè äî êàòàëîãîâ, ãäå èñêàòü óòèëèòû
+**2Fe<x>_ïåpåíàïpàâèòü âûâîä îøèáîê â <x>
+**2Fi<x>_äîáàâèòü <x> ê ïyòÿì äî âêëþ÷àåìûõ ôàéëîâ
+**2Fl<x>_äîáàâèòü <x> ê ïyòÿì äî ôàéëîâ áèáëèîòåê
+*L2FL<x>_èñïîëüçîâàòü <x> êàê äèíàìè÷åñêèé êîìïîíîâùèê
+**2Fo<x>_äîáàâèòü <x> ê ïyòÿì äî îáúåêòíûõ ôàéëîâ
+**2Fr<x>_çàãpyçèòü ôàéë ñîîáùåíèé îá îøèáêàõ <x>
+**2Fu<x>_äîáàâèòü <x> ê ïóòè äî ìîäóëåé
+**2FU<x>_yñòàíîâèòü ïyòü äî ìîäyëåé êàê <x>, îòìåíÿåò -FE
+*g1g_ñîçäàâàòü èíôîðìàöèþ äëÿ îòëàä÷èêà
+*g2gg_èñïîëüçîâàòü GSYM
+*g2gd_èñïîëüçîâàòü DBX
+*g2gh_èñïîëüçîâàòü ìîäyëü ñëåæåíèÿ çà êó÷åé (äëÿ îòëàäêè yòå÷åê ïàìÿòè)
+*g2gl_èñïîëüçîâàòü ëèíèè â èíôîpìàöèîííîì ìîäyëå äëÿ áîëüøåé èíôîpìàöèè ïpè îòëàäêå
+*g2gc_ãåíåðèðîâàòü ïðîâåðêè äëÿ óêàçàòåëåé
+**1i_èíôîpìàöèÿ
+**2iD_âîçâpàùàåò äàòy êîìïèëÿòîpà
+**2iV_âîçpàùàåò âåpñèþ êîìïèëÿòîðà
+**2iSO_âîçâpàùàåò òèï OS, íà êîòîpîé áûë ñîçäàíà ïpîãpàììà
+**2iSP_âîçâpàùàåò òèï ïpîöåññîpà, íà êîòîpîì áûëà ñîçäàíà ïpîãpàììà
+**2iTO_âîçâpàùàåò òèï OS, äëÿ êîòîpîé áûëà ñîçäàíà ïpîãpàììà
+**2iTP_âîçâpàùàåò òèï ïpîöåññîpà, äëÿ êîòîpîãî áûëà ñîçäàíà ïpîãpàììà
+**1I<x>_äîáàâëÿåò <x> â ïyòè äî âêëþ÷àåìûõ ôàéëîâ
+**1k<x>_ïpîõîä <x> êîìïîíîâùèêy
+**1l_çàïèñûâàòü â ïpîãpàììy ëîãîòèï fpc
+**1n_íå ÷èòàòü ñòàíäàpòíûé ôàéë êîíôèãóðàöèè
+**1o<x>_èçìåíèòü èìÿ ïðîãðàììû, íà <x>
+**1pg_ãåíåpàöèÿ ïðîôèëèðóþùåãî êîäà äëÿ GPROF (îïpåäåëÿåò FPC_PROFILE)
+*L1P_èñïîëüçîâàòü ôàéëû â ïàìÿòè (pipes) âìåñòî âðåìåííûõ ôàéëîâ àññåìáëåðà
+**1S_ñèíòàêñè÷åñêèå îïöèè
+**2S2_êëþ÷ âêëþ÷åíèÿ íåêîòîpûõ pàñøèpåíèé Delphi 2
+**2Sc_ïîääåpæèâàòü îïåðàòîðû, ïîõîæèå íà îïåpàòîpû â C (*=,+=,/= è -=)
+**2sa_âêëþ÷àòü êîíòðîëèðóþùèé êîä
+**2Sd_påæèì Delphi-ñîâìåñòèìîñòè
+**2Se<x>_êîìïèëÿòîp îñòàíàâëèâàåòñÿ ïîñëå <x> îøèáêè (ïî óìîë÷àíèþ ïîñëå 1 îøèáêè)
+**2Sg_ïîääåpæèâàòü LABEL è GOTO
+**2Sh_èñïîëüçîâàòü ANSI ñòpîêè
+**2Si_ïîääåpæèâàòü ñòèëü INLINE ÿçûêà C++
+**2Sm_ïîääåpæèâàòü ìàêðîêîìàíäû ïîäîáíî C (ãëîáàëüíî)
+**2So_påæèì TP/BP 7.0 ñîâìåñòèìîñòè
+**2Sp_påæèì GPC ñîâìåñòèìîñòè
+**2Ss_êîíñòpyêòîp äîëæåí èìåòü èìÿ init (äåñòpyêòîp äîëæåí èìåòü èìÿ done)
+**2St_ïîääåpæêà ñòàòè÷åñêèõ êëþ÷åâûõ ñëîâ â îáúåêòàõ
+**1s_íå âûçûâàòü àññåìáëåð è êîìïîíîâùèê ïpè pàáîòå (òîëüêî ñ -a)
+**1u<x>_yäàëÿåò îïpåäåëåíèå ñèìâîëà <x>
+**1U_îïöèè ìîäyëåé
+**2Un_íå ïpîâåpÿòü ñîîòâåòñòâèå èìåíè ìîäyëÿ è èìåíè ôàéëà ìîäyëÿ
+**2Us_ñêîìïèëèpîâàòü ãëàâíûé ìîäyëü (system)
+**1v<x>_ïîäpîáíîñòü <x> ýòî êîìáèíàöèÿ ñëåäyþùèõ ñèìâîëîâ:
+**2*_e : Âñå îøèáêè (ïî óìîë÷àíèþ) d: Èíôîðìàöèÿ äëÿ îòëàäêè
+**2*_w : Ïðåäóïðåæäåíèÿ u: Èíôîðìàöèþ ìîäóëÿ
+**2*_n : Ïðèìå÷àíèÿ t: Ïðîáîâàííûå/èñïîëüçîâàííûå ôàéëû
+**2*_h : Ïîäñêàçêè m: Îïðåäåëåííûå ìàêðîêîìàíäû
+**2*_i : Îáùàÿ èíôîðìàöèÿ p: Êîìïèëèðóåìûå ïðîöåäóðû
+**2*_l : Hîìåpà ëèíèé c: Óñëîâíûå âûðàæåíèÿ
+**2*_a : Âñå ïîêàçûâàòü 0: Hè÷åãî íå ñîîáùàòü, êpîìå îøèáîê
+**2*_b : Ïîêàçàòü âñþ ïpîöåäypy, r: Rhide/GCC ðåæèì ñîâìåñòèìîñòè
+**2*_ åñëè îøèáêà ïpîèñõîäèò x: Èíôîðìàöèÿ î ôàéëå (òîëüêî Win32)
+**2*_ èìåííî â íåé
+**1X_îïöèè âûïîëíåíèÿ
+*L2Xc_ëèíêîâàòü ñ áèáëèîòåêîé ÿçûêà C
+**2Xs_î÷èñòèòü âñå ñèìâîëüíûå èìåíà èç ïpîãpàììû
+**2XD_ëèíêîâàòü äèíàìè÷åñêèå áèáëèîòåêè (îïpåäåëÿåò FPC_LINK_DYNAMIC)
+**2XS_ëèíêîâàòü ñòàòè÷åñêèå áèáëèîòåêè (îïpåäåëÿåò FPC_LINK_STATIC)
+**2XX_ëèíêîâàòü smart-áèáëèîòåêè (îïpåäåëÿåò FPC_LINK_SMART)
+**0*_Îïöèè ñïåöèôè÷íûå äëÿ ïpîöåññîpîâ:
+3*1A<x>_ôîðìàò âûâîäà
+3*2Aas_ôàéë, èñïîëüçóþùèé GNU
+3*2Aasaout_ôàéë, èñïîëüçóþùèé GNU for aout (Go32v1)
+3*2Anasmcoff_coff (Go32v2) ôàéë, èñïîëüçóþùèé Nasm
+3*2Anasmelf_elf32 (Linux) ôàéë, èñïîëüçóþùèé Nasm
+3*2Anasmobj_obj ôàéë, èñïîëüçóþùèé Nasm
+3*2Amasm_obj èñïîëüçyþùèé Masm (Microsoft)
+3*2Atasm_obj èñïîëüçyþùèé Tasm (Borland)
+3*2Acoff_coff (Go32v2) èñïîëüçóÿ âñòðîåííûé àññåìáëåð
+3*2Apecoff_pecoff (Win32) èñïîëüçóÿ âñòðîåííûé àññåìáëåð
+3*1R<x>_ñòèëü ÷òåíèÿ àññåìáëåpà
+3*2Ratt_÷èòàòü êàê àññåìáëåð â ñòèëå AT&T
+3*2Rintel_÷èòàòü êàê àññåìáëåð â ñòèëå Intel
+3*2Rdirect_òåêñò àññåìáëåðà ïåpåäàâàòü íåïîñðåäñòâåííî àññåìáëåðy
+3*1O<x>_òèïû îïòèìèçàöèé
+3*2Og_ãåíåpèpîâàòü ìåíüøèé êîä
+3*2OG_ãåíåpèpîâàòü áûñòpûé êîä (ïî yìîë÷àíèþ)
+3*2Or_ñîõpàíÿòü íåêîòîðûå ïåðåìåííûå â ðåãèñòpàõ
+3*2Ou_âêëþ÷èòü íåîïðåäåëåííûå îïòèìèçàöèè (ñì. äîêóìåíòàöèþ)
+3*2O1_ypîâåíü 1 îïòèìèçàöèè (áûñòðûå îïòèìèçàöèè)
+3*2O2_ypîâåíü 2 îïòèìèçàöèè (-O1 + áîëåå ìåäëåííûå îïòèìèçàöèè)
+3*2O3_ypîâåíü 3 îïòèìèçàöèè (òîò æå ñàìûé êàê -O2u)
+3*2Op_òèï ïðîöåññîðà, äëÿ êîòîpîãî ïpîèñõîäèò êîìïèëÿöèÿ:
+3*3Op1_äëÿ ïðîöåññîðà 386/486
+3*3Op2_äëÿ ïðîöåññîð Pentium/PentiumMMX (tm)
+3*3Op3_ïðîöåññîð Pentium PRO/Pentium II/Cyrix 6X86/AMD K6 (tm)
+3*1T<x>_òèï îïåðàöèîííàÿ ñèñòåìû, äëÿ êîòîpîé ïpîèñõîäèò êîìïèëÿöèÿ:
+3*2TGO32V2_version 2 (DJ Delorie ðàñøèðèòåëü DOS)
+3*2TLINUX_Linux
+3*2TOS2_OS/2 / eComStation
+3*2TWIN32_Windows 32 Bit
+3*1W<x>_Win32 îïöèè
+3*1WB<x>_ Óñòàíîâêà Image áàçû â øåñòíàäöåòèðè÷íîå <x> çíà÷åíèå
+3*1WC_ Îïðåäåëèòü, ÷òî ýòî áóäåò êîíñîëüíîå ïðèëîæåíèå
+3*1WD_ Èñïîëüçîâàòü DEFFILE äëÿ ýêñïîðòèðîâàííûõ ôóíêöèé DLL èëè EXE
+3*1WG_ Îïðåäåëèòü, ÷òî ýòî áóäåò GUI ïðèëîæåíèå
+3*1WN_ Íå ãåíåðèðîâàòü ïåðåìåùàåìûé êîä (íåîáõîäèìî äëÿ îòëàäêè)
+3*1WR_ Ãåíåðèðîâàòü ïåðåìåùàåìûé êîä
+6*1A<x>_ôîðìàò àññåìáëåpà
+6*2Ao_Unix o-ôàéë, èñïîëüçóþùèé GNU àññåìáëåp
+6*2Agas_GNU àññåìáëåð ôèðìû Motorola
+6*2Amit_MIT ñèíòàêñèñ (ñòàðûé GAS)
+6*2Amot_ñòàíäàpòíûé àññåìáëåp ôèðìû Motorola
+6*1O_îïòèìèçàöèè
+6*2Oa_âêëþ÷àåò îïòèìèçàòîp
+6*2Og_ãåíåpèpîâàòü ìåíüøèé êîä
+6*2OG_ãåíåpèpîâàòü áûñòpûé êîä (ïî óìîë÷àíèþ)
+6*2Ox_ìàêñèìàëüíàÿ îïòèìèçàöèÿ (åñòü îøèáêè!)
+6*2O2_äëÿ ïðîöåññîðà MC68020+
+6*1R<x>_ñòèëü ÷òåíèÿ àññåìáëåpà
+6*2RMOT_÷èòàòü êàê Motorola-àññåìáëåp
+6*1T<x>_îïåðàöèîííàÿ ñèñòåìà äëÿ êîòîpîé êîìïèëèpyåòñÿ ôàéë
+6*2TAMIGA_Commodore ÏÝÂÌ ôèðìû Commodore
+6*2TATARI_Atari ST/STe/TT
+6*2TMACOS_Macintosh m68k
+6*2TLINUX_Linux-68k
+**1*_
+**1?_ïîêàçàòü ýòy ñïðàâêy
+**1h_ïîêàçàòü ýòy ñïðàâêy, áåç îæèäàíèÿ <enter>
+]
+#
+# The End
diff --git a/compiler/msg/errorues.msg b/compiler/msg/errorues.msg
new file mode 100644
index 0000000000..767cf629b0
--- /dev/null
+++ b/compiler/msg/errorues.msg
@@ -0,0 +1,2368 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Spanish Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# 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.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilador: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SO del host: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SO de destino: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Usando la ruta para ejecutables: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_Usando la ruta para unidades: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Usando la ruta para inclusiones: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Usando la ruta para bibliotecas: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Usando la ruta para objetos: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Líneas compiladas, $2 seg
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_No queda suficiente memoria disponible
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Escribiendo archivo de recursos de tabla de cadenas: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Escribiendo archivo de recursos de tabla de cadenas: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Aviso:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Consejo:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_La ruta "$1" no existe
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_Compilación abortada
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Final de fichero inesperado
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_La cadena excede la línea
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Caracter inválido
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Error de sintaxis, se esperaba "$1" pero se encontró "$2"
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Empezando a leer el fichero incluido $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Nivel de comentario anidado $1 encontrado
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Directiva de compilación $1 ignorado
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Directiva de compilación $i inválida
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Esta opción de compilacion tiene un efecto global
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante de caracter inválido
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_No se puede abrir el fichero "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_No se puede abrir el fichero de inclusion "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Los campos de los registros pueden ser alineados solo a 1, 2, 4 o 16 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1, 2, 4, 8, 16 and 32 are valid in this case.
+scan_w_only_pack_enum=02016_W_Los tipos enumerados solo pueden ser almacenados en 1, 2 o 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_$1 esperado para $2 definido en la línea $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Error de sintaxis mientras se procesaba una expresión de compilación condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Evaluando una expresión de compilación condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_El contenido de las macros esta limitado a 255 caracteres de longitud
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sin IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Error de usuario: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Error de usuario: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Aviso de usuario: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Nota de usuario: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Consejo de usuario: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Informacion de usuario: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Palabra clave redefinida como macro no tiene efecto
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Desbordamiento del buffer de macro durante la lextura o expansión
+% Your macro or it's result was too long for the compiler.
+can_w_macro_too_deep=02030_W_La expansión de macros excede una profundidad de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Las directivas de compilacióon no estan soportadas en comentarios estilo //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Manejando la directiva "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 encontrado
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Omitiendo hasta...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Presione <retorno> para continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Conmutador "$1" no soportado
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Directiva de compilación "$1" inválida
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Vuelve en $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Tipo de aplicación no soportada: "$1"
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE no es soportado por el SO de destino
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION no es soportado por el SO de destino
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION no es soportado por el SO de destino
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION sólo para EXEs o DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Formato erroneo para la directiva VERSION: "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Estilo de ensamblador inváalido especificado: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_No es posible cambiar el lector dentro de una sentencia asm. "$1" solo sera efectivo en los siguientes
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Modificador de conmutador erróneo, use ON/OFF o +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Los ficheros de recursos no son soportados por la plataforma de destino
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Variable de entorno incluida "$1" no encontrada.
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valor inválido para el registro de la FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_La plataforma de destino solo soporta un archivo de recursos
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_El soporte para macros ha sido deshabilitado
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_El tipo de interfaz especificado es inválido. Debe ser COM, CORBA o DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID solo esta soportado para PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME solo esta soportado para PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Las constantes de cadena no pueden ser de mas de 255 caracteres de longitud
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_La inclusion de archivos no puede exceder 16 niveles
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Demasiados niveles de PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_A POP sin un PUSH previo
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro o variable de compilación "$1" no tiene ningún valor
+% Thus the conditional compiling expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Valor invalido para el conmutado, use ON/OFF/DEFAULT o +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_No esta permitido cambiar de modo a "$1" aqui
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Variable en tiempo de compilación "$1" no ha sido definida.
+% Thus the conditional compile time expression cannot be evaluated.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Analizador - Error de sintaxis
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Los procedimientos INTERRUPT no pueden ser anidados
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo de procedimiento "$1" ignorado
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_No todas las declaraciones de "$1" llevan OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Nombre de funcion exportada "$1" duplicado
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Indice de funcion exportada "$1" duplicado
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Indice de funcion exportada inválido
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_La informacion de depurado $1 para ejecutables o DLLs reubicables no funciona. Desactivado.
+parser_w_parser_win32_debug_needs_WN=03012_W_Para permitir el depurado en win32 las reubicaciones deben ser desactivadas con la opcion -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_El nombre del constructor debe ser INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_El nombre del destructor debe ser DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Procedimientos tipo INLINE no soportados
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_El constructor debería ser público
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_El destructor debería ser público
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Una clase debería tener solo un destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Las definiciones de clases locales no están permitidas
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Las definiciones de clases anónimas no están permitidas
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_El objeto "$1" no tiene VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista de parámetros inválida
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Numero de parámetros incorrecto
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_el identificador sobrecargado "$1" no es una función
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_funciones sobrecargadas tienen los mismos par metros
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_la cabecera de la función no concuerda con la declaración posterior "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_la cabecera de la funcion "$1" no concuerda con la posterior declaración : el nombre de la variable cambia $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_el orden de los valores en una enumeracion debe ser ascendente
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With no puede ser usado con variables en segmentos diferentes
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Anidado de funciones > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_error en la comprobación de rangos mientras se evaluaban constantes
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_error en la comprobacion de rangos mientras se evaluaban constantes
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_etiqueta de caso duplicada
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_El líimite superior del caso es menor que el inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_no se permiten constantes con tipo de clases
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_no se permite asignar a variables de funcion funciones sobrecargadas
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_la longitud de una cadena tiene que ser un valor entre 1 y 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_use la sintaxis estendida de DISPOSE y NEW para instancias de objetos
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_el uso de NEW o DISPOSE para punteros sin tipo no tiene sentido
+parser_e_no_new_dispose_on_void_pointers=03044_E_el uso de NEW o DISPOSE no es posible con punteros sin tipo
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_identificador de clase esperado
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_identificador de tipo no permitido aquí
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_identificador de método esperado
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_la cabecera de la funcion no concuerda con ningún método de esta clase "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_proceduimiento/función $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante de punto flotante inválida
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL solo puede ser usado en constructores
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Los destructores no pueden tener parámetros
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Solo los métodos de clases pueden ser referidos con referencias de clase
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Los métodos de clase solo pueden ser acceder a otros métodos de clase
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Los tipos de la constante y del CASE no concuerdan
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_El símbolo no puede ser exportado de una librería
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Un método heredado ha sido ocultado por "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_No hay un método en una clase antepasada para ser substituido: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_No se suministro un miembro para acceder a propiedad
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_La directiva de propiedad Stored no esta implementada aún
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_símbolo inváalido para el acceso a la propiedad
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_No se puede acceder a un campo protegido de un objeto aquí
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_No se puede acceder a un campo privado de un objeto aquí
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_los métodos reemplazados deben tener el mismo tipo de dato devuelto: "$2" es reemplazado por "$1" que devuelve otro tipo
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Las funciones declarados como EXPORT no pueden estar anidados
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_los métodos no pueden ser EXPORTados
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_en llamadas con parámetros VAR los tipos deben coincidir exactamente. Se recibio "$1" cuando se esperaba "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_La clase no es un ancestor de la clase actual
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF solo está permitido en métodos
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_los métodos solo pueden estar en otros métodos llamados directamente con el tipo identificador de la clase
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso inválido de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Error en la comprobación de rangos en el constructor del set, o elemento duplicado en el set
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Se esperaba un puntero a objeto
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_La expresión tiene que ser una llamada al constructor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_La expresión tiene que ser una llamada al destructor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Orden de los campos del registro incorrecto
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_El tipo de la expresión tiene que ser class o record
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Los procedimientos no pueden devolver ningún valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_constructores y destructores deben ser métodos
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_El operador no esta sobrecargado
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Imposible sobrecargar operador de asignacion para tipos iguales
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Sobrecarga de operador imposible
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-lanzamiento de la excepcion no es posible aquí
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_La sintaxis extendida de new o dispose no está permitida para una clase
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_La sobrecarga de funciones no esta activada
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_No es posible sobrecargar este operador (sobrecarge en cambio "=" )
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operador comparativo tiene que devolver un valor booleano
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Solo los métodos virtuales pueden ser abstractos
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Uso de característica no soportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_No se permite la mezcla de objetos de diferentes tipos (class, object, interface, etc)
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Directiva de procedimiento desconocida fue ignorada: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute solo puede estar asociado a una variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute solo puede ser asociado con var o const
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Solo una variable puede ser inicializada
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Métodos abstractos no deberían tener ninguna definición (con el cuerpo de la función)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Esta función sobrecargada no puede ser local (debe ser exportada)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Métodos virtuales están siendo usados sin un constructor en "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definido: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro indefinido: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 asignado a $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Interpretando interfaz de la unidad $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Interpretando implementacion de la unidad $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilando $1 por segunda vez
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No se encontro la propiedad a reemplazar
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Sólo se permite una única propiedad por defecto
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propiedad por defecto tiene que ser un array
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Solo las clases soportan constructores virtuales
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No hay propiedad por defecto disponible
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_La clase no puede tener una sección published, use el conmutador {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Declaración posterior de la clase "$1" tiene que ser resuelta aquí para usar la clase como antepasado
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Operadores locales no soportados
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Directiva de procedimiento "$1" no permitida en la sección de interfaz
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Directiva de procedimiento "$1" no permitida en la sección de implementacion
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Directiva de procedimiento "$1" no permitida en la declaración de tipo
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La función esta actualmente declarada como Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_No se pueden usar ambos EXPORT y EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" aún no soportado en procedimientos/funciones inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining deshabilitado
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Escribiendo Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_podría ser que falte la de-referencia del puntero
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Lector del ensamblador seleccionado no soportado
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Directiva de procedimiento "$1" causa conflicto con otras directivas
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convencion de llamada actual no concuerda con la definida anteriormente
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_La propiedad no puede tener un valor por defecto
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_El valor por defecto de una propiedad tiene que ser constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_El símbolo no puede ser published, solo puede ser una clase
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Este tipo de propiedad no puede ser published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Se requiere un nombre de importación
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Division por cero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Operacion de punto flotante no válida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Límite superior del rango es menor que el límite inferior
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_La cadena "$1" es mas larga que $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_La longitud de la cadena es mayor que el tamaño array de carácteres
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expresión inválida tras la directiva de mensaje
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Los méetodos de manejo de mensajes deben tener un único parámetro por referencia
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Etiqueta de mensaje duplicada: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self solo puede ser un parámetro explícito en manejadores de mensajes
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars sólo pueden ser globales o estáticos
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Ensamblador directo no soportado para formato binario de salida
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use an other assembler reader
+parser_w_no_objpas_use_mode=03149_W_No carges manuamente la unidad OBJPAS, usa \{\$mode objfpc\} o \{\$mode delphi\}
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE no puede ser usado en objetos
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Tipos de datos que requieran inicializacion/finalizacion no pueden ser usados en registros variables
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings solo pueden ser globales o estáaticos
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit con parámetro no puede ser usado aquí
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_El tipo del símbolo en stored debe ser de tipo booleano
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Este símbolo no puede ser usado en storage para una propiedad
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Solo clases compiladas en $M+ pueden ser publicadas
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Directiva de procedimiento esperada
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_El valor para el índice de una propiedad debe ser de tipo ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nombre del procedimiento demasiado corto para ser exportado
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No se puede generar una entrada DEFFILE para las variables globales de la unidad
+parser_e_dlltool_unit_var_problem2=03161_E_Compile sin la opcion -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Se requiere el modo ObjFpc (-S2) o Delphi (-Sd) para compilar este módulo
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_No se pueden exportar funciones o procedimientos por indice en $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exportar variables no esta soportado en $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintaxis de GUID incorrecta
+parser_w_interface_mapping_notfound=03168_W_No se encontro el procedimiento de nombre "$1" apropiado para implementar $2.$3
+parser_e_interface_id_expected=03169_E_identificador de interfaz esperado
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_El tipo "$1" no puede ser usado como indice en arrays
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_No se permiten constructores/destructores en interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_No se permiten especificadores de acceso en interfaces
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Una interfaz no puede contener campos
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_No se puede declarar un procedimiento local como externo
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Algunos campos anteriores a "$1" no fueron inicializados
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Algunos campos anteriores a "$1" no fueron inicializados
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Algunos campos tras "$1" no fueron inicializados
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Directiva VarArgs sólo es válida con CDecl o External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self debe ser un parámetro normal por valor
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_La interfaz "$1" no tiene identificacion
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Campo de la clase o método desconocido "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Varias convenciones de llamada especificadas, "$1" ignorado al especificar "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_constantes con tipo de tipo Procedure/Function (...) of Object solo pueden ser inicializados a NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Sólo se puede asignar valor por defecto a un parámetro
+parser_e_default_value_expected_for_para=03185_E_Parámetro por defecto requerido para "$1"
+parser_w_unsupported_feature=03186_W_¡Uso de una caracteristica no soportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Arrays tipo C son pasados por referencia
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Array tipo C de const debe ser el ultimo parámetro
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Redefinición del tipo "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Procedimientos y funciones declarados como cdecl no reciben de parámetro el límite superior
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_open strings no son soportados en funciones cdecl
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_No se pueden inicializar variables declaradas como threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_La directiva Message sólo es valida en clases
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Se esperaba un procedimiento o funcion
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Directiva de convención de llama "$1" ignorada
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE no puede ser utilizado en objetos
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Cada parámetro debe tener su propia posición
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Cada parámetro debe tener su propia posición
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Localizacón en el segmento desconocida
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Se esperaba una variable entera de 32 bits o un puntero
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_No se puede usar Goto para saltar a otro procedimiento
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedimiento demasiado complejo. Se requieren demasiados registros
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Expresión inválida
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_La expresión no evalua un número entero
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_calificador inválido
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_El limite superior especificado es menor que el inferior
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_El parámetro de Exit debe ser el nombre del mismo procedimiento en el que está
+% Non local exit is not allowed. This error occur only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Asignación inválida a la variable de bucle "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_No se puede declarar una variable local como externa
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_El procedimiento ya ha sido declarado como externo con anterioridad
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Uso implícito de la unidad Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Clases y métodos estáticos no pueden ser utilizados en interfaces
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Desbordamiento en la operación aritmética
+% An operation on two integers values produced an overflow
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Los tipos no concuerdan
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipos incompatibles: se encontró "$1" esperado "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Los tipos $1 y $2 no concuerdan
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificador de tipo esperado
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificador de variable esperado
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_expression entera esperada, pero se encontró "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Expresion booleana esperada, pero se encontró "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Espresión ordinal esperada
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Se esperaba un tipo puntero, pero se encontró "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Se esperaba un tipo de clase, pero se encontró "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_No se puede evaluar la espresión constante
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Elementos de sets incompatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operación no implementada para sets
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversion automática de tipo de punto flotante a COMP el cual es un tipo entero
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_usa DIV para tener un resultado entero
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Tipos de cadena no concuerdan por la presencia de la opción $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_No se permite el uso de Succ o Pred en enumeraciones que tienen valores asignados explícitamente
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_No se puede leer o escribir variables de este tipo
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_No se puede utilizar readln o writeln en ficheros con tipo
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_No se pueden usar read o write en ficheros sin tipo
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_El set contiene un elemento que no es de tipo compatible
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(longint/dword) devuelve la parte superior/inferior de tipo word
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Espresión entera o real esperada
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo "$1" erróneo en el constructor del array
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipo incompatible para el parámetro número $1: Se recibió "$2", cuando se esperaba "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Variables de tipo método y procedimiento no son compatibles entre si
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante pasada a la función matematica interna no válida
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_No se puede obtener una dirección de una constante
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_No se puede asignar un valor al parámetro
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_No se puede asignar un prodecimiento o funcion local a una variable
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_No se puede asignar un valor a una dirección
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_No se pueden asignar valores a variables constantes
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Se requiere un array para usar [ ]
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Se esperaba "interface" pero se encontró "$1"
+type_w_mixed_signed_unsigned=04035_W_Operaciones mezclando enteros de 32 bits con signo son convertidas a 64 bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mezclar operando con signo y sin signo aqui puede causar errores de comprobación de rango
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_La conversión de tipos ($1 -> $2) en la asignación tiene diferentes tamaños
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_No se pueden usar enums con asignaciones como indices de arrays
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Las clases u objetos "$1" y "$2" no están relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Los tipos de clases "$1" y "$2" no están relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Se esperaba una clase o interfaz, pero se encotró "$1"
+type_e_type_is_not_completly_defined=04042_E_El tipo "$1" no esta definido completamente aún
+type_w_string_too_long=04043_W_La cadena contiene mas caracteres que los admitidos por una cadena corta
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_La comparación es siempre falsa debido a los rangos de los valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_La comparación es siempre verdadera debido a los rangos de los valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Constuyendo un objeto de clase "$1" que contiene métodos abstractos
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_El operando a la izquierda de IN debe ser de tamaño un byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Diferencia del tamaño de los tipos puede causar pérdida de datos o errores de comprobación de rango
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Diferencia del tamaño de los tipos puede causar pérdida de datos o errores de comprobación de rango
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_No se puede obtener la dirección de un método abstracto
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_El operador no es aplicable con los operandos especificados
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Se esperaba una expresió constante
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_La operacion "$1" no está soportada para los tipos "$2" y "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_No es posible realizar una conversión de "$1" a "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_La conversion entre punteros y ordinales no es portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_La conversion entre punteros y ordinales no es portable
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_No se pudo determinar que funcion sobrecargada llamar
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Variable de contador inválida
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificador no encontrado "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Error interno en SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificador duplicado "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_El identificador ya está definido en $1 en la línea $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificador desconocido "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Declaración posterior no solucionada "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Error en definición de tipo
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Tipo posterior no resuelto "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Solo las variables estáticas pueden ser usadas en métodos estáticos o fuera de métodos
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_tipo record o class esperado
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_No se permiten instancias de clases u objetos con un métodos abstractos
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Etiqueta no definida "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Etiqueta "$1" usada pero no definida
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Declaración inválida de la etiqueta
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO y LABEL no son soportados (debe ser habilitado con -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Etiqueta no encontrada
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_el identificador no es una etiqueta
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Etiqueta ya definida
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Definicion de tipo set inválida
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Definición posterior de la clase "$1" no resuelta
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unidad "$1" no utilizada en $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parámetro "$1" no usado
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Variable local no usada "$1"
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Valor asignado a "$1" pero no utilizado
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Valor asignado a la variable local "$1" no utilizado
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Símbolo local $1 "$2" no utilizado
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Campo privado $1.$2 no utilizado
+sym_n_private_identifier_only_set=05030_N_Valor asignado al campo privado $1.$2 pero nunca es utilizado
+sym_n_private_method_not_used=05031_N_Método privado $1.$2 no utilizado
+sym_e_set_expected=05032_E_Tipo set esperado
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_El resultado de la función puede no haber sido asignado
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_El tipo "$1" no esta correctamente alineado para C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Identificador de campo de registro desconocido: "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_La variable local "$1" no parace haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_La variable "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_El identificador "$1" no identifica ningún miembro
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Declaracion encontrada: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Segmento de datos demasiado grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_No se encontro una implementación para el método "$1" de la interfaz
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Símbolo "$1" desaconsejado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_El símbolo "$1" no es portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_El símbolo "$1" no está implementado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_No se puede crear un tipo único a partir de este tipo
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_La variable local "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_La variable "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_El tamaño de la lista de par metros excede 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Los tipos File deben ser pasados por referencia
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_El uso de punteros "far" no esta permitido aqií
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_las funciones declaradas como EXPORT no pueden ser llamadas
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Posible llamada inválida de un constructor o destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_código ineficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_El código no será ejecutado nunca
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Los métodos abstractos no pueden ser llamados directamente
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registro $1 peso $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Se omite generar stack frame
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Métodos de objetos o clases no pueden ser inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Variables de procedimiento o función no pueden ser inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No hay código almacenado para procedimientos inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_No se puede acceder al elemento 0 de cadenas largas, use SetLength/Length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_No se pueden llamar a constructores o destructores en with
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_No se pueden llamar a métodos manejadores de mensajes directamente
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Salto fuera de un bloque de excepción
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_No se admiten instrucciones de control de flujo en un bloque finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_El tamaño del parámetro excede el límite de algunas CPU
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_El tamaño de las variables locales excede el límite de algunas CPU
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_El tamaño de las variables locales excede el límite de la CPU de destino
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK no permitido aquí
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE no permitido aquí
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Iniciando interpretado de ensamblador de estilo $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finalizado interpretado de ensamblador de estilo $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Una patrón que no es una etiqueta contiene @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Error construyendo desplazamiento de registro (record)
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET usado sin identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE usado sin identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_No es posible usar una variable local o parámetro aquí
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Es necesario el uso de OFFSET aquí
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Es necesario el uso de $ auqí
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_No es posible utilizar varios símbolos reubicables
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Símbolos reubicables solo pueden ser añadidos
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Espresió constante inválida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Símbolo reubicable no permitido
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Sintaxis de referencia inválida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_No se puede llegar a $1 desde este código
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_No está permitido el uso símbolos locales o etiquetas como referencias
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso inválido de registros indice y base
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Posible error en el manejo de campos de objetos
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Factor de escala erróneo
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso de multiples registros índice
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo del operando no válido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Cadena no vólida como operando de esta instrucción: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE y @DATA no son soportados
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Referencias a etiqueta nula no permitida
+asmr_e_expr_zero_divide=07025_E_Division entre cero en el evaluador de ensamblador
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expresión inválida
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sequencia de escape ignorada: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Referencia a símbolo inválida
+asmr_w_fwait_emu_prob=07029_W_Fwait puede causar problemas de emulación con emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sin operando interpretado como $1P
+asmr_w_enter_not_supported_by_linux=07031_W_La instruccion ENTER no está soportada por el kernel de Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Llamando a una funcion sobrecargada desde ensamblador
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Tipo de símbolo no soportado para el operando
+asmr_e_constant_out_of_bounds=07034_E_Valor de la constante fuera de rango
+asmr_e_error_converting_decimal=07035_E_Error convirtiendo decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Error convirtiendo octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Error convirtiendo binario $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error convirtiendo hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traducido a $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 esta asociado a una función sobrecargada
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_No se puede usar SELF fuera de un método
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_No se puede usar OLDEBP fuera de un procedimiento anidado
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_No es posible devolver un valor en procedimientos desde código asm
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG no soportado
+asmr_e_size_suffix_and_dest_dont_match=07045_E_No concuerdan el tamaño del prefijo y el del origen o destino
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_No concuerdan el tamaño del prefijo y el del origen o destino
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Error de sintaxis de ensamblador
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinación inválida de operacion y operandos
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Error de sintaxis de ensamblador en operando
+asmr_e_syn_constant=07050_E_Error de sintaxis de ensamblador en constante
+asmr_e_invalid_string_expression=07051_E_Espresión de cadena noáv lida
+asmr_w_const32bit_for_address=07052_W_constante con la direccion del símbolo $1 que no es un puntero
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Instrucción $1 no reconocida
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Falta la instrucción o no es válida
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinación de prefijo y operación inválidos: $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinación de sobrecarga y operación inválidos: $1
+asmr_e_too_many_operands=07057_E_Demasiados operandos en la línea
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorado
+asmr_w_far_ignored=07059_W_FAR ignorado
+asmr_e_dup_local_sym=07060_E_Símbolo local duplicado $1
+asmr_e_unknown_local_sym=07061_E_Símbolo local indefinido $1
+asmr_e_unknown_label_identifier=07062_E_Identificador de etiqueta desconocido $1
+asmr_e_invalid_register=07063_E_Nombre de registro incorrecto
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nombre de registro de punto flotante no válido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo no soportado
+asmr_e_invalid_float_const=07067_E_Constante de punto flotante no válida $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Espresión de punto flotante no válida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Tipo de símbolo erróneo
+asmr_e_cannot_index_relative_var=07070_E_No se puede indexar una var. local o un parámetro con un registro
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Espresión reemplazo de segmento inválida
+asmr_w_id_supposed_external=07072_W_Identificador $1 se supone externo
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Cadenas no permitidas como constantes
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_No hay tipo de variable especificado
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Código ensamblador no devuelto a sección de texto
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_No es una directiva o un símbolo local $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Usando un nombre definido como una etiqueta local
+asmr_e_dollar_without_identifier=07078_E_Tóken de dólar usado sin identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Constante de 32 bits creada para la dirección
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align es dependiente de la plataforma, use .balign o .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_No se puede acceder directamente a los campos de los parámetros
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_No se puede acceder directamente a los campos de objetos o clases
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No se especificó un tamaño y no es posible determinar el tamaño del operando
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_No se puede utilizar RESULT en esta función
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sin operando traducido como "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traducido como "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" traducido como "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_El carácter < no está permitido aquí
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_El carácter > no está permitido aqui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN no es soportado
+asmr_e_no_inc_and_dec_together=07094_E_Inc y Dec no pueden estar juntos en la misma instrucción
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Lista de registros inválida para movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Lista de registros inválida para la instrucción
+asmr_e_higher_cpu_mode_required=07097_E_Se requiere un modo de CPU superior ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No se especificó el tamaño del operando y no pudo ser determinado. Se utilizará DWORD por defecto
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Error de sintaxis tratando de interpretar un operando de desplazamiento
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Demasiados archivos de ensamblador abiertos
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Salida a ensamblador seleccionada no soportada
+asmw_f_comp_not_supported=08002_F_Comp no soportado
+asmw_f_direct_not_supported=08003_F_Direct no soportado por escritores binarios
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Sólo esta permitido alojar datos en la seccion bss
+asmw_f_no_binary_writer_selected=08005_F_No hay seleccionado un escritor binario
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 no está en la tabla
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 combinacion inválida de opcode y operandos
+asmw_e_16bit_not_supported=08008_E_Asm: Referencias de 16 Bit no soportadas
+asmw_e_invalid_effective_address=08009_E_Asm: Dirección efectiva no válida
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Inmediato o referencia esperado
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 valor excede los límites $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Salto corto es fuera de rango $1
+asmw_e_undefined_label=08013_E_Asm: Etiqueta no definida $1
+asmw_e_comp_not_supported=08014_E_Asm: El tipo Comp no está soportado en esta plataforma
+asmw_e_extended_not_supported=08015_E_Asm: El tipo Extended no está soportado en esta plataforma
+asmw_e_duplicate_label=08016_E_Asm: Etiquita $1 duplicada
+asmw_e_redefined_label=08017_E_Asm: Etiqueta $1 redefinida
+asmw_e_first_defined_label=08018_E_Asm: Se definió por primera vez aquí
+asmw_e_invalid_register=08019_E_Asm: Registro $1 inválido
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sistema operativo de origen redefinido
+exec_i_assembling_pipe=09001_I_Ensamblando (pipe) $1
+exec_d_cant_create_asmfile=09002_E_No se puede crear fichero ensamblador $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_No se puede crear fichero objeto: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_No se puede crear fichero de archivado: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Ensamblador $1 no encontrado, cambiando a ensamblado externo
+exec_t_using_assembler=09006_T_Usando ensamblador: $1
+exec_e_error_while_assembling=09007_E_Error mientras se ensamblaba, codigo de terminación $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_No se pudo llamar al ensamblador, error $1. Cambiando a ensamblador externo
+exec_i_assembling=09009_I_Ensamblando $1
+exec_i_assembling_smart=09010_I_Assembling con enlazado inteligente $1
+exec_w_objfile_not_found=09011_W_Objeto $1 no encontrado, el enlazado podria fallar!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Librería $1 no encontrada, el enlazado podria fallar!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Error durante el enlazado
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_No se puede llamar al enlazador, cambiando a enlazado externo
+exec_i_linking=09015_I_Enlazando $1
+exec_e_util_not_found=09016_E_Utilidad $1 no encontrada, cambiando a enlazado externo
+exec_t_using_util=09017_T_Utilizando utilidad $1
+exec_e_exe_not_supported=09018_E_Creacion de ejecutables no soportado
+exec_e_dll_not_supported=09019_E_Creacion de librerías dinámicas/compartidas no soportado
+exec_i_closing_script=09020_I_Cerrando script $1
+exec_e_res_not_found=09021_E_Compilador de recursos no encontrado, cambiando a modo externo
+exec_i_compilingresource=09022_I_Compilando resource $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_La unidad $1 no puede ser enlazada estáticamente, cambiando a enlazado inteligente
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_La unidad $1 no puede ser enlazada inteligentemente, cambiando a enlazado estático
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_La unidad $1 no admite enlazado compartido, cambiando a enlazado estático
+exec_e_unit_not_smart_or_static_linkable=09026_E_La unidad $1 no puede ser enlazada estática o inteligentemente
+exec_e_unit_not_shared_or_static_linkable=09027_E_La unidad $1 no admite enlazado compartido o estático
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09028_F_No se puede post-procesar el ejecutable $1
+execinfo_f_cant_open_executable=09029_F_No se puede abrir el ejecutable $1
+execinfo_x_codesize=09030_X_Tamaño de Código: $1 bytes
+execinfo_x_initdatasize=09031_X_Tamaño de datos inicializados: $1 bytes
+execinfo_x_uninitdatasize=09032_X_Tamaño de datos sin inicializar: $1 bytes
+execinfo_x_stackreserve=09033_X_Espacio reservado para la pila: $1 bytes
+execinfo_x_stackcommit=09034_X_Stack space commited: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Buscando unidad: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Cargando PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Nombre: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Banderas: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Fecha: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Fichero PPU demasiado corto
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Cabecera PPU inválida (no comienza por PPU)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Versión $1 inválida
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU está compilada para otro procesador
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU está compilada para otra plataforma
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_Origen PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Escribiendo $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_No se puede escribir el fichero PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Error leyendo fichero PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fin de fichero inesperado
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrada inválida en fichero PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problema en el contador PPU Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nombre de unidad inválido: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Demasiades unidades
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Referencia circular entre unidades $1 y $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_No se puede compilar la unidad $1, no hay código fuente disponible
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_No se puede encontrar la unidad $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_La unidad $1 no pudo ser encontrada, pero $2 existe
+unit_f_unit_name_error=10024_F_Se buscó la unidad $1 pero se encontró $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compilar la unidad System requiere el conmutador -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Hubo $1 errores compilando el modulo, parando
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Cargado de $1 ($2) unidad $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilando $1, checksum cambiado por $2
+unit_u_recompile_source_found_alone=10029_U_Recompilando $1, solo se encontró el código fuente
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilando unidad, la lib estática es más antigua que la ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilando unidad, la lib compartida es más antigua que la ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilando unidad, obj y asm son más antiguos que ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilando unidad, obj es más antiguo que asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Interpretando interfaz de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Interpretando implementacion de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Segunda carga para la unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Chequeo de fichero PPU $1 fecha $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_No se pudo recompilar la unida $1, pero se encontraron ficheros de inclusió modificados
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_El fichero $1 es mas moderno que la versión Release del archivo PPU $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Se esta utilizando una unidad que no fue compilada con el modo de FPU correcto
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Cargando unidades de interfaz de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Cargando unidades de implementación de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_CRC de la interfaz de la unidad $1 cambiado
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_CRC de la implementacion de la unidad $1 cambiado
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Finalizando compilado de la unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Añadida dependencia de $1 a $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_No hay recarga, es llamada de: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_No hay recarga, ya se esta en la segunda compilación de: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Marcado para recarga: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Recarga forzada
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Estado anterior de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ya se está compilando $1, estableciendo segunda compilación
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Cargando unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Carga de la unidad $1 completada
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrando nueva unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-resolviendo unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Saltando re-resolución de $1, aún se estan cargando las unidades utilizadas
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_$1 [opciones] <fichero_entrada> [opciones]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Solo es soportado un fichero fuente
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Fichero DEF solo puede ser creado para OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Ficheros de respuesta anidados no son soportados
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_No hay fichero fuente en la línea de comandos
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No hay opciones en el archivo de configuración $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parámetro incorrecto: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? escribe las páginas de ayuda
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Demasiados ficheros de configuración anidados
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Imposible abrir fichero $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Leyendo opciones adicionales de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Destino está ya puesto a: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Librerías compartidas no soportadas en la plataforma DOS, regresando a estáticas
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_demasiados IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_demasiados ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_condicional abierto al final del fichero
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_La generación de información de depuración no es soportada por este ejecutable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Prueba recompilando con -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Estas usando el conmutador obsoleto $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Estás usando el conmutador obsoleto $1, porfavor usa $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Cambiando a ensamblador de escritura de código fuente por defecto
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_La salida de ensamblador "$1" no es compatible con "$2"
+option_asm_forced=11022_W_Forzado el uso de ensamblador "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Leyendo opciones del fichero $1
+% Options are also read from this file
+option_using_env=11027_T_Leyendo opciones del entorno $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Procesando pción "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** presione retorno ***
+option_start_reading_configfile=11030_H_Inicio de lectura del archivo de configuración $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Fin de lectura del archivo de configuración $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretando opción "$1"
+option_interpreting_firstpass_option=11036_D_Interpretando primera pasada de la opción "$1"
+option_interpreting_file_option=11033_D_Interpretando opción de archivo "$1"
+option_read_config_file=11034_D_Leyendo archivo de configuración "$1"
+option_found_file=11035_D_encontrado nombre del archivo fuente "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Código de página desconocido
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2005 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versión $FPCVERSION
+
+Fecha del Compilador : $FPCDATE
+CPU de destino : $FPCCPU
+
+Plataformas soportadas:
+ $OSTARGETS
+
+Sets de instrucciones de la CPU soportados:
+ $INSTRUCTIONSETS
+
+Sets de instrucciones de la FPU soportados:
+ $FPUINSTRUCTIONSETS
+
+Este programa esta bajo la licencia GNU General Public Licence
+Para mas informació lea COPYING.FPC
+
+Para informar de errores, sugerencias, etc:
+ bugrep@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_ponga + tras un conmutador booleano para activarlo, - para desactivarlo
+**1a_el compilador no borra los ficheros de ensamblador generados
+**2al_incluir los números de línea del codigo fuente en el archivo ensamblador
+**2an_incluir la informacion de nodos en el archivo ensamblador generado
+*L2ap_usar tuberías (pipes) en lugar de crear archivos de ensamblado temporales
+**2ar_incluir reserva y liberació de registros en el archivo ensamblador
+**2at_incluir informacion de reserva y liberación temporales en el archivo ensamblador
+**1A<x>_formato de salida:
+**2Adefault_usar ensamblador por defecto
+3*2Aas_ensamblar usando GNU AS
+3*2Anasmcoff_coff (Go32v2) usando Nasm
+3*2Anasmelf_elf32 (Linux) usando Nasm
+3*2Anasmwin32_objeto Win32 usando Nasm
+3*2Anasmwdosx_objeto Win32/WDOSX usando Nasm
+3*2Awasm_fichero obj usando Wasm (Watcom)
+3*2Anasmobj_fichero obj usando Nasm
+3*2Amasm_fichero obj usando Masm (Microsoft)
+3*2Atasm_fichero obj usando Tasm (Borland)
+3*2Aelf_elf32 (Linux) usando escritor interno
+3*2Acoff_coff (Go32v2) usando escritor interno
+3*2Apecoff_pecoff (Win32) usando escritor interno
+4*2Aas_ensamblar usando GNU AS
+6*2Aas_archivo o de Unix usando GNU AS
+6*2Agas_ensamblador GNU Motorola
+6*2Amit_Sintaxis MIT (GAS antiguo)
+6*2Amot_Ensamblador Motorola estándar
+A*2Aas_ensamblar usando GNU AS
+P*2Aas_ensamblar usando GNU AS
+S*2Aas_ensamblar usando GNU AS
+**1b_generar informacion de navegado
+**2bl_generar informació de símbolos locales
+**1B_construir(build) todos los modulos
+**1C<x>_opciones de generado de código:
+**2Cc<x>_cambiar la convencion de llamada por defecto a <x>
+**2CD_crear adicionalmente una librería dinámica (no soportado)
+**2Ce_Compilar con opcodes de punto flotante emulados
+**2Cf<x>_Cambiar el set de instrucciones de la FPU usado, fpc -i para posibles valores<x>
+**2Cg_Generar código PIC
+**2Ch<n>_<n> bytes heap (entre 1023 y 67107840)
+**2Ci_Comprobación de E/S
+**2Cn_omitir etapa de enlazado
+**2Co_comprobar desbordamiento en operaciones de enteros
+**2Cp<x>_Cambiar el set de instrucciones usado, fpc -i para posibles valores
+**2Cr_comprobación de rango
+**2CR_verificar validez de objetos de llamada
+**2Cs<n>_definir el tamaño de la pila a <n>
+**2Ct_comprobación de pila
+**2CX_crear adicionalmente una librerí con enlazado inteligente
+**1d<x>_define el símbol <x>
+**1D_generar fichero DEF
+**2Dd<x>_establece la descripción a <x>
+**2Dv<x>_establece la version de la DLL a <x>
+*O2Dw_Aplicación PM
+**1e<x>_establecer ruta al ejecutable
+**1E_igual que -Cn
+**1F<x>_establecer ficheros y rutas:
+**2Fa<x>[,y]_para hacer que el programa cargue las unidades <x> e [y] antes de procesar su uses
+**2Fc<x>_establece el código de pagina de la entrada a <x>
+**2FD<x>_establece la ruta donde buscar las utilidades del compilador
+**2Fe<x>_redirige la salida de errores a <x>
+**2FE<x>_establece la ruta de destino de exe/unidades a <x>
+**2Fi<x>_añade <x> a las rutas de inclusión
+**2Fl<x>_añade <x> a las rutas de librerías
+**2FL<x>_usa <x> como enlazador dinámico
+**2Fo<x>_añade <x> a las rutas de objetos
+**2Fr<x>_load error message file <x>
+**2Fu<x>_adds <x> a las rutas de unidades
+**2FU<x>_establece la ruta de salida de unidades a <x>, reemplaza -FE anteriores
+*g1g_generar información de depurado:
+*g2gc_generar comprobación de punteros
+*g2gd_usar dbx
+*g2gg_usar gsym
+*g2gh_usar unidad de trazado de memoria (para depurar pérdidas de memoria)
+*g2gl_usar informacion de líneas de las unidades para la traza de ejecución (backtrace)
+*g2gv_genera programas trazables con valgrind
+*g2gw_generar información de depurado dwarf
+**1i_información
+**2iD_devuelve la fecha del compilador
+**2iV_devuelve la versión del compilador
+**2iSO_devuelve el SO del compilador
+**2iSP_devuelve el procesador del compilador
+**2iTO_devuelve el SO de destino
+**2iTP_devuelve el procesador de destino
+**1I<x>_añade <x> a las rutas de iclusión
+**1k<x>_Pasar <x> al enlazador
+**1l_mostrar logo
+**1M<x>_establecer modo del lenguaje a <x>
+**2Mfpc_dialecto de free pascal(default)
+**2Mobjfpc_activar algunas extensiones de Delphi 2
+**2Mdelphi_tratar de ser compatible con Delphi
+**2Mtp_tratar de ser compatible con TP/BP 7.0
+**2Mgpc_tratar de ser compatible con gpc
+**2Mmacpas_tratar de ser compatible con dialectos de macintosh pascal
+**1n_no leer la configuración por defecto
+**1o<x>_cambiar el nombre del ejecutable producido a <x>
+**1O<x>_optimizaciones:
+3*2Og_generar código más pequeño
+3*2OG_generar código más rápido (defecto)
+**2Or_mantener algunas variables en registros
+3*2Ou_activar optimizaciones inseguras (ver docs)
+3*2O1_optimizaciones nivel 1 (optimizaciones rápidas)
+3*2O2_optimizaciones nivel 2 (-O1 + optimizaciones más lentas)
+3*2O3_optimizaciones nivel 3 (-O2 repetidamente, max 5 veces)
+3*2Op<x>_procesador de destino:
+3*3Op1_establecer procesador de destino a 386/486
+3*3Op2_establecer procesador de destino a Pentium/PentiumMMX (tm)
+3*3Op3_establecer procesador de destino a PPro/PII/c6x86/K6 (tm)
+6*2Og_generar código más pequeño
+6*2OG_generatr código más rápido (defecto)
+6*2Ox_optimizar al máximo (AUN CON ERRORES!!!)
+6*2O0_establecer procesador de destino a MC68000
+6*2O2_establecer procesador de destino a MC68020+ (defecto)
+**1pg_generar código de perfilado gprof (define FPC_PROFILE)
+**1R<x>_estilo de lectura de ensamblador:
+**2Rdefault_usar ensamblador por defecto
+3*2Ratt_leer ensamblador estilo AT&T
+3*2Rintel_leer ensamblador estilo Intel
+6*2RMOT_leer ensamblador estilo motorola
+**1S<x>_opciones de sintaxis:
+**2S2_igual que -Mobjfpc
+**2Sc_soportar operadores estilo C (*=,+=,/= and -=)
+**2Sa_incluir código de aserción.
+**2Sd_igual que -Mdelphi
+**2Se<x>_opciones de error. <x> es una combinación de los siguientes:
+**3*_<n> : detener el compilador tras <n> errores (por defecto 1)
+**3*_w : detener también tras avisos
+**3*_n : detener también tras notas
+**3*_h : detener también tras consejos
+**2Sg_permitir LABEL y GOTO
+**2Sh_Usar cadenas largas (ansistrings)
+**2Si_soportar INLINE estilo C++
+**2SI<x>_establecer estilo de interfaz a <x>
+**3SIcom_interfaces compatibles COM (defecto)
+**3SIcorba_interfaces compatibles CORBA
+**2Sm_soportar macros tipo C (global)
+**2So_igual que -Mtp
+**2Sp_igual que -Mgpc
+**2Ss_el nombre del constructor debe ser init (el destructor debe ser done)
+**2St_permitir la palabra reservada static en objetos
+**1s_no llamar al ensamblador ni enlazador
+**2sh_Generar script para enlazar en host
+**2st_Generar script para enlazar en destino
+**2sr_Saltar fase de reserva de registros (usar con -alr)
+**1T<x>_Sistema operativo de destino:
+3*2Temx_OS/2 usando EMX (incluyendo extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 de DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_extensor DOS compatible Watcom
+3*2Twdosx_extensor WDOSX DOS
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (no soportado)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin y MacOS X en PowerPC
+P*2Tlinux_Linux en PowerPC
+P*2Tmacos_MacOS (clásico) en PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_elimina la definición del símbolo <x>
+**1U_opciones de unidad:
+**2Un_no comprobar el nombre de la unidad
+**2Ur_generar unidades para distribución (release)
+**2Us_compilar la unidad System
+**1v<x>_Mostrar detalles. <x> es una combinación de las siguientes letras:
+**2*_e : Mostrar errores (defecto) 0 : No mostrar nada (excepto errores)
+**2*_w : Mostrar avisos u : Mostrar info. de la unidad
+**2*_n : Mostrar notas t : Mostrar archivos usados / intentados
+**2*_h : Mostrar consejos c : Mostrar condicionales
+**2*_i : Mostrar info. general d : Mostrar info. de depurado
+**2*_l : Mostrar num de lineas r : Modo compatible con Rhide/GCC
+**2*_a : Mostrar todo x : Info. del ejecutable (Win32 solo)
+**2*_v : escribe fpcdebug.txt con p : Escribir el árbol de parser en tree.log
+**2*_ mucha informacón de depurado
+3*1W<x>_opciones de Win32 o similares
+3*2WB<x>_Establece la dirección hex de base a <x>
+3*2WC_Especifica que la aplicación es de consola
+3*2WD_Usa DEFFILE para exportar funciones de la DLL o EXE
+3*2WF_Especifica aplicación de pantalla completa (OS/2 sólo)
+3*2WG_Especifica que la aplicación es para entorno gráfico
+3*2WN_No generar código de reubicación (necesario para depurar)
+3*2WR_Generar código de reubicación
+P*2WC_Especifica aplicación de colnsola (MacOS sólo)
+P*2WG_Especifica aplicación gráfica (MacOS sólo)
+P*2WT_Especifica aplicación de tipo herramienta (herramienta MPW, MacOS sólo)
+**1X_opciones de ejecutable:
+**2Xc_pasar --shared al enlazador (Unix sólo)
+**2Xd_no utilizar la ruta de librería por defecto (necesario para compilación cruzada)
+**2XD_tratar de enlazar dinámicamente (define FPC_LINK_DYNAMIC)
+**2XP<x>_pone <x> delante de los nombres de binutils
+**2Xr<x>_establece la ruta de librerías a <x> (necesario para compilación cruzada)
+**2Xs_eliminar todos los símbolos del ejecutable
+**2XS_tratar de enlazar estáticamente (defecto) (define FPC_LINK_STATIC)
+**2Xt_enlazar con librerias estáticas (-static es pasado al enlazador)
+**2XX_tratar de enlazar inteligentemente (define FPC_LINK_SMART)
+**1*_
+**1?_muestra esta ayuda
+**1h_muestra esta ayuda sin esperas
+]
+
+#
+# The End...
diff --git a/compiler/msgidx.inc b/compiler/msgidx.inc
new file mode 100644
index 0000000000..d50e33c582
--- /dev/null
+++ b/compiler/msgidx.inc
@@ -0,0 +1,671 @@
+const
+ general_t_compilername=01000;
+ general_d_sourceos=01001;
+ general_i_targetos=01002;
+ general_t_exepath=01003;
+ general_t_unitpath=01004;
+ general_t_includepath=01005;
+ general_t_librarypath=01006;
+ general_t_objectpath=01007;
+ general_i_abslines_compiled=01008;
+ general_f_no_memory_left=01009;
+ general_i_writingresourcefile=01010;
+ general_e_errorwritingresourcefile=01011;
+ general_i_fatal=01012;
+ general_i_error=01013;
+ general_i_warning=01014;
+ general_i_note=01015;
+ general_i_hint=01016;
+ general_e_path_does_not_exist=01017;
+ general_f_compilation_aborted=01018;
+ scan_f_end_of_file=02000;
+ scan_f_string_exceeds_line=02001;
+ scan_f_illegal_char=02002;
+ scan_f_syn_expected=02003;
+ scan_t_start_include_file=02004;
+ scan_w_comment_level=02005;
+ scan_n_ignored_switch=02008;
+ scan_w_illegal_switch=02009;
+ scan_w_switch_is_global=02010;
+ scan_e_illegal_char_const=02011;
+ scan_f_cannot_open_input=02012;
+ scan_f_cannot_open_includefile=02013;
+ scan_e_illegal_pack_records=02015;
+ scan_e_illegal_pack_enum=02016;
+ scan_e_endif_expected=02017;
+ scan_e_preproc_syntax_error=02018;
+ scan_e_error_in_preproc_expr=02019;
+ scan_w_macro_cut_after_255_chars=02020;
+ scan_e_endif_without_if=02021;
+ scan_f_user_defined=02022;
+ scan_e_user_defined=02023;
+ scan_w_user_defined=02024;
+ scan_n_user_defined=02025;
+ scan_h_user_defined=02026;
+ scan_i_user_defined=02027;
+ scan_e_keyword_cant_be_a_macro=02028;
+ scan_f_macro_buffer_overflow=02029;
+ scan_w_macro_too_deep=02030;
+ scan_w_wrong_styled_switch=02031;
+ scan_d_handling_switch=02032;
+ scan_c_endif_found=02033;
+ scan_c_ifdef_found=02034;
+ scan_c_ifopt_found=02035;
+ scan_c_if_found=02036;
+ scan_c_ifndef_found=02037;
+ scan_c_else_found=02038;
+ scan_c_skipping_until=02039;
+ scan_i_press_enter=02040;
+ scan_w_unsupported_switch=02041;
+ scan_w_illegal_directive=02042;
+ scan_t_back_in=02043;
+ scan_w_unsupported_app_type=02044;
+ scan_w_app_type_not_support=02045;
+ scan_w_description_not_support=02046;
+ scan_n_version_not_support=02047;
+ scan_n_only_exe_version=02048;
+ scan_w_wrong_version_ignored=02049;
+ scan_e_illegal_asmmode_specifier=02050;
+ scan_w_no_asm_reader_switch_inside_asm=02051;
+ scan_e_wrong_switch_toggle=02052;
+ scan_e_resourcefiles_not_supported=02053;
+ scan_w_include_env_not_found=02054;
+ scan_e_invalid_maxfpureg_value=02055;
+ scan_w_only_one_resourcefile_supported=02056;
+ scan_w_macro_support_turned_off=02057;
+ scan_e_invalid_interface_type=02058;
+ scan_w_appid_not_support=02059;
+ scan_w_appname_not_support=02060;
+ scan_e_string_exceeds_255_chars=02061;
+ scan_f_include_deep_ten=02062;
+ scan_e_too_many_push=02063;
+ scan_e_too_many_pop=02064;
+ scan_e_error_macro_lacks_value=02065;
+ scan_e_wrong_switch_toggle_default=02066;
+ scan_e_mode_switch_not_allowed=02067;
+ scan_e_error_macro_undefined=02068;
+ scan_e_utf8_bigger_than_65535=02069;
+ scan_e_utf8_malformed=02070;
+ scan_c_switching_to_utf8=02071;
+ scan_e_compile_time_typeerror=02072;
+ parser_e_syntax_error=03000;
+ parser_e_dont_nest_interrupt=03004;
+ parser_w_proc_directive_ignored=03005;
+ parser_e_no_overload_for_all_procs=03006;
+ parser_e_export_name_double=03008;
+ parser_e_export_ordinal_double=03009;
+ parser_e_export_invalid_index=03010;
+ parser_w_parser_reloc_no_debug=03011;
+ parser_w_parser_win32_debug_needs_WN=03012;
+ parser_e_constructorname_must_be_init=03013;
+ parser_e_destructorname_must_be_done=03014;
+ parser_e_proc_inline_not_supported=03016;
+ parser_w_constructor_should_be_public=03018;
+ parser_w_destructor_should_be_public=03019;
+ parser_n_only_one_destructor=03020;
+ parser_e_no_local_objects=03021;
+ parser_f_no_anonym_objects=03022;
+ parser_n_object_has_no_vmt=03023;
+ parser_e_illegal_parameter_list=03024;
+ parser_e_wrong_parameter_size=03026;
+ parser_e_overloaded_no_procedure=03027;
+ parser_e_overloaded_have_same_parameters=03028;
+ parser_e_header_dont_match_forward=03029;
+ parser_e_header_different_var_names=03030;
+ parser_n_duplicate_enum=03031;
+ parser_e_no_with_for_variable_in_other_segments=03033;
+ parser_e_too_much_lexlevel=03034;
+ parser_e_range_check_error=03035;
+ parser_w_range_check_error=03036;
+ parser_e_double_caselabel=03037;
+ parser_e_case_lower_less_than_upper_bound=03038;
+ parser_e_type_const_not_possible=03039;
+ parser_e_no_overloaded_procvars=03040;
+ parser_e_invalid_string_size=03041;
+ parser_w_use_extended_syntax_for_objects=03042;
+ parser_w_no_new_dispose_on_void_pointers=03043;
+ parser_e_no_new_dispose_on_void_pointers=03044;
+ parser_e_class_id_expected=03045;
+ parser_e_no_type_not_allowed_here=03046;
+ parser_e_methode_id_expected=03047;
+ parser_e_header_dont_match_any_member=03048;
+ parser_d_procedure_start=03049;
+ parser_e_error_in_real=03050;
+ parser_e_fail_only_in_constructor=03051;
+ parser_e_no_paras_for_destructor=03052;
+ parser_e_only_class_methods_via_class_ref=03053;
+ parser_e_only_class_methods=03054;
+ parser_e_case_mismatch=03055;
+ parser_e_illegal_symbol_exported=03056;
+ parser_w_should_use_override=03057;
+ parser_e_nothing_to_be_overridden=03058;
+ parser_e_no_procedure_to_access_property=03059;
+ parser_w_stored_not_implemented=03060;
+ parser_e_ill_property_access_sym=03061;
+ parser_e_cant_access_protected_member=03062;
+ parser_e_cant_access_private_member=03063;
+ parser_e_overridden_methods_not_same_ret=03066;
+ parser_e_dont_nest_export=03067;
+ parser_e_methods_dont_be_export=03068;
+ parser_e_call_by_ref_without_typeconv=03069;
+ parser_e_no_super_class=03070;
+ parser_e_self_not_in_method=03071;
+ parser_e_generic_methods_only_in_methods=03072;
+ parser_e_illegal_colon_qualifier=03073;
+ parser_e_illegal_set_expr=03074;
+ parser_e_pointer_to_class_expected=03075;
+ parser_e_expr_have_to_be_constructor_call=03076;
+ parser_e_expr_have_to_be_destructor_call=03077;
+ parser_e_invalid_record_const=03078;
+ parser_e_false_with_expr=03079;
+ parser_e_void_function=03080;
+ parser_e_constructors_always_objects=03081;
+ parser_e_operator_not_overloaded=03082;
+ parser_e_no_such_assignment=03083;
+ parser_e_overload_impossible=03084;
+ parser_e_no_reraise_possible=03085;
+ parser_e_no_new_or_dispose_for_classes=03086;
+ parser_e_procedure_overloading_is_off=03088;
+ parser_e_overload_operator_failed=03089;
+ parser_e_comparative_operator_return_boolean=03090;
+ parser_e_only_virtual_methods_abstract=03091;
+ parser_f_unsupported_feature=03092;
+ parser_e_mix_of_classes_and_objects=03093;
+ parser_w_unknown_proc_directive_ignored=03094;
+ parser_e_absolute_only_one_var=03095;
+ parser_e_absolute_only_to_var_or_const=03096;
+ parser_e_initialized_only_one_var=03097;
+ parser_e_abstract_no_definition=03098;
+ parser_e_overloaded_must_be_all_global=03099;
+ parser_w_virtual_without_constructor=03100;
+ parser_c_macro_defined=03101;
+ parser_c_macro_undefined=03102;
+ parser_c_macro_set_to=03103;
+ parser_i_compiling=03104;
+ parser_u_parsing_interface=03105;
+ parser_u_parsing_implementation=03106;
+ parser_d_compiling_second_time=03107;
+ parser_e_no_property_found_to_override=03109;
+ parser_e_only_one_default_property=03110;
+ parser_e_property_need_paras=03111;
+ parser_e_constructor_cannot_be_not_virtual=03112;
+ parser_e_no_default_property_available=03113;
+ parser_e_cant_have_published=03114;
+ parser_e_forward_declaration_must_be_resolved=03115;
+ parser_e_no_local_operator=03116;
+ parser_e_proc_dir_not_allowed_in_interface=03117;
+ parser_e_proc_dir_not_allowed_in_implementation=03118;
+ parser_e_proc_dir_not_allowed_in_procvar=03119;
+ parser_e_function_already_declared_public_forward=03120;
+ parser_e_not_external_and_export=03121;
+ parser_w_not_supported_for_inline=03123;
+ parser_w_inlining_disabled=03124;
+ parser_i_writing_browser_log=03125;
+ parser_h_maybe_deref_caret_missing=03126;
+ parser_f_assembler_reader_not_supported=03127;
+ parser_e_proc_dir_conflict=03128;
+ parser_e_call_convention_dont_match_forward=03129;
+ parser_e_property_cant_have_a_default_value=03131;
+ parser_e_property_default_value_must_const=03132;
+ parser_e_cant_publish_that=03133;
+ parser_e_cant_publish_that_property=03134;
+ parser_e_empty_import_name=03136;
+ parser_e_division_by_zero=03138;
+ parser_e_invalid_float_operation=03139;
+ parser_e_array_lower_less_than_upper_bound=03140;
+ parser_w_string_too_long=03141;
+ parser_e_string_larger_array=03142;
+ parser_e_ill_msg_expr=03143;
+ parser_e_ill_msg_param=03144;
+ parser_e_duplicate_message_label=03145;
+ parser_e_self_in_non_message_handler=03146;
+ parser_e_threadvars_only_sg=03147;
+ parser_f_direct_assembler_not_allowed=03148;
+ parser_w_no_objpas_use_mode=03149;
+ parser_e_no_object_override=03150;
+ parser_e_cant_use_inittable_here=03151;
+ parser_e_resourcestring_only_sg=03152;
+ parser_e_exit_with_argument_not__possible=03153;
+ parser_e_stored_property_must_be_boolean=03154;
+ parser_e_ill_property_storage_sym=03155;
+ parser_e_only_publishable_classes_can__be_published=03156;
+ parser_e_proc_directive_expected=03157;
+ parser_e_invalid_property_index_value=03158;
+ parser_e_procname_to_short_for_export=03159;
+ parser_e_dlltool_unit_var_problem=03160;
+ parser_e_dlltool_unit_var_problem2=03161;
+ parser_f_need_objfpc_or_delphi_mode=03162;
+ parser_e_no_export_with_index_for_target=03163;
+ parser_e_no_export_of_variables_for_target=03164;
+ parser_e_improper_guid_syntax=03165;
+ parser_w_interface_mapping_notfound=03168;
+ parser_e_interface_id_expected=03169;
+ parser_e_type_cant_be_used_in_array_index=03170;
+ parser_e_no_con_des_in_interfaces=03171;
+ parser_e_no_access_specifier_in_interfaces=03172;
+ parser_e_no_vars_in_interfaces=03173;
+ parser_e_no_local_proc_external=03174;
+ parser_w_skipped_fields_before=03175;
+ parser_e_skipped_fields_before=03176;
+ parser_w_skipped_fields_after=03177;
+ parser_e_varargs_need_cdecl_and_external=03178;
+ parser_e_self_call_by_value=03179;
+ parser_e_interface_has_no_guid=03180;
+ parser_e_illegal_field_or_method=03181;
+ parser_w_proc_overriding_calling=03182;
+ parser_e_no_procvarobj_const=03183;
+ parser_e_default_value_only_one_para=03184;
+ parser_e_default_value_expected_for_para=03185;
+ parser_w_unsupported_feature=03186;
+ parser_h_c_arrays_are_references=03187;
+ parser_e_C_array_of_const_must_be_last=03188;
+ parser_h_type_redef=03189;
+ parser_w_cdecl_has_no_high=03190;
+ parser_w_cdecl_no_openstring=03191;
+ parser_e_initialized_not_for_threadvar=03192;
+ parser_e_msg_only_for_classes=03193;
+ parser_e_procedure_or_function_expected=03194;
+ parser_e_illegal_calling_convention=03195;
+ parser_e_no_object_reintroduce=03196;
+ parser_e_paraloc_only_one_para=03197;
+ parser_e_paraloc_all_paras=03198;
+ parser_e_illegal_explicit_paraloc=03199;
+ parser_e_32bitint_or_pointer_variable_expected=03200;
+ parser_e_goto_outside_proc=03201;
+ parser_f_too_complex_proc=03202;
+ parser_e_illegal_expression=03203;
+ parser_e_invalid_integer=03204;
+ parser_e_invalid_qualifier=03205;
+ parser_e_upper_lower_than_lower=03206;
+ parser_e_macpas_exit_wrong_param=03207;
+ parser_e_illegal_assignment_to_count_var=03208;
+ parser_e_no_local_var_external=03209;
+ parser_e_proc_already_external=03210;
+ parser_w_implicit_uses_of_variants_unit=03211;
+ parser_e_no_static_method_in_interfaces=03212;
+ parser_e_arithmetic_operation_overflow=03213;
+ parser_e_protected_or_private_expected=03214;
+ parser_e_illegal_slice=03215;
+ parser_e_dispinterface_cant_have_parent=03216;
+ parser_e_dispinterface_needs_a_guid=03217;
+ type_e_mismatch=04000;
+ type_e_incompatible_types=04001;
+ type_e_not_equal_types=04002;
+ type_e_type_id_expected=04003;
+ type_e_variable_id_expected=04004;
+ type_e_integer_expr_expected=04005;
+ type_e_boolean_expr_expected=04006;
+ type_e_ordinal_expr_expected=04007;
+ type_e_pointer_type_expected=04008;
+ type_e_class_type_expected=04009;
+ type_e_cant_eval_constant_expr=04011;
+ type_e_set_element_are_not_comp=04012;
+ type_e_set_operation_unknown=04013;
+ type_w_convert_real_2_comp=04014;
+ type_h_use_div_for_int=04015;
+ type_e_strict_var_string_violation=04016;
+ type_e_succ_and_pred_enums_with_assign_not_possible=04017;
+ type_e_cant_read_write_type=04018;
+ type_e_no_readln_writeln_for_typed_file=04019;
+ type_e_no_read_write_for_untyped_file=04020;
+ type_e_typeconflict_in_set=04021;
+ type_w_maybe_wrong_hi_lo=04022;
+ type_e_integer_or_real_expr_expected=04023;
+ type_e_wrong_type_in_array_constructor=04024;
+ type_e_wrong_parameter_type=04025;
+ type_e_no_method_and_procedure_not_compatible=04026;
+ type_e_wrong_math_argument=04027;
+ type_e_no_addr_of_constant=04028;
+ type_e_argument_cant_be_assigned=04029;
+ type_e_cannot_local_proc_to_procvar=04030;
+ type_e_no_assign_to_addr=04031;
+ type_e_no_assign_to_const=04032;
+ type_e_array_required=04033;
+ type_e_interface_type_expected=04034;
+ type_w_mixed_signed_unsigned=04035;
+ type_w_mixed_signed_unsigned2=04036;
+ type_e_typecast_wrong_size_for_assignment=04037;
+ type_e_array_index_enums_with_assign_not_possible=04038;
+ type_e_classes_not_related=04039;
+ type_w_classes_not_related=04040;
+ type_e_class_or_interface_type_expected=04041;
+ type_e_type_is_not_completly_defined=04042;
+ type_w_string_too_long=04043;
+ type_w_signed_unsigned_always_false=04044;
+ type_w_signed_unsigned_always_true=04045;
+ type_w_instance_with_abstract=04046;
+ type_h_in_range_check=04047;
+ type_w_smaller_possible_range_check=04048;
+ type_h_smaller_possible_range_check=04049;
+ type_e_cant_take_address_of_abstract_method=04050;
+ type_e_operator_not_allowed=04051;
+ type_e_constant_expr_expected=04052;
+ type_e_operator_not_supported_for_types=04053;
+ type_e_illegal_type_conversion=04054;
+ type_h_pointer_to_longint_conv_not_portable=04055;
+ type_w_pointer_to_longint_conv_not_portable=04056;
+ type_e_cant_choose_overload_function=04057;
+ type_e_illegal_count_var=04058;
+ sym_e_id_not_found=05000;
+ sym_f_internal_error_in_symtablestack=05001;
+ sym_e_duplicate_id=05002;
+ sym_h_duplicate_id_where=05003;
+ sym_e_unknown_id=05004;
+ sym_e_forward_not_resolved=05005;
+ sym_e_error_in_type_def=05007;
+ sym_e_forward_type_not_resolved=05009;
+ sym_e_only_static_in_static=05010;
+ sym_f_type_must_be_rec_or_class=05012;
+ sym_e_no_instance_of_abstract_object=05013;
+ sym_w_label_not_defined=05014;
+ sym_e_label_used_and_not_defined=05015;
+ sym_e_ill_label_decl=05016;
+ sym_e_goto_and_label_not_supported=05017;
+ sym_e_label_not_found=05018;
+ sym_e_id_is_no_label_id=05019;
+ sym_e_label_already_defined=05020;
+ sym_e_ill_type_decl_set=05021;
+ sym_e_class_forward_not_resolved=05022;
+ sym_n_unit_not_used=05023;
+ sym_h_para_identifier_not_used=05024;
+ sym_n_local_identifier_not_used=05025;
+ sym_h_para_identifier_only_set=05026;
+ sym_n_local_identifier_only_set=05027;
+ sym_h_local_symbol_not_used=05028;
+ sym_n_private_identifier_not_used=05029;
+ sym_n_private_identifier_only_set=05030;
+ sym_n_private_method_not_used=05031;
+ sym_e_set_expected=05032;
+ sym_w_function_result_not_set=05033;
+ sym_w_wrong_C_pack=05034;
+ sym_e_illegal_field=05035;
+ sym_w_uninitialized_local_variable=05036;
+ sym_w_uninitialized_variable=05037;
+ sym_e_id_no_member=05038;
+ sym_h_param_list=05039;
+ sym_e_segment_too_large=05040;
+ sym_e_no_matching_implementation_found=05042;
+ sym_w_deprecated_symbol=05043;
+ sym_w_non_portable_symbol=05044;
+ sym_w_non_implemented_symbol=05055;
+ sym_e_cant_create_unique_type=05056;
+ sym_h_uninitialized_local_variable=05057;
+ sym_h_uninitialized_variable=05058;
+ cg_e_parasize_too_big=06009;
+ cg_e_file_must_call_by_reference=06012;
+ cg_e_cant_use_far_pointer_there=06013;
+ cg_e_dont_call_exported_direct=06015;
+ cg_w_member_cd_call_from_method=06016;
+ cg_n_inefficient_code=06017;
+ cg_w_unreachable_code=06018;
+ cg_e_cant_call_abstract_method=06020;
+ cg_d_register_weight=06027;
+ cg_d_stackframe_omited=06029;
+ cg_e_unable_inline_object_methods=06031;
+ cg_e_unable_inline_procvar=06032;
+ cg_e_no_code_for_inline_stored=06033;
+ cg_e_can_access_element_zero=06035;
+ cg_e_cannot_call_cons_dest_inside_with=06037;
+ cg_e_cannot_call_message_direct=06038;
+ cg_e_goto_inout_of_exception_block=06039;
+ cg_e_control_flow_outside_finally=06040;
+ cg_w_parasize_too_big=06041;
+ cg_w_localsize_too_big=06042;
+ cg_e_localsize_too_big=06043;
+ cg_e_break_not_allowed=06044;
+ cg_e_continue_not_allowed=06045;
+ cg_f_unknown_compilerproc=06046;
+ asmr_d_start_reading=07000;
+ asmr_d_finish_reading=07001;
+ asmr_e_none_label_contain_at=07002;
+ asmr_e_building_record_offset=07004;
+ asmr_e_offset_without_identifier=07005;
+ asmr_e_type_without_identifier=07006;
+ asmr_e_no_local_or_para_allowed=07007;
+ asmr_e_need_offset=07008;
+ asmr_e_need_dollar=07009;
+ asmr_e_cant_have_multiple_relocatable_symbols=07010;
+ asmr_e_only_add_relocatable_symbol=07011;
+ asmr_e_invalid_constant_expression=07012;
+ asmr_e_relocatable_symbol_not_allowed=07013;
+ asmr_e_invalid_reference_syntax=07014;
+ asmr_e_local_para_unreachable=07015;
+ asmr_e_local_label_not_allowed_as_ref=07016;
+ asmr_e_wrong_base_index=07017;
+ asmr_w_possible_object_field_bug=07018;
+ asmr_e_wrong_scale_factor=07019;
+ asmr_e_multiple_index=07020;
+ asmr_e_invalid_operand_type=07021;
+ asmr_e_invalid_string_as_opcode_operand=07022;
+ asmr_w_CODE_and_DATA_not_supported=07023;
+ asmr_e_null_label_ref_not_allowed=07024;
+ asmr_e_expr_zero_divide=07025;
+ asmr_e_expr_illegal=07026;
+ asmr_e_escape_seq_ignored=07027;
+ asmr_e_invalid_symbol_ref=07028;
+ asmr_w_fwait_emu_prob=07029;
+ asmr_w_fadd_to_faddp=07030;
+ asmr_w_enter_not_supported_by_linux=07031;
+ asmr_w_calling_overload_func=07032;
+ asmr_e_unsupported_symbol_type=07033;
+ asmr_e_constant_out_of_bounds=07034;
+ asmr_e_error_converting_decimal=07035;
+ asmr_e_error_converting_octal=07036;
+ asmr_e_error_converting_binary=07037;
+ asmr_e_error_converting_hexadecimal=07038;
+ asmr_h_direct_global_to_mangled=07039;
+ asmr_w_direct_global_is_overloaded_func=07040;
+ asmr_e_cannot_use_SELF_outside_a_method=07041;
+ asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042;
+ asmr_e_void_function=07043;
+ asmr_e_SEG_not_supported=07044;
+ asmr_e_size_suffix_and_dest_dont_match=07045;
+ asmr_w_size_suffix_and_dest_dont_match=07046;
+ asmr_e_syntax_error=07047;
+ asmr_e_invalid_opcode_and_operand=07048;
+ asmr_e_syn_operand=07049;
+ asmr_e_syn_constant=07050;
+ asmr_e_invalid_string_expression=07051;
+ asmr_w_const32bit_for_address=07052;
+ asmr_e_unknown_opcode=07053;
+ asmr_e_invalid_or_missing_opcode=07054;
+ asmr_e_invalid_prefix_and_opcode=07055;
+ asmr_e_invalid_override_and_opcode=07056;
+ asmr_e_too_many_operands=07057;
+ asmr_w_near_ignored=07058;
+ asmr_w_far_ignored=07059;
+ asmr_e_dup_local_sym=07060;
+ asmr_e_unknown_local_sym=07061;
+ asmr_e_unknown_label_identifier=07062;
+ asmr_e_invalid_register=07063;
+ asmr_e_invalid_fpu_register=07064;
+ asmr_w_modulo_not_supported=07066;
+ asmr_e_invalid_float_const=07067;
+ asmr_e_invalid_float_expr=07068;
+ asmr_e_wrong_sym_type=07069;
+ asmr_e_cannot_index_relative_var=07070;
+ asmr_e_invalid_seg_override=07071;
+ asmr_w_id_supposed_external=07072;
+ asmr_e_string_not_allowed_as_const=07073;
+ asmr_e_no_var_type_specified=07074;
+ asmr_w_assembler_code_not_returned_to_text=07075;
+ asmr_e_not_directive_or_local_symbol=07076;
+ asmr_w_using_defined_as_local=07077;
+ asmr_e_dollar_without_identifier=07078;
+ asmr_w_32bit_const_for_address=07079;
+ asmr_n_align_is_target_specific=07080;
+ asmr_e_cannot_access_field_directly_for_parameters=07081;
+ asmr_e_cannot_access_object_field_directly=07082;
+ asmr_e_unable_to_determine_reference_size=07083;
+ asmr_e_cannot_use_RESULT_here=07084;
+ asmr_w_adding_explicit_args_fXX=07086;
+ asmr_w_adding_explicit_first_arg_fXX=07087;
+ asmr_w_adding_explicit_second_arg_fXX=07088;
+ asmr_e_invalid_char_smaller=07089;
+ asmr_e_invalid_char_greater=07090;
+ asmr_w_align_not_supported=07093;
+ asmr_e_no_inc_and_dec_together=07094;
+ asmr_e_invalid_reg_list_in_movem=07095;
+ asmr_e_invalid_reg_list_for_opcode=07096;
+ asmr_e_higher_cpu_mode_required=07097;
+ asmr_w_unable_to_determine_reference_size_using_dword=07098;
+ asmr_e_illegal_shifterop_syntax=07099;
+ asmw_f_too_many_asm_files=08000;
+ asmw_f_assembler_output_not_supported=08001;
+ asmw_f_comp_not_supported=08002;
+ asmw_f_direct_not_supported=08003;
+ asmw_e_alloc_data_only_in_bss=08004;
+ asmw_f_no_binary_writer_selected=08005;
+ asmw_e_opcode_not_in_table=08006;
+ asmw_e_invalid_opcode_and_operands=08007;
+ asmw_e_16bit_not_supported=08008;
+ asmw_e_invalid_effective_address=08009;
+ asmw_e_immediate_or_reference_expected=08010;
+ asmw_e_value_exceeds_bounds=08011;
+ asmw_e_short_jmp_out_of_range=08012;
+ asmw_e_undefined_label=08013;
+ asmw_e_comp_not_supported=08014;
+ asmw_e_extended_not_supported=08015;
+ asmw_e_duplicate_label=08016;
+ asmw_e_redefined_label=08017;
+ asmw_e_first_defined_label=08018;
+ asmw_e_invalid_register=08019;
+ exec_w_source_os_redefined=09000;
+ exec_i_assembling_pipe=09001;
+ exec_d_cant_create_asmfile=09002;
+ exec_e_cant_create_objectfile=09003;
+ exec_e_cant_create_archivefile=09004;
+ exec_e_assembler_not_found=09005;
+ exec_t_using_assembler=09006;
+ exec_e_error_while_assembling=09007;
+ exec_e_cant_call_assembler=09008;
+ exec_i_assembling=09009;
+ exec_i_assembling_smart=09010;
+ exec_w_objfile_not_found=09011;
+ exec_w_libfile_not_found=09012;
+ exec_e_error_while_linking=09013;
+ exec_e_cant_call_linker=09014;
+ exec_i_linking=09015;
+ exec_e_util_not_found=09016;
+ exec_t_using_util=09017;
+ exec_e_exe_not_supported=09018;
+ exec_e_dll_not_supported=09019;
+ exec_i_closing_script=09020;
+ exec_e_res_not_found=09021;
+ exec_i_compilingresource=09022;
+ exec_t_unit_not_static_linkable_switch_to_smart=09023;
+ exec_t_unit_not_smart_linkable_switch_to_static=09024;
+ exec_t_unit_not_shared_linkable_switch_to_static=09025;
+ exec_e_unit_not_smart_or_static_linkable=09026;
+ exec_e_unit_not_shared_or_static_linkable=09027;
+ exec_d_resbin_params=09028;
+ execinfo_f_cant_process_executable=09128;
+ execinfo_f_cant_open_executable=09129;
+ execinfo_x_codesize=09130;
+ execinfo_x_initdatasize=09131;
+ execinfo_x_uninitdatasize=09132;
+ execinfo_x_stackreserve=09133;
+ execinfo_x_stackcommit=09134;
+ unit_t_unitsearch=10000;
+ unit_t_ppu_loading=10001;
+ unit_u_ppu_name=10002;
+ unit_u_ppu_flags=10003;
+ unit_u_ppu_crc=10004;
+ unit_u_ppu_time=10005;
+ unit_u_ppu_file_too_short=10006;
+ unit_u_ppu_invalid_header=10007;
+ unit_u_ppu_invalid_version=10008;
+ unit_u_ppu_invalid_processor=10009;
+ unit_u_ppu_invalid_target=10010;
+ unit_u_ppu_source=10011;
+ unit_u_ppu_write=10012;
+ unit_f_ppu_cannot_write=10013;
+ unit_f_ppu_read_error=10014;
+ unit_f_ppu_read_unexpected_end=10015;
+ unit_f_ppu_invalid_entry=10016;
+ unit_f_ppu_dbx_count_problem=10017;
+ unit_e_illegal_unit_name=10018;
+ unit_f_too_much_units=10019;
+ unit_f_circular_unit_reference=10020;
+ unit_f_cant_compile_unit=10021;
+ unit_f_cant_find_ppu=10022;
+ unit_w_unit_name_error=10023;
+ unit_f_unit_name_error=10024;
+ unit_w_switch_us_missed=10025;
+ unit_f_errors_in_unit=10026;
+ unit_u_load_unit=10027;
+ unit_u_recompile_crc_change=10028;
+ unit_u_recompile_source_found_alone=10029;
+ unit_u_recompile_staticlib_is_older=10030;
+ unit_u_recompile_sharedlib_is_older=10031;
+ unit_u_recompile_obj_and_asm_older=10032;
+ unit_u_recompile_obj_older_than_asm=10033;
+ unit_u_parsing_interface=10034;
+ unit_u_parsing_implementation=10035;
+ unit_u_second_load_unit=10036;
+ unit_u_check_time=10037;
+ unit_w_cant_compile_unit_with_changed_incfile=10040;
+ unit_h_source_modified=10041;
+ unit_u_ppu_invalid_fpumode=10042;
+ unit_u_loading_interface_units=10043;
+ unit_u_loading_implementation_units=10044;
+ unit_u_interface_crc_changed=10045;
+ unit_u_implementation_crc_changed=10046;
+ unit_u_finished_compiling=10047;
+ unit_u_add_depend_to=10048;
+ unit_u_no_reload_is_caller=10049;
+ unit_u_no_reload_in_second_compile=10050;
+ unit_u_flag_for_reload=10051;
+ unit_u_forced_reload=10052;
+ unit_u_previous_state=10053;
+ unit_u_second_compile_unit=10054;
+ unit_u_loading_unit=10055;
+ unit_u_finished_loading_unit=10056;
+ unit_u_registering_new_unit=10057;
+ unit_u_reresolving_unit=10058;
+ unit_u_skipping_reresolving_unit=10059;
+ option_usage=11000;
+ option_only_one_source_support=11001;
+ option_def_only_for_os2=11002;
+ option_no_nested_response_file=11003;
+ option_no_source_found=11004;
+ option_no_option_found=11005;
+ option_illegal_para=11006;
+ option_help_pages_para=11007;
+ option_too_many_cfg_files=11008;
+ option_unable_open_file=11009;
+ option_reading_further_from=11010;
+ option_target_is_already_set=11011;
+ option_no_shared_lib_under_dos=11012;
+ option_too_many_ifdef=11013;
+ option_too_many_endif=11014;
+ option_too_less_endif=11015;
+ option_no_debug_support=11016;
+ option_no_debug_support_recompile_fpc=11017;
+ option_obsolete_switch=11018;
+ option_obsolete_switch_use_new=11019;
+ option_switch_bin_to_src_assembler=11020;
+ option_incompatible_asm=11021;
+ option_asm_forced=11022;
+ option_using_file=11026;
+ option_using_env=11027;
+ option_handling_option=11028;
+ option_help_press_enter=11029;
+ option_start_reading_configfile=11030;
+ option_end_reading_configfile=11031;
+ option_interpreting_option=11032;
+ option_interpreting_firstpass_option=11036;
+ option_interpreting_file_option=11033;
+ option_read_config_file=11034;
+ option_found_file=11035;
+ option_code_page_not_available=11039;
+ option_logo=11023;
+ option_info=11024;
+ option_help_pages=11025;
+
+ MsgTxtSize = 39245;
+
+ MsgIdxMax : array[1..20] of longint=(
+ 19,73,218,59,59,47,100,20,135,60,
+ 40,1,1,1,1,1,1,1,1,1
+ );
diff --git a/compiler/msgtxt.inc b/compiler/msgtxt.inc
new file mode 100644
index 0000000000..e65bbef12f
--- /dev/null
+++ b/compiler/msgtxt.inc
@@ -0,0 +1,958 @@
+{$ifdef Delphi}
+const msgtxt : array[0..000163] of string[240]=(
+{$else Delphi}
+const msgtxt : array[0..000163,1..240] of char=(
+{$endif Delphi}
+ '01000_T_Compiler: $1'#000+
+ '01001_D_Compiler OS: $1'#000+
+ '01002_I_Target OS: $1'#000+
+ '01003_T_Using executable path: $1'#000+
+ '01004_T_Using unit path: $1'#000+
+ '01005_T_Using include path: $1'#000+
+ '01006_T_Using library path: $1'#000+
+ '01007_T_Using object path: $1'#000+
+ '01008_I_$1 Lines co','mpiled, $2 sec'#000+
+ '01009_F_No memory left'#000+
+ '01010_I_Writing Resource String Table file: $1'#000+
+ '01011_E_Writing Resource String Table file: $1'#000+
+ '01012_I_Fatal:'#000+
+ '01013_I_Error:'#000+
+ '01014_I_Warning:'#000+
+ '01015_I_Note:'#000+
+ '01016_I_Hint:'#000+
+ '01017_E_Path "$1" does not exist'#000,
+ '01018_F_Compilation aborted'#000+
+ '02000_F_Unexpected end of file'#000+
+ '02001_F_String exceeds line'#000+
+ '02002_F_illegal character "$1" ($2)'#000+
+ '02003_F_Syntax error, "$1" expected but "$2" found'#000+
+ '02004_TL_Start reading includefile $1'#000+
+ '02005_W_Comment level $1 fou','nd'#000+
+ '02008_N_Ignored compiler switch "$1"'#000+
+ '02009_W_Illegal compiler switch "$1"'#000+
+ '02010_W_Misplaced global compiler switch'#000+
+ '02011_E_Illegal char constant'#000+
+ '02012_F_Can'#039't open file "$1"'#000+
+ '02013_F_Can'#039't open include file "$1"'#000+
+ '02015_E_Illegal record ali','gnment specifier "$1"'#000+
+ '02016_E_Illegal enum minimum-size specifier "$1"'#000+
+ '02017_E_$ENDIF expected for $1 $2 defined in $3 line $4'#000+
+ '02018_E_Syntax error while parsing a conditional compiling expression'#000+
+ '02019_E_Evaluating a conditional compiling ','expression'#000+
+ '02020_W_Macro contents are limited to 255 characters in length'#000+
+ '02021_E_ENDIF without IF(N)DEF'#000+
+ '02022_F_User defined: $1'#000+
+ '02023_E_User defined: $1'#000+
+ '02024_W_User defined: $1'#000+
+ '02025_N_User defined: $1'#000+
+ '02026_H_User defined: $1'#000+
+ '02027_I_Us','er defined: $1'#000+
+ '02028_E_Keyword redefined as macro has no effect'#000+
+ '02029_F_Macro buffer overflow while reading or expanding a macro'#000+
+ '02030_W_Expanding of macros exceeds a depth of 16.'#000+
+ '02031_W_compiler switches aren'#039't supported in // styled comm','ents'+
+ #000+
+ '02032_DL_Handling switch "$1"'#000+
+ '02033_CL_ENDIF $1 found'#000+
+ '02034_CL_IFDEF $1 found, $2'#000+
+ '02035_CL_IFOPT $1 found, $2'#000+
+ '02036_CL_IF $1 found, $2'#000+
+ '02037_CL_IFNDEF $1 found, $2'#000+
+ '02038_CL_ELSE $1 found, $2'#000+
+ '02039_CL_Skipping until...'#000+
+ '02040_I_Press <re','turn> to continue'#000+
+ '02041_W_Unsupported switch "$1"'#000+
+ '02042_W_Illegal compiler directive "$1"'#000+
+ '02043_TL_Back in $1'#000+
+ '02044_W_Unsupported application type: "$1"'#000+
+ '02045_W_APPTYPE is not supported by the target OS'#000+
+ '02046_W_DESCRIPTION is not supported ','by the target OS'#000+
+ '02047_N_VERSION is not supported by target OS'#000+
+ '02048_N_VERSION only for exes or DLLs'#000+
+ '02049_W_Wrong format for VERSION directive "$1"'#000+
+ '02050_E_Illegal assembler style specified "$1"'#000+
+ '02051_W_ASM reader switch is not possible in','side asm statement, "$1"'+
+ ' will be effective only for next'#000+
+ '02052_E_Wrong switch toggle, use ON/OFF or +/-'#000+
+ '02053_E_Resource files are not supported for this target'#000+
+ '02054_W_Include environment "$1" not found in environment'#000+
+ '02055_E_Illegal value',' for FPU register limit'#000+
+ '02056_W_Only one resource file is supported for this target'#000+
+ '02057_W_Macro support has been turned off'#000+
+ '02058_E_Illegal interface type specified. Valids are COM, CORBA or DEF'+
+ 'AULT.'#000+
+ '02059_W_APPID is only supported for Pa','lmOS'#000+
+ '02060_W_APPNAME is only supported for PalmOS'#000+
+ '02061_E_Constant strings can'#039't be longer than 255 chars'#000+
+ '02062_F_Including include files exceeds a depth of 16.'#000+
+ '02063_F_Too many levels of PUSH'#000+
+ '02064_E_A POP without a preceding PUSH'#000+
+ '02065_E_','Macro or compile time variable "$1" does not have any value'#000+
+ '02066_E_Wrong switch toggle, use ON/OFF/DEFAULT or +/-/*'#000+
+ '02067_E_Mode switch "$1" not allowed here'#000+
+ '02068_E_Compile time variable or macro "$1" is not defined.'#000+
+ '02069_E_UTF-8 code gr','eater than 65535 found'#000+
+ '02070_E_Malformed UTF-8 string'#000+
+ '02071_C_UTF-8 signature found, using UTF-8 encoding'#000+
+ '02072_E_Compile time expression: Wanted $1 but got $2 at $3'#000+
+ '03000_E_Parser - Syntax Error'#000+
+ '03004_E_INTERRUPT procedure can'#039't be nested'#000,
+ '03005_W_Procedure type "$1" ignored'#000+
+ '03006_E_Not all declarations of "$1" are declared with OVERLOAD'#000+
+ '03008_E_Duplicate exported function name "$1"'#000+
+ '03009_E_Duplicate exported function index $1'#000+
+ '03010_E_Invalid index for exported function'#000+
+ '03011','_W_Relocatable DLL or executable $1 debug info does not work, d'+
+ 'isabled.'#000+
+ '03012_W_To allow debugging for win32 code you need to disable relocati'+
+ 'on with -WN option'#000+
+ '03013_E_Constructor name must be INIT'#000+
+ '03014_E_Destructor name must be DONE'#000+
+ '0301','6_E_Procedure type INLINE not supported'#000+
+ '03018_W_Constructor should be public'#000+
+ '03019_W_Destructor should be public'#000+
+ '03020_N_Class should have one destructor only'#000+
+ '03021_E_Local class definitions are not allowed'#000+
+ '03022_F_Anonym class definitions ','are not allowed'#000+
+ '03023_N_The object "$1" has no VMT'#000+
+ '03024_E_Illegal parameter list'#000+
+ '03026_E_Wrong number of parameters specified'#000+
+ '03027_E_overloaded identifier "$1" isn'#039't a function'#000+
+ '03028_E_overloaded functions have the same parameter list'#000+
+ '030','29_E_function header doesn'#039't match the forward declaration "$'+
+ '1"'#000+
+ '03030_E_function header "$1" doesn'#039't match forward : var name chan'+
+ 'ges $2 => $3'#000+
+ '03031_N_Values in enumeration types have to be ascending'#000+
+ '03033_E_With can not be used for variabl','es in a different segment'#000+
+ '03034_E_function nesting > 31'#000+
+ '03035_E_range check error while evaluating constants'#000+
+ '03036_W_range check error while evaluating constants'#000+
+ '03037_E_duplicate case label'#000+
+ '03038_E_Upper bound of case range is less than lo','wer bound'#000+
+ '03039_E_typed constants of classes are not allowed'#000+
+ '03040_E_functions variables of overloaded functions are not allowed'#000+
+ '03041_E_string length must be a value from 1 to 255'#000+
+ '03042_W_use extended syntax of NEW and DISPOSE for instance','s of obje'+
+ 'cts'#000+
+ '03043_W_use of NEW or DISPOSE for untyped pointers is meaningless'#000+
+ '03044_E_use of NEW or DISPOSE is not possible for untyped pointers'#000+
+ '03045_E_class identifier expected'#000+
+ '03046_E_type identifier not allowed here'#000+
+ '03047_E_method iden','tifier expected'#000+
+ '03048_E_function header doesn'#039't match any method of this class "$1'+
+ '"'#000+
+ '03049_DL_procedure/function $1'#000+
+ '03050_E_Illegal floating point constant'#000+
+ '03051_E_FAIL can be used in constructors only'#000+
+ '03052_E_Destructors can'#039't have paramete','rs'#000+
+ '03053_E_Only class methods can be referred with class references'#000+
+ '03054_E_Only class methods can be accessed in class methods'#000+
+ '03055_E_Constant and CASE types do not match'#000+
+ '03056_E_The symbol can'#039't be exported from a library'#000+
+ '03057_W_An inhe','rited method is hidden by "$1"'#000+
+ '03058_E_There is no method in an ancestor class to be overridden: "$1"'+
+ #000+
+ '03059_E_No member is provided to access property'#000+
+ '03060_W_Stored property directive is not yet implemented'#000+
+ '03061_E_Illegal symbol for prope','rty access'#000+
+ '03062_E_Cannot access a protected field of an object here'#000+
+ '03063_E_Cannot access a private field of an object here'#000+
+ '03066_E_overridden methods must have the same return type: "$2" is ove'+
+ 'rriden by "$1" which has another return type'#000,
+ '03067_E_EXPORT declared functions can'#039't be nested'#000+
+ '03068_E_methods can'#039't be EXPORTed'#000+
+ '03069_E_call by var parameters have to match exactly: Got "$1" expecte'+
+ 'd "$2"'#000+
+ '03070_E_Class isn'#039't a parent class of the current class'#000+
+ '03071_E_SELF is only al','lowed in methods'#000+
+ '03072_E_methods can be only in other methods called direct with type i'+
+ 'dentifier of the class'#000+
+ '03073_E_Illegal use of '#039':'#039#000+
+ '03074_E_range check error in set constructor or duplicate set element'#000+
+ '03075_E_Pointer to object expecte','d'#000+
+ '03076_E_Expression must be constructor call'#000+
+ '03077_E_Expression must be destructor call'#000+
+ '03078_E_Illegal order of record elements'#000+
+ '03079_E_Expression type must be class or record type'#000+
+ '03080_E_Procedures can'#039't return a value'#000+
+ '03081_E_construct','ors and destructors must be methods'#000+
+ '03082_E_Operator is not overloaded'#000+
+ '03083_E_Impossible to overload assignment for equal types'#000+
+ '03084_E_Impossible operator overload'#000+
+ '03085_E_Re-raise isn'#039't possible there'#000+
+ '03086_E_The extended syntax of new o','r dispose isn'#039't allowed for '+
+ 'a class'#000+
+ '03088_E_Procedure overloading is switched off'#000+
+ '03089_E_It is not possible to overload this operator (overload = inste'+
+ 'ad)'#000+
+ '03090_E_Comparative operator must return a boolean value'#000+
+ '03091_E_Only virtual method','s can be abstract'#000+
+ '03092_F_Use of unsupported feature!'#000+
+ '03093_E_The mix of different kind of objects (class, object, interface'+
+ ', etc) isn'#039't allowed'#000+
+ '03094_W_Unknown procedure directive had to be ignored: "$1"'#000+
+ '03095_E_absolute can only be associ','ated to one variable'#000+
+ '03096_E_absolute can only be associated with a var or const'#000+
+ '03097_E_Only one variable can be initialized'#000+
+ '03098_E_Abstract methods shouldn'#039't have any definition (with funct'+
+ 'ion body)'#000+
+ '03099_E_This overloaded function can'#039't',' be local (must be exporte'+
+ 'd)'#000+
+ '03100_W_Virtual methods are used without a constructor in "$1"'#000+
+ '03101_CL_Macro defined: $1'#000+
+ '03102_CL_Macro undefined: $1'#000+
+ '03103_CL_Macro $1 set to $2'#000+
+ '03104_I_Compiling $1'#000+
+ '03105_UL_Parsing interface of unit $1'#000+
+ '03106','_UL_Parsing implementation of $1'#000+
+ '03107_DL_Compiling $1 for the second time'#000+
+ '03109_E_No property found to override'#000+
+ '03110_E_Only one default property is allowed'#000+
+ '03111_E_The default property must be an array property'#000+
+ '03112_E_Virtual constructor','s are only supported in class object mode'+
+ 'l'#000+
+ '03113_E_No default property available'#000+
+ '03114_E_The class can'#039't have a published section, use the {$M+} sw'+
+ 'itch'#000+
+ '03115_E_Forward declaration of class "$1" must be resolved here to use'+
+ ' the class as ance','stor'#000+
+ '03116_E_Local operators not supported'#000+
+ '03117_E_Procedure directive "$1" not allowed in interface section'#000+
+ '03118_E_Procedure directive "$1" not allowed in implementation section'+
+ #000+
+ '03119_E_Procedure directive "$1" not allowed in procvar decl','aration'#000+
+ '03120_E_Function is already declared Public/Forward "$1"'#000+
+ '03121_E_Can'#039't use both EXPORT and EXTERNAL'#000+
+ '03123_W_"$1" not yet supported inside inline procedure/function'#000+
+ '03124_W_Inlining disabled'#000+
+ '03125_I_Writing Browser log $1'#000+
+ '03126_H_may',' be pointer dereference is missing'#000+
+ '03127_F_Selected assembler reader not supported'#000+
+ '03128_E_Procedure directive "$1" has conflicts with other directives'#000+
+ '03129_E_Calling convention doesn'#039't match forward'#000+
+ '03131_E_Property can'#039't have a default v','alue'#000+
+ '03132_E_The default value of a property must be constant'#000+
+ '03133_E_Symbol can'#039't be published, can be only a class'#000+
+ '03134_E_That kind of property can'#039't be published'#000+
+ '03136_E_An import name is required'#000+
+ '03138_E_Division by zero'#000+
+ '03139_E_Invali','d floating point operation'#000+
+ '03140_E_Upper bound of range is less than lower bound'#000+
+ '03141_W_string "$1" is longer than "$2"'#000+
+ '03142_E_string length is larger than array of char length'#000+
+ '03143_E_Illegal expression after message directive'#000+
+ '03144_E_Me','ssage handlers can take only one call by ref. parameter'#000+
+ '03145_E_Duplicate message label: "$1"'#000+
+ '03146_E_Self can only be an explicit parameter in methods which are me'+
+ 'ssage handlers'#000+
+ '03147_E_Threadvars can be only static or global'#000+
+ '03148_F_Direc','t assembler not supported for binary output format'#000+
+ '03149_W_Don'#039't load OBJPAS unit manually, use \{\$mode objfpc\} or '+
+ '\{\$mode delphi\} instead'#000+
+ '03150_E_OVERRIDE can'#039't be used in objects'#000+
+ '03151_E_Data types which require initialization/finaliz','ation can'#039+
+ 't be used in variant records'#000+
+ '03152_E_Resourcestrings can be only static or global'#000+
+ '03153_E_Exit with argument can'#039't be used here'#000+
+ '03154_E_The type of the storage symbol must be boolean'#000+
+ '03155_E_This symbol isn'#039't allowed as storage sy','mbol'#000+
+ '03156_E_Only class which are compiled in $M+ mode can be published'#000+
+ '03157_E_Procedure directive expected'#000+
+ '03158_E_The value for a property index must be of an ordinal type'#000+
+ '03159_E_Procedure name to short to be exported'#000+
+ '03160_E_No DEFFILE',' entry can be generated for unit global vars'#000+
+ '03161_E_Compile without -WD option'#000+
+ '03162_F_You need ObjFpc (-S2) or Delphi (-Sd) mode to compile this mod'+
+ 'ule'#000+
+ '03163_E_Can'#039't export with index under $1'#000+
+ '03164_E_Exporting of variables is not support','ed under $1'#000+
+ '03165_E_Improper GUID syntax'#000+
+ '03168_W_Procedure named "$1" not found that is suitable for implementi'+
+ 'ng the $2.$3'#000+
+ '03169_E_interface identifier expected'#000+
+ '03170_E_Type "$1" can'#039't be used as array index type'#000+
+ '03171_E_Con- and destructo','rs aren'#039't allowed in interfaces'#000+
+ '03172_E_Access specifiers can'#039't be used in INTERFACES'#000+
+ '03173_E_An interface can'#039't contain fields'#000+
+ '03174_E_Can'#039't declare local procedure as EXTERNAL'#000+
+ '03175_W_Some fields coming before "$1" weren'#039't initialized'#000+
+ '031','76_E_Some fields coming before "$1" weren'#039't initialized'#000+
+ '03177_W_Some fields coming after "$1" weren'#039't initialized'#000+
+ '03178_E_VarArgs directive without CDecl and External'#000+
+ '03179_E_Self must be a normal (call-by-value) parameter'#000+
+ '03180_E_Interface',' "$1" has no interface identification'#000+
+ '03181_E_Unknown class field or method identifier "$1"'#000+
+ '03182_W_Overriding calling convention "$1" with "$2"'#000+
+ '03183_E_Typed constants of the type "procedure of object" can only be '+
+ 'initialized with NIL'#000+
+ '0318','4_E_Default value can only be assigned to one parameter'#000+
+ '03185_E_Default parameter required for "$1"'#000+
+ '03186_W_Use of unsupported feature!'#000+
+ '03187_H_C arrays are passed by reference'#000+
+ '03188_E_C array of const must be the last argument'#000+
+ '03189_H_Type',' "$1" redefinition'#000+
+ '03190_W_cdecl'#039'ared functions have no high parameter'#000+
+ '03191_W_cdecl'#039'ared functions do not support open strings'#000+
+ '03192_E_Cannot initialize variables declared as threadvar'#000+
+ '03193_E_Message directive is only allowed in Classes'#000+
+ '0','3194_E_Procedure or Function expected'#000+
+ '03195_W_Calling convention directive ignored: "$1"'#000+
+ '03196_E_REINTRODUCE can'#039't be used in objects'#000+
+ '03197_E_Each argument must have it'#039's own location'#000+
+ '03198_E_Each argument must have an explicit location'#000+
+ '031','99_E_Unknown argument location'#000+
+ '03200_E_32 Bit-Integer or pointer variable expected'#000+
+ '03201_E_Goto statements aren'#039't allowed between different procedure'+
+ 's'#000+
+ '03202_F_Procedure too complex, it requires too much registers'#000+
+ '03203_E_Illegal expression'#000,
+ '03204_E_Invalid integer expression'#000+
+ '03205_E_Illegal qualifier'#000+
+ '03206_E_High range limit < low range limit'#000+
+ '03207_E_Exit'#039's parameter must be the name of the procedure it is u'+
+ 'sed in'#000+
+ '03208_E_Illegal assignment to for-loop variable "$1"'#000+
+ '03209_E_Ca','n'#039't declare local variable as EXTERNAL'#000+
+ '03210_E_Procedure is already declared EXTERNAL'#000+
+ '03211_W_Implicit uses of Variants unit'#000+
+ '03212_E_Class and static methods can'#039't be used in INTERFACES'#000+
+ '03213_E_Overflow in arithmetic operation'#000+
+ '03214_E_Prote','cted or private expected'#000+
+ '03215_E_SLICE can'#039't be used outside of parameter list'#000+
+ '03216_E_A DISPINTERFACE can'#039't have a parent class'#000+
+ '03217_E_A DISPINTERFACE needs a guid'#000+
+ '04000_E_Type mismatch'#000+
+ '04001_E_Incompatible types: got "$1" expected "$2"'#000+
+ '0','4002_E_Type mismatch between "$1" and "$2"'#000+
+ '04003_E_Type identifier expected'#000+
+ '04004_E_Variable identifier expected'#000+
+ '04005_E_Integer expression expected, but got "$1"'#000+
+ '04006_E_Boolean expression expected, but got "$1"'#000+
+ '04007_E_Ordinal expression ','expected'#000+
+ '04008_E_pointer type expected, but got "$1"'#000+
+ '04009_E_class type expected, but got "$1"'#000+
+ '04011_E_Can'#039't evaluate constant expression'#000+
+ '04012_E_Set elements are not compatible'#000+
+ '04013_E_Operation not implemented for sets'#000+
+ '04014_W_Automatic t','ype conversion from floating type to COMP which i'+
+ 's an integer type'#000+
+ '04015_H_use DIV instead to get an integer result'#000+
+ '04016_E_string types doesn'#039't match, because of $V+ mode'#000+
+ '04017_E_succ or pred on enums with assignments not possible'#000+
+ '04018_E_','Can'#039't read or write variables of this type'#000+
+ '04019_E_Can'#039't use readln or writeln on typed file'#000+
+ '04020_E_Can'#039't use read or write on untyped file.'#000+
+ '04021_E_Type conflict between set elements'#000+
+ '04022_W_lo/hi(dword/qword) returns the upper/lower word','/dword'#000+
+ '04023_E_Integer or real expression expected'#000+
+ '04024_E_Wrong type "$1" in array constructor'#000+
+ '04025_E_Incompatible type for arg no. $1: Got "$2", expected "$3"'#000+
+ '04026_E_Method (variable) and Procedure (variable) are not compatible'#000+
+ '04027_E_','Illegal constant passed to internal math function'#000+
+ '04028_E_Can'#039't get the address of constants'#000+
+ '04029_E_Argument can'#039't be assigned to'#000+
+ '04030_E_Can'#039't assign local procedure/function to procedure variabl'+
+ 'e'#000+
+ '04031_E_Can'#039't assign values to an address',#000+
+ '04032_E_Can'#039't assign values to const variable'#000+
+ '04033_E_Array type required'#000+
+ '04034_E_interface type expected, but got "$1"'#000+
+ '04035_W_Mixing signed expressions and longwords gives a 64bit result'#000+
+ '04036_W_Mixing signed expressions and cardinals he','re may cause a ran'+
+ 'ge check error'#000+
+ '04037_E_Typecast has different size ($1 -> $2) in assignment'#000+
+ '04038_E_enums with assignments can'#039't be used as array index'#000+
+ '04039_E_Class or Object types "$1" and "$2" are not related'#000+
+ '04040_W_Class types "$1" a','nd "$2" are not related'#000+
+ '04041_E_Class or interface type expected, but got "$1"'#000+
+ '04042_E_Type "$1" is not completely defined'#000+
+ '04043_W_String literal has more characters than short string length'#000+
+ '04044_W_Comparison is always false due to range o','f values'#000+
+ '04045_W_Comparison is always true due to range of values'#000+
+ '04046_W_Constructing a class "$1" with abstract methods'#000+
+ '04047_H_The left operand of the IN operator should be byte sized'#000+
+ '04048_W_Type size mismatch, possible loss of data / r','ange check erro'+
+ 'r'#000+
+ '04049_H_Type size mismatch, possible loss of data / range check error'#000+
+ '04050_E_The address of an abstract method can'#039't be taken'#000+
+ '04051_E_The operator is not applicable for the operand type'#000+
+ '04052_E_Constant Expression expected',#000+
+ '04053_E_Operation "$1" not supported for types "$2" and "$3"'#000+
+ '04054_E_Illegal type conversion: "$1" to "$2"'#000+
+ '04055_H_Conversion between ordinals and pointers is not portable'#000+
+ '04056_W_Conversion between ordinals and pointers is not portable'#000+
+ '04','057_E_Can'#039't determine which overloaded function to call'#000+
+ '04058_E_Illegal counter variable'#000+
+ '05000_E_Identifier not found "$1"'#000+
+ '05001_F_Internal Error in SymTableStack()'#000+
+ '05002_E_Duplicate identifier "$1"'#000+
+ '05003_H_Identifier already defined in $1 ','at line $2'#000+
+ '05004_E_Unknown identifier "$1"'#000+
+ '05005_E_Forward declaration not solved "$1"'#000+
+ '05007_E_Error in type definition'#000+
+ '05009_E_Forward type not resolved "$1"'#000+
+ '05010_E_Only static variables can be used in static methods or outside'+
+ ' methods'#000+
+ '05','012_F_record or class type expected'#000+
+ '05013_E_Instances of classes or objects with an abstract method are no'+
+ 't allowed'#000+
+ '05014_W_Label not defined "$1"'#000+
+ '05015_E_Label used but not defined "$1"'#000+
+ '05016_E_Illegal label declaration'#000+
+ '05017_E_GOTO and LA','BEL are not supported (use switch -Sg)'#000+
+ '05018_E_Label not found'#000+
+ '05019_E_identifier isn'#039't a label'#000+
+ '05020_E_label already defined'#000+
+ '05021_E_illegal type declaration of set elements'#000+
+ '05022_E_Forward class definition not resolved "$1"'#000+
+ '05023_H_Unit "','$1" not used in $2'#000+
+ '05024_H_Parameter "$1" not used'#000+
+ '05025_N_Local variable "$1" not used'#000+
+ '05026_H_Value parameter "$1" is assigned but never used'#000+
+ '05027_N_Local variable "$1" is assigned but never used'#000+
+ '05028_H_Local $1 "$2" is not used'#000+
+ '05029_N','_Private field "$1.$2" is never used'#000+
+ '05030_N_Private field "$1.$2" is assigned but never used'#000+
+ '05031_N_Private method "$1.$2" never used'#000+
+ '05032_E_Set type expected'#000+
+ '05033_W_Function result does not seem to be set'#000+
+ '05034_W_Type "$1" is not align','ed correctly in current record for C'#000+
+ '05035_E_Unknown record field identifier "$1"'#000+
+ '05036_W_Local variable "$1" does not seem to be initialized'#000+
+ '05037_W_Variable "$1" does not seem to be initialized'#000+
+ '05038_E_identifier idents no member "$1"'#000+
+ '050','39_H_Found declaration: $1'#000+
+ '05040_E_Data element too large'#000+
+ '05042_E_No matching implementation for interface method "$1" found'#000+
+ '05043_W_Symbol "$1" is deprecated'#000+
+ '05044_W_Symbol "$1" is not portable'#000+
+ '05055_W_Symbol "$1" is not implemented'#000+
+ '05056_','E_Can'#039't create unique type from this type'#000+
+ '05057_H_Local variable "$1" does not seem to be initialized'#000+
+ '05058_H_Variable "$1" does not seem to be initialized'#000+
+ '06009_E_Parameter list size exceeds 65535 bytes'#000+
+ '06012_E_File types must be var param','eters'#000+
+ '06013_E_The use of a far pointer isn'#039't allowed there'#000+
+ '06015_E_EXPORT declared functions can'#039't be called'#000+
+ '06016_W_Possible illegal call of constructor or destructor'#000+
+ '06017_N_Inefficient code'#000+
+ '06018_W_unreachable code'#000+
+ '06020_E_Abstract metho','ds can'#039't be called directly'#000+
+ '06027_DL_Register $1 weight $2 $3'#000+
+ '06029_DL_Stack frame is omitted'#000+
+ '06031_E_Object or class methods can'#039't be inline.'#000+
+ '06032_E_Procvar calls cannot be inline.'#000+
+ '06033_E_No code for inline procedure stored'#000+
+ '06035_E_Eleme','nt zero of an ansi/wide- or longstring can'#039't be acc'+
+ 'essed, use (set)length instead'#000+
+ '06037_E_Constructors or destructors can not be called inside a '#039'wi'+
+ 'th'#039' clause'#000+
+ '06038_E_Cannot call message handler methods directly'#000+
+ '06039_E_Jump in or outside o','f an exception block'#000+
+ '06040_E_Control flow statements aren'#039't allowed in a finally block'#000+
+ '06041_W_Parameters size exceeds limit for certain cpu'#039's'#000+
+ '06042_W_Local variable size exceed limit for certain cpu'#039's'#000+
+ '06043_E_Local variables size exceeds s','upported limit'#000+
+ '06044_E_BREAK not allowed'#000+
+ '06045_E_CONTINUE not allowed'#000+
+ '06046_F_Unknown compilerproc "$1". Check if you use the correct run ti'+
+ 'me library.'#000+
+ '07000_DL_Starting $1 styled assembler parsing'#000+
+ '07001_DL_Finished $1 styled assembler pars','ing'#000+
+ '07002_E_Non-label pattern contains @'#000+
+ '07004_E_Error building record offset'#000+
+ '07005_E_OFFSET used without identifier'#000+
+ '07006_E_TYPE used without identifier'#000+
+ '07007_E_Cannot use local variable or parameters here'#000+
+ '07008_E_need to use OFFSET here'#000+
+ '0','7009_E_need to use $ here'#000+
+ '07010_E_Cannot use multiple relocatable symbols'#000+
+ '07011_E_Relocatable symbol can only be added'#000+
+ '07012_E_Invalid constant expression'#000+
+ '07013_E_Relocatable symbol is not allowed'#000+
+ '07014_E_Invalid reference syntax'#000+
+ '07015_E_Yo','u can not reach $1 from that code'#000+
+ '07016_E_Local symbols/labels aren'#039't allowed as references'#000+
+ '07017_E_Invalid base and index register usage'#000+
+ '07018_W_Possible error in object field handling'#000+
+ '07019_E_Wrong scale factor specified'#000+
+ '07020_E_Multiple ','index register usage'#000+
+ '07021_E_Invalid operand type'#000+
+ '07022_E_Invalid string as opcode operand: $1'#000+
+ '07023_W_@CODE and @DATA not supported'#000+
+ '07024_E_Null label references are not allowed'#000+
+ '07025_E_Divide by zero in asm evaluator'#000+
+ '07026_E_Illegal expre','ssion'#000+
+ '07027_E_escape sequence ignored: $1'#000+
+ '07028_E_Invalid symbol reference'#000+
+ '07029_W_Fwait can cause emulation problems with emu387'#000+
+ '07030_W_$1 without operand translated into $1P'#000+
+ '07031_W_ENTER instruction is not supported by Linux kernel'#000+
+ '0703','2_W_Calling an overload function in assembler'#000+
+ '07033_E_Unsupported symbol type for operand'#000+
+ '07034_E_Constant value out of bounds'#000+
+ '07035_E_Error converting decimal $1'#000+
+ '07036_E_Error converting octal $1'#000+
+ '07037_E_Error converting binary $1'#000+
+ '07038_E_','Error converting hexadecimal $1'#000+
+ '07039_H_$1 translated to $2'#000+
+ '07040_W_$1 is associated to an overloaded function'#000+
+ '07041_E_Cannot use SELF outside a method'#000+
+ '07042_E_Cannot use OLDEBP outside a nested procedure'#000+
+ '07043_W_Procedures can'#039't return any',' value in asm code'#000+
+ '07044_E_SEG not supported'#000+
+ '07045_E_Size suffix and destination or source size do not match'#000+
+ '07046_W_Size suffix and destination or source size do not match'#000+
+ '07047_E_Assembler syntax error'#000+
+ '07048_E_Invalid combination of opcod','e and operands'#000+
+ '07049_E_Assembler syntax error in operand'#000+
+ '07050_E_Assembler syntax error in constant'#000+
+ '07051_E_Invalid String expression'#000+
+ '07052_W_constant with symbol $1 for address which is not on a pointer'#000+
+ '07053_E_Unrecognized opcode $1'#000+
+ '07054','_E_Invalid or missing opcode'#000+
+ '07055_E_Invalid combination of prefix and opcode: $1'#000+
+ '07056_E_Invalid combination of override and opcode: $1'#000+
+ '07057_E_Too many operands on line'#000+
+ '07058_W_NEAR ignored'#000+
+ '07059_W_FAR ignored'#000+
+ '07060_E_Duplicate local symb','ol $1'#000+
+ '07061_E_Undefined local symbol $1'#000+
+ '07062_E_Unknown label identifier $1'#000+
+ '07063_E_Invalid register name'#000+
+ '07064_E_Invalid floating point register name'#000+
+ '07066_W_Modulo not supported'#000+
+ '07067_E_Invalid floating point constant $1'#000+
+ '07068_E_Invalid f','loating point expression'#000+
+ '07069_E_Wrong symbol type'#000+
+ '07070_E_Cannot index a local var or parameter with a register'#000+
+ '07071_E_Invalid segment override expression'#000+
+ '07072_W_Identifier $1 supposed external'#000+
+ '07073_E_Strings not allowed as constants'#000+
+ '07','074_No type of variable specified'#000+
+ '07075_E_assembler code not returned to text section'#000+
+ '07076_E_Not a directive or local symbol $1'#000+
+ '07077_E_Using a defined name as a local label'#000+
+ '07078_E_Dollar token is used without an identifier'#000+
+ '07079_W_32bit ','constant created for address'#000+
+ '07080_N_.align is target specific, use .balign or .p2align'#000+
+ '07081_E_Can'#039't access fields directly for parameters'#000+
+ '07082_E_Can'#039't access fields of objects/classes directly'#000+
+ '07083_E_No size specified and unable to dete','rmine the size of the op'+
+ 'erands'#000+
+ '07084_E_Cannot use RESULT in this function'#000+
+ '07086_W_"$1" without operand translated into "$1 %st,%st(1)"'#000+
+ '07087_W_"$1 %st(n)" translated into "$1 %st,%st(n)"'#000+
+ '07088_W_"$1 %st(n)" translated into "$1 %st(n),%st"'#000+
+ '0','7089_E_Char < not allowed here'#000+
+ '07090_E_Char > not allowed here'#000+
+ '07093_W_ALIGN not supported'#000+
+ '07094_E_Inc and Dec cannot be together'#000+
+ '07095_E_Invalid reglist for movem'#000+
+ '07096_E_Reglist invalid for opcode'#000+
+ '07097_E_Higher cpu mode required ($1)'#000+
+ '070','98_W_No size specified and unable to determine the size of the op'+
+ 'erands, using DWORD as default'#000+
+ '07099_E_Syntax error while trying to parse a shifter operand'#000+
+ '08000_F_Too many assembler files'#000+
+ '08001_F_Selected assembler output not supported'#000+
+ '08','002_F_Comp not supported'#000+
+ '08003_F_Direct not support for binary writers'#000+
+ '08004_E_Allocating of data is only allowed in bss section'#000+
+ '08005_F_No binary writer selected'#000+
+ '08006_E_Asm: Opcode $1 not in table'#000+
+ '08007_E_Asm: $1 invalid combination of op','code and operands'#000+
+ '08008_E_Asm: 16 Bit references not supported'#000+
+ '08009_E_Asm: Invalid effective address'#000+
+ '08010_E_Asm: Immediate or reference expected'#000+
+ '08011_E_Asm: $1 value exceeds bounds $2'#000+
+ '08012_E_Asm: Short jump is out of range $1'#000+
+ '08013_E_As','m: Undefined label $1'#000+
+ '08014_E_Asm: Comp type not supported for this target'#000+
+ '08015_E_Asm: Extended type not supported for this target'#000+
+ '08016_E_Asm: Duplicate label $1'#000+
+ '08017_E_Asm: Redefined label $1'#000+
+ '08018_E_Asm: First defined here'#000+
+ '08019_E_Asm:',' Invalid register $1'#000+
+ '09000_W_Source operating system redefined'#000+
+ '09001_I_Assembling (pipe) $1'#000+
+ '09002_E_Can'#039't create assembler file: $1'#000+
+ '09003_E_Can'#039't create object file: $1'#000+
+ '09004_E_Can'#039't create archive file: $1'#000+
+ '09005_E_Assembler $1 not found, s','witching to external assembling'#000+
+ '09006_T_Using assembler: $1'#000+
+ '09007_E_Error while assembling exitcode $1'#000+
+ '09008_E_Can'#039't call the assembler, error $1 switching to external a'+
+ 'ssembling'#000+
+ '09009_I_Assembling $1'#000+
+ '09010_I_Assembling with smartlinking $1',#000+
+ '09011_W_Object $1 not found, Linking may fail !'#000+
+ '09012_W_Library $1 not found, Linking may fail !'#000+
+ '09013_E_Error while linking'#000+
+ '09014_E_Can'#039't call the linker, switching to external linking'#000+
+ '09015_I_Linking $1'#000+
+ '09016_E_Util $1 not found, switchi','ng to external linking'#000+
+ '09017_T_Using util $1'#000+
+ '09018_E_Creation of Executables not supported'#000+
+ '09019_E_Creation of Dynamic/Shared Libraries not supported'#000+
+ '09020_I_Closing script $1'#000+
+ '09021_E_resource compiler not found, switching to external mode'#000,
+ '09022_I_Compiling resource $1'#000+
+ '09023_T_unit $1 can'#039't be statically linked, switching to smart lin'+
+ 'king'#000+
+ '09024_T_unit $1 can'#039't be smart linked, switching to static linking'+
+ #000+
+ '09025_T_unit $1 can'#039't be shared linked, switching to static linkin'+
+ 'g'#000+
+ '0902','6_E_unit $1 can'#039't be smart or static linked'#000+
+ '09027_E_unit $1 can'#039't be shared or static linked'#000+
+ '09028_D_Calling resource compiler "$1" with "$2" as command line'#000+
+ '09128_F_Can'#039't post process executable $1'#000+
+ '09129_F_Can'#039't open executable $1'#000+
+ '09130_X_','Size of Code: $1 bytes'#000+
+ '09131_X_Size of initialized data: $1 bytes'#000+
+ '09132_X_Size of uninitialized data: $1 bytes'#000+
+ '09133_X_Stack space reserved: $1 bytes'#000+
+ '09134_X_Stack space commited: $1 bytes'#000+
+ '10000_T_Unitsearch: $1'#000+
+ '10001_T_PPU Loading $1'#000+
+ '10002','_U_PPU Name: $1'#000+
+ '10003_U_PPU Flags: $1'#000+
+ '10004_U_PPU Crc: $1'#000+
+ '10005_U_PPU Time: $1'#000+
+ '10006_U_PPU File too short'#000+
+ '10007_U_PPU Invalid Header (no PPU at the begin)'#000+
+ '10008_U_PPU Invalid Version $1'#000+
+ '10009_U_PPU is compiled for another processor'#000+
+ '10010_U_','PPU is compiled for an other target'#000+
+ '10011_U_PPU Source: $1'#000+
+ '10012_U_Writing $1'#000+
+ '10013_F_Can'#039't Write PPU-File'#000+
+ '10014_F_Error reading PPU-File'#000+
+ '10015_F_unexpected end of PPU-File'#000+
+ '10016_F_Invalid PPU-File entry: $1'#000+
+ '10017_F_PPU Dbx count problem'#000+
+ '10','018_E_Illegal unit name: $1'#000+
+ '10019_F_Too much units'#000+
+ '10020_F_Circular unit reference between $1 and $2'#000+
+ '10021_F_Can'#039't compile unit $1, no sources available'#000+
+ '10022_F_Can'#039't find unit $1'#000+
+ '10023_W_Unit $1 was not found but $2 exists'#000+
+ '10024_F_Unit $1 ','searched but $2 found'#000+
+ '10025_W_Compiling the system unit requires the -Us switch'#000+
+ '10026_F_There were $1 errors compiling module, stopping'#000+
+ '10027_U_Load from $1 ($2) unit $3'#000+
+ '10028_U_Recompiling $1, checksum changed for $2'#000+
+ '10029_U_Recompiling $1',', source found only'#000+
+ '10030_U_Recompiling unit, static lib is older than ppufile'#000+
+ '10031_U_Recompiling unit, shared lib is older than ppufile'#000+
+ '10032_U_Recompiling unit, obj and asm are older than ppufile'#000+
+ '10033_U_Recompiling unit, obj is older th','an asm'#000+
+ '10034_U_Parsing interface of $1'#000+
+ '10035_U_Parsing implementation of $1'#000+
+ '10036_U_Second load for unit $1'#000+
+ '10037_U_PPU Check file $1 time $2'#000+
+ '10040_W_Can'#039't recompile unit $1, but found modifed include files'#000+
+ '10041_H_File $1 is newer than Rel','ease PPU file $2'#000+
+ '10042_U_Using a unit which was not compiled with correct FPU mode'#000+
+ '10043_U_Loading interface units from $1'#000+
+ '10044_U_Loading implementation units from $1'#000+
+ '10045_U_Interface CRC changed for unit $1'#000+
+ '10046_U_Implementation CRC cha','nged for unit $1'#000+
+ '10047_U_Finished compiling unit $1'#000+
+ '10048_U_Add dependency of $1 to $2'#000+
+ '10049_U_No reload, is caller: $1'#000+
+ '10050_U_No reload, already in second compile: $1'#000+
+ '10051_U_Flag for reload: $1'#000+
+ '10052_U_Forced reloading'#000+
+ '10053_U_Previous s','tate of $1: $2'#000+
+ '10054_U_Already compiling $1, setting second compile'#000+
+ '10055_U_Loading unit $1'#000+
+ '10056_U_Finished loading unit $1'#000+
+ '10057_U_Registering new unit $1'#000+
+ '10058_U_Re-resolving unit $1'#000+
+ '10059_U_Skipping re-resolving unit $1, still loading u','sed units'#000+
+ '11000_$1 [options] <inputfile> [options]'#000+
+ '11001_W_Only one source file supported'#000+
+ '11002_W_DEF file can be created only for OS/2'#000+
+ '11003_E_nested response files are not supported'#000+
+ '11004_F_No source file name in command line'#000+
+ '11005_N_No o','ption inside $1 config file'#000+
+ '11006_E_Illegal parameter: $1'#000+
+ '11007_H_-? writes help pages'#000+
+ '11008_F_Too many config files nested'#000+
+ '11009_F_Unable to open file $1'#000+
+ '11010_D_Reading further options from $1'#000+
+ '11011_W_Target is already set to: $1'#000+
+ '11012_W_','Shared libs not supported on DOS platform, reverting to stat'+
+ 'ic'#000+
+ '11013_F_too many IF(N)DEFs'#000+
+ '11014_F_too many ENDIFs'#000+
+ '11015_F_open conditional at the end of the file'#000+
+ '11016_W_Debug information generation is not supported by this executab'+
+ 'le'#000+
+ '11017','_H_Try recompiling with -dGDB'#000+
+ '11018_E_You are using the obsolete switch $1'#000+
+ '11019_E_You are using the obsolete switch $1, please use $2'#000+
+ '11020_N_Switching assembler to default source writing assembler'#000+
+ '11021_W_Assembler output selected "$1" is',' not compatible with "$2"'#000+
+ '11022_W_"$1" assembler use forced'#000+
+ '11026_T_Reading options from file $1'#000+
+ '11027_T_Reading options from environment $1'#000+
+ '11028_D_Handling option "$1"'#000+
+ '11029__*** press enter ***'#000+
+ '11030_H_Start of reading config file $1'#000+
+ '110','31_H_End of reading config file $1'#000+
+ '11032_D_interpreting option "$1"'#000+
+ '11036_D_interpreting firstpass option "$1"'#000+
+ '11033_D_interpreting file option "$1"'#000+
+ '11034_D_Reading config file "$1"'#000+
+ '11035_D_found source file name "$1"'#000+
+ '11039_E_Unknown code p','age'#000+
+ '11023_Free Pascal Compiler version $FPCVERSION [$FPCDATE] for $FPCCPU'#010+
+ 'Copyright (c) 1993-2005 by Florian Klaempfl'#000+
+ '11024_Free Pascal Compiler version $FPCVERSION'#010+
+ #010+
+ 'Compiler Date : $FPCDATE'#010+
+ 'Compiler CPU Target: $FPCCPU'#010+
+ #010+
+ 'Supported targ','ets:'#010+
+ ' $OSTARGETS'#010+
+ #010+
+ 'Supported CPU instruction sets:'#010+
+ ' $INSTRUCTIONSETS'#010+
+ #010+
+ 'Supported FPU instruction sets:'#010+
+ ' $FPUINSTRUCTIONSETS'#010+
+ #010+
+ 'This program comes under the GNU General Public Licence'#010+
+ 'For more information read COPYING.FPC'#010+
+ #010+
+ 'Report bugs,suggest','ions etc to:'#010+
+ ' bugrep@freepascal.org'#000+
+ '11025_**0*_put + after a boolean switch option to enable it, - to disa'+
+ 'ble it'#010+
+ '**1a_the compiler doesn'#039't delete the generated assembler file'#010+
+ '**2al_list sourcecode lines in assembler file'#010+
+ '**2','an_list node info in assembler file'#010+
+ '*L2ap_use pipes instead of creating temporary assembler files'#010+
+ '**2ar_list register allocation/release info in assembler file'#010+
+ '**2at_list temp allocation/release info in assembler file'#010+
+ '**1A<x>_output format:',#010+
+ '**2Adefault_use default assembler'#010+
+ '3*2Aas_assemble using GNU AS'#010+
+ '3*2Anasmcoff_coff (Go32v2) file using Nasm'#010+
+ '3*2Anasmelf_elf32 (Linux) file using Nasm'#010+
+ '3*2Anasmwin32_Win32 object file using Nasm'#010+
+ '3*2Anasmwdosx_Win32/WDOSX object file using Nasm',#010+
+ '3*2Awasm_obj file using Wasm (Watcom)'#010+
+ '3*2Anasmobj_obj file using Nasm'#010+
+ '3*2Amasm_obj file using Masm (Microsoft)'#010+
+ '3*2Atasm_obj file using Tasm (Borland)'#010+
+ '3*2Aelf_elf32 (Linux) using internal writer'#010+
+ '3*2Acoff_coff (Go32v2) using internal writer'#010,
+ '3*2Apecoff_pecoff (Win32) using internal writer'#010+
+ '4*2Aas_assemble using GNU AS'#010+
+ '6*2Aas_Unix o-file using GNU AS'#010+
+ '6*2Agas_GNU Motorola assembler'#010+
+ '6*2Amit_MIT Syntax (old GAS)'#010+
+ '6*2Amot_Standard Motorola assembler'#010+
+ 'A*2Aas_assemble using GNU AS'#010+
+ 'P*2Aas','_assemble using GNU AS'#010+
+ 'S*2Aas_assemble using GNU AS'#010+
+ '**1b_generate browser info'#010+
+ '**2bl_generate local symbol info'#010+
+ '**1B_build all modules'#010+
+ '**1C<x>_code generation options:'#010+
+ '**2Cc<x>_set default calling convention to <x>'#010+
+ '**2CD_create also dynamic',' library (not supported)'#010+
+ '**2Ce_Compilation with emulated floating point opcodes'#010+
+ '**2Cf<x>_Select fpu instruction set to use, see fpc -i for possible va'+
+ 'lues'#010+
+ '**2Cg_Generate PIC code'#010+
+ '**2Ch<n>_<n> bytes heap (between 1023 and 67107840)'#010+
+ '**2Ci_IO-','checking'#010+
+ '**2Cn_omit linking stage'#010+
+ '**2Co_check overflow of integer operations'#010+
+ '**2Cp<x>_select instruction set, see fpc -i for possible values'#010+
+ '**2Cr_range checking'#010+
+ '**2CR_verify object method call validity'#010+
+ '**2Cs<n>_set stack size to <n>'#010+
+ '**2Ct_','stack checking'#010+
+ '**2CX_create also smartlinked library'#010+
+ '**1d<x>_defines the symbol <x>'#010+
+ '**1D_generate a DEF file'#010+
+ '**2Dd<x>_set description to <x>'#010+
+ '**2Dv<x>_set DLL version to <x>'#010+
+ '*O2Dw_PM application'#010+
+ '**1e<x>_set path to executable'#010+
+ '**1E_same as -C','n'#010+
+ '**1F<x>_set file names and paths:'#010+
+ '**2Fa<x>[,y]_for a program load first units <x> and [y] before uses is'+
+ ' parsed'#010+
+ '**2Fc<x>_sets input codepage to <x>'#010+
+ '**2FD<x>_sets the directory where to search for compiler utilities'#010+
+ '**2Fe<x>_redirect error',' output to <x>'#010+
+ '**2FE<x>_set exe/unit output path to <x>'#010+
+ '**2Fi<x>_adds <x> to include path'#010+
+ '**2Fl<x>_adds <x> to library path'#010+
+ '**2FL<x>_uses <x> as dynamic linker'#010+
+ '**2Fo<x>_adds <x> to object path'#010+
+ '**2Fr<x>_load error message file <x>'#010+
+ '**2Fu<x>_a','dds <x> to unit path'#010+
+ '**2FU<x>_set unit output path to <x>, overrides -FE'#010+
+ '*g1g_generate debugger information:'#010+
+ '*g2gc_generate checks for pointers'#010+
+ '*g2gd_use dbx'#010+
+ '*g2gg_use gsym'#010+
+ '*g2gh_use heap trace unit (for memory leak debugging)'#010+
+ '*g2gl_use lin','e info unit to show more info for backtraces'#010+
+ '*g2gv_generates programs tracable with valgrind'#010+
+ '*g2gw_generate dwarf debugging info'#010+
+ '**1i_information'#010+
+ '**2iD_return compiler date'#010+
+ '**2iV_return compiler version'#010+
+ '**2iSO_return compiler OS'#010+
+ '**2iSP_retu','rn compiler processor'#010+
+ '**2iTO_return target OS'#010+
+ '**2iTP_return target processor'#010+
+ '**1I<x>_adds <x> to include path'#010+
+ '**1k<x>_Pass <x> to the linker'#010+
+ '**1l_write logo'#010+
+ '**1M<x>_set language mode to <x>'#010+
+ '**2Mfpc_free pascal dialect (default)'#010+
+ '**2Mobjfpc_s','witch some Delphi 2 extensions on'#010+
+ '**2Mdelphi_tries to be Delphi compatible'#010+
+ '**2Mtp_tries to be TP/BP 7.0 compatible'#010+
+ '**2Mgpc_tries to be gpc compatible'#010+
+ '**2Mmacpas_tries to be compatible to the macintosh pascal dialects'#010+
+ '**1n_don'#039't read the def','ault config file'#010+
+ '**1N<x>node tree optimizations'#010+
+ '**2Nu_unroll loops'#010+
+ '**1o<x>_change the name of the executable produced to <x>'#010+
+ '**1O<x>_optimizations:'#010+
+ '3*2Og_generate smaller code'#010+
+ '3*2OG_generate faster code (default)'#010+
+ '**2Or_keep certain variable','s in registers'#010+
+ '3*2Ou_enable uncertain optimizations (see docs)'#010+
+ '3*2O1_level 1 optimizations (quick optimizations)'#010+
+ '3*2O2_level 2 optimizations (-O1 + slower optimizations)'#010+
+ '3*2O3_level 3 optimizations (-O2 repeatedly, max 5 times)'#010+
+ '3*2Op<x>_tar','get processor:'#010+
+ '3*3Op1_set target processor to 386/486'#010+
+ '3*3Op2_set target processor to Pentium/PentiumMMX (tm)'#010+
+ '3*3Op3_set target processor to PPro/PII/c6x86/K6 (tm)'#010+
+ '6*2Og_generate smaller code'#010+
+ '6*2OG_generate faster code (default)'#010+
+ '6*2Ox_optimi','ze maximum (still BUGGY!!!)'#010+
+ '6*2O0_set target processor to a MC68000'#010+
+ '6*2O2_set target processor to a MC68020+ (default)'#010+
+ '**1pg_generate profile code for gprof (defines FPC_PROFILE)'#010+
+ '**1R<x>_assembler reading style:'#010+
+ '**2Rdefault_use default asse','mbler'#010+
+ '3*2Ratt_read AT&T style assembler'#010+
+ '3*2Rintel_read Intel style assembler'#010+
+ '6*2RMOT_read motorola style assembler'#010+
+ '**1S<x>_syntax options:'#010+
+ '**2S2_same as -Mobjfpc'#010+
+ '**2Sc_supports operators like C (*=,+=,/= and -=)'#010+
+ '**2Sa_include assertion code','.'#010+
+ '**2Sd_same as -Mdelphi'#010+
+ '**2Se<x>_error options. <x> is a combination of the following:'#010+
+ '**3*_<n> : compiler stops after the <n> errors (default is 1)'#010+
+ '**3*_w : compiler stops also after warnings'#010+
+ '**3*_n : compiler stops also after notes'#010+
+ '**3*_','h : compiler stops also after hints'#010+
+ '**2Sg_allow LABEL and GOTO'#010+
+ '**2Sh_Use ansistrings'#010+
+ '**2Si_support C++ styled INLINE'#010+
+ '**2Sk_load fpcylix unit'#010+
+ '**2SI<x>_set interface style to <x>'#010+
+ '**3SIcom_COM compatible interface (default)'#010+
+ '**3SIcorba_CORBA co','mpatible interface'#010+
+ '**2Sm_support macros like C (global)'#010+
+ '**2So_same as -Mtp'#010+
+ '**2Sp_same as -Mgpc'#010+
+ '**2Ss_constructor name must be init (destructor must be done)'#010+
+ '**2St_allow static keyword in objects'#010+
+ '**1s_don'#039't call assembler and linker'#010+
+ '**2sh_Ge','nerate script to link on host'#010+
+ '**2st_Generate script to link on target'#010+
+ '**2sr_Skip register allocation phase (use with -alr)'#010+
+ '**1T<x>_Target operating system:'#010+
+ '3*2Temx_OS/2 via EMX (including EMX/RSX extender)'#010+
+ '3*2Tfreebsd_FreeBSD'#010+
+ '3*2Tgo32v2_Ver','sion 2 of DJ Delorie DOS extender'#010+
+ '3*2Tlinux_Linux'#010+
+ '3*2Tnetbsd_NetBSD'#010+
+ '3*2Tnetware_Novell Netware Module (clib)'#010+
+ '3*2Tnetwlibc_Novell Netware Module (libc)'#010+
+ '3*2Topenbsd_OpenBSD'#010+
+ '3*2Tos2_OS/2 / eComStation'#010+
+ '3*2Tsunos_SunOS/Solaris'#010+
+ '3*2Twatcom_Watcom ','compatible DOS extender'#010+
+ '3*2Twdosx_WDOSX DOS extender'#010+
+ '3*2Twin32_Windows 32 Bit'#010+
+ '3*2Twince_Windows CE'#010+
+ '4*2Tlinux_Linux'#010+
+ '6*2Tamiga_Commodore Amiga'#010+
+ '6*2Tatari_Atari ST/STe/TT'#010+
+ '6*2Tlinux_Linux-68k'#010+
+ '6*2Tmacos_Macintosh m68k (not supported)'#010+
+ '6*2Tpalmos_P','almOS'#010+
+ 'A*2Tlinux_Linux'#010+
+ 'A*2Twince_Windows CE'#010+
+ 'P*2Tdarwin_Darwin and MacOS X on PowerPC'#010+
+ 'P*2Tlinux_Linux on PowerPC'#010+
+ 'P*2Tmacos_MacOS (classic) on PowerPC'#010+
+ 'P*2Tmorphos_MorphOS'#010+
+ 'S*2Tlinux_Linux'#010+
+ '**1u<x>_undefines the symbol <x>'#010+
+ '**1U_unit options:'#010+
+ '**2U','n_don'#039't check the unit name'#010+
+ '**2Ur_generate release unit files'#010+
+ '**2Us_compile a system unit'#010+
+ '**1v<x>_Be verbose. <x> is a combination of the following letters:'#010+
+ '**2*_e : Show errors (default) 0 : Show nothing (except errors)'#010+
+ '**2*_w : Show',' warnings u : Show unit info'#010+
+ '**2*_n : Show notes t : Show tried/used files'#010+
+ '**2*_h : Show hints c : Show conditionals'#010+
+ '**2*_i : Show general info d : Show debug info'#010+
+ '**2*_l : Show line','numbers r : Rhide/GCC compatibility mod'+
+ 'e'#010+
+ '**2*_a : Show everything x : Executable info (Win32 only)'#010+
+ '**2*_b : Write file names messages with full path'#010+
+ '**2*_v : write fpcdebug.txt with p : Write tree.log with parse t','r'+
+ 'ee'#010+
+ '**2*_ lots of debugging info'#010+
+ '3*1W<x>_Win32-like target options'#010+
+ '3*2WB_Create a relocatable image'#010+
+ '3*2WB<x>_Set Image base to Hexadecimal <x> value'#010+
+ '3*2WC_Specify console type application'#010+
+ '3*2WD_Use DEFFILE to export functions of DLL or E','XE'#010+
+ '3*2WF_Specify full-screen type application (OS/2 only)'#010+
+ '3*2WG_Specify graphic type application'#010+
+ '3*2WN_Do not generate relocation code (necessary for debugging)'#010+
+ '3*2WR_Generate relocation code'#010+
+ 'P*2WC_Specify console type application (MacOS on','ly)'#010+
+ 'P*2WG_Specify graphic type application (MacOS only)'#010+
+ 'P*2WT_Specify tool type application (MPW tool, MacOS only)'#010+
+ '**1X_executable options:'#010+
+ '**2Xc_pass --shared to the linker (Unix only)'#010+
+ '**2Xd_don'#039't use standard library search path (needed f','or cross c'+
+ 'ompile)'#010+
+ '**2XD_try to link units dynamic (defines FPC_LINK_DYNAMIC)'#010+
+ '**2Xm_generate link map'#010+
+ '**2XM<x>_set the name of the '#039'main'#039' program routine (default i'+
+ 's '#039'main'#039')'#010+
+ '**2XP<x>_prepend the binutils names with the prefix <x>'#010+
+ '**','2Xr<x>_set library search path to <x> (needed for cross compile)'#010+
+ '**2Xs_strip all symbols from executable'#010+
+ '**2XS_try to link units static (default) (defines FPC_LINK_STATIC)'#010+
+ '**2Xt_link with static libraries (-static is passed to linker)'#010+
+ '**2XX','_try to link units smart (defines FPC_LINK_SMART)'#010+
+ '**1*_'#010+
+ '**1?_shows this help'#010+
+ '**1h_shows this help without waiting'#000
+);
diff --git a/compiler/nadd.pas b/compiler/nadd.pas
new file mode 100644
index 0000000000..d4e45c7cb3
--- /dev/null
+++ b/compiler/nadd.pas
@@ -0,0 +1,2290 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Type checking and register allocation for add 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 nadd;
+
+{$i fpcdefs.inc}
+
+{ define addstringopt}
+
+interface
+
+ uses
+ node,symtype;
+
+ type
+ taddnode = class(tbinopnode)
+ resultrealtype : ttype;
+ constructor create(tt : tnodetype;l,r : tnode);override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function simplify : tnode;override;
+ {$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+ {$endif}
+ protected
+ { override the following if you want to implement }
+ { parts explicitely in the code generator (JM) }
+ function first_addstring: tnode; virtual;
+ function first_addset: tnode; virtual;
+ { only implements "muln" nodes, the rest always has to be done in }
+ { the code generator for performance reasons (JM) }
+ function first_add64bitint: tnode; virtual;
+
+ { This routine calls internal runtime library helpers
+ for all floating point arithmetic in the case
+ where the emulation switches is on. Otherwise
+ returns nil, and everything must be done in
+ the code generation phase.
+ }
+ function first_addfloat : tnode; virtual;
+ end;
+ taddnodeclass = class of taddnode;
+
+ var
+ { caddnode is used to create nodes of the add type }
+ { the virtual constructor allows to assign }
+ { another class type to caddnode => processor }
+ { specific node types can be created }
+ caddnode : taddnodeclass;
+
+implementation
+
+ uses
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+ sysutils,
+{$ENDIF MACOS_USE_FAKE_SYSUTILS}
+ globtype,systems,
+ cutils,verbose,globals,widestr,
+ symconst,symdef,symsym,symtable,defutil,defcmp,
+ cgbase,
+ htypechk,pass_1,
+ nbas,nmat,ncnv,ncon,nset,nopt,ncal,ninl,nmem,nutils,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif}
+ cpuinfo,procinfo;
+
+
+{*****************************************************************************
+ TADDNODE
+*****************************************************************************}
+
+{$ifdef fpc}
+{$maxfpuregisters 0}
+{$endif fpc}
+
+ function getbestreal(const t1,t2 : ttype) : ttype;
+ const
+ floatweight : array[tfloattype] of byte =
+ (2,3,4,0,1,5);
+ begin
+ if t1.def.deftype=floatdef then
+ begin
+ result:=t1;
+ if t2.def.deftype=floatdef then
+ begin
+ { when a comp or currency is used, use always the
+ best float type to calculate the result }
+ if (tfloatdef(t2.def).typ in [s64comp,s64currency]) or
+ (tfloatdef(t2.def).typ in [s64comp,s64currency]) then
+ result:=pbestrealtype^
+ else
+ if floatweight[tfloatdef(t2.def).typ]>floatweight[tfloatdef(t1.def).typ] then
+ result:=t2;
+ end;
+ end
+ else if t2.def.deftype=floatdef then
+ result:=t2
+ else internalerror(200508061);
+ end;
+
+
+ constructor taddnode.create(tt : tnodetype;l,r : tnode);
+ begin
+ inherited create(tt,l,r);
+ end;
+
+
+ function taddnode.simplify : tnode;
+ var
+ t : tnode;
+ lt,rt : tnodetype;
+ rd,ld : tdef;
+ rv,lv : tconstexprint;
+ rvd,lvd : bestreal;
+ ws1,ws2 : pcompilerwidestring;
+ concatstrings : boolean;
+ c1,c2 : array[0..1] of char;
+ s1,s2 : pchar;
+ l1,l2 : longint;
+ resultset : Tconstset;
+ b : boolean;
+ begin
+ result:=nil;
+ { is one a real float, then both need to be floats, this
+ need to be done before the constant folding so constant
+ operation on a float and int are also handled }
+ resultrealtype:=pbestrealtype^;
+ if (right.resulttype.def.deftype=floatdef) or (left.resulttype.def.deftype=floatdef) then
+ begin
+ { when both floattypes are already equal then use that
+ floattype for results }
+ if (right.resulttype.def.deftype=floatdef) and
+ (left.resulttype.def.deftype=floatdef) and
+ (tfloatdef(left.resulttype.def).typ=tfloatdef(right.resulttype.def).typ) then
+ resultrealtype:=left.resulttype
+ { when there is a currency type then use currency, but
+ only when currency is defined as float }
+ else
+ if (is_currency(right.resulttype.def) or
+ is_currency(left.resulttype.def)) and
+ ((s64currencytype.def.deftype = floatdef) or
+ (nodetype <> slashn)) then
+ begin
+ resultrealtype:=s64currencytype;
+ inserttypeconv(right,resultrealtype);
+ inserttypeconv(left,resultrealtype);
+ end
+ else
+ begin
+ resultrealtype:=getbestreal(left.resulttype,right.resulttype);
+ inserttypeconv(right,resultrealtype);
+ inserttypeconv(left,resultrealtype);
+ end;
+ end;
+
+ { If both operands are constant and there is a widechar
+ or widestring then convert everything to widestring. This
+ allows constant folding like char+widechar }
+ if is_constnode(right) and is_constnode(left) and
+ (is_widestring(right.resulttype.def) or
+ is_widestring(left.resulttype.def) or
+ is_widechar(right.resulttype.def) or
+ is_widechar(left.resulttype.def)) then
+ begin
+ inserttypeconv(right,cwidestringtype);
+ inserttypeconv(left,cwidestringtype);
+ end;
+
+ { load easier access variables }
+ rd:=right.resulttype.def;
+ ld:=left.resulttype.def;
+ rt:=right.nodetype;
+ lt:=left.nodetype;
+
+ if (nodetype = slashn) and
+ (((rt = ordconstn) and
+ (tordconstnode(right).value = 0)) or
+ ((rt = realconstn) and
+ (trealconstnode(right).value_real = 0.0))) then
+ begin
+ if (cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches) then
+ begin
+ result:=crealconstnode.create(1,pbestrealtype^);
+ Message(parser_e_division_by_zero);
+ exit;
+ end;
+ end;
+
+
+ { both are int constants }
+ if (
+ (
+ is_constintnode(left) and
+ is_constintnode(right)
+ ) or
+ (
+ is_constboolnode(left) and
+ is_constboolnode(right) and
+ (nodetype in [slashn,ltn,lten,gtn,gten,equaln,unequaln,andn,xorn,orn])
+ ) or
+ (
+ is_constenumnode(left) and
+ is_constenumnode(right) and
+ allowenumop(nodetype))
+ ) or
+ (
+ (lt = pointerconstn) and
+ is_constintnode(right) and
+ (nodetype in [addn,subn])
+ ) or
+ (
+ (lt in [pointerconstn,niln]) and
+ (rt in [pointerconstn,niln]) and
+ (nodetype in [ltn,lten,gtn,gten,equaln,unequaln,subn])
+ ) then
+ begin
+ t:=nil;
+ { when comparing/substracting pointers, make sure they are }
+ { of the same type (JM) }
+ if (lt = pointerconstn) and (rt = pointerconstn) then
+ begin
+ if not(cs_extsyntax in aktmoduleswitches) and
+ not(nodetype in [equaln,unequaln]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename)
+ else
+ if (nodetype <> subn) and
+ is_voidpointer(rd) then
+ inserttypeconv(right,left.resulttype)
+ else if (nodetype <> subn) and
+ is_voidpointer(ld) then
+ inserttypeconv(left,right.resulttype)
+ else if not(equal_defs(ld,rd)) then
+ IncompatibleTypes(ld,rd);
+ end
+ else if (ld.deftype=enumdef) and (rd.deftype=enumdef) then
+ begin
+ if not(equal_defs(ld,rd)) then
+ inserttypeconv(right,left.resulttype);
+ end;
+
+ { load values }
+ case lt of
+ ordconstn:
+ lv:=tordconstnode(left).value;
+ pointerconstn:
+ lv:=tpointerconstnode(left).value;
+ niln:
+ lv:=0;
+ else
+ internalerror(2002080202);
+ end;
+ case rt of
+ ordconstn:
+ rv:=tordconstnode(right).value;
+ pointerconstn:
+ rv:=tpointerconstnode(right).value;
+ niln:
+ rv:=0;
+ else
+ internalerror(2002080203);
+ end;
+ if (lt = pointerconstn) and
+ (rt <> pointerconstn) then
+ rv := rv * tpointerdef(left.resulttype.def).pointertype.def.size;
+ if (rt = pointerconstn) and
+ (lt <> pointerconstn) then
+ lv := lv * tpointerdef(right.resulttype.def).pointertype.def.size;
+ case nodetype of
+ addn :
+ begin
+ {$ifopt Q-}
+ {$define OVERFLOW_OFF}
+ {$Q+}
+ {$endif}
+ try
+ if (lt=pointerconstn) then
+ t := cpointerconstnode.create(lv+rv,left.resulttype)
+ else
+ if is_integer(ld) then
+ t := genintconstnode(lv+rv)
+ else
+ t := cordconstnode.create(lv+rv,left.resulttype,(ld.deftype<>enumdef));
+ except
+ on E:EIntOverflow do
+ begin
+ Message(parser_e_arithmetic_operation_overflow);
+ { Recover }
+ t:=genintconstnode(0)
+ end;
+ end;
+ {$ifdef OVERFLOW_OFF}
+ {$Q-}
+ {$undef OVERFLOW_OFF}
+ {$endif}
+ end;
+ subn :
+ begin
+ {$ifopt Q-}
+ {$define OVERFLOW_OFF}
+ {$Q+}
+ {$endif}
+ try
+ if (lt=pointerconstn) then
+ begin
+ { pointer-pointer results in an integer }
+ if (rt=pointerconstn) then
+ t := genintconstnode((lv-rv) div tpointerdef(ld).pointertype.def.size)
+ else
+ t := cpointerconstnode.create(lv-rv,left.resulttype);
+ end
+ else
+ begin
+ if is_integer(ld) then
+ t:=genintconstnode(lv-rv)
+ else
+ t:=cordconstnode.create(lv-rv,left.resulttype,(ld.deftype<>enumdef));
+ end;
+ except
+ on E:EIntOverflow do
+ begin
+ Message(parser_e_arithmetic_operation_overflow);
+ { Recover }
+ t:=genintconstnode(0)
+ end;
+ end;
+ {$ifdef OVERFLOW_OFF}
+ {$Q-}
+ {$undef OVERFLOW_OFF}
+ {$endif}
+ end;
+ muln :
+ begin
+ {$ifopt Q-}
+ {$define OVERFLOW_OFF}
+ {$Q+}
+ {$endif}
+ try
+ if (torddef(ld).typ <> u64bit) or
+ (torddef(rd).typ <> u64bit) then
+ t:=genintconstnode(lv*rv)
+ else
+ t:=genintconstnode(int64(qword(lv)*qword(rv)));
+ except
+ on E:EIntOverflow do
+ begin
+ Message(parser_e_arithmetic_operation_overflow);
+ { Recover }
+ t:=genintconstnode(0)
+ end;
+ end;
+ {$ifdef OVERFLOW_OFF}
+ {$Q-}
+ {$undef OVERFLOW_OFF}
+ {$endif}
+ end;
+ xorn :
+ if is_integer(ld) then
+ t:=genintconstnode(lv xor rv)
+ else
+ t:=cordconstnode.create(lv xor rv,left.resulttype,true);
+ orn :
+ if is_integer(ld) then
+ t:=genintconstnode(lv or rv)
+ else
+ t:=cordconstnode.create(lv or rv,left.resulttype,true);
+ andn :
+ if is_integer(ld) then
+ t:=genintconstnode(lv and rv)
+ else
+ t:=cordconstnode.create(lv and rv,left.resulttype,true);
+ ltn :
+ t:=cordconstnode.create(ord(lv<rv),booltype,true);
+ lten :
+ t:=cordconstnode.create(ord(lv<=rv),booltype,true);
+ gtn :
+ t:=cordconstnode.create(ord(lv>rv),booltype,true);
+ gten :
+ t:=cordconstnode.create(ord(lv>=rv),booltype,true);
+ equaln :
+ t:=cordconstnode.create(ord(lv=rv),booltype,true);
+ unequaln :
+ t:=cordconstnode.create(ord(lv<>rv),booltype,true);
+ slashn :
+ begin
+ { int/int becomes a real }
+ rvd:=rv;
+ lvd:=lv;
+ t:=crealconstnode.create(lvd/rvd,resultrealtype);
+ end;
+ else
+ begin
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ t:=cnothingnode.create;
+ end;
+ end;
+ result:=t;
+ exit;
+ end;
+
+ { both real constants ? }
+ if (lt=realconstn) and (rt=realconstn) then
+ begin
+ lvd:=trealconstnode(left).value_real;
+ rvd:=trealconstnode(right).value_real;
+ case nodetype of
+ addn :
+ t:=crealconstnode.create(lvd+rvd,resultrealtype);
+ subn :
+ t:=crealconstnode.create(lvd-rvd,resultrealtype);
+ muln :
+ t:=crealconstnode.create(lvd*rvd,resultrealtype);
+ starstarn,
+ caretn :
+ begin
+ if lvd<0 then
+ begin
+ Message(parser_e_invalid_float_operation);
+ t:=crealconstnode.create(0,resultrealtype);
+ end
+ else if lvd=0 then
+ t:=crealconstnode.create(1.0,resultrealtype)
+ else
+ t:=crealconstnode.create(exp(ln(lvd)*rvd),resultrealtype);
+ end;
+ slashn :
+ t:=crealconstnode.create(lvd/rvd,resultrealtype);
+ ltn :
+ t:=cordconstnode.create(ord(lvd<rvd),booltype,true);
+ lten :
+ t:=cordconstnode.create(ord(lvd<=rvd),booltype,true);
+ gtn :
+ t:=cordconstnode.create(ord(lvd>rvd),booltype,true);
+ gten :
+ t:=cordconstnode.create(ord(lvd>=rvd),booltype,true);
+ equaln :
+ t:=cordconstnode.create(ord(lvd=rvd),booltype,true);
+ unequaln :
+ t:=cordconstnode.create(ord(lvd<>rvd),booltype,true);
+ else
+ begin
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ t:=cnothingnode.create;
+ end;
+ end;
+ result:=t;
+ exit;
+ end;
+
+ { first, we handle widestrings, so we can check later for }
+ { stringconstn only }
+
+ { widechars are converted above to widestrings too }
+ { this isn't veryy efficient, but I don't think }
+ { that it does matter that much (FK) }
+ if (lt=stringconstn) and (rt=stringconstn) and
+ (tstringconstnode(left).st_type=st_widestring) and
+ (tstringconstnode(right).st_type=st_widestring) then
+ begin
+ initwidestring(ws1);
+ initwidestring(ws2);
+ copywidestring(pcompilerwidestring(tstringconstnode(left).value_str),ws1);
+ copywidestring(pcompilerwidestring(tstringconstnode(right).value_str),ws2);
+ case nodetype of
+ addn :
+ begin
+ concatwidestrings(ws1,ws2);
+ t:=cstringconstnode.createwstr(ws1);
+ end;
+ ltn :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)<0),booltype,true);
+ lten :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)<=0),booltype,true);
+ gtn :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)>0),booltype,true);
+ gten :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)>=0),booltype,true);
+ equaln :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)=0),booltype,true);
+ unequaln :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)<>0),booltype,true);
+ else
+ begin
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ t:=cnothingnode.create;
+ end;
+ end;
+ donewidestring(ws1);
+ donewidestring(ws2);
+ result:=t;
+ exit;
+ end;
+
+ { concating strings ? }
+ concatstrings:=false;
+
+ if (lt=ordconstn) and (rt=ordconstn) and
+ is_char(ld) and is_char(rd) then
+ begin
+ c1[0]:=char(byte(tordconstnode(left).value));
+ c1[1]:=#0;
+ l1:=1;
+ c2[0]:=char(byte(tordconstnode(right).value));
+ c2[1]:=#0;
+ l2:=1;
+ s1:=@c1;
+ s2:=@c2;
+ concatstrings:=true;
+ end
+ else if (lt=stringconstn) and (rt=ordconstn) and is_char(rd) then
+ begin
+ s1:=tstringconstnode(left).value_str;
+ l1:=tstringconstnode(left).len;
+ c2[0]:=char(byte(tordconstnode(right).value));
+ c2[1]:=#0;
+ s2:=@c2;
+ l2:=1;
+ concatstrings:=true;
+ end
+ else if (lt=ordconstn) and (rt=stringconstn) and is_char(ld) then
+ begin
+ c1[0]:=char(byte(tordconstnode(left).value));
+ c1[1]:=#0;
+ l1:=1;
+ s1:=@c1;
+ s2:=tstringconstnode(right).value_str;
+ l2:=tstringconstnode(right).len;
+ concatstrings:=true;
+ end
+ else if (lt=stringconstn) and (rt=stringconstn) then
+ begin
+ s1:=tstringconstnode(left).value_str;
+ l1:=tstringconstnode(left).len;
+ s2:=tstringconstnode(right).value_str;
+ l2:=tstringconstnode(right).len;
+ concatstrings:=true;
+ end;
+ if concatstrings then
+ begin
+ case nodetype of
+ addn :
+ t:=cstringconstnode.createpchar(concatansistrings(s1,s2,l1,l2),l1+l2,st_conststring);
+ ltn :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)<0),booltype,true);
+ lten :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)<=0),booltype,true);
+ gtn :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)>0),booltype,true);
+ gten :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)>=0),booltype,true);
+ equaln :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)=0),booltype,true);
+ unequaln :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)<>0),booltype,true);
+ else
+ begin
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ t:=cnothingnode.create;
+ end;
+ end;
+ result:=t;
+ exit;
+ end;
+
+ { set constant evaluation }
+ if (right.nodetype=setconstn) and
+ not assigned(tsetconstnode(right).left) and
+ (left.nodetype=setconstn) and
+ not assigned(tsetconstnode(left).left) then
+ begin
+ { check if size adjusting is needed, only for left
+ to right as the other way is checked in the typeconv }
+ if (tsetdef(right.resulttype.def).settype=smallset) and
+ (tsetdef(left.resulttype.def).settype<>smallset) then
+ right.resulttype.setdef(tsetdef.create(tsetdef(right.resulttype.def).elementtype,255));
+ { check base types }
+ inserttypeconv(left,right.resulttype);
+
+ if codegenerror then
+ begin
+ { recover by only returning the left part }
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ case nodetype of
+ addn :
+ begin
+ resultset:=tsetconstnode(right).value_set^ + tsetconstnode(left).value_set^;
+ t:=csetconstnode.create(@resultset,left.resulttype);
+ end;
+ muln :
+ begin
+ resultset:=tsetconstnode(right).value_set^ * tsetconstnode(left).value_set^;
+ t:=csetconstnode.create(@resultset,left.resulttype);
+ end;
+ subn :
+ begin
+ resultset:=tsetconstnode(left).value_set^ - tsetconstnode(right).value_set^;
+ t:=csetconstnode.create(@resultset,left.resulttype);
+ end;
+ symdifn :
+ begin
+ resultset:=tsetconstnode(right).value_set^ >< tsetconstnode(left).value_set^;
+ t:=csetconstnode.create(@resultset,left.resulttype);
+ end;
+ unequaln :
+ begin
+ b:=tsetconstnode(right).value_set^ <> tsetconstnode(left).value_set^;
+ t:=cordconstnode.create(byte(b),booltype,true);
+ end;
+ equaln :
+ begin
+ b:=tsetconstnode(right).value_set^ = tsetconstnode(left).value_set^;
+ t:=cordconstnode.create(byte(b),booltype,true);
+ end;
+ lten :
+ begin
+ b:=tsetconstnode(left).value_set^ <= tsetconstnode(right).value_set^;
+ t:=cordconstnode.create(byte(b),booltype,true);
+ end;
+ gten :
+ begin
+ b:=tsetconstnode(left).value_set^ >= tsetconstnode(right).value_set^;
+ t:=cordconstnode.create(byte(b),booltype,true);
+ end;
+ else
+ begin
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ t:=cnothingnode.create;
+ end;
+ end;
+ result:=t;
+ exit;
+ end;
+
+ end;
+
+
+ function taddnode.det_resulttype:tnode;
+ var
+ hp : tnode;
+ lt,rt : tnodetype;
+ rd,ld : tdef;
+ htype : ttype;
+ ot : tnodetype;
+ hsym : tfieldvarsym;
+ i : longint;
+ strtype : tstringtype;
+ b : boolean;
+{$ifdef state_tracking}
+ factval : Tnode;
+ change : boolean;
+{$endif}
+
+ begin
+ result:=nil;
+ { first do the two subtrees }
+ resulttypepass(left);
+ resulttypepass(right);
+ { both left and right need to be valid }
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+ maybe_call_procvar(right,true);
+
+ { convert array constructors to sets, because there is no other operator
+ possible for array constructors }
+ if is_array_constructor(left.resulttype.def) then
+ begin
+ arrayconstructor_to_set(left);
+ resulttypepass(left);
+ end;
+ if is_array_constructor(right.resulttype.def) then
+ begin
+ arrayconstructor_to_set(right);
+ resulttypepass(right);
+ end;
+
+ { allow operator overloading }
+ hp:=self;
+ if isbinaryoverloaded(hp) then
+ begin
+ result:=hp;
+ exit;
+ end;
+ { Stop checking when an error was found in the operator checking }
+ if codegenerror then
+ begin
+ result:=cerrornode.create;
+ exit;
+ end;
+
+
+ { Kylix allows enum+ordconstn in an enum declaration (blocktype
+ is bt_type), we need to do the conversion here before the
+ constant folding }
+ if (m_delphi in aktmodeswitches) and
+ (blocktype=bt_type) then
+ begin
+ if (left.resulttype.def.deftype=enumdef) and
+ (right.resulttype.def.deftype=orddef) then
+ begin
+ { insert explicit typecast to default signed int }
+ left:=ctypeconvnode.create_internal(left,sinttype);
+ resulttypepass(left);
+ end
+ else
+ if (left.resulttype.def.deftype=orddef) and
+ (right.resulttype.def.deftype=enumdef) then
+ begin
+ { insert explicit typecast to default signed int }
+ right:=ctypeconvnode.create_internal(right,sinttype);
+ resulttypepass(right);
+ end;
+ end;
+
+ result:=simplify;
+ if assigned(result) then
+ exit;
+
+ { load easier access variables }
+ rd:=right.resulttype.def;
+ ld:=left.resulttype.def;
+ rt:=right.nodetype;
+ lt:=left.nodetype;
+
+ { but an int/int gives real/real! }
+ if nodetype=slashn then
+ begin
+ if is_currency(left.resulttype.def) and
+ is_currency(right.resulttype.def) then
+ { In case of currency, converting to float means dividing by 10000 }
+ { However, since this is already a division, both divisions by }
+ { 10000 are eliminated when we divide the results -> we can skip }
+ { them. }
+ if s64currencytype.def.deftype = floatdef then
+ begin
+ { there's no s64comptype or so, how do we avoid the type conversion?
+ left.resulttype := s64comptype;
+ right.resulttype := s64comptype; }
+ end
+ else
+ begin
+ left.resulttype := s64inttype;
+ right.resulttype := s64inttype;
+ end
+ else if (left.resulttype.def.deftype <> floatdef) and
+ (right.resulttype.def.deftype <> floatdef) then
+ CGMessage(type_h_use_div_for_int);
+ inserttypeconv(right,resultrealtype);
+ inserttypeconv(left,resultrealtype);
+ end
+
+ { if both are orddefs then check sub types }
+ else if (ld.deftype=orddef) and (rd.deftype=orddef) then
+ begin
+ { optimize multiplacation by a power of 2 }
+ if not(cs_check_overflow in aktlocalswitches) and
+ (nodetype = muln) and
+ (((left.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(left).value,i)) or
+ ((right.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(right).value,i))) then
+ begin
+ if left.nodetype = ordconstn then
+ begin
+ tordconstnode(left).value := i;
+ result := cshlshrnode.create(shln,right,left);
+ end
+ else
+ begin
+ tordconstnode(right).value := i;
+ result := cshlshrnode.create(shln,left,right);
+ end;
+ left := nil;
+ right := nil;
+ exit;
+ end;
+
+ { 2 booleans? Make them equal to the largest boolean }
+ if is_boolean(ld) and is_boolean(rd) then
+ begin
+ if torddef(left.resulttype.def).size>torddef(right.resulttype.def).size then
+ begin
+ right:=ctypeconvnode.create_internal(right,left.resulttype);
+ ttypeconvnode(right).convtype:=tc_bool_2_int;
+ resulttypepass(right);
+ end
+ else if torddef(left.resulttype.def).size<torddef(right.resulttype.def).size then
+ begin
+ left:=ctypeconvnode.create_internal(left,right.resulttype);
+ ttypeconvnode(left).convtype:=tc_bool_2_int;
+ resulttypepass(left);
+ end;
+ case nodetype of
+ xorn,
+ ltn,
+ lten,
+ gtn,
+ gten,
+ andn,
+ orn:
+ begin
+ end;
+ unequaln,
+ equaln:
+ begin
+ if not(cs_full_boolean_eval in aktlocalswitches) then
+ begin
+ { Remove any compares with constants }
+ if (left.nodetype=ordconstn) then
+ begin
+ hp:=right;
+ b:=(tordconstnode(left).value<>0);
+ ot:=nodetype;
+ left.free;
+ left:=nil;
+ right:=nil;
+ if (not(b) and (ot=equaln)) or
+ (b and (ot=unequaln)) then
+ begin
+ hp:=cnotnode.create(hp);
+ end;
+ result:=hp;
+ exit;
+ end;
+ if (right.nodetype=ordconstn) then
+ begin
+ hp:=left;
+ b:=(tordconstnode(right).value<>0);
+ ot:=nodetype;
+ right.free;
+ right:=nil;
+ left:=nil;
+ if (not(b) and (ot=equaln)) or
+ (b and (ot=unequaln)) then
+ begin
+ hp:=cnotnode.create(hp);
+ end;
+ result:=hp;
+ exit;
+ end;
+ end;
+ end;
+ else
+ begin
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ result:=cnothingnode.create;
+ exit;
+ end;
+ end;
+ end
+ { Both are chars? }
+ else if is_char(rd) and is_char(ld) then
+ begin
+ if nodetype=addn then
+ begin
+ resulttype:=cshortstringtype;
+ if not(is_constcharnode(left) and is_constcharnode(right)) then
+ begin
+ inserttypeconv(left,cshortstringtype);
+{$ifdef addstringopt}
+ hp := genaddsstringcharoptnode(self);
+ result := hp;
+ exit;
+{$endif addstringopt}
+ end;
+ end;
+ end
+ { There is a widechar? }
+ else if is_widechar(rd) or is_widechar(ld) then
+ begin
+ { widechar+widechar gives widestring }
+ if nodetype=addn then
+ begin
+ inserttypeconv(left,cwidestringtype);
+ if (torddef(rd).typ<>uwidechar) then
+ inserttypeconv(right,cwidechartype);
+ resulttype:=cwidestringtype;
+ end
+ else
+ begin
+ if (torddef(ld).typ<>uwidechar) then
+ inserttypeconv(left,cwidechartype);
+ if (torddef(rd).typ<>uwidechar) then
+ inserttypeconv(right,cwidechartype);
+ end;
+ end
+ { is there a currency type ? }
+ else if ((torddef(rd).typ=scurrency) or (torddef(ld).typ=scurrency)) then
+ begin
+ if (torddef(ld).typ<>scurrency) then
+ inserttypeconv(left,s64currencytype);
+ if (torddef(rd).typ<>scurrency) then
+ inserttypeconv(right,s64currencytype);
+ end
+ { and,or,xor work on bit patterns and don't care
+ about the sign of integers }
+ else if (nodetype in [andn,orn,xorn]) and
+ is_integer(ld) and is_integer(rd) then
+ begin
+ if rd.size>ld.size then
+ inserttypeconv_internal(left,right.resulttype)
+ else
+ inserttypeconv_internal(right,left.resulttype);
+ end
+ { is there a signed 64 bit type ? }
+ else if ((torddef(rd).typ=s64bit) or (torddef(ld).typ=s64bit)) then
+ begin
+ if (torddef(ld).typ<>s64bit) then
+ inserttypeconv(left,s64inttype);
+ if (torddef(rd).typ<>s64bit) then
+ inserttypeconv(right,s64inttype);
+ end
+ { is there a unsigned 64 bit type ? }
+ else if ((torddef(rd).typ=u64bit) or (torddef(ld).typ=u64bit)) then
+ begin
+ if (torddef(ld).typ<>u64bit) then
+ inserttypeconv(left,u64inttype);
+ if (torddef(rd).typ<>u64bit) then
+ inserttypeconv(right,u64inttype);
+ end
+ { 64 bit cpus do calculations always in 64 bit }
+{$ifndef cpu64bit}
+ { is there a cardinal? }
+ else if ((torddef(rd).typ=u32bit) or (torddef(ld).typ=u32bit)) then
+ begin
+ { convert positive constants to u32bit }
+ if (torddef(ld).typ<>u32bit) and
+ is_constintnode(left) and
+ (tordconstnode(left).value >= 0) then
+ inserttypeconv(left,u32inttype);
+ if (torddef(rd).typ<>u32bit) and
+ is_constintnode(right) and
+ (tordconstnode(right).value >= 0) then
+ inserttypeconv(right,u32inttype);
+ { when one of the operand is signed perform
+ the operation in 64bit, can't use rd/ld here because there
+ could be already typeconvs inserted }
+ if is_signed(left.resulttype.def) or
+ is_signed(right.resulttype.def) then
+ begin
+ CGMessage(type_w_mixed_signed_unsigned);
+ inserttypeconv(left,s64inttype);
+ inserttypeconv(right,s64inttype);
+ end
+ else
+ begin
+ if (torddef(left.resulttype.def).typ<>u32bit) then
+ inserttypeconv(left,u32inttype);
+ if (torddef(right.resulttype.def).typ<>u32bit) then
+ inserttypeconv(right,u32inttype);
+ end;
+ end
+{$endif cpu64bit}
+ { generic ord conversion is sinttype }
+ else
+ begin
+ { if the left or right value is smaller than the normal
+ type sinttype and is unsigned, and the other value
+ is a constant < 0, the result will always be false/true
+ for equal / unequal nodes.
+ }
+ if (
+ { left : unsigned ordinal var, right : < 0 constant }
+ (
+ ((is_signed(ld)=false) and (is_constintnode(left) =false)) and
+ ((is_constintnode(right)) and (tordconstnode(right).value < 0))
+ ) or
+ { right : unsigned ordinal var, left : < 0 constant }
+ (
+ ((is_signed(rd)=false) and (is_constintnode(right) =false)) and
+ ((is_constintnode(left)) and (tordconstnode(left).value < 0))
+ )
+ ) then
+ begin
+ if nodetype = equaln then
+ CGMessage(type_w_signed_unsigned_always_false)
+ else
+ if nodetype = unequaln then
+ CGMessage(type_w_signed_unsigned_always_true)
+ else
+ if (is_constintnode(left) and (nodetype in [ltn,lten])) or
+ (is_constintnode(right) and (nodetype in [gtn,gten])) then
+ CGMessage(type_w_signed_unsigned_always_true)
+ else
+ if (is_constintnode(right) and (nodetype in [ltn,lten])) or
+ (is_constintnode(left) and (nodetype in [gtn,gten])) then
+ CGMessage(type_w_signed_unsigned_always_false);
+ end;
+
+ { When there is a signed type or there is a minus operation
+ we convert to signed int. Otherwise (both are unsigned) we keep
+ the result also unsigned. This is compatible with Delphi (PFV) }
+ if is_signed(ld) or
+ is_signed(rd) or
+ (nodetype=subn) then
+ begin
+ inserttypeconv(right,sinttype);
+ inserttypeconv(left,sinttype);
+ end
+ else
+ begin
+ inserttypeconv(right,uinttype);
+ inserttypeconv(left,uinttype);
+ end;
+ end;
+ end
+
+ { if both are floatdefs, conversion is already done before constant folding }
+ else if (ld.deftype=floatdef) then
+ begin
+ if not(nodetype in [addn,subn,muln,slashn,equaln,unequaln,ltn,lten,gtn,gten]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { left side a setdef, must be before string processing,
+ else array constructor can be seen as array of char (PFV) }
+ else if (ld.deftype=setdef) then
+ begin
+ { trying to add a set element? }
+ if (nodetype=addn) and (rd.deftype<>setdef) then
+ begin
+ if (rt=setelementn) then
+ begin
+ if not(equal_defs(tsetdef(ld).elementtype.def,rd)) then
+ CGMessage(type_e_set_element_are_not_comp);
+ end
+ else
+ CGMessage(type_e_mismatch)
+ end
+ else
+ begin
+ if not(nodetype in [addn,subn,symdifn,muln,equaln,unequaln,lten,gten]) then
+ CGMessage(type_e_set_operation_unknown);
+ { right def must be a also be set }
+ if (rd.deftype<>setdef) or not(equal_defs(rd,ld)) then
+ CGMessage(type_e_set_element_are_not_comp);
+ end;
+
+ { ranges require normsets }
+ if (tsetdef(ld).settype=smallset) and
+ (rt=setelementn) and
+ assigned(tsetelementnode(right).right) then
+ begin
+ { generate a temporary normset def, it'll be destroyed
+ when the symtable is unloaded }
+ htype.setdef(tsetdef.create(tsetdef(ld).elementtype,255));
+ inserttypeconv(left,htype);
+ end;
+
+ { if the right side is also a setdef then the settype must
+ be the same as the left setdef }
+ if (rd.deftype=setdef) and
+ (tsetdef(ld).settype<>tsetdef(rd).settype) then
+ begin
+ { when right is a normset we need to typecast both
+ to normsets }
+ if (tsetdef(rd).settype=normset) then
+ inserttypeconv(left,right.resulttype)
+ else
+ inserttypeconv(right,left.resulttype);
+ end;
+ end
+ { pointer comparision and subtraction }
+ else if (
+ (rd.deftype=pointerdef) and (ld.deftype=pointerdef)
+ ) or
+ { compare/add pchar to variable (not stringconst) char arrays
+ by addresses like BP/Delphi }
+ (
+ (nodetype in [equaln,unequaln,subn,addn]) and
+ (
+ ((is_pchar(ld) or (lt=niln)) and is_chararray(rd) and (rt<>stringconstn)) or
+ ((is_pchar(rd) or (rt=niln)) and is_chararray(ld) and (lt<>stringconstn))
+ )
+ ) then
+ begin
+ { convert char array to pointer }
+ if is_chararray(rd) then
+ begin
+ inserttypeconv(right,charpointertype);
+ rd:=right.resulttype.def;
+ end
+ else if is_chararray(ld) then
+ begin
+ inserttypeconv(left,charpointertype);
+ ld:=left.resulttype.def;
+ end;
+
+ case nodetype of
+ equaln,unequaln :
+ begin
+ if is_voidpointer(right.resulttype.def) then
+ inserttypeconv(right,left.resulttype)
+ else if is_voidpointer(left.resulttype.def) then
+ inserttypeconv(left,right.resulttype)
+ else if not(equal_defs(ld,rd)) then
+ IncompatibleTypes(ld,rd);
+ { now that the type checking is done, convert both to charpointer, }
+ { because methodpointers are 8 bytes even though only the first 4 }
+ { bytes must be compared. This can happen here if we are in }
+ { TP/Delphi mode, because there @methodpointer = voidpointer (but }
+ { a voidpointer of 8 bytes). A conversion to voidpointer would be }
+ { optimized away, since the result already was a voidpointer, so }
+ { use a charpointer instead (JM) }
+ inserttypeconv_internal(left,charpointertype);
+ inserttypeconv_internal(right,charpointertype);
+ end;
+ ltn,lten,gtn,gten:
+ begin
+ if (cs_extsyntax in aktmoduleswitches) then
+ begin
+ if is_voidpointer(right.resulttype.def) then
+ inserttypeconv(right,left.resulttype)
+ else if is_voidpointer(left.resulttype.def) then
+ inserttypeconv(left,right.resulttype)
+ else if not(equal_defs(ld,rd)) then
+ IncompatibleTypes(ld,rd);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end;
+ subn:
+ begin
+ if (cs_extsyntax in aktmoduleswitches) then
+ begin
+ if is_voidpointer(right.resulttype.def) then
+ inserttypeconv(right,left.resulttype)
+ else if is_voidpointer(left.resulttype.def) then
+ inserttypeconv(left,right.resulttype)
+ else if not(equal_defs(ld,rd)) then
+ IncompatibleTypes(ld,rd);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+
+ if not(nf_has_pointerdiv in flags) and
+ (tpointerdef(rd).pointertype.def.size>1) then
+ begin
+ hp:=getcopy;
+ include(hp.flags,nf_has_pointerdiv);
+ result:=cmoddivnode.create(divn,hp,cordconstnode.create(tpointerdef(rd).pointertype.def.size,sinttype,false));
+ end;
+ resulttype:=sinttype;
+ exit;
+ end;
+ addn:
+ begin
+ if (cs_extsyntax in aktmoduleswitches) then
+ begin
+ if is_voidpointer(right.resulttype.def) then
+ inserttypeconv(right,left.resulttype)
+ else if is_voidpointer(left.resulttype.def) then
+ inserttypeconv(left,right.resulttype)
+ else if not(equal_defs(ld,rd)) then
+ IncompatibleTypes(ld,rd);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ resulttype:=sinttype;
+ exit;
+ end;
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end;
+ end
+
+ { is one of the operands a string?,
+ chararrays are also handled as strings (after conversion), also take
+ care of chararray+chararray and chararray+char.
+ Note: Must be done after pointerdef+pointerdef has been checked, else
+ pchar is converted to string }
+ else if (rd.deftype=stringdef) or
+ (ld.deftype=stringdef) or
+ ((is_pchar(rd) or is_chararray(rd) or is_char(rd) or is_open_chararray(rd) or
+ is_pwidechar(rd) or is_widechararray(rd) or is_widechar(rd) or is_open_widechararray(rd)) and
+ (is_pchar(ld) or is_chararray(ld) or is_char(ld) or is_open_chararray(ld) or
+ is_pwidechar(ld) or is_widechararray(ld) or is_widechar(ld) or is_open_widechararray(ld))) then
+ begin
+ if (nodetype in [addn,equaln,unequaln,lten,gten,ltn,gtn]) then
+ begin
+ { Is there a widestring? }
+ if is_widestring(rd) or is_widestring(ld) or
+ is_pwidechar(rd) or is_widechararray(rd) or is_widechar(rd) or is_open_widechararray(rd) or
+ is_pwidechar(ld) or is_widechararray(ld) or is_widechar(ld) or is_open_widechararray(ld) then
+ strtype:= st_widestring
+ else
+ if is_ansistring(rd) or is_ansistring(ld) or
+ ((cs_ansistrings in aktlocalswitches) and
+ //todo: Move some of this to longstring's then they are implemented?
+ (
+ is_pchar(rd) or (is_chararray(rd) and (rd.size > 255)) or is_open_chararray(rd) or
+ is_pchar(ld) or (is_chararray(ld) and (ld.size > 255)) or is_open_chararray(ld)
+ )
+ ) then
+ strtype:= st_ansistring
+ else
+ if is_longstring(rd) or is_longstring(ld) then
+ strtype:= st_longstring
+ else
+ begin
+ {$warning todo: add a warning/hint here if one converting a too large array}
+ { nodes is PChar, array [with size > 255] or OpenArrayOfChar.
+ Note: Delphi halts with error if "array [0..xx] of char"
+ is assigned to ShortString and string length is less
+ then array size }
+ strtype:= st_shortstring;
+ end;
+
+ // Now convert nodes to common string type
+ case strtype of
+ st_widestring :
+ begin
+ if not(is_widestring(rd)) then
+ inserttypeconv(right,cwidestringtype);
+ if not(is_widestring(ld)) then
+ inserttypeconv(left,cwidestringtype);
+ end;
+ st_ansistring :
+ begin
+ if not(is_ansistring(rd)) then
+ inserttypeconv(right,cansistringtype);
+ if not(is_ansistring(ld)) then
+ inserttypeconv(left,cansistringtype);
+ end;
+ st_longstring :
+ begin
+ if not(is_longstring(rd)) then
+ inserttypeconv(right,clongstringtype);
+ if not(is_longstring(ld)) then
+ inserttypeconv(left,clongstringtype);
+ end;
+ st_shortstring :
+ begin
+ if not(is_shortstring(ld)) then
+ inserttypeconv(left,cshortstringtype);
+ { don't convert char, that can be handled by the optimized node }
+ if not(is_shortstring(rd) or is_char(rd)) then
+ inserttypeconv(right,cshortstringtype);
+ end;
+ else
+ internalerror(2005101);
+ end;
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { class or interface equation }
+ else if is_class_or_interface(rd) or is_class_or_interface(ld) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ begin
+ if is_class_or_interface(rd) and is_class_or_interface(ld) then
+ begin
+ if tobjectdef(rd).is_related(tobjectdef(ld)) then
+ inserttypeconv(right,left.resulttype)
+ else
+ inserttypeconv(left,right.resulttype);
+ end
+ else if is_class_or_interface(rd) then
+ inserttypeconv(left,right.resulttype)
+ else
+ inserttypeconv(right,left.resulttype);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ else if (rd.deftype=classrefdef) and (ld.deftype=classrefdef) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ begin
+ if tobjectdef(tclassrefdef(rd).pointertype.def).is_related(
+ tobjectdef(tclassrefdef(ld).pointertype.def)) then
+ inserttypeconv(right,left.resulttype)
+ else
+ inserttypeconv(left,right.resulttype);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { allows comperasion with nil pointer }
+ else if is_class_or_interface(rd) or (rd.deftype=classrefdef) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ inserttypeconv(left,right.resulttype)
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ else if is_class_or_interface(ld) or (ld.deftype=classrefdef) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ inserttypeconv(right,left.resulttype)
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { support procvar=nil,procvar<>nil }
+ else if ((ld.deftype=procvardef) and (rt=niln)) or
+ ((rd.deftype=procvardef) and (lt=niln)) then
+ begin
+ if not(nodetype in [equaln,unequaln]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ { find proc field in methodpointer record }
+ hsym:=tfieldvarsym(trecorddef(methodpointertype.def).symtable.search('proc'));
+ if not assigned(hsym) then
+ internalerror(200412043);
+ { For methodpointers compare only tmethodpointer.proc }
+ if (rd.deftype=procvardef) and
+ (not tprocvardef(rd).is_addressonly) then
+ begin
+ right:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(right,methodpointertype));
+ end;
+ if (ld.deftype=procvardef) and
+ (not tprocvardef(ld).is_addressonly) then
+ begin
+ left:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(left,methodpointertype));
+ end;
+ end
+
+ { support dynamicarray=nil,dynamicarray<>nil }
+ else if (is_dynamic_array(ld) and (rt=niln)) or
+ (is_dynamic_array(rd) and (lt=niln)) or
+ (is_dynamic_array(ld) and is_dynamic_array(rd)) then
+ begin
+ if not(nodetype in [equaln,unequaln]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+{$ifdef SUPPORT_MMX}
+ { mmx support, this must be before the zero based array
+ check }
+ else if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(ld) and
+ is_mmx_able_array(rd) and
+ equal_defs(ld,rd) then
+ begin
+ case nodetype of
+ addn,subn,xorn,orn,andn:
+ ;
+ { mul is a little bit restricted }
+ muln:
+ if not(mmx_type(ld) in [mmxu16bit,mmxs16bit,mmxfixed16]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end;
+ end
+{$endif SUPPORT_MMX}
+
+ { this is a little bit dangerous, also the left type }
+ { pointer to should be checked! This broke the mmx support }
+ else if (rd.deftype=pointerdef) or is_zero_based_array(rd) then
+ begin
+ if is_zero_based_array(rd) then
+ begin
+ resulttype.setdef(tpointerdef.create(tarraydef(rd).elementtype));
+ inserttypeconv(right,resulttype);
+ end
+ else
+ resulttype:=right.resulttype;
+ inserttypeconv(left,sinttype);
+ if nodetype=addn then
+ begin
+ if not(cs_extsyntax in aktmoduleswitches) or
+ (not(is_pchar(ld)) and not(m_add_pointer in aktmodeswitches)) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ if (rd.deftype=pointerdef) and
+ (tpointerdef(rd).pointertype.def.size>1) then
+ begin
+ left:=caddnode.create(muln,left,
+ cordconstnode.create(tpointerdef(rd).pointertype.def.size,sinttype,true));
+ end;
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ else if (ld.deftype=pointerdef) or is_zero_based_array(ld) then
+ begin
+ if is_zero_based_array(ld) then
+ begin
+ resulttype.setdef(tpointerdef.create(tarraydef(ld).elementtype));
+ inserttypeconv(left,resulttype);
+ end
+ else
+ resulttype:=left.resulttype;
+
+ inserttypeconv(right,sinttype);
+ if nodetype in [addn,subn] then
+ begin
+ if not(cs_extsyntax in aktmoduleswitches) or
+ (not(is_pchar(ld)) and not(m_add_pointer in aktmodeswitches)) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ if (ld.deftype=pointerdef) and
+ (tpointerdef(ld).pointertype.def.size>1) then
+ begin
+ right:=caddnode.create(muln,right,
+ cordconstnode.create(tpointerdef(ld).pointertype.def.size,sinttype,true));
+ end
+ else
+ if is_zero_based_array(ld) and
+ (tarraydef(ld).elementtype.def.size>1) then
+ begin
+ right:=caddnode.create(muln,right,
+ cordconstnode.create(tarraydef(ld).elementtype.def.size,sinttype,true));
+ end;
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ else if (rd.deftype=procvardef) and
+ (ld.deftype=procvardef) and
+ equal_defs(rd,ld) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ begin
+ if tprocvardef(rd).is_addressonly then
+ begin
+ inserttypeconv_internal(right,voidpointertype);
+ inserttypeconv_internal(left,voidpointertype);
+ end
+ else
+ begin
+ { find proc field in methodpointer record }
+ hsym:=tfieldvarsym(trecorddef(methodpointertype.def).symtable.search('proc'));
+ if not assigned(hsym) then
+ internalerror(200412043);
+ { Compare tmehodpointer(left).proc }
+ right:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(right,methodpointertype));
+ left:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(left,methodpointertype));
+ end;
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { enums }
+ else if (ld.deftype=enumdef) and (rd.deftype=enumdef) then
+ begin
+ if allowenumop(nodetype) then
+ inserttypeconv(right,left.resulttype)
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { generic conversion, this is for error recovery }
+ else
+ begin
+ inserttypeconv(left,sinttype);
+ inserttypeconv(right,sinttype);
+ end;
+
+ { set resulttype if not already done }
+ if not assigned(resulttype.def) then
+ begin
+ case nodetype of
+ ltn,lten,gtn,gten,equaln,unequaln :
+ resulttype:=booltype;
+ slashn :
+ resulttype:=resultrealtype;
+ addn:
+ begin
+ { for strings, return is always a 255 char string }
+ if is_shortstring(left.resulttype.def) then
+ resulttype:=cshortstringtype
+ else
+ resulttype:=left.resulttype;
+ end;
+ else
+ resulttype:=left.resulttype;
+ end;
+ end;
+
+ { when the result is currency we need some extra code for
+ multiplication and division. this should not be done when
+ the muln or slashn node is created internally }
+ if not(nf_is_currency in flags) and
+ is_currency(resulttype.def) then
+ begin
+ case nodetype of
+ slashn :
+ begin
+ { slashn will only work with floats }
+ hp:=caddnode.create(muln,getcopy,crealconstnode.create(10000.0,s64currencytype));
+ include(hp.flags,nf_is_currency);
+ result:=hp;
+ end;
+ muln :
+ begin
+ if s64currencytype.def.deftype=floatdef then
+ hp:=caddnode.create(slashn,getcopy,crealconstnode.create(10000.0,s64currencytype))
+ else
+ hp:=cmoddivnode.create(divn,getcopy,cordconstnode.create(10000,s64currencytype,false));
+ include(hp.flags,nf_is_currency);
+ result:=hp
+ end;
+ end;
+ end;
+ end;
+
+
+ function taddnode.first_addstring: tnode;
+ var
+ p: tnode;
+ begin
+ { when we get here, we are sure that both the left and the right }
+ { node are both strings of the same stringtype (JM) }
+ case nodetype of
+ addn:
+ begin
+ { create the call to the concat routine both strings as arguments }
+ result := ccallnode.createintern('fpc_'+
+ tstringdef(resulttype.def).stringtypname+'_concat',
+ ccallparanode.create(right,ccallparanode.create(left,nil)));
+ { we reused the arguments }
+ left := nil;
+ right := nil;
+ end;
+ ltn,lten,gtn,gten,equaln,unequaln :
+ begin
+ { generate better code for comparison with empty string, we
+ only need to compare the length with 0 }
+ if (nodetype in [equaln,unequaln,gtn,gten,ltn,lten]) and
+ (((left.nodetype=stringconstn) and (str_length(left)=0)) or
+ ((right.nodetype=stringconstn) and (str_length(right)=0))) then
+ begin
+ { switch so that the constant is always on the right }
+ if left.nodetype = stringconstn then
+ begin
+ p := left;
+ left := right;
+ right := p;
+ end;
+ if is_shortstring(left.resulttype.def) or
+ (nodetype in [gtn,gten,ltn,lten]) then
+ { compare the length with 0 }
+ result := caddnode.create(nodetype,
+ cinlinenode.create(in_length_x,false,left),
+ cordconstnode.create(0,s32inttype,false))
+ else
+ begin
+ { compare the pointer with nil (for ansistrings etc), }
+ { faster than getting the length (JM) }
+ result:= caddnode.create(nodetype,
+ ctypeconvnode.create_internal(left,voidpointertype),
+ cpointerconstnode.create(0,voidpointertype));
+ end;
+ { left is reused }
+ left := nil;
+ { right isn't }
+ right.free;
+ right := nil;
+ exit;
+ end;
+ { no string constant -> call compare routine }
+ result := ccallnode.createintern('fpc_'+
+ tstringdef(left.resulttype.def).stringtypname+'_compare',
+ ccallparanode.create(right,ccallparanode.create(left,nil)));
+ { and compare its result with 0 according to the original operator }
+ result := caddnode.create(nodetype,result,
+ cordconstnode.create(0,s32inttype,false));
+ left := nil;
+ right := nil;
+ end;
+ end;
+ end;
+
+
+ function taddnode.first_addset: tnode;
+ var
+ procname: string[31];
+ tempn: tnode;
+ paras: tcallparanode;
+ srsym: ttypesym;
+ begin
+ { get the sym that represents the fpc_normal_set type }
+ if not searchsystype('FPC_NORMAL_SET',srsym) then
+ internalerror(200108313);
+
+ case nodetype of
+ equaln,unequaln,lten,gten:
+ begin
+ case nodetype of
+ equaln,unequaln:
+ procname := 'fpc_set_comp_sets';
+ lten,gten:
+ begin
+ procname := 'fpc_set_contains_sets';
+ { (left >= right) = (right <= left) }
+ if nodetype = gten then
+ begin
+ tempn := left;
+ left := right;
+ right := tempn;
+ end;
+ end;
+ end;
+ { convert the arguments (explicitely) to fpc_normal_set's }
+ left := ctypeconvnode.create_internal(left,srsym.restype);
+ right := ctypeconvnode.create_internal(right,srsym.restype);
+ result := ccallnode.createintern(procname,ccallparanode.create(right,
+ ccallparanode.create(left,nil)));
+ { left and right are reused as parameters }
+ left := nil;
+ right := nil;
+ { for an unequaln, we have to negate the result of comp_sets }
+ if nodetype = unequaln then
+ result := cnotnode.create(result);
+ end;
+ addn:
+ begin
+ { optimize first loading of a set }
+ if (right.nodetype=setelementn) and
+ not(assigned(tsetelementnode(right).right)) and
+ is_emptyset(left) then
+ begin
+ { type cast the value to pass as argument to a byte, }
+ { since that's what the helper expects }
+ tsetelementnode(right).left :=
+ ctypeconvnode.create_internal(tsetelementnode(right).left,u8inttype);
+ { set the resulttype to the actual one (otherwise it's }
+ { "fpc_normal_set") }
+ result := ccallnode.createinternres('fpc_set_create_element',
+ ccallparanode.create(tsetelementnode(right).left,nil),
+ resulttype);
+ { reused }
+ tsetelementnode(right).left := nil;
+ end
+ else
+ begin
+ if right.nodetype=setelementn then
+ begin
+ { convert the arguments to bytes, since that's what }
+ { the helper expects }
+ tsetelementnode(right).left :=
+ ctypeconvnode.create_internal(tsetelementnode(right).left,
+ u8inttype);
+
+ { convert the original set (explicitely) to an }
+ { fpc_normal_set so we can pass it to the helper }
+ left := ctypeconvnode.create_internal(left,srsym.restype);
+
+ { add a range or a single element? }
+ if assigned(tsetelementnode(right).right) then
+ begin
+ tsetelementnode(right).right :=
+ ctypeconvnode.create_internal(tsetelementnode(right).right,
+ u8inttype);
+
+ { create the call }
+ result := ccallnode.createinternres('fpc_set_set_range',
+ ccallparanode.create(tsetelementnode(right).right,
+ ccallparanode.create(tsetelementnode(right).left,
+ ccallparanode.create(left,nil))),resulttype);
+ end
+ else
+ begin
+ result := ccallnode.createinternres('fpc_set_set_byte',
+ ccallparanode.create(tsetelementnode(right).left,
+ ccallparanode.create(left,nil)),resulttype);
+ end;
+ { remove reused parts from original node }
+ tsetelementnode(right).right := nil;
+ tsetelementnode(right).left := nil;
+ left := nil;
+ end
+ else
+ begin
+ { add two sets }
+
+ { convert the sets to fpc_normal_set's }
+ result := ccallnode.createinternres('fpc_set_add_sets',
+ ccallparanode.create(
+ ctypeconvnode.create_explicit(right,srsym.restype),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(left,srsym.restype),nil)),resulttype);
+ { remove reused parts from original node }
+ left := nil;
+ right := nil;
+ end;
+ end
+ end;
+ subn,symdifn,muln:
+ begin
+ { convert the sets to fpc_normal_set's }
+ paras := ccallparanode.create(ctypeconvnode.create_internal(right,srsym.restype),
+ ccallparanode.create(ctypeconvnode.create_internal(left,srsym.restype),nil));
+ case nodetype of
+ subn:
+ result := ccallnode.createinternres('fpc_set_sub_sets',
+ paras,resulttype);
+ symdifn:
+ result := ccallnode.createinternres('fpc_set_symdif_sets',
+ paras,resulttype);
+ muln:
+ result := ccallnode.createinternres('fpc_set_mul_sets',
+ paras,resulttype);
+ end;
+ { remove reused parts from original node }
+ left := nil;
+ right := nil;
+ end;
+ else
+ internalerror(200108311);
+ end;
+ end;
+
+
+ function taddnode.first_add64bitint: tnode;
+ var
+ procname: string[31];
+ temp: tnode;
+ power: longint;
+ begin
+ result := nil;
+ { create helper calls mul }
+ if nodetype <> muln then
+ exit;
+
+ { make sure that if there is a constant, that it's on the right }
+ if left.nodetype = ordconstn then
+ begin
+ temp := right;
+ right := left;
+ left := temp;
+ end;
+
+ { can we use a shift instead of a mul? }
+ if not (cs_check_overflow in aktlocalswitches) and
+ (right.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(right).value,power) then
+ begin
+ tordconstnode(right).value := power;
+ result := cshlshrnode.create(shln,left,right);
+ { left and right are reused }
+ left := nil;
+ right := nil;
+ { return firstpassed new node }
+ exit;
+ end;
+
+ { when currency is used set the result of the
+ parameters to s64bit, so they are not converted }
+ if is_currency(resulttype.def) then
+ begin
+ left.resulttype:=s64inttype;
+ right.resulttype:=s64inttype;
+ end;
+
+ { otherwise, create the parameters for the helper }
+ right := ccallparanode.create(
+ cordconstnode.create(ord(cs_check_overflow in aktlocalswitches),booltype,true),
+ ccallparanode.create(right,ccallparanode.create(left,nil)));
+ left := nil;
+ { only qword needs the unsigned code, the
+ signed code is also used for currency }
+ if is_signed(resulttype.def) then
+ procname := 'fpc_mul_int64'
+ else
+ procname := 'fpc_mul_qword';
+ result := ccallnode.createintern(procname,right);
+ right := nil;
+ end;
+
+
+ function taddnode.first_addfloat : tnode;
+ var
+ procname: string[31];
+ { do we need to reverse the result ? }
+ notnode : boolean;
+ begin
+ result := nil;
+ notnode := false;
+ { In non-emulation mode, real opcodes are
+ emitted for floating point values.
+ }
+ if not (cs_fp_emulation in aktmoduleswitches) then
+ exit;
+
+ if not(target_info.system in system_wince) then
+ begin
+ case tfloatdef(left.resulttype.def).typ of
+ s32real:
+ procname:='float32';
+ s64real:
+ procname:='float64';
+ {!!! not yet implemented
+ s128real:
+ }
+ else
+ internalerror(2005082601);
+ end;
+
+ case nodetype of
+ addn:
+ procname:=procname+'_add';
+ muln:
+ procname:=procname+'_mul';
+ subn:
+ procname:=procname+'_sub';
+ slashn:
+ procname:=procname+'_div';
+ ltn:
+ procname:=procname+'_lt';
+ lten:
+ procname:=procname+'_le';
+ gtn:
+ begin
+ procname:=procname+'_le';
+ notnode:=true;
+ end;
+ gten:
+ begin
+ procname:=procname+'_lt';
+ notnode:=true;
+ end;
+ equaln:
+ procname:=procname+'_eq';
+ unequaln:
+ begin
+ procname:=procname+'_eq';
+ notnode:=true;
+ end;
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),left.resulttype.def.typename,right.resulttype.def.typename);
+ end;
+ end
+ else
+ begin
+ case nodetype of
+ addn:
+ procname:='ADD';
+ muln:
+ procname:='MUL';
+ subn:
+ procname:='SUB';
+ slashn:
+ procname:='DIV';
+ ltn:
+ procname:='LT';
+ lten:
+ procname:='LE';
+ gtn:
+ procname:='GT';
+ gten:
+ procname:='GE';
+ equaln:
+ procname:='EQ';
+ unequaln:
+ procname:='NE';
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),left.resulttype.def.typename,right.resulttype.def.typename);
+ end;
+ case tfloatdef(left.resulttype.def).typ of
+ s32real:
+ procname:=procname+'S';
+ s64real:
+ procname:=procname+'D';
+ {!!! not yet implemented
+ s128real:
+ }
+ else
+ internalerror(2005082602);
+ end;
+
+ end;
+ result:=ccallnode.createintern(procname,ccallparanode.create(right,
+ ccallparanode.create(left,nil)));
+ left:=nil;
+ right:=nil;
+
+ { do we need to reverse the result }
+ if notnode then
+ result:=cnotnode.create(result);
+ end;
+
+
+ function taddnode.pass_1 : tnode;
+ var
+{$ifdef addstringopt}
+ hp : tnode;
+{$endif addstringopt}
+ lt,rt : tnodetype;
+ rd,ld : tdef;
+ begin
+ result:=nil;
+ { first do the two subtrees }
+ firstpass(left);
+ firstpass(right);
+
+ if codegenerror then
+ exit;
+
+ { load easier access variables }
+ rd:=right.resulttype.def;
+ ld:=left.resulttype.def;
+ rt:=right.nodetype;
+ lt:=left.nodetype;
+
+ { int/int gives real/real! }
+ if nodetype=slashn then
+ begin
+{$ifdef cpufpemu}
+ if (aktfputype=fpu_soft) or (cs_fp_emulation in aktmoduleswitches) then
+ begin
+ result:=first_addfloat;
+ if assigned(result) then
+ exit;
+ end;
+{$endif cpufpemu}
+ expectloc:=LOC_FPUREGISTER;
+ { maybe we need an integer register to save }
+ { a reference }
+ if ((left.expectloc<>LOC_FPUREGISTER) or
+ (right.expectloc<>LOC_FPUREGISTER)) and
+ (left.registersint=right.registersint) then
+ calcregisters(self,1,1,0)
+ else
+ calcregisters(self,0,1,0);
+ { an add node always first loads both the left and the }
+ { right in the fpu before doing the calculation. However, }
+ { calcregisters(0,2,0) will overestimate the number of }
+ { necessary registers (it will make it 3 in case one of }
+ { the operands is already in the fpu) (JM) }
+ if ((left.expectloc<>LOC_FPUREGISTER) or
+ (right.expectloc<>LOC_FPUREGISTER)) and
+ (registersfpu < 2) then
+ inc(registersfpu);
+ end
+
+ { if both are orddefs then check sub types }
+ else if (ld.deftype=orddef) and (rd.deftype=orddef) then
+ begin
+ { 2 booleans ? }
+ if is_boolean(ld) and is_boolean(rd) then
+ begin
+ if not(cs_full_boolean_eval in aktlocalswitches) and
+ (nodetype in [andn,orn]) then
+ begin
+ expectloc:=LOC_JUMP;
+ calcregisters(self,0,0,0);
+ end
+ else
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ begin
+ expectloc:=LOC_FLAGS;
+ if (left.expectloc in [LOC_JUMP,LOC_FLAGS]) and
+ (left.expectloc in [LOC_JUMP,LOC_FLAGS]) then
+ calcregisters(self,2,0,0)
+ else
+ calcregisters(self,1,0,0);
+ end
+ else
+ begin
+ expectloc:=LOC_REGISTER;
+ calcregisters(self,0,0,0);
+ end;
+ end;
+ end
+ else
+ { Both are chars? only convert to shortstrings for addn }
+ if is_char(ld) then
+ begin
+ if nodetype=addn then
+ internalerror(200103291);
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end
+{$ifndef cpu64bit}
+ { is there a 64 bit type ? }
+ else if (torddef(ld).typ in [s64bit,u64bit,scurrency]) then
+ begin
+ result := first_add64bitint;
+ if assigned(result) then
+ exit;
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_JUMP;
+ calcregisters(self,2,0,0)
+ end
+{$endif cpu64bit}
+ { is there a cardinal? }
+ else if (torddef(ld).typ=u32bit) then
+ begin
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ { for unsigned mul we need an extra register }
+ if nodetype=muln then
+ inc(registersint);
+ end
+ { generic s32bit conversion }
+ else
+ begin
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end;
+ end
+
+ { left side a setdef, must be before string processing,
+ else array constructor can be seen as array of char (PFV) }
+ else if (ld.deftype=setdef) then
+ begin
+ if tsetdef(ld).settype=smallset then
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ expectloc:=LOC_FLAGS
+ else
+ expectloc:=LOC_REGISTER;
+ { are we adding set elements ? }
+ if right.nodetype=setelementn then
+ calcregisters(self,2,0,0)
+ else
+ calcregisters(self,1,0,0);
+ end
+ else
+{$ifdef MMXSET}
+{$ifdef i386}
+ if cs_mmx in aktlocalswitches then
+ begin
+ expectloc:=LOC_MMXREGISTER;
+ calcregisters(self,0,0,4);
+ end
+ else
+{$endif}
+{$endif MMXSET}
+ begin
+ result := first_addset;
+ if assigned(result) then
+ exit;
+ expectloc:=LOC_CREFERENCE;
+ calcregisters(self,0,0,0);
+ { here we call SET... }
+ include(current_procinfo.flags,pi_do_call);
+ end;
+ end
+
+ { compare pchar by addresses like BP/Delphi }
+ else if is_pchar(ld) then
+ begin
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end
+
+ { is one of the operands a string }
+ else if (ld.deftype=stringdef) then
+ begin
+ if is_widestring(ld) then
+ begin
+ { this is only for add, the comparisaion is handled later }
+ expectloc:=LOC_REGISTER;
+ end
+ else if is_ansistring(ld) then
+ begin
+ { this is only for add, the comparisaion is handled later }
+ expectloc:=LOC_REGISTER;
+ end
+ else if is_longstring(ld) then
+ begin
+ { this is only for add, the comparisaion is handled later }
+ expectloc:=LOC_REFERENCE;
+ end
+ else
+ begin
+{$ifdef addstringopt}
+ { can create a call which isn't handled by callparatemp }
+ if canbeaddsstringcharoptnode(self) then
+ begin
+ hp := genaddsstringcharoptnode(self);
+ pass_1 := hp;
+ exit;
+ end
+ else
+{$endif addstringopt}
+ begin
+ { Fix right to be shortstring }
+ if is_char(right.resulttype.def) then
+ begin
+ inserttypeconv(right,cshortstringtype);
+ firstpass(right);
+ end;
+ end;
+{$ifdef addstringopt}
+ { can create a call which isn't handled by callparatemp }
+ if canbeaddsstringcsstringoptnode(self) then
+ begin
+ hp := genaddsstringcsstringoptnode(self);
+ pass_1 := hp;
+ exit;
+ end;
+{$endif addstringopt}
+ end;
+ { otherwise, let addstring convert everything }
+ result := first_addstring;
+ exit;
+ end
+
+ { is one a real float ? }
+ else if (rd.deftype=floatdef) or (ld.deftype=floatdef) then
+ begin
+{$ifdef cpufpemu}
+ if (aktfputype=fpu_soft) or (cs_fp_emulation in aktmoduleswitches) then
+ begin
+ result:=first_addfloat;
+ if assigned(result) then
+ exit;
+ end;
+{$endif cpufpemu}
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_FPUREGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,0,1,0);
+ { an add node always first loads both the left and the }
+ { right in the fpu before doing the calculation. However, }
+ { calcregisters(0,2,0) will overestimate the number of }
+ { necessary registers (it will make it 3 in case one of }
+ { the operands is already in the fpu) (JM) }
+ if ((left.expectloc<>LOC_FPUREGISTER) or
+ (right.expectloc<>LOC_FPUREGISTER)) and
+ (registersfpu < 2) then
+ inc(registersfpu);
+ end
+
+ { pointer comperation and subtraction }
+ else if (ld.deftype=pointerdef) then
+ begin
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end
+
+ else if is_class_or_interface(ld) then
+ begin
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end
+
+ else if (ld.deftype=classrefdef) then
+ begin
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end
+
+ { support procvar=nil,procvar<>nil }
+ else if ((ld.deftype=procvardef) and (rt=niln)) or
+ ((rd.deftype=procvardef) and (lt=niln)) then
+ begin
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end
+
+{$ifdef SUPPORT_MMX}
+ { mmx support, this must be before the zero based array
+ check }
+ else if (cs_mmx in aktlocalswitches) and is_mmx_able_array(ld) and
+ is_mmx_able_array(rd) then
+ begin
+ expectloc:=LOC_MMXREGISTER;
+ calcregisters(self,0,0,1);
+ end
+{$endif SUPPORT_MMX}
+
+ else if (rd.deftype=pointerdef) or (ld.deftype=pointerdef) then
+ begin
+ expectloc:=LOC_REGISTER;
+ calcregisters(self,1,0,0);
+ end
+
+ else if (rd.deftype=procvardef) and
+ (ld.deftype=procvardef) and
+ equal_defs(rd,ld) then
+ begin
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end
+
+ else if (ld.deftype=enumdef) then
+ begin
+ expectloc:=LOC_FLAGS;
+ calcregisters(self,1,0,0);
+ end
+
+{$ifdef SUPPORT_MMX}
+ else if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(ld) and
+ is_mmx_able_array(rd) then
+ begin
+ expectloc:=LOC_MMXREGISTER;
+ calcregisters(self,0,0,1);
+ end
+{$endif SUPPORT_MMX}
+
+ { the general solution is to convert to 32 bit int }
+ else
+ begin
+ expectloc:=LOC_REGISTER;
+ calcregisters(self,1,0,0);
+ end;
+ end;
+
+{$ifdef state_tracking}
+ function Taddnode.track_state_pass(exec_known:boolean):boolean;
+
+ var factval:Tnode;
+
+ begin
+ track_state_pass:=false;
+ if left.track_state_pass(exec_known) then
+ begin
+ track_state_pass:=true;
+ left.resulttype.def:=nil;
+ do_resulttypepass(left);
+ end;
+ factval:=aktstate.find_fact(left);
+ if factval<>nil then
+ begin
+ track_state_pass:=true;
+ left.destroy;
+ left:=factval.getcopy;
+ end;
+ if right.track_state_pass(exec_known) then
+ begin
+ track_state_pass:=true;
+ right.resulttype.def:=nil;
+ do_resulttypepass(right);
+ end;
+ factval:=aktstate.find_fact(right);
+ if factval<>nil then
+ begin
+ track_state_pass:=true;
+ right.destroy;
+ right:=factval.getcopy;
+ end;
+ end;
+{$endif}
+
+begin
+ caddnode:=taddnode;
+end.
diff --git a/compiler/nbas.pas b/compiler/nbas.pas
new file mode 100644
index 0000000000..18c786b55f
--- /dev/null
+++ b/compiler/nbas.pas
@@ -0,0 +1,1042 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ This unit implements some basic 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 nbas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cpuinfo,cpubase,cgbase,cgutils,
+ aasmbase,aasmtai,aasmcpu,
+ node,
+ symtype;
+
+ type
+ tnothingnode = class(tnode)
+ constructor create;virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ end;
+ tnothingnodeclass = class of tnothingnode;
+
+ terrornode = class(tnode)
+ constructor create;virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ procedure mark_write;override;
+ end;
+ terrornodeclass = class of terrornode;
+
+ tasmnode = class(tnode)
+ p_asm : taasmoutput;
+ currenttai : tai;
+ { Used registers in assembler block }
+ used_regs_int,
+ used_regs_fpu : tcpuregisterset;
+ constructor create(p : taasmoutput);virtual;
+ constructor create_get_position;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ tasmnodeclass = class of tasmnode;
+
+ tstatementnode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ procedure printnodetree(var t:text);override;
+ end;
+ tstatementnodeclass = class of tstatementnode;
+
+ tblocknode = class(tunarynode)
+ constructor create(l : tnode);virtual;
+ destructor destroy; override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+{$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+{$endif state_tracking}
+ end;
+ tblocknodeclass = class of tblocknode;
+
+ ttempcreatenode = class;
+
+ { to allow access to the location by temp references even after the temp has }
+ { already been disposed and to make sure the coherency between temps and }
+ { temp references is kept after a getcopy }
+ ptempinfo = ^ttempinfo;
+ ttempinfo = record
+ { set to the copy of a tempcreate pnode (if it gets copied) so that the }
+ { refs and deletenode can hook to this copy once they get copied too }
+ hookoncopy : ptempinfo;
+ restype : ttype;
+ temptype : ttemptype;
+ owner : ttempcreatenode;
+ may_be_in_reg : boolean;
+ valid : boolean;
+ nextref_set_hookoncopy_nil : boolean;
+ location : tlocation;
+ end;
+
+ { a node which will create a (non)persistent temp of a given type with a given }
+ { size (the size is separate to allow creating "void" temps with a custom size) }
+ ttempcreatenode = class(tnode)
+ size: aint;
+ tempinfo: ptempinfo;
+ { * persistent temps are used in manually written code where the temp }
+ { be usable among different statements and where you can manually say }
+ { when the temp has to be freed (using a ttempdeletenode) }
+ { * non-persistent temps are mostly used in typeconversion helpers, }
+ { where the node that receives the temp becomes responsible for }
+ { freeing it. In this last case, you must use only one reference }
+ { to it and *not* generate a ttempdeletenode }
+ constructor create(const _restype: ttype; _size: aint; _temptype: ttemptype;allowreg:boolean); virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy: tnode; override;
+ function pass_1 : tnode; override;
+ function det_resulttype: tnode; override;
+ function docompare(p: tnode): boolean; override;
+ procedure printnodedata(var t:text);override;
+ end;
+ ttempcreatenodeclass = class of ttempcreatenode;
+
+ { a node which is a reference to a certain temp }
+ ttemprefnode = class(tnode)
+ constructor create(const temp: ttempcreatenode); virtual;
+ constructor create_offset(const temp: ttempcreatenode;aoffset:longint);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function _getcopy: tnode; override;
+ procedure derefnode;override;
+ function pass_1 : tnode; override;
+ function det_resulttype : tnode; override;
+ procedure mark_write;override;
+ function docompare(p: tnode): boolean; override;
+ procedure printnodedata(var t:text);override;
+ protected
+ tempinfo: ptempinfo;
+ offset : longint;
+ private
+ tempidx : longint;
+ end;
+ ttemprefnodeclass = class of ttemprefnode;
+
+ { a node which removes a temp }
+ ttempdeletenode = class(tnode)
+ constructor create(const temp: ttempcreatenode); virtual;
+ { this will convert the persistant temp to a normal temp
+ for returning to the other nodes }
+ constructor create_normal_temp(const temp: ttempcreatenode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function _getcopy: tnode; override;
+ procedure derefnode;override;
+ function pass_1: tnode; override;
+ function det_resulttype: tnode; override;
+ function docompare(p: tnode): boolean; override;
+ destructor destroy; override;
+ procedure printnodedata(var t:text);override;
+ protected
+ tempinfo: ptempinfo;
+ release_to_normal : boolean;
+ private
+ tempidx : longint;
+ end;
+ ttempdeletenodeclass = class of ttempdeletenode;
+
+ var
+ cnothingnode : tnothingnodeclass;
+ cerrornode : terrornodeclass;
+ casmnode : tasmnodeclass;
+ cstatementnode : tstatementnodeclass;
+ cblocknode : tblocknodeclass;
+ ctempcreatenode : ttempcreatenodeclass;
+ ctemprefnode : ttemprefnodeclass;
+ ctempdeletenode : ttempdeletenodeclass;
+
+ { Create a blocknode and statement node for multiple statements
+ generated internally by the parser }
+ function internalstatements(var laststatement:tstatementnode):tblocknode;
+ function laststatement(block:tblocknode):tstatementnode;
+ procedure addstatement(var laststatement:tstatementnode;n:tnode);
+
+
+implementation
+
+ uses
+ cutils,
+ verbose,globals,systems,
+ symconst,symdef,defutil,defcmp,
+ pass_1,
+ nld,ncal,nflw,
+ procinfo
+ ;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function internalstatements(var laststatement:tstatementnode):tblocknode;
+ begin
+ { create dummy initial statement }
+ laststatement := cstatementnode.create(cnothingnode.create,nil);
+ internalstatements := cblocknode.create(laststatement);
+ end;
+
+
+ function laststatement(block:tblocknode):tstatementnode;
+ begin
+ result:=tstatementnode(block.left);
+ while assigned(result) and assigned(result.right) do
+ result:=tstatementnode(result.right);
+ end;
+
+
+ procedure addstatement(var laststatement:tstatementnode;n:tnode);
+ begin
+ if assigned(laststatement.right) then
+ internalerror(200204201);
+ laststatement.right:=cstatementnode.create(n,nil);
+ laststatement:=tstatementnode(laststatement.right);
+ end;
+
+
+{*****************************************************************************
+ TFIRSTNOTHING
+*****************************************************************************}
+
+ constructor tnothingnode.create;
+ begin
+ inherited create(nothingn);
+ end;
+
+
+ function tnothingnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ end;
+
+
+ function tnothingnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+{*****************************************************************************
+ TFIRSTERROR
+*****************************************************************************}
+
+ constructor terrornode.create;
+
+ begin
+ inherited create(errorn);
+ end;
+
+
+ function terrornode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ include(flags,nf_error);
+ codegenerror:=true;
+ resulttype:=generrortype;
+ end;
+
+
+ function terrornode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ codegenerror:=true;
+ end;
+
+
+ procedure terrornode.mark_write;
+ begin
+ end;
+
+{*****************************************************************************
+ TSTATEMENTNODE
+*****************************************************************************}
+
+ constructor tstatementnode.create(l,r : tnode);
+
+ begin
+ inherited create(statementn,l,r);
+ end;
+
+ function tstatementnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+
+ { left is the statement itself calln assignn or a complex one }
+ resulttypepass(left);
+ if (not (cs_extsyntax in aktmoduleswitches)) and
+ assigned(left.resulttype.def) and
+ not((left.nodetype=calln) and
+ { don't complain when funcretrefnode is set, because then the
+ value is already used. And also not for constructors }
+ (assigned(tcallnode(left).funcretnode) or
+ (tcallnode(left).procdefinition.proctypeoption=potype_constructor))) and
+ not(is_void(left.resulttype.def)) then
+ CGMessage(parser_e_illegal_expression);
+ if codegenerror then
+ exit;
+
+ { right is the next statement in the list }
+ if assigned(right) then
+ resulttypepass(right);
+ if codegenerror then
+ exit;
+ end;
+
+
+ function tstatementnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ { left is the statement itself calln assignn or a complex one }
+ firstpass(left);
+ if codegenerror then
+ exit;
+ expectloc:=left.expectloc;
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ { right is the next in the list }
+ if assigned(right) then
+ firstpass(right);
+ if codegenerror then
+ exit;
+ end;
+
+
+ procedure tstatementnode.printnodetree(var t:text);
+ begin
+ printnodelist(t);
+ end;
+
+{*****************************************************************************
+ TBLOCKNODE
+*****************************************************************************}
+
+ constructor tblocknode.create(l : tnode);
+
+ begin
+ inherited create(blockn,l);
+ end;
+
+ destructor tblocknode.destroy;
+
+ var
+ hp, next: tstatementnode;
+ begin
+ hp := tstatementnode(left);
+ left := nil;
+ while assigned(hp) do
+ begin
+ next := tstatementnode(hp.right);
+ hp.right := nil;
+ hp.free;
+ hp := next;
+ end;
+ inherited destroy;
+ end;
+
+ function tblocknode.det_resulttype:tnode;
+ var
+ hp : tstatementnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+
+ hp:=tstatementnode(left);
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ codegenerror:=false;
+ resulttypepass(hp.left);
+ if not(codegenerror) and
+ not(cs_extsyntax in aktmoduleswitches) and
+ (hp.left.nodetype=calln) and
+ not(is_void(hp.left.resulttype.def)) and
+ not(cnf_return_value_used in tcallnode(hp.left).callnodeflags) and
+ not((tcallnode(hp.left).procdefinition.proctypeoption=potype_constructor) and
+ assigned(tprocdef(tcallnode(hp.left).procdefinition)._class) and
+ is_object(tprocdef(tcallnode(hp.left).procdefinition)._class)) then
+ CGMessagePos(hp.left.fileinfo,parser_e_illegal_expression);
+ { the resulttype of the block is the last type that is
+ returned. Normally this is a voidtype. But when the
+ compiler inserts a block of multiple statements then the
+ last entry can return a value }
+ resulttype:=hp.left.resulttype;
+ end;
+ hp:=tstatementnode(hp.right);
+ end;
+ end;
+
+
+ function tblocknode.pass_1 : tnode;
+ var
+ hp : tstatementnode;
+ count : longint;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ count:=0;
+ hp:=tstatementnode(left);
+ while assigned(hp) do
+ begin
+(*
+ if cs_regvars in aktglobalswitches then
+ begin
+ { node transformations }
+
+ { concat function result to exit }
+ { this is wrong for string or other complex
+ result types !!! }
+ if {ret_in_acc(current_procinfo.procdef.rettype.def) and }
+ (is_ordinal(current_procinfo.procdef.rettype.def) or
+ is_smallset(current_procinfo.procdef.rettype.def)) and
+ assigned(hp.right) and
+ assigned(tstatementnode(hp.right).left) and
+ (tstatementnode(hp.right).left.nodetype=exitn) and
+ (hp.left.nodetype=assignn) and
+ { !!!! this tbinarynode should be tassignmentnode }
+ (tbinarynode(hp.left).left.nodetype=loadn) and
+ (is_funcret_sym(tloadnode(tbinarynode(hp.left).left).symtableentry)) then
+ begin
+ if assigned(texitnode(tstatementnode(hp.right).left).left) then
+ CGMessage(cg_n_inefficient_code)
+ else
+ begin
+ texitnode(tstatementnode(hp.right).left).left:=tassignmentnode(hp.left).right;
+ tassignmentnode(hp.left).right:=nil;
+ hp.left.free;
+ hp.left:=nil;
+ end;
+ end
+ { warning if unreachable code occurs and elimate this }
+ else if (hp.left.nodetype in
+ [exitn,breakn,continuen,goton]) and
+ { statement node (JM) }
+ assigned(hp.right) and
+ { kind of statement! (JM) }
+ assigned(tstatementnode(hp.right).left) and
+ (tstatementnode(hp.right).left.nodetype<>labeln) then
+ begin
+ { use correct line number }
+ aktfilepos:=hp.right.fileinfo;
+ hp.right.free;
+ hp.right:=nil;
+ CGMessage(cg_w_unreachable_code);
+ { old lines }
+ aktfilepos:=hp.left.fileinfo;
+ end;
+ end;
+*)
+ if assigned(hp.left) then
+ begin
+ codegenerror:=false;
+ firstpass(hp.left);
+
+ hp.expectloc:=hp.left.expectloc;
+ hp.registersint:=hp.left.registersint;
+ hp.registersfpu:=hp.left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ hp.registersmmx:=hp.left.registersmmx;
+{$endif SUPPORT_MMX}
+ end
+ else
+ hp.registersint:=0;
+
+ if hp.registersint>registersint then
+ registersint:=hp.registersint;
+ if hp.registersfpu>registersfpu then
+ registersfpu:=hp.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if hp.registersmmx>registersmmx then
+ registersmmx:=hp.registersmmx;
+{$endif}
+ expectloc:=hp.expectloc;
+ inc(count);
+ hp:=tstatementnode(hp.right);
+ end;
+ end;
+
+{$ifdef state_tracking}
+ function Tblocknode.track_state_pass(exec_known:boolean):boolean;
+
+ var hp:Tstatementnode;
+
+ begin
+ track_state_pass:=false;
+ hp:=Tstatementnode(left);
+ while assigned(hp) do
+ begin
+ if hp.left.track_state_pass(exec_known) then
+ track_state_pass:=true;
+ hp:=Tstatementnode(hp.right);
+ end;
+ end;
+{$endif state_tracking}
+
+{*****************************************************************************
+ TASMNODE
+*****************************************************************************}
+
+ constructor tasmnode.create(p : taasmoutput);
+ begin
+ inherited create(asmn);
+ p_asm:=p;
+ currenttai:=nil;
+ used_regs_int:=[];
+ used_regs_fpu:=[];
+ end;
+
+
+ constructor tasmnode.create_get_position;
+ begin
+ inherited create(asmn);
+ p_asm:=nil;
+ include(flags,nf_get_asm_position);
+ currenttai:=nil;
+ end;
+
+
+ destructor tasmnode.destroy;
+ begin
+ if assigned(p_asm) then
+ p_asm.free;
+ inherited destroy;
+ end;
+
+
+ constructor tasmnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ var
+ hp : tai;
+ begin
+ inherited ppuload(t,ppufile);
+ if not(nf_get_asm_position in flags) then
+ begin
+ p_asm:=taasmoutput.create;
+ repeat
+ hp:=ppuloadai(ppufile);
+ if hp=nil then
+ break;
+ p_asm.concat(hp);
+ until false;
+ end
+ else
+ p_asm:=nil;
+ currenttai:=nil;
+ end;
+
+
+ procedure tasmnode.ppuwrite(ppufile:tcompilerppufile);
+ var
+ hp : tai;
+ begin
+ inherited ppuwrite(ppufile);
+{$warning FIXME Add saving of register sets}
+ if not(nf_get_asm_position in flags) then
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ ppuwriteai(ppufile,hp);
+ hp:=tai(hp.next);
+ end;
+ { end is marked by a nil }
+ ppuwriteai(ppufile,nil);
+ end;
+ end;
+
+
+ procedure tasmnode.buildderefimpl;
+ var
+ hp : tai;
+ begin
+ inherited buildderefimpl;
+ if not(nf_get_asm_position in flags) then
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ hp.buildderefimpl;
+ hp:=tai(hp.next);
+ end;
+ end;
+ end;
+
+
+ procedure tasmnode.derefimpl;
+ var
+ hp : tai;
+ begin
+ inherited derefimpl;
+ if not(nf_get_asm_position in flags) then
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ hp.derefimpl;
+ hp:=tai(hp.next);
+ end;
+ end;
+ end;
+
+
+ function tasmnode._getcopy: tnode;
+ var
+ n: tasmnode;
+ begin
+ n := tasmnode(inherited _getcopy);
+ if assigned(p_asm) then
+ begin
+ n.p_asm:=taasmoutput.create;
+ n.p_asm.concatlistcopy(p_asm);
+ end
+ else n.p_asm := nil;
+ n.currenttai:=currenttai;
+ result:=n;
+ end;
+
+
+ function tasmnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ if not(nf_get_asm_position in flags) then
+ include(current_procinfo.flags,pi_has_assembler_block);
+ end;
+
+
+ function tasmnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+ function tasmnode.docompare(p: tnode): boolean;
+ begin
+ { comparing of asmlists is not implemented (JM) }
+ docompare := false;
+ end;
+
+
+{*****************************************************************************
+ TEMPCREATENODE
+*****************************************************************************}
+
+ constructor ttempcreatenode.create(const _restype: ttype; _size: aint; _temptype: ttemptype;allowreg:boolean);
+ begin
+ inherited create(tempcreaten);
+ size := _size;
+ new(tempinfo);
+ fillchar(tempinfo^,sizeof(tempinfo^),0);
+ tempinfo^.restype := _restype;
+ tempinfo^.temptype := _temptype;
+ tempinfo^.owner:=self;
+ tempinfo^.may_be_in_reg:=
+ allowreg and
+ { temp must fit a single register }
+ (tstoreddef(_restype.def).is_fpuregable or
+ (tstoreddef(_restype.def).is_intregable and
+ (_size<=TCGSize2Size[OS_64]))) and
+ { size of register operations must be known }
+ (def_cgsize(_restype.def)<>OS_NO) and
+ { no init/final needed }
+ not (_restype.def.needs_inittable) and
+ ((_restype.def.deftype <> pointerdef) or
+ (not tpointerdef(_restype.def).pointertype.def.needs_inittable));
+ end;
+
+ function ttempcreatenode._getcopy: tnode;
+ var
+ n: ttempcreatenode;
+ begin
+ n := ttempcreatenode(inherited _getcopy);
+ n.size := size;
+
+ new(n.tempinfo);
+ fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
+ n.tempinfo^.owner:=n;
+ n.tempinfo^.restype := tempinfo^.restype;
+ n.tempinfo^.temptype := tempinfo^.temptype;
+
+ { when the tempinfo has already a hookoncopy then it is not
+ reset by a tempdeletenode }
+ if assigned(tempinfo^.hookoncopy) then
+ internalerror(200211262);
+
+ { signal the temprefs that the temp they point to has been copied, }
+ { so that if the refs get copied as well, they can hook themselves }
+ { to the copy of the temp }
+ tempinfo^.hookoncopy := n.tempinfo;
+ tempinfo^.nextref_set_hookoncopy_nil := false;
+
+ result := n;
+ end;
+
+
+ constructor ttempcreatenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+
+ size:=ppufile.getlongint;
+ new(tempinfo);
+ fillchar(tempinfo^,sizeof(tempinfo^),0);
+ tempinfo^.may_be_in_reg:=boolean(ppufile.getbyte);
+ ppufile.gettype(tempinfo^.restype);
+ tempinfo^.temptype := ttemptype(ppufile.getbyte);
+ tempinfo^.owner:=self;
+ end;
+
+
+ procedure ttempcreatenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(size);
+ ppufile.putbyte(byte(tempinfo^.may_be_in_reg));
+ ppufile.puttype(tempinfo^.restype);
+ ppufile.putbyte(byte(tempinfo^.temptype));
+ end;
+
+
+ procedure ttempcreatenode.buildderefimpl;
+ begin
+ tempinfo^.restype.buildderef;
+ end;
+
+
+ procedure ttempcreatenode.derefimpl;
+ begin
+ tempinfo^.restype.resolve;
+ end;
+
+
+ function ttempcreatenode.pass_1 : tnode;
+ begin
+ result := nil;
+ expectloc:=LOC_VOID;
+ if (tempinfo^.restype.def.needs_inittable) then
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ end;
+
+
+ function ttempcreatenode.det_resulttype: tnode;
+ begin
+ result := nil;
+ { a tempcreatenode doesn't have a resulttype, only temprefnodes do }
+ resulttype := voidtype;
+ end;
+
+
+ function ttempcreatenode.docompare(p: tnode): boolean;
+ begin
+ result :=
+ inherited docompare(p) and
+ (ttempcreatenode(p).size = size) and
+ (ttempcreatenode(p).tempinfo^.may_be_in_reg = tempinfo^.may_be_in_reg) and
+ equal_defs(ttempcreatenode(p).tempinfo^.restype.def,tempinfo^.restype.def);
+ end;
+
+
+ procedure ttempcreatenode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'size = ',size,', temprestype = "',tempinfo^.restype.def.gettypename,'", tempinfo = $',hexstr(ptruint(tempinfo),sizeof(ptruint)*2));
+ end;
+
+
+{*****************************************************************************
+ TEMPREFNODE
+*****************************************************************************}
+
+ constructor ttemprefnode.create(const temp: ttempcreatenode);
+ begin
+ inherited create(temprefn);
+ tempinfo := temp.tempinfo;
+ offset:=0;
+ end;
+
+
+ constructor ttemprefnode.create_offset(const temp: ttempcreatenode;aoffset:longint);
+ begin
+ self.create(temp);
+ offset := aoffset;
+ end;
+
+
+ function ttemprefnode._getcopy: tnode;
+ var
+ n: ttemprefnode;
+ begin
+ n := ttemprefnode(inherited _getcopy);
+ n.offset := offset;
+
+ if assigned(tempinfo^.hookoncopy) then
+ { if the temp has been copied, assume it becomes a new }
+ { temp which has to be hooked by the copied reference }
+ begin
+ { hook the ref to the copied temp }
+ n.tempinfo := tempinfo^.hookoncopy;
+ { if we passed a ttempdeletenode that changed the temp }
+ { from a persistent one into a normal one, we must be }
+ { the last reference (since our parent should free the }
+ { temp (JM) }
+ if (tempinfo^.nextref_set_hookoncopy_nil) then
+ tempinfo^.hookoncopy := nil;
+ end
+ else
+ { if the temp we refer to hasn't been copied, assume }
+ { we're just a new reference to that temp }
+ begin
+ n.tempinfo := tempinfo;
+ end;
+
+ if not assigned(n.tempinfo) then
+ internalerror(2005071901);
+
+ result := n;
+ end;
+
+
+ constructor ttemprefnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ tempidx:=ppufile.getlongint;
+ offset:=ppufile.getlongint;
+ end;
+
+
+ procedure ttemprefnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(tempinfo^.owner.ppuidx);
+ ppufile.putlongint(offset);
+ end;
+
+
+ procedure ttemprefnode.derefnode;
+ var
+ temp : ttempcreatenode;
+ begin
+ temp:=ttempcreatenode(nodeppuidxget(tempidx));
+ if temp.nodetype<>tempcreaten then
+ internalerror(200311075);
+ tempinfo:=temp.tempinfo;
+ end;
+
+
+ function ttemprefnode.pass_1 : tnode;
+ begin
+ expectloc := LOC_REFERENCE;
+ if not tempinfo^.restype.def.needs_inittable and
+ tempinfo^.may_be_in_reg then
+ begin
+ if tempinfo^.restype.def.deftype=floatdef then
+ begin
+ if (tempinfo^.temptype = tt_persistent) then
+ expectloc := LOC_CFPUREGISTER
+ else
+ expectloc := LOC_FPUREGISTER;
+ end
+ else
+ begin
+ if (tempinfo^.temptype = tt_persistent) then
+ expectloc := LOC_CREGISTER
+ else
+ expectloc := LOC_REGISTER;
+ end;
+ end;
+ result := nil;
+ end;
+
+ function ttemprefnode.det_resulttype: tnode;
+ begin
+ { check if the temp is already resulttype passed }
+ if not assigned(tempinfo^.restype.def) then
+ internalerror(200108233);
+ result := nil;
+ resulttype := tempinfo^.restype;
+ end;
+
+ function ttemprefnode.docompare(p: tnode): boolean;
+ begin
+ result :=
+ inherited docompare(p) and
+ (ttemprefnode(p).tempinfo = tempinfo) and
+ (ttemprefnode(p).offset = offset);
+ end;
+
+ procedure Ttemprefnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ procedure ttemprefnode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'temprestype = "',tempinfo^.restype.def.gettypename,'", tempinfo = $',hexstr(ptruint(tempinfo),sizeof(ptruint)*2));
+ end;
+
+
+{*****************************************************************************
+ TEMPDELETENODE
+*****************************************************************************}
+
+ constructor ttempdeletenode.create(const temp: ttempcreatenode);
+ begin
+ inherited create(tempdeleten);
+ tempinfo := temp.tempinfo;
+ release_to_normal := false;
+ end;
+
+
+ constructor ttempdeletenode.create_normal_temp(const temp: ttempcreatenode);
+ begin
+ inherited create(tempdeleten);
+ tempinfo := temp.tempinfo;
+ release_to_normal := true;
+ if tempinfo^.temptype <> tt_persistent then
+ internalerror(200204211);
+ end;
+
+
+ function ttempdeletenode._getcopy: tnode;
+ var
+ n: ttempdeletenode;
+ begin
+ n := ttempdeletenode(inherited _getcopy);
+ n.release_to_normal := release_to_normal;
+
+ if assigned(tempinfo^.hookoncopy) then
+ { if the temp has been copied, assume it becomes a new }
+ { temp which has to be hooked by the copied deletenode }
+ begin
+ { hook the tempdeletenode to the copied temp }
+ n.tempinfo := tempinfo^.hookoncopy;
+ { the temp shall not be used, reset hookoncopy }
+ { Only if release_to_normal is false, otherwise }
+ { the temp can still be referenced once more (JM) }
+ if (not release_to_normal) then
+ tempinfo^.hookoncopy:=nil
+ else
+ tempinfo^.nextref_set_hookoncopy_nil := true;
+ end
+ else
+ { if the temp we refer to hasn't been copied, we have a }
+ { problem since that means we now have two delete nodes }
+ { for one temp }
+ internalerror(200108234);
+ result := n;
+ end;
+
+ constructor ttempdeletenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ tempidx:=ppufile.getlongint;
+ release_to_normal:=(ppufile.getbyte<>0);
+ end;
+
+
+ procedure ttempdeletenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(tempinfo^.owner.ppuidx);
+ ppufile.putbyte(byte(release_to_normal));
+ end;
+
+
+ procedure ttempdeletenode.derefnode;
+ var
+ temp : ttempcreatenode;
+ begin
+ temp:=ttempcreatenode(nodeppuidxget(tempidx));
+ if temp.nodetype<>tempcreaten then
+ internalerror(200311075);
+ tempinfo:=temp.tempinfo;
+ end;
+
+
+ function ttempdeletenode.pass_1 : tnode;
+ begin
+ expectloc:=LOC_VOID;
+ result := nil;
+ end;
+
+ function ttempdeletenode.det_resulttype: tnode;
+ begin
+ result := nil;
+ resulttype := voidtype;
+ end;
+
+ function ttempdeletenode.docompare(p: tnode): boolean;
+ begin
+ result :=
+ inherited docompare(p) and
+ (ttemprefnode(p).tempinfo = tempinfo);
+ end;
+
+ destructor ttempdeletenode.destroy;
+ begin
+ dispose(tempinfo);
+ end;
+
+ procedure ttempdeletenode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'release_to_normal: ',release_to_normal,', temprestype = "',tempinfo^.restype.def.gettypename,'", tempinfo = $',hexstr(ptruint(tempinfo),sizeof(ptruint)*2));
+ end;
+
+begin
+ cnothingnode:=tnothingnode;
+ cerrornode:=terrornode;
+ casmnode:=tasmnode;
+ cstatementnode:=tstatementnode;
+ cblocknode:=tblocknode;
+ ctempcreatenode:=ttempcreatenode;
+ ctemprefnode:=ttemprefnode;
+ ctempdeletenode:=ttempdeletenode;
+end.
diff --git a/compiler/ncal.pas b/compiler/ncal.pas
new file mode 100644
index 0000000000..4ea78a5d43
--- /dev/null
+++ b/compiler/ncal.pas
@@ -0,0 +1,2560 @@
+{
+ This file implements the node for sub procedure calling.
+
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ 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 ncal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,
+ paramgr,parabase,
+ node,nbas,nutils,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif state_tracking}
+ symbase,symtype,symsym,symdef,symtable;
+
+ type
+ tcallnodeflag = (
+ cnf_restypeset,
+ cnf_return_value_used,
+ cnf_inherited,
+ cnf_anon_inherited,
+ cnf_new_call,
+ cnf_dispose_call,
+ cnf_member_call, { called with implicit methodpointer tree }
+ cnf_uses_varargs { varargs are used in the declaration }
+ );
+ tcallnodeflags = set of tcallnodeflag;
+
+ tcallnode = class(tbinarynode)
+ private
+ { info for inlining }
+ inlinelocals: TList;
+ { number of parameters passed from the source, this does not include the hidden parameters }
+ paralength : smallint;
+ function gen_self_tree_methodpointer:tnode;
+ function gen_self_tree:tnode;
+ function gen_vmt_tree:tnode;
+ procedure bind_parasym;
+
+ { function return node, this is used to pass the data for a
+ ret_in_param return value }
+ _funcretnode : tnode;
+ procedure setfuncretnode(const returnnode: tnode);
+ procedure convert_carg_array_of_const;
+ procedure order_parameters;
+
+ procedure createinlineparas(var createstatement, deletestatement: tstatementnode);
+ function replaceparaload(var n: tnode; arg: pointer): foreachnoderesult;
+ procedure createlocaltemps(p:TNamedIndexItem;arg:pointer);
+ function pass1_inline:tnode;
+ protected
+ pushedparasize : longint;
+ public
+ { the symbol containing the definition of the procedure }
+ { to call }
+ symtableprocentry : tprocsym;
+ symtableprocentryderef : tderef;
+ { symtable where the entry was found, needed for with support }
+ symtableproc : tsymtable;
+ { the definition of the procedure to call }
+ procdefinition : tabstractprocdef;
+ procdefinitionderef : tderef;
+ { tree that contains the pointer to the object for this method }
+ methodpointerinit,
+ methodpointerdone : tblocknode;
+ methodpointer : tnode;
+ { varargs parasyms }
+ varargsparas : tvarargsparalist;
+ { node that specifies where the result should be put for calls }
+ { that return their result in a parameter }
+ property funcretnode: tnode read _funcretnode write setfuncretnode;
+
+
+ { separately specified resulttype for some compilerprocs (e.g. }
+ { you can't have a function with an "array of char" resulttype }
+ { the RTL) (JM) }
+ restype: ttype;
+ callnodeflags : tcallnodeflags;
+
+ { only the processor specific nodes need to override this }
+ { constructor }
+ constructor create(l:tnode; v : tprocsym;st : tsymtable; mp: tnode; callflags:tcallnodeflags);virtual;
+ constructor create_procvar(l,r:tnode);
+ constructor createintern(const name: string; params: tnode);
+ constructor createinternres(const name: string; params: tnode; const res: ttype);
+ constructor createinternreturn(const name: string; params: tnode; returnnode : tnode);
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ { Goes through all symbols in a class and subclasses and calls
+ verify abstract for each .
+ }
+ procedure verifyabstractcalls;
+ { called for each definition in a class and verifies if a method
+ is abstract or not, if it is abstract, give out a warning
+ }
+ procedure verifyabstract(p : tnamedindexitem;arg:pointer);
+ procedure insertintolist(l : tnodelist);override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ {$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+ {$endif state_tracking}
+ function docompare(p: tnode): boolean; override;
+ procedure printnodedata(var t:text);override;
+ function para_count:longint;
+ function get_load_methodpointer:tnode;
+ private
+ AbstractMethodsList : TStringList;
+ end;
+ tcallnodeclass = class of tcallnode;
+
+ tcallparaflag = (
+ cpf_is_colon_para,
+ cpf_varargs_para { belongs this para to varargs }
+ );
+ tcallparaflags = set of tcallparaflag;
+
+ tcallparanode = class(tbinarynode)
+ public
+ callparaflags : tcallparaflags;
+ parasym : tparavarsym;
+ used_by_callnode : boolean;
+ { only the processor specific nodes need to override this }
+ { constructor }
+ constructor create(expr,next : tnode);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function _getcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure get_paratype;
+ procedure insert_typeconv(do_count : boolean);
+ procedure det_registers;
+ procedure firstcallparan;
+ procedure secondcallparan;virtual;abstract;
+ function docompare(p: tnode): boolean; override;
+ procedure printnodetree(var t:text);override;
+ end;
+ tcallparanodeclass = class of tcallparanode;
+
+ function reverseparameters(p: tcallparanode): tcallparanode;
+
+ var
+ ccallnode : tcallnodeclass;
+ ccallparanode : tcallparanodeclass;
+
+ { Current callnode, this is needed for having a link
+ between the callparanodes and the callnode they belong to }
+ aktcallnode : tcallnode;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,
+ symconst,defutil,defcmp,
+ htypechk,pass_1,
+ ncnv,nld,ninl,nadd,ncon,nmem,
+ procinfo,
+ cgbase
+ ;
+
+type
+ tobjectinfoitem = class(tlinkedlistitem)
+ objinfo : tobjectdef;
+ constructor create(def : tobjectdef);
+ end;
+
+
+{****************************************************************************
+ HELPERS
+ ****************************************************************************}
+
+ function reverseparameters(p: tcallparanode): tcallparanode;
+ var
+ hp1, hp2: tcallparanode;
+ begin
+ hp1:=nil;
+ while assigned(p) do
+ begin
+ { pull out }
+ hp2:=p;
+ p:=tcallparanode(p.right);
+ { pull in }
+ hp2.right:=hp1;
+ hp1:=hp2;
+ end;
+ reverseparameters:=hp1;
+ end;
+
+
+ procedure maybe_load_para_in_temp(var p:tnode);
+
+ function is_simple_node(hp:tnode):boolean;
+ begin
+ is_simple_node:=(hp.nodetype in [typen,loadvmtaddrn,loadn,arrayconstructorn]);
+ end;
+
+ var
+ hp,
+ loadp,
+ refp : tnode;
+ htype : ttype;
+ ptemp : ttempcreatenode;
+ usederef : boolean;
+ newinitstatement,
+ newdonestatement : tstatementnode;
+ begin
+ if not assigned(aktcallnode) then
+ internalerror(200410121);
+
+ { Load all complex loads into a temp to prevent
+ double calls to a function. We can't simply check for a hp.nodetype=calln
+ }
+ hp:=p;
+ while assigned(hp) and
+ (hp.nodetype=typeconvn) and
+ (ttypeconvnode(hp).convtype=tc_equal) do
+ hp:=tunarynode(hp).left;
+ if assigned(hp) and
+ not is_simple_node(hp) then
+ begin
+ if not assigned(aktcallnode.methodpointerinit) then
+ begin
+ aktcallnode.methodpointerinit:=internalstatements(newinitstatement);
+ aktcallnode.methodpointerdone:=internalstatements(newdonestatement);
+ end
+ else
+ begin
+ newinitstatement:=laststatement(aktcallnode.methodpointerinit);
+ newdonestatement:=laststatement(aktcallnode.methodpointerdone);
+ end;
+ { temp create }
+ usederef:=(p.resulttype.def.deftype in [arraydef,recorddef]) or
+ is_shortstring(p.resulttype.def) or
+ is_object(p.resulttype.def);
+ if usederef then
+ htype.setdef(tpointerdef.create(p.resulttype))
+ else
+ htype:=p.resulttype;
+ ptemp:=ctempcreatenode.create(htype,htype.def.size,tt_persistent,true);
+ if usederef then
+ begin
+ loadp:=caddrnode.create_internal(p);
+ refp:=cderefnode.create(ctemprefnode.create(ptemp));
+ end
+ else
+ begin
+ loadp:=p;
+ refp:=ctemprefnode.create(ptemp);
+ end;
+ addstatement(newinitstatement,ptemp);
+ addstatement(newinitstatement,cassignmentnode.create(
+ ctemprefnode.create(ptemp),
+ loadp));
+ { new tree is only a temp reference }
+ p:=refp;
+ { temp release. We need to return a reference to the methodpointer
+ otherwise the conversion from callnode to loadnode can't be done
+ for the methodpointer unless the loadnode will also get a methodpointerinit and
+ methodpointerdone node. For the moment we use register as temp and therefor
+ don't create a temp-leak in the stackframe (PFV) }
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newdonestatement,ctempdeletenode.create_normal_temp(ptemp));
+ addstatement(newdonestatement,ctemprefnode.create(ptemp));
+ { call resulttypepass for new nodes }
+ resulttypepass(p);
+ resulttypepass(aktcallnode.methodpointerinit);
+ resulttypepass(aktcallnode.methodpointerdone);
+ end;
+ end;
+
+
+ function gen_high_tree(var p:tnode;paradef:tdef):tnode;
+ var
+ temp: tnode;
+ len : integer;
+ loadconst : boolean;
+ hightree : tnode;
+ begin
+ len:=-1;
+ loadconst:=true;
+ hightree:=nil;
+ case p.resulttype.def.deftype of
+ arraydef :
+ begin
+ if (paradef.deftype<>arraydef) then
+ internalerror(200405241);
+ { passing a string to an array of char }
+ if (p.nodetype=stringconstn) then
+ begin
+ len:=str_length(p);
+ if len>0 then
+ dec(len);
+ end
+ else
+ { handle special case of passing an single array to an array of array }
+ if compare_defs(tarraydef(paradef).elementtype.def,p.resulttype.def,nothingn)>=te_equal then
+ len:=0
+ else
+ begin
+ { handle via a normal inline in_high_x node }
+ loadconst:=false;
+ { slice? }
+ if (p.nodetype=inlinen) and (tinlinenode(p).inlinenumber=in_slice_x) then
+ begin
+ hightree:=tcallparanode(tcallparanode(tinlinenode(p).left).right).left;
+ hightree:=caddnode.create(subn,hightree,genintconstnode(1));
+ tcallparanode(tcallparanode(tinlinenode(p).left).right).left:=nil;
+
+ temp:=p;
+ p:=tcallparanode(tinlinenode(p).left).left;
+ tcallparanode(tinlinenode(temp).left).left:=nil;
+ temp.free;
+
+ resulttypepass(hightree);
+ end
+ else
+ begin
+ maybe_load_para_in_temp(p);
+ hightree:=geninlinenode(in_high_x,false,p.getcopy);
+ resulttypepass(hightree);
+ { only substract low(array) if it's <> 0 }
+ temp:=geninlinenode(in_low_x,false,p.getcopy);
+ resulttypepass(temp);
+ if (temp.nodetype <> ordconstn) or
+ (tordconstnode(temp).value <> 0) then
+ hightree := caddnode.create(subn,hightree,temp)
+ else
+ temp.free;
+ end;
+ end;
+ end;
+ stringdef :
+ begin
+ if is_open_string(paradef) then
+ begin
+ maybe_load_para_in_temp(p);
+ { handle via a normal inline in_high_x node }
+ loadconst := false;
+ hightree := geninlinenode(in_high_x,false,p.getcopy);
+ end
+ else
+ begin
+ { passing a string to an array of char }
+ if (p.nodetype=stringconstn) then
+ begin
+ len:=str_length(p);
+ if len>0 then
+ dec(len);
+ end
+ else
+ begin
+ maybe_load_para_in_temp(p);
+ hightree:=caddnode.create(subn,geninlinenode(in_length_x,false,p.getcopy),
+ cordconstnode.create(1,sinttype,false));
+ loadconst:=false;
+ end;
+ end;
+ end;
+ else
+ len:=0;
+ end;
+ if loadconst then
+ hightree:=cordconstnode.create(len,sinttype,true)
+ else
+ begin
+ if not assigned(hightree) then
+ internalerror(200304071);
+ { Need to use explicit, because it can also be a enum }
+ hightree:=ctypeconvnode.create_internal(hightree,sinttype);
+ end;
+ result:=hightree;
+ end;
+
+
+{****************************************************************************
+ TOBJECTINFOITEM
+ ****************************************************************************}
+
+ constructor tobjectinfoitem.create(def : tobjectdef);
+ begin
+ inherited create;
+ objinfo := def;
+ end;
+
+
+{****************************************************************************
+ TCALLPARANODE
+ ****************************************************************************}
+
+ constructor tcallparanode.create(expr,next : tnode);
+
+ begin
+ inherited create(callparan,expr,next);
+ if not assigned(expr) then
+ internalerror(200305091);
+ expr.fileinfo:=fileinfo;
+ callparaflags:=[];
+ end;
+
+ destructor tcallparanode.destroy;
+
+ begin
+ { When the node is used by callnode then
+ we don't destroy left, the callnode takes care of it }
+ if used_by_callnode then
+ left:=nil;
+ inherited destroy;
+ end;
+
+
+ constructor tcallparanode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getsmallset(callparaflags);
+ end;
+
+
+ procedure tcallparanode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putsmallset(callparaflags);
+ end;
+
+
+ function tcallparanode._getcopy : tnode;
+
+ var
+ n : tcallparanode;
+
+ begin
+ n:=tcallparanode(inherited _getcopy);
+ n.callparaflags:=callparaflags;
+ n.parasym:=parasym;
+ result:=n;
+ end;
+
+ procedure tcallparanode.insertintolist(l : tnodelist);
+
+ begin
+ end;
+
+
+ procedure tcallparanode.get_paratype;
+ var
+ old_array_constructor : boolean;
+ begin
+ inc(parsing_para_level);
+ if assigned(right) then
+ tcallparanode(right).get_paratype;
+ old_array_constructor:=allow_array_constructor;
+ allow_array_constructor:=true;
+ resulttypepass(left);
+ allow_array_constructor:=old_array_constructor;
+ if codegenerror then
+ resulttype:=generrortype
+ else
+ resulttype:=left.resulttype;
+ dec(parsing_para_level);
+ end;
+
+
+ procedure tcallparanode.insert_typeconv(do_count : boolean);
+ var
+ oldtype : ttype;
+ hp : tnode;
+{$ifdef extdebug}
+ store_count_ref : boolean;
+{$endif def extdebug}
+ begin
+ inc(parsing_para_level);
+
+{$ifdef extdebug}
+ if do_count then
+ begin
+ store_count_ref:=count_ref;
+ count_ref:=true;
+ end;
+{$endif def extdebug}
+ { Be sure to have the resulttype }
+ if not assigned(left.resulttype.def) then
+ resulttypepass(left);
+
+ if (left.nodetype<>nothingn) then
+ begin
+ { Convert tp procvars, this is needs to be done
+ here to make the change permanent. in the overload
+ choosing the changes are only made temporary }
+ if (left.resulttype.def.deftype=procvardef) and
+ (parasym.vartype.def.deftype<>procvardef) then
+ begin
+ if maybe_call_procvar(left,true) then
+ resulttype:=left.resulttype;
+ end;
+
+ { Remove implicitly inserted typecast to pointer for
+ @procvar in macpas }
+ if (m_mac_procvar in aktmodeswitches) and
+ (parasym.vartype.def.deftype=procvardef) and
+ (left.nodetype=typeconvn) and
+ is_voidpointer(left.resulttype.def) and
+ (ttypeconvnode(left).left.nodetype=typeconvn) and
+ (ttypeconvnode(ttypeconvnode(left).left).convtype=tc_proc_2_procvar) then
+ begin
+ hp:=left;
+ left:=ttypeconvnode(left).left;
+ ttypeconvnode(hp).left:=nil;
+ hp.free;
+ end;
+
+ { Handle varargs and hidden paras directly, no typeconvs or }
+ { typechecking needed }
+ if (cpf_varargs_para in callparaflags) then
+ begin
+ { convert pascal to C types }
+ case left.resulttype.def.deftype of
+ stringdef :
+ inserttypeconv(left,charpointertype);
+ floatdef :
+ inserttypeconv(left,s64floattype);
+ end;
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ resulttype:=left.resulttype;
+ { also update parasym type to get the correct parameter location
+ for the new types }
+ parasym.vartype:=left.resulttype;
+ end
+ else
+ if (vo_is_hidden_para in parasym.varoptions) then
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ resulttype:=left.resulttype;
+ end
+ else
+ begin
+
+ { Do we need arrayconstructor -> set conversion, then insert
+ it here before the arrayconstructor node breaks the tree
+ with its conversions of enum->ord }
+ if (left.nodetype=arrayconstructorn) and
+ (parasym.vartype.def.deftype=setdef) then
+ inserttypeconv(left,parasym.vartype);
+
+ { set some settings needed for arrayconstructor }
+ if is_array_constructor(left.resulttype.def) then
+ begin
+ if left.nodetype<>arrayconstructorn then
+ internalerror(200504041);
+ if is_array_of_const(parasym.vartype.def) then
+ begin
+ { force variant array }
+ include(left.flags,nf_forcevaria);
+ end
+ else
+ begin
+ include(left.flags,nf_novariaallowed);
+ { now that the resultting type is know we can insert the required
+ typeconvs for the array constructor }
+ if parasym.vartype.def.deftype=arraydef then
+ tarrayconstructornode(left).force_type(tarraydef(parasym.vartype.def).elementtype);
+ end;
+ end;
+
+ { check if local proc/func is assigned to procvar }
+ if left.resulttype.def.deftype=procvardef then
+ test_local_to_procvar(tprocvardef(left.resulttype.def),parasym.vartype.def);
+
+ { test conversions }
+ if not(is_shortstring(left.resulttype.def) and
+ is_shortstring(parasym.vartype.def)) and
+ (parasym.vartype.def.deftype<>formaldef) then
+ begin
+ { Process open parameters }
+ if paramanager.push_high_param(parasym.varspez,parasym.vartype.def,aktcallnode.procdefinition.proccalloption) then
+ begin
+ { insert type conv but hold the ranges of the array }
+ oldtype:=left.resulttype;
+ inserttypeconv(left,parasym.vartype);
+ left.resulttype:=oldtype;
+ end
+ else
+ begin
+ { for ordinals, floats and enums, verify if we might cause
+ some range-check errors. }
+ if (parasym.vartype.def.deftype in [enumdef,orddef,floatdef]) and
+ (left.resulttype.def.deftype in [enumdef,orddef,floatdef]) and
+ (left.nodetype in [vecn,loadn,calln]) then
+ begin
+ if (left.resulttype.def.size>parasym.vartype.def.size) then
+ begin
+ if (cs_check_range in aktlocalswitches) then
+ Message(type_w_smaller_possible_range_check)
+ else
+ Message(type_h_smaller_possible_range_check);
+ end;
+ end;
+ inserttypeconv(left,parasym.vartype);
+ end;
+ if codegenerror then
+ begin
+ dec(parsing_para_level);
+ exit;
+ end;
+ end;
+
+ { check var strings }
+ if (cs_strict_var_strings in aktlocalswitches) and
+ is_shortstring(left.resulttype.def) and
+ is_shortstring(parasym.vartype.def) and
+ (parasym.varspez in [vs_out,vs_var]) and
+ not(is_open_string(parasym.vartype.def)) and
+ not(equal_defs(left.resulttype.def,parasym.vartype.def)) then
+ begin
+ aktfilepos:=left.fileinfo;
+ CGMessage(type_e_strict_var_string_violation);
+ end;
+
+ { Handle formal parameters separate }
+ if (parasym.vartype.def.deftype=formaldef) then
+ begin
+ { load procvar if a procedure is passed }
+ if ((m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches)) and
+ (left.nodetype=calln) and
+ (is_void(left.resulttype.def)) then
+ load_procvar_from_calln(left);
+
+ case parasym.varspez of
+ vs_var,
+ vs_out :
+ begin
+ if not valid_for_formal_var(left) then
+ CGMessagePos(left.fileinfo,parser_e_illegal_parameter_list);
+ end;
+ vs_const :
+ begin
+ if not valid_for_formal_const(left) then
+ CGMessagePos(left.fileinfo,parser_e_illegal_parameter_list);
+ end;
+ end;
+ end
+ else
+ begin
+ { check if the argument is allowed }
+ if (parasym.varspez in [vs_out,vs_var]) then
+ valid_for_var(left);
+ end;
+
+ if parasym.varspez = vs_var then
+ set_unique(left);
+
+ { When the address needs to be pushed then the register is
+ not regable. Exception is when the location is also a var
+ parameter and we can pass the address transparently }
+ if (
+ not(
+ (vo_is_hidden_para in parasym.varoptions) and
+ (left.resulttype.def.deftype in [pointerdef,classrefdef])
+ ) and
+ paramanager.push_addr_param(parasym.varspez,parasym.vartype.def,
+ aktcallnode.procdefinition.proccalloption) and
+ not(
+ (left.nodetype=loadn) and
+ (tloadnode(left).is_addr_param_load)
+ )
+ ) then
+ make_not_regable(left);
+
+ if do_count then
+ begin
+ case parasym.varspez of
+ vs_out :
+ set_varstate(left,vs_used,[]);
+ vs_var :
+ set_varstate(left,vs_used,[vsf_must_be_valid,vsf_use_hints]);
+ else
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ end;
+ end;
+ { must only be done after typeconv PM }
+ resulttype:=parasym.vartype;
+ end;
+ end;
+
+ { process next node }
+ if assigned(right) then
+ tcallparanode(right).insert_typeconv(do_count);
+
+ dec(parsing_para_level);
+{$ifdef extdebug}
+ if do_count then
+ count_ref:=store_count_ref;
+{$endif def extdebug}
+ end;
+
+
+ procedure tcallparanode.det_registers;
+ begin
+ if assigned(right) then
+ begin
+ tcallparanode(right).det_registers;
+
+ registersint:=right.registersint;
+ registersfpu:=right.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=right.registersmmx;
+{$endif}
+ end;
+
+ firstpass(left);
+
+ if left.registersint>registersint then
+ registersint:=left.registersint;
+ if left.registersfpu>registersfpu then
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if left.registersmmx>registersmmx then
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+
+ procedure tcallparanode.firstcallparan;
+ begin
+ if not assigned(left.resulttype.def) then
+ get_paratype;
+ det_registers;
+ end;
+
+
+ function tcallparanode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (callparaflags = tcallparanode(p).callparaflags)
+ ;
+ end;
+
+
+ procedure tcallparanode.printnodetree(var t:text);
+ begin
+ printnodelist(t);
+ end;
+
+
+{****************************************************************************
+ TCALLNODE
+ ****************************************************************************}
+
+ constructor tcallnode.create(l:tnode;v : tprocsym;st : tsymtable; mp: tnode; callflags:tcallnodeflags);
+ begin
+ inherited create(calln,l,nil);
+ symtableprocentry:=v;
+ symtableproc:=st;
+ callnodeflags:=callflags+[cnf_return_value_used];
+ methodpointer:=mp;
+ methodpointerinit:=nil;
+ methodpointerdone:=nil;
+ procdefinition:=nil;
+ _funcretnode:=nil;
+ paralength:=-1;
+ varargsparas:=nil;
+ end;
+
+
+ constructor tcallnode.create_procvar(l,r:tnode);
+ begin
+ inherited create(calln,l,r);
+ symtableprocentry:=nil;
+ symtableproc:=nil;
+ methodpointer:=nil;
+ methodpointerinit:=nil;
+ methodpointerdone:=nil;
+ procdefinition:=nil;
+ callnodeflags:=[cnf_return_value_used];
+ _funcretnode:=nil;
+ paralength:=-1;
+ varargsparas:=nil;
+ end;
+
+
+ constructor tcallnode.createintern(const name: string; params: tnode);
+ var
+ srsym: tsym;
+ symowner: tsymtable;
+ begin
+ if not (cs_compilesystem in aktmoduleswitches) then
+ begin
+ srsym := searchsymonlyin(systemunit,name);
+ symowner := systemunit;
+ end
+ else
+ begin
+ searchsym(name,srsym,symowner);
+ if not assigned(srsym) then
+ searchsym(upper(name),srsym,symowner);
+ end;
+ if not assigned(srsym) or
+ (srsym.typ<>procsym) then
+ Message1(cg_f_unknown_compilerproc,name);
+ self.create(params,tprocsym(srsym),symowner,nil,[]);
+ end;
+
+
+ constructor tcallnode.createinternres(const name: string; params: tnode; const res: ttype);
+ begin
+ self.createintern(name,params);
+ restype := res;
+ include(callnodeflags,cnf_restypeset);
+ { both the normal and specified resulttype either have to be returned via a }
+ { parameter or not, but no mixing (JM) }
+ if paramanager.ret_in_param(restype.def,symtableprocentry.first_procdef.proccalloption) xor
+ paramanager.ret_in_param(symtableprocentry.first_procdef.rettype.def,symtableprocentry.first_procdef.proccalloption) then
+ internalerror(200108291);
+ end;
+
+
+ constructor tcallnode.createinternreturn(const name: string; params: tnode; returnnode : tnode);
+ begin
+ self.createintern(name,params);
+ _funcretnode:=returnnode;
+ if not paramanager.ret_in_param(symtableprocentry.first_procdef.rettype.def,symtableprocentry.first_procdef.proccalloption) then
+ internalerror(200204247);
+ end;
+
+
+ procedure tcallnode.setfuncretnode(const returnnode: tnode);
+ var
+ para: tcallparanode;
+ begin
+ if assigned(_funcretnode) then
+ _funcretnode.free;
+ _funcretnode := returnnode;
+ { if the resulttype pass hasn't occurred yet, that one will do }
+ { everything }
+ if assigned(resulttype.def) then
+ begin
+ { these are returned as values, but we can optimize their loading }
+ { as well }
+ if is_ansistring(resulttype.def) or
+ is_widestring(resulttype.def) then
+ exit;
+ para := tcallparanode(left);
+ while assigned(para) do
+ begin
+ if (vo_is_hidden_para in para.parasym.varoptions) and
+ (vo_is_funcret in tparavarsym(para.parasym).varoptions) then
+ begin
+ para.left.free;
+ para.left := _funcretnode.getcopy;
+ exit;
+ end;
+ para := tcallparanode(para.right);
+ end;
+ { no hidden resultpara found, error! }
+ if not(po_inline in procdefinition.procoptions) then
+ internalerror(200306087);
+ end;
+ end;
+
+
+ destructor tcallnode.destroy;
+ var
+ i : longint;
+ begin
+ methodpointer.free;
+ methodpointerinit.free;
+ methodpointerdone.free;
+ _funcretnode.free;
+ if assigned(varargsparas) then
+ begin
+ for i:=0 to varargsparas.count-1 do
+ tparavarsym(varargsparas[i]).free;
+ varargsparas.free;
+ end;
+ inherited destroy;
+ end;
+
+
+ constructor tcallnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(symtableprocentryderef);
+{$ifdef fpc}
+{$warning FIXME: No withsymtable support}
+{$endif}
+ symtableproc:=nil;
+ ppufile.getderef(procdefinitionderef);
+ ppufile.getsmallset(callnodeflags);
+ methodpointer:=ppuloadnode(ppufile);
+ methodpointerinit:=tblocknode(ppuloadnode(ppufile));
+ methodpointerdone:=tblocknode(ppuloadnode(ppufile));
+ _funcretnode:=ppuloadnode(ppufile);
+ end;
+
+
+ procedure tcallnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(symtableprocentryderef);
+ ppufile.putderef(procdefinitionderef);
+ ppufile.putsmallset(callnodeflags);
+ ppuwritenode(ppufile,methodpointer);
+ ppuwritenode(ppufile,methodpointerinit);
+ ppuwritenode(ppufile,methodpointerdone);
+ ppuwritenode(ppufile,_funcretnode);
+ end;
+
+
+ procedure tcallnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ symtableprocentryderef.build(symtableprocentry);
+ procdefinitionderef.build(procdefinition);
+ if assigned(methodpointer) then
+ methodpointer.buildderefimpl;
+ if assigned(methodpointerinit) then
+ methodpointerinit.buildderefimpl;
+ if assigned(methodpointerdone) then
+ methodpointerdone.buildderefimpl;
+ if assigned(_funcretnode) then
+ _funcretnode.buildderefimpl;
+ end;
+
+
+ procedure tcallnode.derefimpl;
+ var
+ pt : tcallparanode;
+ i : integer;
+ begin
+ inherited derefimpl;
+ symtableprocentry:=tprocsym(symtableprocentryderef.resolve);
+ if assigned(symtableprocentry) then
+ symtableproc:=symtableprocentry.owner;
+ procdefinition:=tabstractprocdef(procdefinitionderef.resolve);
+ if assigned(methodpointer) then
+ methodpointer.derefimpl;
+ if assigned(methodpointerinit) then
+ methodpointerinit.derefimpl;
+ if assigned(methodpointerdone) then
+ methodpointerdone.derefimpl;
+ if assigned(_funcretnode) then
+ _funcretnode.derefimpl;
+ { Connect parasyms }
+ pt:=tcallparanode(left);
+ while assigned(pt) and
+ (cpf_varargs_para in pt.callparaflags) do
+ pt:=tcallparanode(pt.right);
+ for i:=procdefinition.paras.count-1 downto 0 do
+ begin
+ if not assigned(pt) then
+ internalerror(200311077);
+ pt.parasym:=tparavarsym(procdefinition.paras[i]);
+ pt:=tcallparanode(pt.right);
+ end;
+ if assigned(pt) then
+ internalerror(200311078);
+ end;
+
+
+ function tcallnode._getcopy : tnode;
+ var
+ n : tcallnode;
+ i : integer;
+ hp,hpn : tparavarsym;
+ oldleft : tnode;
+ begin
+ { Need to use a hack here to prevent the parameters from being copied.
+ The parameters must be copied between methodpointerinit/methodpointerdone because
+ the can reference methodpointer }
+ oldleft:=left;
+ left:=nil;
+ n:=tcallnode(inherited _getcopy);
+ left:=oldleft;
+ n.symtableprocentry:=symtableprocentry;
+ n.symtableproc:=symtableproc;
+ n.procdefinition:=procdefinition;
+ n.restype := restype;
+ n.callnodeflags := callnodeflags;
+ if assigned(methodpointerinit) then
+ n.methodpointerinit:=tblocknode(methodpointerinit._getcopy)
+ else
+ n.methodpointerinit:=nil;
+ { methodpointerinit is copied, now references to the temp will also be copied
+ correctly. We can now copy the parameters and methodpointer }
+ if assigned(left) then
+ n.left:=left._getcopy
+ else
+ n.left:=nil;
+ if assigned(methodpointer) then
+ n.methodpointer:=methodpointer._getcopy
+ else
+ n.methodpointer:=nil;
+ if assigned(methodpointerdone) then
+ n.methodpointerdone:=tblocknode(methodpointerdone._getcopy)
+ else
+ n.methodpointerdone:=nil;
+ if assigned(_funcretnode) then
+ n._funcretnode:=_funcretnode._getcopy
+ else
+ n._funcretnode:=nil;
+
+ if assigned(varargsparas) then
+ begin
+ n.varargsparas:=tvarargsparalist.create;
+ for i:=0 to varargsparas.count-1 do
+ begin
+ hp:=tparavarsym(varargsparas[i]);
+ hpn:=tparavarsym.create(hp.realname,hp.paranr,hp.varspez,hp.vartype,[]);
+ n.varargsparas.add(hpn);
+ end;
+ end
+ else
+ n.varargsparas:=nil;
+ result:=n;
+ end;
+
+
+ procedure tcallnode.insertintolist(l : tnodelist);
+
+ begin
+ end;
+
+
+ procedure tcallnode.convert_carg_array_of_const;
+ var
+ hp : tarrayconstructornode;
+ oldleft : tcallparanode;
+ begin
+ oldleft:=tcallparanode(left);
+ if oldleft.left.nodetype<>arrayconstructorn then
+ begin
+ CGMessage1(type_e_wrong_type_in_array_constructor,oldleft.left.resulttype.def.typename);
+ exit;
+ end;
+ include(callnodeflags,cnf_uses_varargs);
+ { Get arrayconstructor node and insert typeconvs }
+ hp:=tarrayconstructornode(oldleft.left);
+ hp.insert_typeconvs;
+ { Add c args parameters }
+ { It could be an empty set }
+ if assigned(hp) and
+ assigned(hp.left) then
+ begin
+ while assigned(hp) do
+ begin
+ left:=ccallparanode.create(hp.left,left);
+ { set callparanode resulttype and flags }
+ left.resulttype:=hp.left.resulttype;
+ include(tcallparanode(left).callparaflags,cpf_varargs_para);
+ hp.left:=nil;
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ { Remove value of old array of const parameter, but keep it
+ in the list because it is required for bind_parasym.
+ Generate a nothign to keep callparanoed.left valid }
+ oldleft.left.free;
+ oldleft.left:=cnothingnode.create;
+ end;
+
+
+ procedure tcallnode.verifyabstract(p : tnamedindexitem;arg:pointer);
+
+ var
+ hp : tprocdef;
+ j: integer;
+ begin
+ if (tsym(p).typ=procsym) then
+ begin
+ for j:=1 to tprocsym(p).procdef_count do
+ begin
+ { index starts at 1 }
+ hp:=tprocsym(p).procdef[j];
+ { If this is an abstract method insert into the list }
+ if (po_abstractmethod in hp.procoptions) then
+ AbstractMethodsList.Insert(hp.procsym.realname)
+ else
+ { If this symbol is a virtual (includes override) method,
+ then remove it from the list }
+ if po_virtualmethod in hp.procoptions then
+ AbstractMethodsList.Remove(hp.procsym.realname);
+ end;
+ end;
+ end;
+
+
+ procedure tcallnode.verifyabstractcalls;
+ var
+ objectdf : tobjectdef;
+ parents : tlinkedlist;
+ objectinfo : tobjectinfoitem;
+ stritem : tstringlistitem;
+ begin
+ objectdf := nil;
+ { verify if trying to create an instance of a class which contains
+ non-implemented abstract methods }
+
+ { first verify this class type, no class than exit }
+ { also, this checking can only be done if the constructor is directly
+ called, indirect constructor calls cannot be checked.
+ }
+ if assigned(methodpointer) then
+ begin
+ if (methodpointer.resulttype.def.deftype = objectdef) then
+ objectdf:=tobjectdef(methodpointer.resulttype.def)
+ else
+ if (methodpointer.resulttype.def.deftype = classrefdef) and
+ (tclassrefdef(methodpointer.resulttype.def).pointertype.def.deftype = objectdef) and
+ (methodpointer.nodetype in [typen,loadvmtaddrn]) then
+ objectdf:=tobjectdef(tclassrefdef(methodpointer.resulttype.def).pointertype.def);
+ end;
+ if not assigned(objectdf) then
+ exit;
+
+ parents := tlinkedlist.create;
+ AbstractMethodsList := tstringlist.create;
+
+ { insert all parents in this class : the first item in the
+ list will be the base parent of the class .
+ }
+ while assigned(objectdf) do
+ begin
+ objectinfo:=tobjectinfoitem.create(objectdf);
+ parents.insert(objectinfo);
+ objectdf := objectdf.childof;
+ end;
+ { now all parents are in the correct order
+ insert all abstract methods in the list, and remove
+ those which are overriden by parent classes.
+ }
+ objectinfo:=tobjectinfoitem(parents.first);
+ while assigned(objectinfo) do
+ begin
+ objectdf := objectinfo.objinfo;
+ if assigned(objectdf.symtable) then
+ objectdf.symtable.foreach(@verifyabstract,nil);
+ objectinfo:=tobjectinfoitem(objectinfo.next);
+ end;
+ if assigned(parents) then
+ parents.free;
+ { Finally give out a warning for each abstract method still in the list }
+ stritem := tstringlistitem(AbstractMethodsList.first);
+ if assigned(stritem) then
+ Message1(type_w_instance_with_abstract,objectdf.objrealname^);
+ while assigned(stritem) do
+ begin
+ if assigned(stritem.fpstr) then
+ Message1(sym_h_param_list,stritem.str);
+ stritem := tstringlistitem(stritem.next);
+ end;
+ if assigned(AbstractMethodsList) then
+ AbstractMethodsList.Free;
+ end;
+
+
+ function tcallnode.gen_self_tree_methodpointer:tnode;
+ var
+ hsym : tfieldvarsym;
+ begin
+ { find self field in methodpointer record }
+ hsym:=tfieldvarsym(trecorddef(methodpointertype.def).symtable.search('self'));
+ if not assigned(hsym) then
+ internalerror(200305251);
+ { Load tmehodpointer(right).self }
+ result:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(right.getcopy,methodpointertype));
+ end;
+
+
+ function tcallnode.gen_self_tree:tnode;
+ var
+ selftree : tnode;
+ begin
+ selftree:=nil;
+
+ { inherited }
+ if (cnf_inherited in callnodeflags) then
+ selftree:=load_self_node
+ else
+ { constructors }
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ { push 0 as self when allocation is needed }
+ if (methodpointer.resulttype.def.deftype=classrefdef) or
+ (cnf_new_call in callnodeflags) then
+ selftree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ begin
+ if methodpointer.nodetype=typen then
+ selftree:=load_self_node
+ else
+ selftree:=methodpointer.getcopy;
+ end;
+ end
+ else
+ { Calling a static/class method }
+ if (po_classmethod in procdefinition.procoptions) or
+ (po_staticmethod in procdefinition.procoptions) then
+ begin
+ if (procdefinition.deftype<>procdef) then
+ internalerror(200305062);
+ if (oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
+ begin
+ { we only need the vmt, loading self is not required and there is no
+ need to check for typen, because that will always get the
+ loadvmtaddrnode added }
+ selftree:=methodpointer.getcopy;
+ if methodpointer.resulttype.def.deftype<>classrefdef then
+ selftree:=cloadvmtaddrnode.create(selftree);
+ end
+ else
+ selftree:=cpointerconstnode.create(0,voidpointertype);
+ end
+ else
+ begin
+ if methodpointer.nodetype=typen then
+ selftree:=load_self_node
+ else
+ selftree:=methodpointer.getcopy;
+ end;
+ result:=selftree;
+ end;
+
+
+ function tcallnode.gen_vmt_tree:tnode;
+ var
+ vmttree : tnode;
+ begin
+ vmttree:=nil;
+ if not(procdefinition.proctypeoption in [potype_constructor,potype_destructor]) then
+ internalerror(200305051);
+
+ { Handle classes and legacy objects separate to make it
+ more maintainable }
+ if (methodpointer.resulttype.def.deftype=classrefdef) then
+ begin
+ if not is_class(tclassrefdef(methodpointer.resulttype.def).pointertype.def) then
+ internalerror(200501041);
+
+ { constructor call via classreference => allocate memory }
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ vmttree:=methodpointer.getcopy;
+ { Only a typenode can be passed when it is called with <class of xx>.create }
+ if vmttree.nodetype=typen then
+ vmttree:=cloadvmtaddrnode.create(vmttree);
+ end
+ else
+ begin
+ { Call afterconstruction }
+ vmttree:=cpointerconstnode.create(1,voidpointertype);
+ end;
+ end
+ else
+ { Class style objects }
+ if is_class(methodpointer.resulttype.def) then
+ begin
+ { inherited call, no create/destroy }
+ if (cnf_inherited in callnodeflags) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ { do not create/destroy when called from member function
+ without specifying self explicit }
+ if (cnf_member_call in callnodeflags) then
+ begin
+ { destructor: don't release instance, vmt=0
+ constructor:
+ if called from a constructor in the same class then
+ don't call afterconstruction, vmt=0
+ else
+ call afterconstrution, vmt=1 }
+ if (procdefinition.proctypeoption=potype_destructor) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ begin
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+ (procdefinition.proctypeoption=potype_constructor) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ vmttree:=cpointerconstnode.create(1,voidpointertype);
+ end;
+ end
+ else
+ { normal call to method like cl1.proc }
+ begin
+ { destructor: release instance, vmt=1
+ constructor:
+ if called from a constructor in the same class using self.create then
+ don't call afterconstruction, vmt=0
+ else
+ call afterconstrution, vmt=1 }
+ if (procdefinition.proctypeoption=potype_destructor) then
+ vmttree:=cpointerconstnode.create(1,voidpointertype)
+ else
+ begin
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+ (procdefinition.proctypeoption=potype_constructor) and
+ (nf_is_self in methodpointer.flags) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ vmttree:=cpointerconstnode.create(1,voidpointertype);
+ end;
+ end;
+ end
+ else
+ { Old style object }
+ begin
+ { constructor with extended syntax called from new }
+ if (cnf_new_call in callnodeflags) then
+ vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resulttype))
+ else
+ { destructor with extended syntax called from dispose }
+ if (cnf_dispose_call in callnodeflags) then
+ vmttree:=cloadvmtaddrnode.create(methodpointer.getcopy)
+ else
+ { inherited call, no create/destroy }
+ if (cnf_inherited in callnodeflags) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ { do not create/destroy when called from member function
+ without specifying self explicit }
+ if (cnf_member_call in callnodeflags) then
+ begin
+ { destructor: don't release instance, vmt=0
+ constructor: don't initialize instance, vmt=0 }
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ end
+ else
+ { normal object call like obj.proc }
+ begin
+ { destructor: direct call, no dispose, vmt=0
+ constructor: initialize object, load vmt }
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ { old styled inherited call? }
+ if (methodpointer.nodetype=typen) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resulttype))
+ end
+ else
+ vmttree:=cpointerconstnode.create(0,voidpointertype);
+ end;
+ end;
+ result:=vmttree;
+ end;
+
+
+ procedure tcallnode.bind_parasym;
+ var
+ i : integer;
+ pt : tcallparanode;
+ oldppt : ^tcallparanode;
+ varargspara,
+ currpara : tparavarsym;
+ used_by_callnode : boolean;
+ hiddentree : tnode;
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ begin
+ pt:=tcallparanode(left);
+ oldppt:=@left;
+
+ { flag all callparanodes that belong to the varargs }
+ i:=paralength;
+ while (i>procdefinition.maxparacount) do
+ begin
+ include(pt.callparaflags,cpf_varargs_para);
+ oldppt:=@pt.right;
+ pt:=tcallparanode(pt.right);
+ dec(i);
+ end;
+
+ { skip varargs that are inserted by array of const }
+ while assigned(pt) and
+ (cpf_varargs_para in pt.callparaflags) do
+ pt:=tcallparanode(pt.right);
+
+ { process normal parameters and insert hidden parameters }
+ for i:=procdefinition.paras.count-1 downto 0 do
+ begin
+ currpara:=tparavarsym(procdefinition.paras[i]);
+ if vo_is_hidden_para in currpara.varoptions then
+ begin
+ { generate hidden tree }
+ used_by_callnode:=false;
+ hiddentree:=nil;
+ if (vo_is_funcret in currpara.varoptions) then
+ begin
+ { Generate funcretnode if not specified }
+ if assigned(funcretnode) then
+ begin
+ hiddentree:=funcretnode.getcopy;
+ end
+ else
+ begin
+ hiddentree:=internalstatements(newstatement);
+ { need to use resulttype instead of procdefinition.rettype,
+ because they can be different }
+ temp:=ctempcreatenode.create(resulttype,resulttype.def.size,tt_persistent,false);
+ addstatement(newstatement,temp);
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+ end;
+ end
+ else
+ if vo_is_high_para in currpara.varoptions then
+ begin
+ if not assigned(pt) or
+ (i=0) then
+ internalerror(200304082);
+ { we need the information of the previous parameter }
+ hiddentree:=gen_high_tree(pt.left,tparavarsym(procdefinition.paras[i-1]).vartype.def);
+ end
+ else
+ if vo_is_self in currpara.varoptions then
+ begin
+ if assigned(right) then
+ hiddentree:=gen_self_tree_methodpointer
+ else
+ hiddentree:=gen_self_tree;
+ end
+ else
+ if vo_is_vmt in currpara.varoptions then
+ begin
+ hiddentree:=gen_vmt_tree;
+ end
+{$ifdef powerpc}
+ else
+ if vo_is_syscall_lib in currpara.varoptions then
+ begin
+ { lib parameter has no special type but proccalloptions must be a syscall }
+ hiddentree:=cloadnode.create(tprocdef(procdefinition).libsym,tprocdef(procdefinition).libsym.owner);
+ end
+{$endif powerpc}
+ else
+ if vo_is_parentfp in currpara.varoptions then
+ begin
+ if not(assigned(procdefinition.owner.defowner)) then
+ internalerror(200309287);
+ hiddentree:=cloadparentfpnode.create(tprocdef(procdefinition.owner.defowner));
+ end;
+ { add the hidden parameter }
+ if not assigned(hiddentree) then
+ internalerror(200304073);
+ { Already insert para and let the previous node point to
+ this new node }
+ pt:=ccallparanode.create(hiddentree,oldppt^);
+ pt.used_by_callnode:=used_by_callnode;
+ oldppt^:=pt;
+ end;
+ if not assigned(pt) then
+ internalerror(200310052);
+ pt.parasym:=currpara;
+ oldppt:=@pt.right;
+ pt:=tcallparanode(pt.right);
+ end;
+
+
+ { Create parasyms for varargs, first count the number of varargs paras,
+ then insert the parameters with numbering in reverse order. The SortParas
+ will set the correct order at the end}
+ pt:=tcallparanode(left);
+ i:=0;
+ while assigned(pt) do
+ begin
+ if cpf_varargs_para in pt.callparaflags then
+ inc(i);
+ pt:=tcallparanode(pt.right);
+ end;
+ if (i>0) then
+ begin
+ varargsparas:=tvarargsparalist.create;
+ pt:=tcallparanode(left);
+ while assigned(pt) do
+ begin
+ if cpf_varargs_para in pt.callparaflags then
+ begin
+ varargspara:=tparavarsym.create('va'+tostr(i),i,vs_value,pt.resulttype,[]);
+ dec(i);
+ { varargspara is left-right, use insert
+ instead of concat }
+ varargsparas.add(varargspara);
+ pt.parasym:=varargspara;
+ end;
+ pt:=tcallparanode(pt.right);
+ end;
+ varargsparas.sortparas;
+ end;
+ end;
+
+
+ function tcallnode.det_resulttype:tnode;
+ var
+ candidates : tcallcandidates;
+ oldcallnode : tcallnode;
+ hpt : tnode;
+ pt : tcallparanode;
+ lastpara : longint;
+ paraidx,
+ cand_cnt : integer;
+ i : longint;
+ is_const : boolean;
+ label
+ errorexit;
+ begin
+ result:=nil;
+ candidates:=nil;
+
+ oldcallnode:=aktcallnode;
+ aktcallnode:=self;
+
+ { determine length of parameter list }
+ pt:=tcallparanode(left);
+ paralength:=0;
+ while assigned(pt) do
+ begin
+ inc(paralength);
+ pt:=tcallparanode(pt.right);
+ end;
+
+ { determine the type of the parameters }
+ if assigned(left) then
+ begin
+ tcallparanode(left).get_paratype;
+ if codegenerror then
+ goto errorexit;
+ end;
+
+ if assigned(methodpointer) then
+ begin
+ resulttypepass(methodpointer);
+ maybe_load_para_in_temp(methodpointer);
+ end;
+
+ { procedure variable ? }
+ if assigned(right) then
+ begin
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ resulttypepass(right);
+ if codegenerror then
+ exit;
+
+ procdefinition:=tabstractprocdef(right.resulttype.def);
+
+ { Compare parameters from right to left }
+ paraidx:=procdefinition.Paras.count-1;
+ { Skip default parameters }
+ if not(po_varargs in procdefinition.procoptions) then
+ begin
+ { ignore hidden parameters }
+ while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+ dec(paraidx);
+ for i:=1 to procdefinition.maxparacount-paralength do
+ begin
+ if paraidx<0 then
+ internalerror(200402261);
+ if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ goto errorexit;
+ end;
+ dec(paraidx);
+ end;
+ end;
+ while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+ dec(paraidx);
+ pt:=tcallparanode(left);
+ lastpara:=paralength;
+ while (paraidx>=0) and assigned(pt) do
+ begin
+ { only goto next para if we're out of the varargs }
+ if not(po_varargs in procdefinition.procoptions) or
+ (lastpara<=procdefinition.maxparacount) then
+ begin
+ repeat
+ dec(paraidx);
+ until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
+ end;
+ pt:=tcallparanode(pt.right);
+ dec(lastpara);
+ end;
+ if assigned(pt) or
+ ((paraidx>=0) and
+ not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)) then
+ begin
+ if assigned(pt) then
+ aktfilepos:=pt.fileinfo;
+ CGMessage(parser_e_wrong_parameter_size);
+ goto errorexit;
+ end;
+ end
+ else
+ { not a procedure variable }
+ begin
+ { do we know the procedure to call ? }
+ if not(assigned(procdefinition)) then
+ begin
+ candidates:=tcallcandidates.create(symtableprocentry,symtableproc,left,(nf_isproperty in flags),
+ { ignore possible private in delphi mode for anon. inherited (FK) }
+ (m_delphi in aktmodeswitches) and (cnf_anon_inherited in callnodeflags));
+
+ { no procedures found? then there is something wrong
+ with the parameter size or the procedures are
+ not accessible }
+ if candidates.count=0 then
+ begin
+ { when it's an auto inherited call and there
+ is no procedure found, but the procedures
+ were defined with overload directive and at
+ least two procedures are defined then we ignore
+ this inherited by inserting a nothingn. Only
+ do this ugly hack in Delphi mode as it looks more
+ like a bug. It's also not documented }
+ if (m_delphi in aktmodeswitches) and
+ (cnf_anon_inherited in callnodeflags) and
+ (symtableprocentry.owner.symtabletype=objectsymtable) and
+ (po_overload in symtableprocentry.first_procdef.procoptions) and
+ (symtableprocentry.procdef_count>=2) then
+ result:=cnothingnode.create
+ else
+ begin
+ { in tp mode we can try to convert to procvar if
+ there are no parameters specified. Only try it
+ when there is only one proc definition, else the
+ loadnode will give a strange error }
+ if not(assigned(left)) and
+ not(cnf_inherited in callnodeflags) and
+ ((m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches)) and
+ (symtableprocentry.procdef_count=1) then
+ begin
+ hpt:=cloadnode.create(tprocsym(symtableprocentry),symtableproc);
+ if assigned(methodpointer) then
+ tloadnode(hpt).set_mp(get_load_methodpointer);
+ resulttypepass(hpt);
+ result:=hpt;
+ end
+ else
+ begin
+ if assigned(left) then
+ aktfilepos:=left.fileinfo;
+ CGMessage(parser_e_wrong_parameter_size);
+ symtableprocentry.write_parameter_lists(nil);
+ end;
+ end;
+ goto errorexit;
+ end;
+
+ { Retrieve information about the candidates }
+ candidates.get_information;
+{$ifdef EXTDEBUG}
+ { Display info when multiple candidates are found }
+ if candidates.count>1 then
+ candidates.dump_info(V_Debug);
+{$endif EXTDEBUG}
+
+ { Choose the best candidate and count the number of
+ candidates left }
+ cand_cnt:=candidates.choose_best(procdefinition);
+
+ { All parameters are checked, check if there are any
+ procedures left }
+ if cand_cnt>0 then
+ begin
+ { Multiple candidates left? }
+ if cand_cnt>1 then
+ begin
+ CGMessage(type_e_cant_choose_overload_function);
+{$ifdef EXTDEBUG}
+ candidates.dump_info(V_Hint);
+{$else EXTDEBUG}
+ candidates.list(false);
+{$endif EXTDEBUG}
+ { we'll just use the first candidate to make the
+ call }
+ end;
+
+ { assign procdefinition }
+ if symtableproc=nil then
+ symtableproc:=procdefinition.owner;
+
+ { update browser information }
+ if make_ref then
+ begin
+ tprocdef(procdefinition).lastref:=tref.create(tprocdef(procdefinition).lastref,@fileinfo);
+ inc(tprocdef(procdefinition).refcount);
+ if tprocdef(procdefinition).defref=nil then
+ tprocdef(procdefinition).defref:=tprocdef(procdefinition).lastref;
+ end;
+ end
+ else
+ begin
+ { No candidates left, this must be a type error,
+ because wrong size is already checked. procdefinition
+ is filled with the first (random) definition that is
+ found. We use this definition to display a nice error
+ message that the wrong type is passed }
+ candidates.find_wrong_para;
+ candidates.list(true);
+{$ifdef EXTDEBUG}
+ candidates.dump_info(V_Hint);
+{$endif EXTDEBUG}
+
+ { We can not proceed, release all procs and exit }
+ candidates.free;
+ goto errorexit;
+ end;
+
+ candidates.free;
+ end; { end of procedure to call determination }
+ end;
+
+ { add needed default parameters }
+ if assigned(procdefinition) and
+ (paralength<procdefinition.maxparacount) then
+ begin
+ paraidx:=0;
+ i:=0;
+ while (i<paralength) do
+ begin
+ if paraidx>=procdefinition.Paras.count then
+ internalerror(200306181);
+ if not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) then
+ inc(i);
+ inc(paraidx);
+ end;
+ while (paraidx<procdefinition.paras.count) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+ inc(paraidx);
+ while (paraidx<procdefinition.paras.count) do
+ begin
+ if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
+ internalerror(200212142);
+ left:=ccallparanode.create(genconstsymtree(
+ tconstsym(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)),left);
+ { Ignore vs_hidden parameters }
+ repeat
+ inc(paraidx);
+ until (paraidx>=procdefinition.paras.count) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
+ end;
+ end;
+
+ { handle predefined procedures }
+ is_const:=(po_internconst in procdefinition.procoptions) and
+ ((block_type in [bt_const,bt_type]) or
+ (assigned(left) and (tcallparanode(left).left.nodetype in [realconstn,ordconstn])));
+ if (procdefinition.proccalloption=pocall_internproc) or is_const then
+ begin
+ if assigned(left) then
+ begin
+ { ptr and settextbuf needs two args }
+ if assigned(tcallparanode(left).right) then
+ begin
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,left);
+ left:=nil;
+ end
+ else
+ begin
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,tcallparanode(left).left);
+ tcallparanode(left).left:=nil;
+ end;
+ end
+ else
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,nil);
+ result:=hpt;
+ goto errorexit;
+ end;
+
+ { ensure that the result type is set }
+ if not(cnf_restypeset in callnodeflags) then
+ begin
+ { constructors return their current class type, not the type where the
+ constructor is declared, this can be different because of inheritance }
+ if (procdefinition.proctypeoption=potype_constructor) and
+ assigned(methodpointer) and
+ assigned(methodpointer.resulttype.def) and
+ (methodpointer.resulttype.def.deftype=classrefdef) then
+ resulttype:=tclassrefdef(methodpointer.resulttype.def).pointertype
+ else
+ { Member call to a (inherited) constructor from the class, the return
+ value is always self, so we change it to voidtype to generate an
+ error and to prevent users from generating non-working code
+ when they expect to clone the current instance, see bug 3662 (PFV) }
+ if (procdefinition.proctypeoption=potype_constructor) and
+ is_class(tprocdef(procdefinition)._class) and
+ assigned(methodpointer) and
+ (nf_is_self in methodpointer.flags) then
+ resulttype:=voidtype
+ else
+ resulttype:=procdefinition.rettype;
+ end
+ else
+ resulttype:=restype;
+
+ {if resulttype.def.needs_inittable then
+ include(current_procinfo.flags,pi_needs_implicit_finally);}
+
+ if assigned(methodpointer) then
+ begin
+ { when methodpointer is a callnode we must load it first into a
+ temp to prevent the processing callnode twice }
+ if (methodpointer.nodetype=calln) then
+ internalerror(200405121);
+
+ { direct call to inherited abstract method, then we
+ can already give a error in the compiler instead
+ of a runtime error }
+ if (cnf_inherited in callnodeflags) and
+ (po_abstractmethod in procdefinition.procoptions) then
+ CGMessage(cg_e_cant_call_abstract_method);
+
+ { if an inherited con- or destructor should be }
+ { called in a con- or destructor then a warning }
+ { will be made }
+ { con- and destructors need a pointer to the vmt }
+ if (cnf_inherited in callnodeflags) and
+ (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and
+ is_object(methodpointer.resulttype.def) and
+ not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then
+ CGMessage(cg_w_member_cd_call_from_method);
+
+ if methodpointer.nodetype<>typen then
+ begin
+ { Remove all postfix operators }
+ hpt:=methodpointer;
+ while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
+ hpt:=tunarynode(hpt).left;
+
+ if (procdefinition.proctypeoption=potype_constructor) and
+ assigned(symtableproc) and
+ (symtableproc.symtabletype=withsymtable) and
+ (tnode(twithsymtable(symtableproc).withrefnode).nodetype=temprefn) then
+ CGmessage(cg_e_cannot_call_cons_dest_inside_with);
+
+ { R.Init then R will be initialized by the constructor,
+ Also allow it for simple loads }
+ if (procdefinition.proctypeoption=potype_constructor) or
+ ((hpt.nodetype=loadn) and
+ (
+ (methodpointer.resulttype.def.deftype=classrefdef) or
+ (
+ (methodpointer.resulttype.def.deftype=objectdef) and
+ not(oo_has_virtual in tobjectdef(methodpointer.resulttype.def).objectoptions)
+ )
+ )
+ ) then
+ set_varstate(methodpointer,vs_used,[])
+ else
+ set_varstate(methodpointer,vs_used,[vsf_must_be_valid]);
+
+ { The object is already used if it is called once }
+ if (hpt.nodetype=loadn) and
+ (tloadnode(hpt).symtableentry.typ in [localvarsym,paravarsym,globalvarsym]) then
+ tabstractvarsym(tloadnode(hpt).symtableentry).varstate:=vs_used;
+ end;
+
+ { if we are calling the constructor check for abstract
+ methods. Ignore inherited and member calls, because the
+ class is then already created }
+ if (procdefinition.proctypeoption=potype_constructor) and
+ not(cnf_inherited in callnodeflags) and
+ not(cnf_member_call in callnodeflags) then
+ verifyabstractcalls;
+ end
+ else
+ begin
+ { When this is method the methodpointer must be available }
+ if (right=nil) and
+ (procdefinition.owner.symtabletype=objectsymtable) then
+ internalerror(200305061);
+ end;
+
+ { Set flag that the procedure uses varargs, also if they are not passed it is still
+ needed for x86_64 to pass the number of SSE registers used }
+ if po_varargs in procdefinition.procoptions then
+ include(callnodeflags,cnf_uses_varargs);
+
+ { Change loading of array of const to varargs }
+ if assigned(left) and
+ is_array_of_const(tparavarsym(procdefinition.paras[procdefinition.paras.count-1]).vartype.def) and
+ (procdefinition.proccalloption in [pocall_cppdecl,pocall_cdecl]) then
+ convert_carg_array_of_const;
+
+ { bind parasyms to the callparanodes and insert hidden parameters }
+ bind_parasym;
+
+ { insert type conversions for parameters }
+ if assigned(left) then
+ tcallparanode(left).insert_typeconv(true);
+
+ errorexit:
+ aktcallnode:=oldcallnode;
+ end;
+
+
+ procedure tcallnode.order_parameters;
+ var
+ hp,hpcurr,hpnext,hpfirst,hpprev : tcallparanode;
+ currloc : tcgloc;
+ begin
+ hpfirst:=nil;
+ hpcurr:=tcallparanode(left);
+ while assigned(hpcurr) do
+ begin
+ { pull out }
+ hpnext:=tcallparanode(hpcurr.right);
+ { pull in at the correct place.
+ Used order:
+ 1. LOC_REFERENCE with smallest offset (x86 only)
+ 2. LOC_REFERENCE with most registers
+ 3. LOC_REGISTER with most registers
+ For the moment we only look at the first parameter field. Combining it
+ with multiple parameter fields will make things a lot complexer (PFV) }
+ if not assigned(hpcurr.parasym.paraloc[callerside].location) then
+ internalerror(200412152);
+ currloc:=hpcurr.parasym.paraloc[callerside].location^.loc;
+ hpprev:=nil;
+ hp:=hpfirst;
+ while assigned(hp) do
+ begin
+ case currloc of
+ LOC_REFERENCE :
+ begin
+ case hp.parasym.paraloc[callerside].location^.loc of
+ LOC_REFERENCE :
+ begin
+ { Offset is calculated like:
+ sub esp,12
+ mov [esp+8],para3
+ mov [esp+4],para2
+ mov [esp],para1
+ call function
+ That means the for pushes the para with the
+ highest offset (see para3) needs to be pushed first
+ }
+ if (hpcurr.registersint>hp.registersint)
+{$ifdef x86}
+ or (hpcurr.parasym.paraloc[callerside].location^.reference.offset>hp.parasym.paraloc[callerside].location^.reference.offset)
+{$endif x86}
+ then
+ break;
+ end;
+ LOC_REGISTER,
+ LOC_FPUREGISTER :
+ break;
+ end;
+ end;
+ LOC_FPUREGISTER,
+ LOC_REGISTER :
+ begin
+ if (hp.parasym.paraloc[callerside].location^.loc=currloc) and
+ (hpcurr.registersint>hp.registersint) then
+ break;
+ end;
+ end;
+ hpprev:=hp;
+ hp:=tcallparanode(hp.right);
+ end;
+ hpcurr.right:=hp;
+ if assigned(hpprev) then
+ hpprev.right:=hpcurr
+ else
+ hpfirst:=hpcurr;
+ { next }
+ hpcurr:=hpnext;
+ end;
+ left:=hpfirst;
+ end;
+
+
+ function tcallnode.replaceparaload(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ paras: tcallparanode;
+ temp: tnode;
+ begin
+ result := fen_false;
+ n.fileinfo := pfileposinfo(arg)^;
+ if (n.nodetype = loadn) then
+ begin
+ case tloadnode(n).symtableentry.typ of
+ paravarsym :
+ begin
+ paras := tcallparanode(left);
+ while assigned(paras) and
+ (paras.parasym <> tloadnode(n).symtableentry) do
+ paras := tcallparanode(paras.right);
+ if assigned(paras) then
+ begin
+ n.free;
+ n := paras.left.getcopy;
+ resulttypepass(n);
+ result := fen_true;
+ end;
+ end;
+ localvarsym :
+ begin
+ { local? }
+ if (tloadnode(n).symtableentry.owner <> tprocdef(procdefinition).localst) then
+ exit;
+ if (tloadnode(n).symtableentry.indexnr >= inlinelocals.count) or
+ not assigned(inlinelocals[tloadnode(n).symtableentry.indexnr]) then
+ internalerror(20040720);
+ temp := tnode(inlinelocals[tloadnode(n).symtableentry.indexnr]).getcopy;
+ n.free;
+ n := temp;
+ resulttypepass(n);
+ result := fen_true;
+ end;
+ end;
+ end;
+ end;
+
+
+ type
+ ptempnodes = ^ttempnodes;
+ ttempnodes = record
+ createstatement, deletestatement: tstatementnode;
+ end;
+
+ procedure tcallnode.createlocaltemps(p:TNamedIndexItem;arg:pointer);
+ var
+ tempinfo: ptempnodes absolute arg;
+ tempnode: ttempcreatenode;
+ begin
+ if (tsymentry(p).typ <> localvarsym) then
+ exit;
+ if (p.indexnr >= inlinelocals.count) then
+ inlinelocals.count:=p.indexnr+10;
+ if (vo_is_funcret in tabstractvarsym(p).varoptions) and
+ assigned(funcretnode) then
+ begin
+ if node_complexity(funcretnode) > 1 then
+ begin
+ { can this happen? }
+ { we may have to replace the funcretnode with the address of funcretnode }
+ { loaded in a temp in this case, because the expression may e.g. contain }
+ { a global variable that gets changed inside the function }
+ internalerror(2004072101);
+ end;
+ inlinelocals[tabstractvarsym(p).indexnr] := funcretnode.getcopy
+ end
+ else
+ begin
+ tempnode := ctempcreatenode.create(tabstractvarsym(p).vartype,tabstractvarsym(p).vartype.def.size,tt_persistent,tabstractvarsym(p).varregable<>vr_none);
+ addstatement(tempinfo^.createstatement,tempnode);
+ if assigned(tlocalvarsym(p).defaultconstsym) then
+ begin
+ { warning: duplicate from psub.pas:initializevars() -> must refactor }
+ addstatement(tempinfo^.createstatement,cassignmentnode.create(
+ ctemprefnode.create(tempnode),
+ cloadnode.create(tlocalvarsym(p).defaultconstsym,tlocalvarsym(p).defaultconstsym.owner)));
+ end;
+ if (vo_is_funcret in tlocalvarsym(p).varoptions) then
+ begin
+ funcretnode := ctemprefnode.create(tempnode);
+ addstatement(tempinfo^.deletestatement,ctempdeletenode.create_normal_temp(tempnode));
+ end
+ else
+ addstatement(tempinfo^.deletestatement,ctempdeletenode.create(tempnode));
+ inlinelocals[p.indexnr] := ctemprefnode.create(tempnode);
+ end;
+ end;
+
+
+ procedure tcallnode.createinlineparas(var createstatement, deletestatement: tstatementnode);
+ var
+ para: tcallparanode;
+ tempnode: ttempcreatenode;
+ tempnodes: ttempnodes;
+ n: tnode;
+ begin
+ { parameters }
+ para := tcallparanode(left);
+ while assigned(para) do
+ begin
+ if (para.parasym.typ = paravarsym) and
+ { para.left will already be the same as funcretnode in the following case, so don't change }
+ (not(vo_is_funcret in tparavarsym(para.parasym).varoptions) or
+ (not assigned(funcretnode))) then
+ begin
+ { must take copy of para.left, because if it contains a }
+ { temprefn pointing to a copied temp (e.g. methodpointer), }
+ { then this parameter must be changed to point to the copy of }
+ { that temp (JM) }
+ n := para.left.getcopy;
+ para.left.free;
+ para.left := n;
+
+ { create temps for value parameters, function result and also for }
+ { const parameters which are passed by value instead of by reference }
+ { we need to take care that we use the type of the defined parameter and not of the
+ passed parameter, because these can be different in case of a formaldef (PFV) }
+ if
+ (
+ { the problem is that we can't take the address of a function result :( }
+ (vo_is_funcret in tparavarsym(para.parasym).varoptions) or
+ (para.parasym.varspez = vs_value) or
+ ((para.parasym.varspez = vs_const) and
+ (para.parasym.vartype.def.deftype<>formaldef) and
+ { the compiler expects that it can take the address of parameters passed by reference in
+ the case of const so we can't replace the node simply by a constant node
+ When playing with this code, ensure that
+ function f(const a,b : longint) : longint;inline;
+ begin
+ result:=a*b;
+ end;
+
+ [...]
+ ...:=f(10,20));
+ [...]
+
+ is still folded. (FK)
+ }
+ (
+ { this must be a not ... of course }
+ not(paramanager.push_addr_param(vs_const,para.parasym.vartype.def,procdefinition.proccalloption)) or
+ (node_complexity(para.left) >= NODE_COMPLEXITY_INF)
+ ))
+ ) then
+ begin
+ { in theory, this is always regable, but ncgcall can't }
+ { handle it yet in all situations (JM) }
+ tempnode := ctempcreatenode.create(para.parasym.vartype,para.parasym.vartype.def.size,tt_persistent,tparavarsym(para.parasym).varregable <> vr_none);
+ addstatement(createstatement,tempnode);
+ { assign the value of the parameter to the temp, except in case of the function result }
+ { (in that case, para.left is a block containing the creation of a new temp, while we }
+ { only need a temprefnode, so delete the old stuff) }
+ if not(vo_is_funcret in tparavarsym(para.parasym).varoptions) then
+ begin
+ addstatement(createstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
+ para.left));
+ para.left := ctemprefnode.create(tempnode);
+ addstatement(deletestatement,ctempdeletenode.create(tempnode));
+ end
+ else
+ begin
+ if not(assigned(funcretnode)) then
+ funcretnode := ctemprefnode.create(tempnode);
+ para.left.free;
+ para.left := ctemprefnode.create(tempnode);
+
+ addstatement(deletestatement,ctempdeletenode.create_normal_temp(tempnode));
+ end
+ end
+ else if (node_complexity(para.left) > 1) then
+ begin
+ tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent,tparavarsym(para.parasym).varregable<>vr_none);
+ addstatement(createstatement,tempnode);
+ addstatement(createstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
+ caddrnode.create_internal(para.left)));
+ para.left := ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),para.left.resulttype);
+ addstatement(deletestatement,ctempdeletenode.create(tempnode));
+ end;
+ end;
+ para := tcallparanode(para.right);
+ end;
+ { local variables }
+ if not assigned(tprocdef(procdefinition).localst) or
+ (tprocdef(procdefinition).localst.symindex.count = 0) then
+ exit;
+ tempnodes.createstatement := createstatement;
+ tempnodes.deletestatement := deletestatement;
+ inlinelocals.count:=tprocdef(procdefinition).localst.symindex.count;
+ tprocdef(procdefinition).localst.foreach(@createlocaltemps,@tempnodes);
+ createstatement := tempnodes.createstatement;
+ deletestatement := tempnodes.deletestatement;
+ end;
+
+
+
+ function tcallnode.pass1_inline:tnode;
+ var
+ createstatement,deletestatement: tstatementnode;
+ createblock,deleteblock: tblocknode;
+ body : tnode;
+ i: longint;
+ begin
+ if not(assigned(tprocdef(procdefinition).inlininginfo) and
+ assigned(tprocdef(procdefinition).inlininginfo^.code)) then
+ internalerror(200412021);
+ { inherit flags }
+ current_procinfo.flags := current_procinfo.flags + ((procdefinition as tprocdef).inlininginfo^.flags*inherited_inlining_flags);
+ { create blocks for loading/deleting of local data }
+ createblock:=internalstatements(createstatement);
+ deleteblock:=internalstatements(deletestatement);
+
+ { add methodpointer init code to init statement }
+ { (fini must be done later, as it will delete the hookoncopy info) }
+ if assigned(methodpointerinit) then
+ addstatement(createstatement,methodpointerinit.getcopy);
+
+ inlinelocals:=tlist.create;
+ { get copy of the procedure body }
+ body:=tprocdef(procdefinition).inlininginfo^.code.getcopy;
+ { replace complex parameters with temps }
+ createinlineparas(createstatement,deletestatement);
+ { replace the parameter loads with the parameter values }
+ foreachnode(body,@replaceparaload,@fileinfo);
+
+ { copy methodpointer fini code }
+ if assigned(methodpointerdone) then
+ addstatement(deletestatement,methodpointerdone.getcopy);
+
+ { free the temps for the locals }
+ for i := 0 to inlinelocals.count-1 do
+ if assigned(inlinelocals[i]) then
+ tnode(inlinelocals[i]).free;
+ inlinelocals.free;
+ inlinelocals:=nil;
+ addstatement(createstatement,body);
+ addstatement(createstatement,deleteblock);
+ { set function result location if necessary }
+ if assigned(funcretnode) and
+ (cnf_return_value_used in callnodeflags) then
+ addstatement(createstatement,funcretnode.getcopy);
+
+ { consider it must not be inlined if called
+ again inside the args or itself }
+ exclude(procdefinition.procoptions,po_inline);
+
+ dosimplify(createblock);
+
+ firstpass(createblock);
+ include(procdefinition.procoptions,po_inline);
+ { return inlined block }
+ result := createblock;
+
+{$ifdef DEBUGINLINE}
+ writeln;
+ writeln('**************************',tprocdef(procdefinition).mangledname);
+ printnode(output,result);
+{$endif DEBUGINLINE}
+ end;
+
+
+ function tcallnode.pass_1 : tnode;
+ var
+ st : tsymtable;
+ begin
+ result:=nil;
+
+ { Can we inline the procedure? }
+ if ([po_inline,po_has_inlininginfo] <= procdefinition.procoptions) then
+ begin
+ { Check if we can inline the procedure when it references proc/var that
+ are not in the globally available }
+ st:=procdefinition.owner;
+ if (st.symtabletype=objectsymtable) then
+ st:=st.defowner.owner;
+ if (pi_uses_static_symtable in tprocdef(procdefinition).inlininginfo^.flags) and
+ (st.symtabletype=globalsymtable) and
+ (not st.iscurrentunit) then
+ begin
+ Comment(V_lineinfo+V_Debug,'Not inlining "'+tprocdef(procdefinition).procsym.realname+'", references static symtable');
+ end
+ else
+ begin
+ result:=pass1_inline;
+ exit;
+ end;
+ end;
+
+ { calculate the parameter info for the procdef }
+ if not procdefinition.has_paraloc_info then
+ begin
+ procdefinition.requiredargarea:=paramanager.create_paraloc_info(procdefinition,callerside);
+ procdefinition.has_paraloc_info:=true;
+ end;
+
+ { calculate the parameter size needed for this call include varargs if they are available }
+ if assigned(varargsparas) then
+ pushedparasize:=paramanager.create_varargs_paraloc_info(procdefinition,varargsparas)
+ else
+ pushedparasize:=procdefinition.requiredargarea;
+
+ { record maximum parameter size used in this proc }
+ current_procinfo.allocate_push_parasize(pushedparasize);
+
+ { work trough all parameters to get the register requirements }
+ if assigned(left) then
+ tcallparanode(left).det_registers;
+
+ { order parameters }
+ order_parameters;
+
+ if assigned(methodpointerinit) then
+ firstpass(methodpointerinit);
+
+ if assigned(methodpointerdone) then
+ firstpass(methodpointerdone);
+
+ { function result node }
+ if assigned(_funcretnode) then
+ firstpass(_funcretnode);
+
+ { procedure variable ? }
+ if assigned(right) then
+ firstpass(right);
+
+ if not (block_type in [bt_const,bt_type]) then
+ include(current_procinfo.flags,pi_do_call);
+
+ { implicit finally needed ? }
+ if resulttype.def.needs_inittable and
+ not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) and
+ not assigned(funcretnode) then
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+
+ { get a register for the return value }
+ if (not is_void(resulttype.def)) then
+ begin
+ if paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
+ begin
+ expectloc:=LOC_REFERENCE;
+ end
+ else
+ { for win32 records returned in EDX:EAX, we
+ move them to memory after ... }
+ if (resulttype.def.deftype=recorddef) then
+ begin
+ expectloc:=LOC_REFERENCE;
+ end
+ else
+ { ansi/widestrings must be registered, so we can dispose them }
+ if is_ansistring(resulttype.def) or
+ is_widestring(resulttype.def) then
+ begin
+ expectloc:=LOC_REFERENCE;
+ registersint:=1;
+ end
+ else
+ { we have only to handle the result if it is used }
+ if (cnf_return_value_used in callnodeflags) then
+ begin
+ case resulttype.def.deftype of
+ enumdef,
+ orddef :
+ begin
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ expectloc:=LOC_REGISTER;
+ registersint:=1;
+ end
+ else
+ begin
+ expectloc:=LOC_REGISTER;
+ if is_64bit(resulttype.def) then
+ registersint:=2
+ else
+ registersint:=1;
+ end;
+ end;
+ floatdef :
+ begin
+ expectloc:=LOC_FPUREGISTER;
+{$ifdef cpufpemu}
+ if (cs_fp_emulation in aktmoduleswitches) then
+ registersint:=1
+ else
+{$endif cpufpemu}
+{$ifdef m68k}
+ if (tfloatdef(resulttype.def).typ=s32real) then
+ registersint:=1
+ else
+{$endif m68k}
+ registersfpu:=1;
+ end;
+ else
+ begin
+ expectloc:=LOC_REGISTER;
+ registersint:=1;
+ end;
+ end;
+ end
+ else
+ expectloc:=LOC_VOID;
+ end
+ else
+ expectloc:=LOC_VOID;
+
+{$ifdef m68k}
+ { we need one more address register for virtual calls on m68k }
+ if (po_virtualmethod in procdefinition.procoptions) then
+ inc(registersint);
+{$endif m68k}
+ { a fpu can be used in any procedure !! }
+{$ifdef i386}
+ registersfpu:=procdefinition.fpu_used;
+{$endif i386}
+ { if this is a call to a method calc the registers }
+ if (methodpointer<>nil) then
+ begin
+ if methodpointer.nodetype<>typen then
+ begin
+ firstpass(methodpointer);
+ registersfpu:=max(methodpointer.registersfpu,registersfpu);
+ registersint:=max(methodpointer.registersint,registersint);
+{$ifdef SUPPORT_MMX }
+ registersmmx:=max(methodpointer.registersmmx,registersmmx);
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+ { determine the registers of the procedure variable }
+ { is this OK for inlined procs also ?? (PM) }
+ if assigned(right) then
+ begin
+ registersfpu:=max(right.registersfpu,registersfpu);
+ registersint:=max(right.registersint,registersint);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(right.registersmmx,registersmmx);
+{$endif SUPPORT_MMX}
+ end;
+ { determine the registers of the procedure }
+ if assigned(left) then
+ begin
+ registersfpu:=max(left.registersfpu,registersfpu);
+ registersint:=max(left.registersint,registersint);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(left.registersmmx,registersmmx);
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+{$ifdef state_tracking}
+ function Tcallnode.track_state_pass(exec_known:boolean):boolean;
+
+ var hp:Tcallparanode;
+ value:Tnode;
+
+ begin
+ track_state_pass:=false;
+ hp:=Tcallparanode(left);
+ while assigned(hp) do
+ begin
+ if left.track_state_pass(exec_known) then
+ begin
+ left.resulttype.def:=nil;
+ do_resulttypepass(left);
+ end;
+ value:=aktstate.find_fact(hp.left);
+ if value<>nil then
+ begin
+ track_state_pass:=true;
+ hp.left.destroy;
+ hp.left:=value.getcopy;
+ do_resulttypepass(hp.left);
+ end;
+ hp:=Tcallparanode(hp.right);
+ end;
+ end;
+{$endif}
+
+
+ function tcallnode.para_count:longint;
+ var
+ ppn : tcallparanode;
+ begin
+ result:=0;
+ ppn:=tcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if not(assigned(ppn.parasym) and
+ (vo_is_hidden_para in ppn.parasym.varoptions)) then
+ inc(result);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ end;
+
+
+ function tcallnode.get_load_methodpointer:tnode;
+ var
+ newstatement : tstatementnode;
+ begin
+ if assigned(methodpointerinit) then
+ begin
+ result:=internalstatements(newstatement);
+ addstatement(newstatement,methodpointerinit);
+ addstatement(newstatement,methodpointer);
+ addstatement(newstatement,methodpointerdone);
+ methodpointerinit:=nil;
+ methodpointer:=nil;
+ methodpointerdone:=nil;
+ end
+ else
+ begin
+ result:=methodpointer;
+ methodpointer:=nil;
+ end;
+ end;
+
+
+ function tcallnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (symtableprocentry = tcallnode(p).symtableprocentry) and
+ (procdefinition = tcallnode(p).procdefinition) and
+ (methodpointer.isequal(tcallnode(p).methodpointer)) and
+ (((cnf_restypeset in callnodeflags) and (cnf_restypeset in tcallnode(p).callnodeflags) and
+ (equal_defs(restype.def,tcallnode(p).restype.def))) or
+ (not(cnf_restypeset in callnodeflags) and not(cnf_restypeset in tcallnode(p).callnodeflags)));
+ end;
+
+
+ procedure tcallnode.printnodedata(var t:text);
+ begin
+ if assigned(procdefinition) and
+ (procdefinition.deftype=procdef) then
+ writeln(t,printnodeindention,'proc = ',tprocdef(procdefinition).fullprocname(true))
+ else
+ begin
+ if assigned(symtableprocentry) then
+ writeln(t,printnodeindention,'proc = ',symtableprocentry.name)
+ else
+ writeln(t,printnodeindention,'proc = <nil>');
+ end;
+ printnode(t,methodpointer);
+ printnode(t,right);
+ printnode(t,left);
+ end;
+
+
+begin
+ ccallnode:=tcallnode;
+ ccallparanode:=tcallparanode;
+end.
diff --git a/compiler/ncgadd.pas b/compiler/ncgadd.pas
new file mode 100644
index 0000000000..f85f03cbd2
--- /dev/null
+++ b/compiler/ncgadd.pas
@@ -0,0 +1,792 @@
+{
+ Copyright (c) 2000-2002 by the FPC development team
+
+ Code generation for add nodes (generic version)
+
+ 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 ncgadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,cpubase;
+
+ type
+ tcgaddnode = class(taddnode)
+{ function pass_1: tnode; override;}
+ procedure pass_2;override;
+ protected
+ { call secondpass for both left and right }
+ procedure pass_left_right;
+ { set the register of the result location }
+ procedure set_result_location_reg;
+ { load left and right nodes into registers }
+ procedure force_reg_left_right(allow_swap,allow_constant:boolean);
+
+ procedure second_opfloat;
+ procedure second_opboolean;
+ procedure second_opsmallset;
+ procedure second_op64bit;
+ procedure second_opordinal;
+
+ procedure second_addstring;virtual;
+ procedure second_addfloat;virtual;abstract;
+ procedure second_addboolean;virtual;
+ procedure second_addsmallset;virtual;
+{$ifdef x86}
+{$ifdef SUPPORT_MMX}
+ procedure second_opmmxset;virtual;abstract;
+ procedure second_opmmx;virtual;abstract;
+{$endif SUPPORT_MMX}
+{$endif x86}
+ procedure second_add64bit;virtual;
+ procedure second_addordinal;virtual;
+ procedure second_cmpfloat;virtual;abstract;
+ procedure second_cmpboolean;virtual;
+ procedure second_cmpsmallset;virtual;abstract;
+ procedure second_cmp64bit;virtual;abstract;
+ procedure second_cmpordinal;virtual;abstract;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,defutil,
+ cgbase,pass_2,
+ ncon,nset,ncgutil,cgobj,cgutils
+ ;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure tcgaddnode.pass_left_right;
+ var
+ tmpreg : tregister;
+ isjump,
+ pushedfpu : boolean;
+ otl,ofl : tasmlabel;
+ begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ { in case of constant put it to the left }
+ if (left.nodetype=ordconstn) then
+ swapleftright;
+
+ isjump:=(left.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(left);
+ if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(exprasmlist,left.location,def_cgsize(resulttype.def),false);
+ if isjump then
+ begin
+ truelabel:=otl;
+ falselabel:=ofl;
+ end;
+
+ { are too few registers free? }
+ if left.location.loc=LOC_FPUREGISTER then
+ pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
+ else
+ pushedfpu:=false;
+ isjump:=(right.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(right);
+ if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(exprasmlist,right.location,def_cgsize(resulttype.def),false);
+ if isjump then
+ begin
+ truelabel:=otl;
+ falselabel:=ofl;
+ end;
+ if pushedfpu then
+ begin
+ tmpreg := cg.getfpuregister(exprasmlist,left.location.size);
+ cg.a_loadfpu_loc_reg(exprasmlist,left.location,tmpreg);
+ location_reset(left.location,LOC_FPUREGISTER,left.location.size);
+ left.location.register := tmpreg;
+{$ifdef x86}
+ { left operand is now on top of the stack, instead of the right one! }
+ toggleflag(nf_swaped);
+{$endif x86}
+ end;
+ end;
+
+
+ procedure tcgaddnode.set_result_location_reg;
+ begin
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
+{$ifdef x86}
+ if left.location.loc=LOC_REGISTER then
+ begin
+ if TCGSize2Size[left.location.size]<>TCGSize2Size[location.size] then
+ internalerror(200307041);
+{$ifndef cpu64bit}
+ if location.size in [OS_64,OS_S64] then
+ begin
+ location.register64.reglo := left.location.register64.reglo;
+ location.register64.reghi := left.location.register64.reghi;
+ end
+ else
+{$endif}
+ location.register := left.location.register;
+ end
+ else
+ if right.location.loc=LOC_REGISTER then
+ begin
+ if TCGSize2Size[right.location.size]<>TCGSize2Size[location.size] then
+ internalerror(200307042);
+{$ifndef cpu64bit}
+ if location.size in [OS_64,OS_S64] then
+ begin
+ location.register64.reglo := right.location.register64.reglo;
+ location.register64.reghi := right.location.register64.reghi;
+ end
+ else
+{$endif}
+ location.register := right.location.register;
+ end
+ else
+{$endif}
+ begin
+{$ifndef cpu64bit}
+ if location.size in [OS_64,OS_S64] then
+ begin
+ location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ end
+ else
+{$endif}
+ location.register := cg.getintregister(exprasmlist,location.size);
+ end;
+ end;
+
+
+ procedure tcgaddnode.force_reg_left_right(allow_swap,allow_constant:boolean);
+ begin
+ if (left.location.loc<>LOC_REGISTER) and
+ not(
+ allow_constant and
+ (left.location.loc in [LOC_CONSTANT,LOC_CREGISTER])
+ ) then
+ location_force_reg(exprasmlist,left.location,left.location.size,false);
+ if (right.location.loc<>LOC_REGISTER) and
+ not(
+ allow_constant and
+ (right.location.loc in [LOC_CONSTANT,LOC_CREGISTER]) and
+ (left.location.loc<>LOC_CONSTANT)
+ ) then
+ location_force_reg(exprasmlist,right.location,right.location.size,false);
+
+ { Left is always a register, right can be register or constant }
+ if left.location.loc=LOC_CONSTANT then
+ begin
+ { when it is not allowed to swap we have a constant on
+ left, that will give problems }
+ if not allow_swap then
+ internalerror(200307041);
+ swapleftright;
+ end;
+ end;
+
+
+{*****************************************************************************
+ Smallsets
+*****************************************************************************}
+
+ procedure tcgaddnode.second_opsmallset;
+ begin
+ { when a setdef is passed, it has to be a smallset }
+ if ((left.resulttype.def.deftype=setdef) and
+ (tsetdef(left.resulttype.def).settype<>smallset)) or
+ ((right.resulttype.def.deftype=setdef) and
+ (tsetdef(right.resulttype.def).settype<>smallset)) then
+ internalerror(200203301);
+
+ if nodetype in [equaln,unequaln,gtn,gten,lten,ltn] then
+ second_cmpsmallset
+ else
+ second_addsmallset;
+ end;
+
+
+ procedure tcgaddnode.second_addsmallset;
+ var
+ cgop : TOpCg;
+ tmpreg : tregister;
+ opdone : boolean;
+ begin
+ opdone := false;
+
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ { setelementn is a special case, it must be on right.
+ We need an extra check if left is a register because the
+ default case can skip the register loading when the
+ setelementn is in a register (PFV) }
+ if (nf_swaped in flags) and
+ (left.nodetype=setelementn) then
+ swapleftright;
+ if (right.nodetype=setelementn) and
+ (left.location.loc<>LOC_REGISTER) then
+ location_force_reg(exprasmlist,left.location,left.location.size,false);
+
+ set_result_location_reg;
+
+ case nodetype of
+ addn :
+ begin
+ { are we adding set elements ? }
+ if right.nodetype=setelementn then
+ begin
+ { no range support for smallsets! }
+ if assigned(tsetelementnode(right).right) then
+ internalerror(43244);
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(exprasmlist,OP_OR,location.size,
+ aint(1 shl right.location.value),
+ left.location.register,location.register)
+ else
+ begin
+ tmpreg := cg.getintregister(exprasmlist,location.size);
+ cg.a_load_const_reg(exprasmlist,location.size,1,tmpreg);
+ cg.a_op_reg_reg(exprasmlist,OP_SHL,location.size,
+ right.location.register,tmpreg);
+ if left.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(exprasmlist,OP_OR,location.size,tmpreg,
+ left.location.register,location.register)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,OP_OR,location.size,
+ left.location.value,tmpreg,location.register);
+ end;
+ opdone := true;
+ end
+ else
+ cgop := OP_OR;
+ end;
+ symdifn :
+ cgop:=OP_XOR;
+ muln :
+ cgop:=OP_AND;
+ subn :
+ begin
+ cgop:=OP_AND;
+ if (not(nf_swaped in flags)) then
+ if (right.location.loc=LOC_CONSTANT) then
+ right.location.value := not(right.location.value)
+ else
+ opdone := true
+ else if (left.location.loc=LOC_CONSTANT) then
+ left.location.value := not(left.location.value)
+ else
+ begin
+ swapleftright;
+ opdone := true;
+ end;
+ if opdone then
+ begin
+ if left.location.loc = LOC_CONSTANT then
+ begin
+ tmpreg := cg.getintregister(exprasmlist,location.size);
+ cg.a_load_const_reg(exprasmlist,location.size,
+ left.location.value,tmpreg);
+ cg.a_op_reg_reg(exprasmlist,OP_NOT,location.size,right.location.register,right.location.register);
+ cg.a_op_reg_reg(exprasmlist,OP_AND,location.size,right.location.register,tmpreg);
+ cg.a_load_reg_reg(exprasmlist,OS_INT,location.size,tmpreg,location.register);
+ end
+ else
+ begin
+ cg.a_op_reg_reg(exprasmlist,OP_NOT,right.location.size,right.location.register,right.location.register);
+ cg.a_op_reg_reg(exprasmlist,OP_AND,left.location.size,right.location.register,left.location.register);
+ cg.a_load_reg_reg(exprasmlist,left.location.size,location.size,left.location.register,location.register);
+ end;
+ end;
+ end;
+ else
+ internalerror(2002072701);
+ end;
+
+ if not opdone then
+ begin
+ // these are all commutative operations
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(exprasmlist,cgop,location.size,
+ right.location.value,left.location.register,
+ location.register)
+ else
+ cg.a_op_reg_reg_reg(exprasmlist,cgop,location.size,
+ right.location.register,left.location.register,
+ location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Boolean
+*****************************************************************************}
+
+ procedure tcgaddnode.second_opboolean;
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ second_cmpboolean
+ else
+ second_addboolean;
+ end;
+
+
+ procedure tcgaddnode.second_addboolean;
+ var
+ cgop : TOpCg;
+ otl,ofl : tasmlabel;
+ begin
+ { And,Or will only evaluate from left to right only the
+ needed nodes unless full boolean evaluation is enabled }
+ if (nodetype in [orn,andn]) and
+ not(cs_full_boolean_eval in aktlocalswitches) then
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ case nodetype of
+ andn :
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ cg.a_label(exprasmlist,truelabel);
+ truelabel:=otl;
+ end;
+ orn :
+ begin
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ cg.a_label(exprasmlist,falselabel);
+ falselabel:=ofl;
+ end;
+ else
+ internalerror(200307044);
+ end;
+ secondpass(right);
+ maketojumpbool(exprasmlist,right,lr_load_regvars);
+ end
+ else
+ begin
+ pass_left_right;
+ force_reg_left_right(false,true);
+ set_result_location_reg;
+
+ case nodetype of
+ xorn :
+ cgop:=OP_XOR;
+ orn :
+ cgop:=OP_OR;
+ andn :
+ cgop:=OP_AND;
+ else
+ internalerror(200203247);
+ end;
+
+ if right.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(exprasmlist,cgop,location.size,
+ left.location.register,right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,cgop,location.size,
+ right.location.value,left.location.register,
+ location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ 64-bit
+*****************************************************************************}
+
+ procedure tcgaddnode.second_op64bit;
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ second_cmp64bit
+ else
+ second_add64bit;
+ end;
+
+
+
+ procedure tcgaddnode.second_add64bit;
+ var
+ op : TOpCG;
+ checkoverflow : boolean;
+ ovloc : tlocation;
+ begin
+ ovloc.loc:=LOC_VOID;
+
+ pass_left_right;
+ force_reg_left_right(false,(cs_check_overflow in aktlocalswitches) and
+ (nodetype in [addn,subn]));
+ set_result_location_reg;
+
+ { assume no overflow checking is required }
+ checkoverflow := false;
+ case nodetype of
+ addn :
+ begin
+ op:=OP_ADD;
+ checkoverflow:=true;
+ end;
+ subn :
+ begin
+ op:=OP_SUB;
+ checkoverflow:=true;
+ end;
+ xorn:
+ op:=OP_XOR;
+ orn:
+ op:=OP_OR;
+ andn:
+ op:=OP_AND;
+ muln:
+ begin
+ { should be handled in pass_1 (JM) }
+ internalerror(200109051);
+ end;
+ else
+ internalerror(2002072705);
+ end;
+
+{$ifdef cpu64bit}
+ case nodetype of
+ xorn,orn,andn,addn:
+ begin
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(exprasmlist,op,location.size,right.location.value,
+ left.location.register,location.register)
+ else
+ cg.a_op_reg_reg_reg(exprasmlist,op,location.size,right.location.register,
+ left.location.register,location.register);
+ end;
+ subn:
+ begin
+ if (nf_swaped in flags) then
+ swapleftright;
+
+ if left.location.loc <> LOC_CONSTANT then
+ begin
+ if right.location.loc <> LOC_CONSTANT then
+ // reg64 - reg64
+ cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ right.location.register,left.location.register,location.register,
+ checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
+ else
+ // reg64 - const64
+ cg.a_op_const_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ right.location.value,left.location.register,location.register,
+ checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
+ end
+ else
+ begin
+ // const64 - reg64
+ location_force_reg(exprasmlist,left.location,left.location.size,true);
+ cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ right.location.register,left.location.register,location.register,
+ checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
+ end;
+ end;
+ else
+ internalerror(2002072803);
+ end;
+{$else cpu64bit}
+ case nodetype of
+ xorn,orn,andn,addn:
+ begin
+ if (right.location.loc = LOC_CONSTANT) then
+ cg64.a_op64_const_reg_reg_checkoverflow(exprasmlist,op,location.size,right.location.value64,
+ left.location.register64,location.register64,
+ checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
+ else
+ cg64.a_op64_reg_reg_reg_checkoverflow(exprasmlist,op,location.size,right.location.register64,
+ left.location.register64,location.register64,
+ checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
+ end;
+ subn:
+ begin
+ if (nf_swaped in flags) then
+ swapleftright;
+
+ if left.location.loc <> LOC_CONSTANT then
+ begin
+ if right.location.loc <> LOC_CONSTANT then
+ // reg64 - reg64
+ cg64.a_op64_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ right.location.register64,left.location.register64,
+ location.register64,
+ checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
+ else
+ // reg64 - const64
+ cg64.a_op64_const_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ right.location.value64,left.location.register64,
+ location.register64,
+ checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
+ end
+ else
+ begin
+ // const64 - reg64
+ location_force_reg(exprasmlist,left.location,left.location.size,true);
+ cg64.a_op64_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ right.location.register64,left.location.register64,
+ location.register64,
+ checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
+ end;
+ end;
+ else
+ internalerror(2002072803);
+ end;
+{$endif cpu64bit}
+
+ { emit overflow check if enabled }
+ if checkoverflow then
+ cg.g_overflowcheck_loc(exprasmlist,Location,ResultType.Def,ovloc);
+ end;
+
+
+{*****************************************************************************
+ Strings
+*****************************************************************************}
+
+ procedure tcgaddnode.second_addstring;
+ begin
+ { this should already be handled in pass1 }
+ internalerror(2002072402);
+ end;
+
+
+{*****************************************************************************
+ Floats
+*****************************************************************************}
+
+ procedure tcgaddnode.second_opfloat;
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ second_cmpfloat
+ else
+ second_addfloat;
+ end;
+
+
+{*****************************************************************************
+ Ordinals
+*****************************************************************************}
+
+ procedure tcgaddnode.second_opordinal;
+ begin
+ if (nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) then
+ second_cmpordinal
+ else
+ second_addordinal;
+ end;
+
+
+ procedure tcgaddnode.second_addordinal;
+ var
+ unsigned,
+ checkoverflow : boolean;
+ cgop : topcg;
+ tmpreg : tregister;
+ ovloc : tlocation;
+ begin
+ ovloc.loc:=LOC_VOID;
+
+ pass_left_right;
+ force_reg_left_right(false,(cs_check_overflow in aktlocalswitches) and
+ (nodetype in [addn,subn,muln]));
+ set_result_location_reg;
+
+ { determine if the comparison will be unsigned }
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+
+ { assume no overflow checking is require }
+ checkoverflow := false;
+
+ case nodetype of
+ addn:
+ begin
+ cgop:=OP_ADD;
+ checkoverflow:=true;
+ end;
+ xorn :
+ begin
+ cgop:=OP_XOR;
+ end;
+ orn :
+ begin
+ cgop:=OP_OR;
+ end;
+ andn:
+ begin
+ cgop:=OP_AND;
+ end;
+ muln:
+ begin
+ checkoverflow:=true;
+ if unsigned then
+ cgop:=OP_MUL
+ else
+ cgop:=OP_IMUL;
+ end;
+ subn :
+ begin
+ checkoverflow:=true;
+ cgop:=OP_SUB;
+ end;
+ end;
+
+ if nodetype<>subn then
+ begin
+ if (right.location.loc >LOC_CONSTANT) then
+ cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,cgop,location.size,
+ left.location.register,right.location.register,
+ location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
+ else
+ cg.a_op_const_reg_reg_checkoverflow(exprasmlist,cgop,location.size,
+ right.location.value,left.location.register,
+ location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
+ end
+ else { subtract is a special case since its not commutative }
+ begin
+ if (nf_swaped in flags) then
+ swapleftright;
+ if left.location.loc<>LOC_CONSTANT then
+ begin
+ if right.location.loc<>LOC_CONSTANT then
+ cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ right.location.register,left.location.register,
+ location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
+ else
+ cg.a_op_const_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ aword(right.location.value),left.location.register,
+ location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
+ end
+ else
+ begin
+ tmpreg:=cg.getintregister(exprasmlist,location.size);
+ cg.a_load_const_reg(exprasmlist,location.size,
+ aword(left.location.value),tmpreg);
+ cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
+ right.location.register,tmpreg,location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
+ end;
+ end;
+
+ { emit overflow check if required }
+ if checkoverflow then
+ cg.g_overflowcheck_loc(exprasmlist,Location,ResultType.Def,ovloc);
+ end;
+
+
+ procedure tcgaddnode.second_cmpboolean;
+ begin
+ second_cmpordinal;
+ end;
+
+
+{*****************************************************************************
+ pass_2
+*****************************************************************************}
+
+ procedure tcgaddnode.pass_2;
+ begin
+ case left.resulttype.def.deftype of
+ orddef :
+ begin
+ { handling boolean expressions }
+ if is_boolean(left.resulttype.def) and
+ is_boolean(right.resulttype.def) then
+ second_opboolean
+ { 64bit operations }
+ else if is_64bit(left.resulttype.def) then
+ second_op64bit
+ else
+ second_opordinal;
+ end;
+ stringdef :
+ begin
+ second_addstring;
+ end;
+ setdef :
+ begin
+ {Normalsets are already handled in pass1 if mmx
+ should not be used.}
+ if (tsetdef(left.resulttype.def).settype<>smallset) then
+ begin
+{$ifdef SUPPORT_MMX}
+ {$ifdef i386}
+ if cs_mmx in aktlocalswitches then
+ second_opmmxset
+ else
+ {$endif}
+{$endif SUPPORT_MMX}
+ internalerror(200109041);
+ end
+ else
+ second_opsmallset;
+ end;
+ arraydef :
+ begin
+ { support dynarr=nil }
+ if is_dynamic_array(left.resulttype.def) then
+ second_opordinal
+{$ifdef SUPPORT_MMX}
+ else
+ if is_mmx_able_array(left.resulttype.def) then
+ second_opmmx
+{$endif SUPPORT_MMX}
+ else
+ internalerror(200306016);
+ end;
+ floatdef :
+ second_opfloat;
+ else
+ second_opordinal;
+ end;
+ end;
+
+begin
+ caddnode:=tcgaddnode;
+end.
diff --git a/compiler/ncgbas.pas b/compiler/ncgbas.pas
new file mode 100644
index 0000000000..39761affdb
--- /dev/null
+++ b/compiler/ncgbas.pas
@@ -0,0 +1,512 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ This unit implements some basic 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 ncgbas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgutils,
+ node,nbas;
+
+ type
+ tcgnothingnode = class(tnothingnode)
+ procedure pass_2;override;
+ end;
+
+ tcgasmnode = class(tasmnode)
+ procedure pass_2;override;
+ end;
+
+ tcgstatementnode = class(tstatementnode)
+ procedure pass_2;override;
+ end;
+
+ tcgblocknode = class(tblocknode)
+ procedure pass_2;override;
+ end;
+
+ tcgtempcreatenode = class(ttempcreatenode)
+ procedure pass_2;override;
+ end;
+
+ tcgtemprefnode = class(ttemprefnode)
+ procedure pass_2;override;
+ { Changes the location of this temp to ref. Useful when assigning }
+ { another temp to this one. The current location will be freed. }
+ { Can only be called in pass 2 (since earlier, the temp location }
+ { isn't known yet) }
+ procedure changelocation(const ref: treference);
+ end;
+
+ tcgtempdeletenode = class(ttempdeletenode)
+ procedure pass_2;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,
+ aasmbase,aasmtai,aasmcpu,symsym,symconst,
+ defutil,
+ nflw,pass_2,
+ cgbase,cgobj,
+ procinfo,
+ tgobj
+ ;
+
+{*****************************************************************************
+ TNOTHING
+*****************************************************************************}
+
+ procedure tcgnothingnode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { avoid an abstract rte }
+ end;
+
+
+{*****************************************************************************
+ TSTATEMENTNODE
+*****************************************************************************}
+
+ procedure tcgstatementnode.pass_2;
+ var
+ hp : tstatementnode;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ hp:=self;
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ secondpass(hp.left);
+ { Compiler inserted blocks can return values }
+ location_copy(hp.location,hp.left.location);
+ end;
+ hp:=tstatementnode(hp.right);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TASMNODE
+*****************************************************************************}
+
+ procedure tcgasmnode.pass_2;
+
+ procedure ReLabel(var p:tasmsymbol);
+ begin
+ { Only relabel local tasmlabels }
+ if (p.defbind = AB_LOCAL) and
+ (p is tasmlabel) then
+ begin
+ if not assigned(p.altsymbol) then
+ objectlibrary.GenerateAltSymbol(p);
+ p:=p.altsymbol;
+ p.increfs;
+ end;
+ end;
+
+ procedure ResolveRef(var op:toper);
+ var
+ sym : tabstractnormalvarsym;
+{$ifdef x86}
+ scale : byte;
+{$endif x86}
+ forceref,
+ getoffset : boolean;
+ indexreg : tregister;
+ sofs : longint;
+ begin
+ if (op.typ=top_local) then
+ begin
+ sofs:=op.localoper^.localsymofs;
+ indexreg:=op.localoper^.localindexreg;
+{$ifdef x86}
+ scale:=op.localoper^.localscale;
+{$endif x86}
+ getoffset:=op.localoper^.localgetoffset;
+ forceref:=op.localoper^.localforceref;
+ sym:=tabstractnormalvarsym(pointer(op.localoper^.localsym));
+ dispose(op.localoper);
+ case sym.localloc.loc of
+ LOC_REFERENCE :
+ begin
+ if getoffset then
+ begin
+ if indexreg=NR_NO then
+ begin
+ op.typ:=top_const;
+ op.val:=sym.localloc.reference.offset+sofs;
+ end
+ else
+ begin
+ op.typ:=top_ref;
+ new(op.ref);
+ reference_reset_base(op.ref^,indexreg,sym.localloc.reference.offset+sofs);
+ end;
+ end
+ else
+ begin
+ op.typ:=top_ref;
+ new(op.ref);
+ reference_reset_base(op.ref^,sym.localloc.reference.base,sym.localloc.reference.offset+sofs);
+ op.ref^.index:=indexreg;
+{$ifdef x86}
+ op.ref^.scalefactor:=scale;
+{$endif x86}
+ end;
+ end;
+ LOC_REGISTER :
+ begin
+ if getoffset then
+ Message(asmr_e_invalid_reference_syntax);
+ { Subscribed access }
+ if forceref or
+ (sofs<>0) then
+ begin
+ op.typ:=top_ref;
+ new(op.ref);
+ reference_reset_base(op.ref^,sym.localloc.register,sofs);
+ op.ref^.index:=indexreg;
+{$ifdef x86}
+ op.ref^.scalefactor:=scale;
+{$endif x86}
+ end
+ else
+ begin
+ op.typ:=top_reg;
+ op.reg:=sym.localloc.register;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ var
+ hp,hp2 : tai;
+ i : longint;
+ skipnode : boolean;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ if (nf_get_asm_position in flags) then
+ begin
+ { Add a marker, to be sure the list is not empty }
+ exprasmlist.concat(tai_marker.create(marker_position));
+ currenttai:=tai(exprasmlist.last);
+ exit;
+ end;
+
+ { Allocate registers used in the assembler block }
+ cg.alloccpuregisters(exprasmlist,R_INTREGISTER,used_regs_int);
+
+ if (po_inline in current_procinfo.procdef.procoptions) then
+ begin
+ objectlibrary.CreateUsedAsmSymbolList;
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ hp2:=tai(hp.getcopy);
+ skipnode:=false;
+ case hp2.typ of
+ ait_label :
+ ReLabel(tasmsymbol(tai_label(hp2).l));
+ ait_const_64bit,
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_const_indirect_symbol :
+ begin
+ if assigned(tai_const(hp2).sym) then
+ ReLabel(tai_const(hp2).sym);
+ if assigned(tai_const(hp2).endsym) then
+ ReLabel(tai_const(hp2).endsym);
+ end;
+ ait_instruction :
+ begin
+ { remove cached insentry, because the new code can
+ require an other less optimized instruction }
+{$ifdef i386}
+{$ifndef NOAG386BIN}
+ taicpu(hp2).ResetPass1;
+{$endif}
+{$endif}
+ { fixup the references }
+ for i:=1 to taicpu(hp2).ops do
+ begin
+ ResolveRef(taicpu(hp2).oper[i-1]^);
+ with taicpu(hp2).oper[i-1]^ do
+ begin
+ case typ of
+ top_ref :
+ begin
+ if assigned(ref^.symbol) then
+ ReLabel(ref^.symbol);
+ if assigned(ref^.relsymbol) then
+ ReLabel(ref^.relsymbol);
+ end;
+ end;
+ end;
+ end;
+ end;
+ ait_marker :
+ begin
+ { it's not an assembler block anymore }
+ if (tai_marker(hp2).kind in [AsmBlockStart, AsmBlockEnd]) then
+ skipnode:=true;
+ end;
+ end;
+ if not skipnode then
+ exprasmList.concat(hp2)
+ else
+ hp2.free;
+ hp:=tai(hp.next);
+ end;
+ { restore used symbols }
+ objectlibrary.UsedAsmSymbolListResetAltSym;
+ objectlibrary.DestroyUsedAsmSymbolList;
+ end
+ else
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_instruction :
+ begin
+ { remove cached insentry, because the new code can
+ require an other less optimized instruction }
+{$ifdef i386}
+{$ifndef NOAG386BIN}
+ taicpu(hp).ResetPass1;
+{$endif}
+{$endif}
+ { fixup the references }
+ for i:=1 to taicpu(hp).ops do
+ ResolveRef(taicpu(hp).oper[i-1]^);
+ end;
+ end;
+ hp:=tai(hp.next);
+ end;
+ { insert the list }
+ exprasmList.concatlist(p_asm);
+ end;
+
+ { Release register used in the assembler block }
+ cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,used_regs_int);
+ end;
+
+
+{*****************************************************************************
+ TBLOCKNODE
+*****************************************************************************}
+
+ procedure tcgblocknode.pass_2;
+ var
+ hp : tstatementnode;
+ oldexitlabel : tasmlabel;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { replace exitlabel? }
+ if nf_block_with_exit in flags then
+ begin
+ oldexitlabel:=current_procinfo.aktexitlabel;
+ objectlibrary.getjumplabel(current_procinfo.aktexitlabel);
+ end;
+
+ { do second pass on left node }
+ if assigned(left) then
+ begin
+ hp:=tstatementnode(left);
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ secondpass(hp.left);
+ location_copy(hp.location,hp.left.location);
+ end;
+ location_copy(location,hp.location);
+ hp:=tstatementnode(hp.right);
+ end;
+ end;
+
+ { write exitlabel }
+ if nf_block_with_exit in flags then
+ begin
+ cg.a_label(exprasmlist,current_procinfo.aktexitlabel);
+ current_procinfo.aktexitlabel:=oldexitlabel;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TTEMPCREATENODE
+*****************************************************************************}
+
+ procedure tcgtempcreatenode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
+ if tempinfo^.valid then
+ internalerror(200108222);
+
+ { get a (persistent) temp }
+ if tempinfo^.restype.def.needs_inittable then
+ begin
+ location_reset(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
+ tg.GetTempTyped(exprasmlist,tempinfo^.restype.def,tempinfo^.temptype,tempinfo^.location.reference);
+ end
+ else if tempinfo^.may_be_in_reg then
+ begin
+ if tempinfo^.restype.def.deftype=floatdef then
+ begin
+ if (tempinfo^.temptype = tt_persistent) then
+ location_reset(tempinfo^.location,LOC_CFPUREGISTER,def_cgsize(tempinfo^.restype.def))
+ else
+ location_reset(tempinfo^.location,LOC_FPUREGISTER,def_cgsize(tempinfo^.restype.def));
+ tempinfo^.location.register:=cg.getfpuregister(exprasmlist,tempinfo^.location.size);
+ end
+ else
+ begin
+ if (tempinfo^.temptype = tt_persistent) then
+ location_reset(tempinfo^.location,LOC_CREGISTER,def_cgsize(tempinfo^.restype.def))
+ else
+ location_reset(tempinfo^.location,LOC_REGISTER,def_cgsize(tempinfo^.restype.def));
+{$ifndef cpu64bit}
+ if tempinfo^.location.size in [OS_64,OS_S64] then
+ begin
+ tempinfo^.location.register64.reglo:=cg.getintregister(exprasmlist,OS_32);
+ tempinfo^.location.register64.reghi:=cg.getintregister(exprasmlist,OS_32);
+ end
+ else
+{$endif cpu64bit}
+ tempinfo^.location.register:=cg.getintregister(exprasmlist,tempinfo^.location.size);
+ end;
+ end
+ else
+ begin
+ location_reset(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
+ tg.GetTemp(exprasmlist,size,tempinfo^.temptype,tempinfo^.location.reference);
+ end;
+ tempinfo^.valid := true;
+ end;
+
+
+{*****************************************************************************
+ TTEMPREFNODE
+*****************************************************************************}
+
+ procedure tcgtemprefnode.pass_2;
+ begin
+ { check if the temp is valid }
+ if not tempinfo^.valid then
+ internalerror(200108231);
+ location:=tempinfo^.location;
+ if tempinfo^.location.loc=LOC_REFERENCE then
+ inc(location.reference.offset,offset);
+ end;
+
+
+ procedure tcgtemprefnode.changelocation(const ref: treference);
+ begin
+ { check if the temp is valid }
+ if not tempinfo^.valid then
+ internalerror(200306081);
+ if (tempinfo^.location.loc<>LOC_REFERENCE) then
+ internalerror(2004020203);
+ if (tempinfo^.temptype = tt_persistent) then
+ tg.ChangeTempType(exprasmlist,tempinfo^.location.reference,tt_normal);
+ tg.ungettemp(exprasmlist,tempinfo^.location.reference);
+ tempinfo^.location.reference := ref;
+ tg.ChangeTempType(exprasmlist,tempinfo^.location.reference,tempinfo^.temptype);
+ { adapt location }
+ location.reference := ref;
+ inc(location.reference.offset,offset);
+ end;
+
+
+{*****************************************************************************
+ TTEMPDELETENODE
+*****************************************************************************}
+
+ procedure tcgtempdeletenode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ case tempinfo^.location.loc of
+ LOC_REFERENCE:
+ begin
+ if release_to_normal then
+ tg.ChangeTempType(exprasmlist,tempinfo^.location.reference,tt_normal)
+ else
+ tg.UnGetTemp(exprasmlist,tempinfo^.location.reference);
+ end;
+ LOC_CREGISTER,
+ LOC_REGISTER:
+ begin
+ { make sure the register allocator doesn't reuse the }
+ { register e.g. in the middle of a loop }
+{$ifndef cpu64bit}
+ if tempinfo^.location.size in [OS_64,OS_S64] then
+ begin
+ cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reghi);
+ cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reglo);
+ end
+ else
+{$endif cpu64bit}
+ cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
+ if release_to_normal then
+ tempinfo^.location.loc := LOC_REGISTER;
+ end;
+ LOC_CFPUREGISTER,
+ LOC_FPUREGISTER:
+ begin
+ { make sure the register allocator doesn't reuse the }
+ { register e.g. in the middle of a loop }
+ cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
+ if release_to_normal then
+ tempinfo^.location.loc := LOC_FPUREGISTER;
+ end;
+ else
+ internalerror(200507161);
+ end;
+ end;
+
+
+begin
+ cnothingnode:=tcgnothingnode;
+ casmnode:=tcgasmnode;
+ cstatementnode:=tcgstatementnode;
+ cblocknode:=tcgblocknode;
+ ctempcreatenode:=tcgtempcreatenode;
+ ctemprefnode:=tcgtemprefnode;
+ ctempdeletenode:=tcgtempdeletenode;
+end.
diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas
new file mode 100644
index 0000000000..fce722fbad
--- /dev/null
+++ b/compiler/ncgcal.pas
@@ -0,0 +1,1030 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for call 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 ncgcal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ globtype,
+ parabase,cgutils,
+ symdef,node,ncal;
+
+ type
+ tcgcallparanode = class(tcallparanode)
+ private
+ tempcgpara : tcgpara;
+ procedure push_addr_para;
+ procedure push_value_para;
+ public
+ constructor create(expr,next : tnode);override;
+ destructor destroy;override;
+ procedure secondcallparan;override;
+ end;
+
+ tcgcallnode = class(tcallnode)
+ private
+ procedure release_para_temps;
+ procedure pushparas;
+ procedure freeparas;
+ protected
+ framepointer_paraloc : tcgpara;
+ refcountedtemp : treference;
+ procedure handle_return_value;
+ {# This routine is used to push the current frame pointer
+ on the stack. This is used in nested routines where the
+ value of the frame pointer is always pushed as an extra
+ parameter.
+
+ The default handling is the standard handling used on
+ most stack based machines, where the frame pointer is
+ the first invisible parameter.
+ }
+ procedure pop_parasize(pop_size:longint);virtual;
+ procedure extra_interrupt_code;virtual;
+ procedure extra_call_code;virtual;
+ procedure extra_post_call_code;virtual;
+ procedure do_syscall;virtual;abstract;
+ public
+ procedure pass_2;override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ cutils,verbose,globals,
+ symconst,symtable,defutil,paramgr,
+ cgbase,pass_2,
+ aasmbase,aasmtai,
+ nbas,nmem,nld,ncnv,nutils,
+{$ifdef x86}
+ cga,cgx86,
+{$endif x86}
+ ncgutil,
+ cgobj,tgobj,
+ procinfo;
+
+
+{*****************************************************************************
+ TCGCALLPARANODE
+*****************************************************************************}
+
+ constructor tcgcallparanode.create(expr,next : tnode);
+ begin
+ inherited create(expr,next);
+ tempcgpara.init;
+ end;
+
+
+ destructor tcgcallparanode.destroy;
+ begin
+ tempcgpara.done;
+ inherited destroy;
+ end;
+
+
+ procedure tcgcallparanode.push_addr_para;
+ begin
+ if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ internalerror(200304235);
+ cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempcgpara);
+ end;
+
+
+ procedure tcgcallparanode.push_value_para;
+{$ifdef i386}
+ var
+ href : treference;
+ size : longint;
+{$endif i386}
+ begin
+ { we've nothing to push when the size of the parameter is 0 }
+ if left.resulttype.def.size=0 then
+ exit;
+
+ { Move flags and jump in register to make it less complex }
+ if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
+
+ { Handle Floating point types differently }
+ if (left.resulttype.def.deftype=floatdef) and not(cs_fp_emulation in aktmoduleswitches) then
+ begin
+{$ifdef i386}
+ if tempcgpara.location^.loc<>LOC_REFERENCE then
+ internalerror(200309291);
+ case left.location.loc of
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ size:=align(TCGSize2Size[left.location.size],tempcgpara.alignment);
+ if tempcgpara.location^.reference.index=NR_STACK_POINTER_REG then
+ begin
+ cg.g_stackpointer_alloc(exprasmlist,size);
+ reference_reset_base(href,NR_STACK_POINTER_REG,0);
+ end
+ else
+ reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
+ cg.a_loadfpu_reg_ref(exprasmlist,left.location.size,left.location.register,href);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ size:=align(tfloatdef(left.resulttype.def).size,tempcgpara.alignment);
+ if tempcgpara.location^.reference.index=NR_STACK_POINTER_REG then
+ begin
+ cg.g_stackpointer_alloc(exprasmlist,size);
+ reference_reset_base(href,NR_STACK_POINTER_REG,0);
+ end
+ else
+ reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
+ cg.a_loadmm_reg_ref(exprasmlist,left.location.size,left.location.size,left.location.register,href,mms_movescalar);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ size:=align(left.resulttype.def.size,tempcgpara.alignment);
+ if tempcgpara.location^.reference.index=NR_STACK_POINTER_REG then
+ cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara)
+ else
+ begin
+ reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
+ cg.g_concatcopy(exprasmlist,left.location.reference,href,size);
+ end;
+ end;
+ else
+ internalerror(2002042430);
+ end;
+{$else i386}
+ case left.location.loc of
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ case tempcgpara.location^.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ cg.a_parammm_reg(exprasmlist,left.location.size,left.location.register,tempcgpara,mms_movescalar);
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ location_force_fpureg(exprasmlist,left.location,false);
+ cg.a_paramfpu_reg(exprasmlist,left.location.size,left.location.register,tempcgpara);
+ end;
+ else
+ internalerror(200204249);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ case tempcgpara.location^.loc of
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ location_force_mmregscalar(exprasmlist,left.location,false);
+ cg.a_parammm_reg(exprasmlist,left.location.size,left.location.register,tempcgpara,mms_movescalar);
+ end;
+{$ifdef x86_64}
+ { x86_64 pushes s64comp in normal register }
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ location_force_mem(exprasmlist,left.location);
+ { force integer size }
+ left.location.size:=int_cgsize(tcgsize2size[left.location.size]);
+ cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
+ end;
+{$endif x86_64}
+{$if defined(sparc) or defined(arm)}
+ { sparc and arm pass floats in normal registers }
+ LOC_REGISTER,
+ LOC_CREGISTER,
+{$endif sparc}
+ LOC_REFERENCE,
+ LOC_CREFERENCE,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ cg.a_paramfpu_reg(exprasmlist,left.location.size,left.location.register,tempcgpara);
+ else
+ internalerror(2002042433);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ case tempcgpara.location^.loc of
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ cg.a_parammm_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara,mms_movescalar);
+{$ifdef x86_64}
+ { x86_64 pushes s64comp in normal register }
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ { force integer size }
+ left.location.size:=int_cgsize(tcgsize2size[left.location.size]);
+ cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
+ end;
+{$endif x86_64}
+{$if defined(sparc) or defined(arm) }
+ { sparc and arm pass floats in normal registers }
+ LOC_REGISTER,
+ LOC_CREGISTER,
+{$endif sparc}
+ LOC_REFERENCE,
+ LOC_CREFERENCE,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ cg.a_paramfpu_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
+ else
+ internalerror(2002042431);
+ end;
+ else
+ internalerror(2002042432);
+ end;
+{$endif i386}
+ end
+ else
+ begin
+ case left.location.loc of
+ LOC_CONSTANT,
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+{$ifndef cpu64bit}
+ { use cg64 only for int64, not for 8 byte records }
+ if is_64bit(left.resulttype.def) then
+ cg64.a_param64_loc(exprasmlist,left.location,tempcgpara)
+ else
+{$endif cpu64bit}
+ begin
+{$ifndef cpu64bit}
+ { Only a_param_ref supports multiple locations, when the
+ value is still a const or in a register then write it
+ to a reference first. This situation can be triggered
+ by typecasting an int64 constant to a record of 8 bytes }
+ if left.location.size in [OS_64,OS_S64] then
+ location_force_mem(exprasmlist,left.location);
+{$endif cpu64bit}
+ cg.a_param_loc(exprasmlist,left.location,tempcgpara);
+ end;
+ end;
+{$ifdef SUPPORT_MMX}
+ LOC_MMXREGISTER,
+ LOC_CMMXREGISTER:
+ cg.a_parammm_reg(exprasmlist,OS_M64,left.location.register,tempcgpara,nil);
+{$endif SUPPORT_MMX}
+ else
+ internalerror(200204241);
+ end;
+ end;
+ end;
+
+
+ procedure tcgcallparanode.secondcallparan;
+ var
+ href : treference;
+ otlabel,
+ oflabel : tasmlabel;
+ begin
+ if not(assigned(parasym)) then
+ internalerror(200304242);
+
+ { Skip nothingn nodes which are used after disabling
+ a parameter }
+ if (left.nodetype<>nothingn) then
+ begin
+ otlabel:=truelabel;
+ oflabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+
+ { release memory for refcnt out parameters }
+ if (parasym.varspez=vs_out) and
+ (left.resulttype.def.needs_inittable) then
+ begin
+ location_get_data_ref(exprasmlist,left.location,href,false);
+ cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
+ end;
+
+ paramanager.createtempparaloc(exprasmlist,aktcallnode.procdefinition.proccalloption,parasym,tempcgpara);
+
+ { handle varargs first, because parasym is not valid }
+ if (cpf_varargs_para in callparaflags) then
+ begin
+ if paramanager.push_addr_param(vs_value,left.resulttype.def,
+ aktcallnode.procdefinition.proccalloption) then
+ push_addr_para
+ else
+ push_value_para;
+ end
+ { hidden parameters }
+ else if (vo_is_hidden_para in parasym.varoptions) then
+ begin
+ { don't push a node that already generated a pointer type
+ by address for implicit hidden parameters }
+ if (vo_is_funcret in parasym.varoptions) or
+ (not(left.resulttype.def.deftype in [pointerdef,classrefdef]) and
+ paramanager.push_addr_param(parasym.varspez,parasym.vartype.def,
+ aktcallnode.procdefinition.proccalloption)) then
+ push_addr_para
+ else
+ push_value_para;
+ end
+ { formal def }
+ else if (parasym.vartype.def.deftype=formaldef) then
+ begin
+ { allow passing of a constant to a const formaldef }
+ if (parasym.varspez=vs_const) and
+ (left.location.loc=LOC_CONSTANT) then
+ location_force_mem(exprasmlist,left.location);
+ push_addr_para;
+ end
+ { Normal parameter }
+ else
+ begin
+ { don't push a node that already generated a pointer type
+ by address for implicit hidden parameters }
+ if (not(
+ (vo_is_hidden_para in parasym.varoptions) and
+ (left.resulttype.def.deftype in [pointerdef,classrefdef])
+ ) and
+ paramanager.push_addr_param(parasym.varspez,parasym.vartype.def,
+ aktcallnode.procdefinition.proccalloption)) and
+ { dyn. arrays passed to an array of const must be passed by value, see tests/webtbs/tw4219.pp }
+ not(
+ is_array_of_const(parasym.vartype.def) and
+ is_dynamic_array(left.resulttype.def)
+ ) then
+ begin
+ { Passing a var parameter to a var parameter, we can
+ just push the address transparently }
+ if (left.nodetype=loadn) and
+ (tloadnode(left).is_addr_param_load) then
+ begin
+ if (left.location.reference.index<>NR_NO) or
+ (left.location.reference.offset<>0) then
+ internalerror(200410107);
+ cg.a_param_reg(exprasmlist,OS_ADDR,left.location.reference.base,tempcgpara)
+ end
+ else
+ begin
+ { Check for passing a constant to var,out parameter }
+ if (parasym.varspez in [vs_var,vs_out]) and
+ (left.location.loc<>LOC_REFERENCE) then
+ begin
+ { passing self to a var parameter is allowed in
+ TP and delphi }
+ if not((left.location.loc=LOC_CREFERENCE) and
+ is_self_node(left)) then
+ internalerror(200106041);
+ end;
+ { Force to be in memory }
+ if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ location_force_mem(exprasmlist,left.location);
+ push_addr_para;
+ end;
+ end
+ else
+ push_value_para;
+ end;
+ truelabel:=otlabel;
+ falselabel:=oflabel;
+
+ { update return location in callnode when this is the function
+ result }
+ if assigned(parasym) and
+ (vo_is_funcret in parasym.varoptions) then
+ location_copy(aktcallnode.location,left.location);
+ end;
+
+ { next parameter }
+ if assigned(right) then
+ tcallparanode(right).secondcallparan;
+ end;
+
+
+{*****************************************************************************
+ TCGCALLNODE
+*****************************************************************************}
+
+ procedure tcgcallnode.extra_interrupt_code;
+ begin
+ end;
+
+
+ procedure tcgcallnode.extra_call_code;
+ begin
+ end;
+
+
+ procedure tcgcallnode.extra_post_call_code;
+ begin
+ end;
+
+
+ procedure tcgcallnode.pop_parasize(pop_size:longint);
+ begin
+ end;
+
+
+ procedure tcgcallnode.handle_return_value;
+ var
+ cgsize : tcgsize;
+ retloc : tlocation;
+ hregister : tregister;
+ tempnode : tnode;
+ begin
+ cgsize:=procdefinition.funcretloc[callerside].size;
+
+ { structured results are easy to handle....
+ needed also when result_no_used !! }
+ if (procdefinition.proctypeoption<>potype_constructor) and
+ paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
+ begin
+ { Location should be setup by the funcret para }
+ if location.loc<>LOC_REFERENCE then
+ internalerror(200304241);
+ end
+ else
+ { ansi/widestrings must be registered, so we can dispose them }
+ if resulttype.def.needs_inittable then
+ begin
+ if procdefinition.funcretloc[callerside].loc<>LOC_REGISTER then
+ internalerror(200409261);
+
+ { the FUNCTION_RESULT_REG is already allocated }
+ if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
+ cg.ungetcpuregister(exprasmlist,procdefinition.funcretloc[callerside].register);
+ if not assigned(funcretnode) then
+ begin
+ { reg_ref could generate two instrcutions and allocate a register so we've to
+ save the result first before releasing it }
+ hregister:=cg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,procdefinition.funcretloc[callerside].register,hregister);
+
+ location_reset(location,LOC_REFERENCE,OS_ADDR);
+ location.reference:=refcountedtemp;
+ cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
+ end
+ else
+ begin
+ hregister := cg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,procdefinition.funcretloc[callerside].register,hregister);
+ { in case of a regular funcretnode with ret_in_param, the }
+ { original funcretnode isn't touched -> make sure it's }
+ { the same here (not sure if it's necessary) }
+ tempnode := funcretnode.getcopy;
+ tempnode.pass_2;
+ location := tempnode.location;
+ tempnode.free;
+ cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference);
+ cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
+ end;
+ end
+ else
+ { normal (ordinal,float,pointer) result value }
+ begin
+ { we have only to handle the result if it is used }
+ if (cnf_return_value_used in callnodeflags) then
+ begin
+ location.loc:=procdefinition.funcretloc[callerside].loc;
+ case procdefinition.funcretloc[callerside].loc of
+ LOC_FPUREGISTER:
+ begin
+ location_reset(location,LOC_FPUREGISTER,cgsize);
+ location.register:=procdefinition.funcretloc[callerside].register;
+{$ifdef x86}
+ tcgx86(cg).inc_fpu_stack;
+{$else x86}
+ if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
+ cg.ungetcpuregister(exprasmlist,procdefinition.funcretloc[callerside].register);
+ hregister:=cg.getfpuregister(exprasmlist,location.size);
+ cg.a_loadfpu_reg_reg(exprasmlist,location.size,location.register,hregister);
+ location.register:=hregister;
+{$endif x86}
+ end;
+
+ LOC_REGISTER:
+ begin
+ if cgsize<>OS_NO then
+ begin
+ location_reset(location,LOC_REGISTER,cgsize);
+{$ifndef cpu64bit}
+ if cgsize in [OS_64,OS_S64] then
+ begin
+ retloc:=procdefinition.funcretloc[callerside];
+ if retloc.loc<>LOC_REGISTER then
+ internalerror(200409141);
+ { the function result registers are already allocated }
+ if getsupreg(retloc.register64.reglo)<first_int_imreg then
+ cg.ungetcpuregister(exprasmlist,retloc.register64.reglo);
+ location.register64.reglo:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
+ if getsupreg(retloc.register64.reghi)<first_int_imreg then
+ cg.ungetcpuregister(exprasmlist,retloc.register64.reghi);
+ location.register64.reghi:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
+ end
+ else
+{$endif cpu64bit}
+ begin
+ { change register size after the unget because the
+ getregister was done for the full register
+ def_cgsize(resulttype.def) is used here because
+ it could be a constructor call }
+ if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
+ cg.ungetcpuregister(exprasmlist,procdefinition.funcretloc[callerside].register);
+ location.register:=cg.getintregister(exprasmlist,def_cgsize(resulttype.def));
+ cg.a_load_reg_reg(exprasmlist,cgsize,def_cgsize(resulttype.def),procdefinition.funcretloc[callerside].register,location.register);
+ end;
+ end
+ else
+ begin
+ if resulttype.def.size>0 then
+ internalerror(200305131);
+ end;
+ end;
+
+ LOC_MMREGISTER:
+ begin
+ location_reset(location,LOC_MMREGISTER,cgsize);
+ if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
+ cg.ungetcpuregister(exprasmlist,procdefinition.funcretloc[callerside].register);
+ location.register:=cg.getmmregister(exprasmlist,cgsize);
+ cg.a_loadmm_reg_reg(exprasmlist,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
+ end;
+
+ else
+ internalerror(200405023);
+ end;
+ end
+ else
+ begin
+{$ifdef x86}
+ { release FPU stack }
+ if procdefinition.funcretloc[callerside].loc=LOC_FPUREGISTER then
+ emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
+{$endif x86}
+ if cgsize<>OS_NO then
+ location_free(exprasmlist,procdefinition.funcretloc[callerside]);
+ location_reset(location,LOC_VOID,OS_NO);
+ end;
+ end;
+
+ { When the result is not used we need to finalize the result and
+ can release the temp }
+ if not(cnf_return_value_used in callnodeflags) then
+ begin
+ if location.loc=LOC_REFERENCE then
+ begin
+ if resulttype.def.needs_inittable then
+ cg.g_finalize(exprasmlist,resulttype.def,location.reference);
+ tg.ungetiftemp(exprasmlist,location.reference)
+ end;
+ end;
+ end;
+
+
+ procedure tcgcallnode.release_para_temps;
+ var
+ hp : tnode;
+ ppn : tcallparanode;
+ begin
+ { Release temps from parameters }
+ ppn:=tcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if assigned(ppn.left) then
+ begin
+ { don't release the funcret temp }
+ if not(assigned(ppn.parasym)) or
+ not(vo_is_funcret in ppn.parasym.varoptions) then
+ location_freetemp(exprasmlist,ppn.left.location);
+ { process also all nodes of an array of const }
+ hp:=ppn.left;
+ while (hp.nodetype=typeconvn) do
+ hp:=ttypeconvnode(hp).left;
+ if (hp.nodetype=arrayconstructorn) and
+ assigned(tarrayconstructornode(hp).left) then
+ begin
+ while assigned(hp) do
+ begin
+ location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
+ hp:=tarrayconstructornode(hp).right;
+ end;
+ end;
+ end;
+ ppn:=tcallparanode(ppn.right);
+ end;
+ end;
+
+
+ procedure tcgcallnode.pushparas;
+ var
+ ppn : tcgcallparanode;
+ callerparaloc,
+ tmpparaloc : pcgparalocation;
+ sizeleft: aint;
+{$ifdef cputargethasfixedstack}
+ htempref,
+ href : treference;
+{$endif cputargethasfixedstack}
+ begin
+ { copy all resources to the allocated registers }
+ ppn:=tcgcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if (ppn.left.nodetype<>nothingn) then
+ begin
+ { better check for the real location of the parameter here, when stack passed parameters
+ are saved temporary in registers, checking for the tmpparaloc.loc is wrong
+ }
+ paramanager.freeparaloc(exprasmlist,ppn.tempcgpara);
+ tmpparaloc:=ppn.tempcgpara.location;
+ sizeleft:=ppn.tempcgpara.intsize;
+ callerparaloc:=ppn.parasym.paraloc[callerside].location;
+ while assigned(callerparaloc) do
+ begin
+ { Every paraloc must have a matching tmpparaloc }
+ if not assigned(tmpparaloc) then
+ internalerror(200408224);
+ if callerparaloc^.size<>tmpparaloc^.size then
+ internalerror(200408225);
+ case callerparaloc^.loc of
+ LOC_REGISTER:
+ begin
+ if tmpparaloc^.loc<>LOC_REGISTER then
+ internalerror(200408221);
+ if getsupreg(callerparaloc^.register)<first_int_imreg then
+ cg.getcpuregister(exprasmlist,callerparaloc^.register);
+ cg.a_load_reg_reg(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,
+ tmpparaloc^.register,callerparaloc^.register);
+ end;
+ LOC_FPUREGISTER:
+ begin
+ if tmpparaloc^.loc<>LOC_FPUREGISTER then
+ internalerror(200408222);
+ if getsupreg(callerparaloc^.register)<first_fpu_imreg then
+ cg.getcpuregister(exprasmlist,callerparaloc^.register);
+ cg.a_loadfpu_reg_reg(exprasmlist,ppn.tempcgpara.size,tmpparaloc^.register,callerparaloc^.register);
+ end;
+ LOC_MMREGISTER:
+ begin
+ if tmpparaloc^.loc<>LOC_MMREGISTER then
+ internalerror(200408223);
+ if getsupreg(callerparaloc^.register)<first_mm_imreg then
+ cg.getcpuregister(exprasmlist,callerparaloc^.register);
+ cg.a_loadmm_reg_reg(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,
+ tmpparaloc^.register,callerparaloc^.register,mms_movescalar);
+ end;
+ LOC_REFERENCE:
+ begin
+{$ifdef cputargethasfixedstack}
+ { Can't have a data copied to the stack, every location
+ must contain a valid size field }
+
+ if (ppn.tempcgpara.size=OS_NO) and
+ ((tmpparaloc^.loc<>LOC_REFERENCE) or
+ assigned(tmpparaloc^.next)) then
+ internalerror(200501281);
+ reference_reset_base(href,callerparaloc^.reference.index,callerparaloc^.reference.offset);
+ { copy parameters in case they were moved to a temp. location because we've a fixed stack }
+ case tmpparaloc^.loc of
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(htempref,tmpparaloc^.reference.index,tmpparaloc^.reference.offset);
+ { use concatcopy, because it can also be a float which fails when
+ load_ref_ref is used }
+ if (ppn.tempcgpara.size <> OS_NO) then
+ cg.g_concatcopy(exprasmlist,htempref,href,tcgsize2size[tmpparaloc^.size])
+ else
+ cg.g_concatcopy(exprasmlist,htempref,href,sizeleft)
+ end;
+ LOC_REGISTER:
+ cg.a_load_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
+ LOC_FPUREGISTER:
+ cg.a_loadfpu_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.register,href);
+ LOC_MMREGISTER:
+ cg.a_loadmm_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href,mms_movescalar);
+ else
+ internalerror(200402081);
+ end;
+{$endif cputargethasfixedstack}
+ end;
+ end;
+ dec(sizeleft,tcgsize2size[tmpparaloc^.size]);
+ callerparaloc:=callerparaloc^.next;
+ tmpparaloc:=tmpparaloc^.next;
+ end;
+ end;
+ ppn:=tcgcallparanode(ppn.right);
+ end;
+ end;
+
+
+ procedure tcgcallnode.freeparas;
+ var
+ ppn : tcgcallparanode;
+ begin
+ { free the resources allocated for the parameters }
+ ppn:=tcgcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if (ppn.left.nodetype<>nothingn) then
+ begin
+ if (ppn.parasym.paraloc[callerside].location^.loc <> LOC_REFERENCE) then
+ paramanager.freeparaloc(exprasmlist,ppn.parasym.paraloc[callerside]);
+ end;
+ ppn:=tcgcallparanode(ppn.right);
+ end;
+ end;
+
+
+
+ procedure tcgcallnode.pass_2;
+ var
+ regs_to_save_int,
+ regs_to_save_fpu,
+ regs_to_save_mm : Tcpuregisterset;
+ href : treference;
+ pop_size : longint;
+ pvreg,
+ vmtreg : tregister;
+ oldaktcallnode : tcallnode;
+ begin
+ if not assigned(procdefinition) or
+ not procdefinition.has_paraloc_info then
+ internalerror(200305264);
+
+ if assigned(methodpointerinit) then
+ secondpass(methodpointerinit);
+
+ if resulttype.def.needs_inittable and
+ not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) and
+ not assigned(funcretnode) then
+ begin
+ tg.gettemptyped(exprasmlist,resulttype.def,tt_normal,refcountedtemp);
+ cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp);
+ end;
+
+ regs_to_save_int:=paramanager.get_volatile_registers_int(procdefinition.proccalloption);
+ regs_to_save_fpu:=paramanager.get_volatile_registers_fpu(procdefinition.proccalloption);
+ regs_to_save_mm:=paramanager.get_volatile_registers_mm(procdefinition.proccalloption);
+
+ { Include Function result registers }
+ if (not is_void(resulttype.def)) then
+ begin
+ case procdefinition.funcretloc[callerside].loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ include(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ include(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ include(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
+ LOC_REFERENCE,
+ LOC_VOID:
+ ;
+ else
+ internalerror(2004110213);
+ end;
+ end;
+
+ { Process parameters, register parameters will be loaded
+ in imaginary registers. The actual load to the correct
+ register is done just before the call }
+ oldaktcallnode:=aktcallnode;
+ aktcallnode:=self;
+ if assigned(left) then
+ tcallparanode(left).secondcallparan;
+ aktcallnode:=oldaktcallnode;
+
+ { procedure variable or normal function call ? }
+ if (right=nil) then
+ begin
+ { When methodpointer is typen we don't need (and can't) load
+ a pointer. We can directly call the correct procdef (PFV) }
+ if (po_virtualmethod in procdefinition.procoptions) and
+ assigned(methodpointer) and
+ (methodpointer.nodetype<>typen) then
+ begin
+ { virtual methods require an index }
+ if tprocdef(procdefinition).extnumber=$ffff then
+ internalerror(200304021);
+
+ secondpass(methodpointer);
+
+ { Load VMT from self }
+ if methodpointer.resulttype.def.deftype=objectdef then
+ gen_load_vmt_register(exprasmlist,tobjectdef(methodpointer.resulttype.def),methodpointer.location,vmtreg)
+ else
+ begin
+ { Load VMT value in register }
+ location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
+ vmtreg:=methodpointer.location.register;
+ end;
+
+ { test validity of VMT }
+ if not(is_interface(tprocdef(procdefinition)._class)) and
+ not(is_cppclass(tprocdef(procdefinition)._class)) then
+ cg.g_maybe_testvmt(exprasmlist,vmtreg,tprocdef(procdefinition)._class);
+
+ pvreg:=cg.getintregister(exprasmlist,OS_ADDR);
+ reference_reset_base(href,vmtreg,
+ tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,pvreg);
+
+ { Load parameters that are in temporary registers in the
+ correct parameter register }
+ if assigned(left) then
+ begin
+ pushparas;
+ { free the resources allocated for the parameters }
+ freeparas;
+ end;
+
+ cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
+ if cg.uses_registers(R_FPUREGISTER) then
+ cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
+ if cg.uses_registers(R_MMREGISTER) then
+ cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
+
+ { call method }
+ extra_call_code;
+ cg.a_call_reg(exprasmlist,pvreg);
+ extra_post_call_code;
+ end
+ else
+ begin
+ { Load parameters that are in temporary registers in the
+ correct parameter register }
+ if assigned(left) then
+ begin
+ pushparas;
+ { free the resources allocated for the parameters }
+ freeparas;
+ end;
+
+ cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
+ if cg.uses_registers(R_FPUREGISTER) then
+ cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
+ if cg.uses_registers(R_MMREGISTER) then
+ cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
+
+ if procdefinition.proccalloption=pocall_syscall then
+ do_syscall
+ else
+ begin
+ { Calling interrupt from the same code requires some
+ extra code }
+ if (po_interrupt in procdefinition.procoptions) then
+ extra_interrupt_code;
+ extra_call_code;
+ cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
+ extra_post_call_code;
+ end;
+ end;
+ end
+ else
+ { now procedure variable case }
+ begin
+ secondpass(right);
+
+ pvreg:=cg.getintregister(exprasmlist,OS_ADDR);
+ { Only load OS_ADDR from the reference }
+ if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,right.location.reference,pvreg)
+ else
+ cg.a_load_loc_reg(exprasmlist,OS_ADDR,right.location,pvreg);
+ location_freetemp(exprasmlist,right.location);
+
+ { Load parameters that are in temporary registers in the
+ correct parameter register }
+ if assigned(left) then
+ begin
+ pushparas;
+ { free the resources allocated for the parameters }
+ freeparas;
+ end;
+
+ cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
+ if cg.uses_registers(R_FPUREGISTER) then
+ cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
+ if cg.uses_registers(R_MMREGISTER) then
+ cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
+
+ { Calling interrupt from the same code requires some
+ extra code }
+ if (po_interrupt in procdefinition.procoptions) then
+ extra_interrupt_code;
+ extra_call_code;
+ cg.a_call_reg(exprasmlist,pvreg);
+ extra_post_call_code;
+ end;
+
+ { Need to remove the parameters from the stack? }
+ if (procdefinition.proccalloption in clearstack_pocalls) then
+ begin
+ pop_size:=pushedparasize;
+ { for Cdecl functions we don't need to pop the funcret when it
+ was pushed by para }
+ if paramanager.ret_in_param(procdefinition.rettype.def,procdefinition.proccalloption) then
+ dec(pop_size,sizeof(aint));
+ { Remove parameters/alignment from the stack }
+ pop_parasize(pop_size);
+ end;
+
+ { Release registers, but not the registers that contain the
+ function result }
+ if (not is_void(resulttype.def)) then
+ begin
+ case procdefinition.funcretloc[callerside].loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+{$ifndef cpu64bit}
+ if procdefinition.funcretloc[callerside].size in [OS_64,OS_S64] then
+ begin
+ exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register64.reghi));
+ exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register64.reglo));
+ end
+ else
+{$endif cpu64bit}
+ exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ exclude(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ exclude(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
+ LOC_REFERENCE,
+ LOC_VOID:
+ ;
+ else
+ internalerror(2004110214);
+ end;
+ end;
+ if cg.uses_registers(R_MMREGISTER) then
+ cg.dealloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
+ if cg.uses_registers(R_FPUREGISTER) then
+ cg.dealloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
+ cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
+
+ { handle function results }
+ if (not is_void(resulttype.def)) then
+ handle_return_value
+ else
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { perhaps i/o check ? }
+ if (cs_check_io in aktlocalswitches) and
+ (po_iocheck in procdefinition.procoptions) and
+ not(po_iocheck in current_procinfo.procdef.procoptions) and
+ { no IO check for methods and procedure variables }
+ (right=nil) and
+ not(po_virtualmethod in procdefinition.procoptions) then
+ begin
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_IOCHECK');
+ cg.deallocallcpuregisters(exprasmlist);
+ end;
+
+ { release temps of paras }
+ release_para_temps;
+
+
+ if assigned(methodpointerdone) then
+ secondpass(methodpointerdone);
+ end;
+
+
+begin
+ ccallparanode:=tcgcallparanode;
+ ccallnode:=tcgcallnode;
+end.
diff --git a/compiler/ncgcnv.pas b/compiler/ncgcnv.pas
new file mode 100644
index 0000000000..cb2770adf5
--- /dev/null
+++ b/compiler/ncgcnv.pas
@@ -0,0 +1,566 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Generate assembler for nodes that handle type conversions which are
+ the same for all (most) processors
+
+ 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 ncgcnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,defutil,defcmp;
+
+ type
+ tcgtypeconvnode = class(ttypeconvnode)
+ procedure second_int_to_int;override;
+ procedure second_cstring_to_pchar;override;
+ procedure second_cstring_to_int;override;
+ procedure second_string_to_chararray;override;
+ procedure second_array_to_pointer;override;
+ procedure second_pointer_to_array;override;
+ procedure second_char_to_string;override;
+ procedure second_real_to_real;override;
+ procedure second_cord_to_pointer;override;
+ procedure second_proc_to_procvar;override;
+ procedure second_bool_to_int;override;
+ procedure second_bool_to_bool;override;
+ procedure second_ansistring_to_pchar;override;
+ procedure second_class_to_intf;override;
+ procedure second_char_to_char;override;
+ procedure second_nothing;override;
+ procedure pass_2;override;
+ end;
+
+ tcgasnode = class(tasnode)
+ procedure pass_2;override;
+ end;
+
+ implementation
+
+ uses
+ cutils,verbose,globtype,globals,
+ aasmbase,aasmtai,aasmcpu,symconst,symdef,paramgr,
+ ncon,ncal,
+ cpubase,systems,
+ pass_2,
+ cgbase,
+ cgutils,cgobj,
+ ncgutil,
+ tgobj
+ ;
+
+
+ procedure tcgtypeconvnode.second_int_to_int;
+ var
+ orgsize,
+ newsize : tcgsize;
+ ressize,
+ leftsize : longint;
+ begin
+ newsize:=def_cgsize(resulttype.def);
+
+ { insert range check if not explicit conversion }
+ if not(nf_explicit in flags) then
+ cg.g_rangecheck(exprasmlist,left.location,left.resulttype.def,resulttype.def);
+
+ { is the result size smaller? when typecasting from void
+ we always reuse the current location, because there is
+ nothing that we can load in a register }
+ ressize := resulttype.def.size;
+ leftsize := left.resulttype.def.size;
+ if (ressize<>leftsize) and
+ not is_void(left.resulttype.def) then
+ begin
+ location_copy(location,left.location);
+ { reuse a loc_reference when the newsize is smaller than
+ than the original, else load it to a register }
+ if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
+ (ressize<leftsize) then
+ begin
+ location.size:=newsize;
+ if (target_info.endian = ENDIAN_BIG) then
+ inc(location.reference.offset,leftsize-ressize);
+ end
+ else
+ location_force_reg(exprasmlist,location,newsize,false);
+{$ifndef cpu64bit}
+ // if is_signed(left.resulttype) and
+{$endif cpu64bit}
+ end
+ else
+ begin
+ { no special loading is required, reuse current location }
+
+ { that's not true, if you go from signed to unsiged or }
+ { vice versa, you need sign extension/removal if the }
+ { value is already in a register (at least for archs }
+ { which don't have 8bit register components etc) (JM) }
+ location_copy(location,left.location);
+ location.size:=newsize;
+ orgsize := def_cgsize(left.resulttype.def);
+ if (ressize < tcgsize2size[OS_INT]) and
+ (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
+ (orgsize <> newsize) then
+ begin
+ location.register := cg.getintregister(exprasmlist,newsize);
+ location.loc := LOC_REGISTER;
+ cg.a_load_reg_reg(exprasmlist,orgsize,newsize,left.location.register,location.register);
+ end;
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_cstring_to_pchar;
+
+ var
+ hr : treference;
+
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ case tstringdef(left.resulttype.def).string_typ of
+ st_conststring :
+ begin
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
+ end;
+ st_shortstring :
+ begin
+ inc(left.location.reference.offset);
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
+ end;
+ st_ansistring :
+ begin
+ if (left.nodetype=stringconstn) and
+ (str_length(left)=0) then
+ begin
+ reference_reset(hr);
+ hr.symbol:=objectlibrary.newasmsymbol('FPC_EMPTYCHAR',AB_EXTERNAL,AT_DATA);
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
+ end
+ else
+ begin
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.register);
+ end;
+ end;
+ st_longstring:
+ begin
+ {!!!!!!!}
+ internalerror(8888);
+ end;
+ st_widestring:
+ begin
+ if (left.nodetype=stringconstn) and
+ (str_length(left)=0) then
+ begin
+ reference_reset(hr);
+ hr.symbol:=objectlibrary.newasmsymbol('FPC_EMPTYCHAR',AB_EXTERNAL,AT_DATA);
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
+ end
+ else
+ begin
+ location.register:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_INT,left.location.reference,
+ location.register);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_cstring_to_int;
+ begin
+ { this can't happen because constants are already processed in
+ pass 1 }
+ internalerror(200510013);
+ end;
+
+
+ procedure tcgtypeconvnode.second_string_to_chararray;
+ begin
+ if (left.nodetype = stringconstn) and
+ (tstringdef(left.resulttype.def).string_typ=st_conststring) then
+ begin
+ location_copy(location,left.location);
+ exit;
+ end;
+ { should be handled already in resulttype pass (JM) }
+ internalerror(200108292);
+ end;
+
+
+ procedure tcgtypeconvnode.second_array_to_pointer;
+
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
+ end;
+
+
+ procedure tcgtypeconvnode.second_pointer_to_array;
+
+ begin
+ location_reset(location,LOC_REFERENCE,OS_NO);
+ case left.location.loc of
+ LOC_REGISTER :
+ begin
+ {$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ location.reference.base:=rg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
+ left.location.register,location.reference.base);
+ end
+ else
+ {$endif}
+ location.reference.base := left.location.register;
+ end;
+ LOC_CREGISTER :
+ begin
+ location.reference.base:=cg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,
+ location.reference.base);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location.reference.base:=cg.getaddressregister(exprasmlist);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,
+ location.reference.base);
+ location_freetemp(exprasmlist,left.location);
+ end;
+ else
+ internalerror(2002032216);
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_char_to_string;
+ begin
+ location_reset(location,LOC_REFERENCE,OS_NO);
+ case tstringdef(resulttype.def).string_typ of
+ st_shortstring :
+ begin
+ tg.GetTemp(exprasmlist,256,tt_normal,location.reference);
+ cg.a_load_loc_ref(exprasmlist,left.location.size,left.location,
+ location.reference);
+ location_freetemp(exprasmlist,left.location);
+ end;
+ { the rest is removed in the resulttype pass and converted to compilerprocs }
+ else
+ internalerror(4179);
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_real_to_real;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+{$ifdef x86}
+ { extended types in memory which should be loaded into the sse unit
+ must be converted by the fpu first, so force them to be loaded into
+ the fpu }
+ if (expectloc=LOC_MMREGISTER) and
+ (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
+ (left.location.size=OS_F80) then
+ location_force_fpureg(exprasmlist,left.location,false);
+{$endif x86}
+ case left.location.loc of
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ location_copy(location,left.location);
+ location.size:=def_cgsize(resulttype.def);
+ case expectloc of
+ LOC_FPUREGISTER:
+ ;
+ LOC_MMREGISTER:
+ location_force_mmregscalar(exprasmlist,location,false);
+ else
+ internalerror(2003012262);
+ end;
+ exit
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ if expectloc=LOC_MMREGISTER then
+ begin
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resulttype.def));
+ location.register:=cg.getmmregister(exprasmlist,location.size);
+ cg.a_loadmm_loc_reg(exprasmlist,location.size,left.location,location.register,mms_movescalar)
+ end
+ else
+ begin
+ location.register:=cg.getfpuregister(exprasmlist,left.location.size);
+ cg.a_loadfpu_loc_reg(exprasmlist,left.location,location.register);
+ end;
+ location_freetemp(exprasmlist,left.location);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ location_copy(location,left.location);
+ case expectloc of
+ LOC_FPUREGISTER:
+ begin
+ location_force_fpureg(exprasmlist,location,false);
+ location.size:=def_cgsize(resulttype.def);
+ end;
+ LOC_MMREGISTER:
+ ;
+ else
+ internalerror(2003012261);
+ end;
+ end;
+ else
+ internalerror(2002032215);
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_cord_to_pointer;
+ begin
+ { this can't happen because constants are already processed in
+ pass 1 }
+ internalerror(47423985);
+ end;
+
+
+ procedure tcgtypeconvnode.second_proc_to_procvar;
+ begin
+ if tabstractprocdef(resulttype.def).is_addressonly then
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
+ end
+ else
+ location_copy(location,left.location);
+ end;
+
+
+ procedure tcgtypeconvnode.second_bool_to_int;
+ var
+ oldtruelabel,oldfalselabel : tasmlabel;
+ begin
+ oldtruelabel:=truelabel;
+ oldfalselabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ location_copy(location,left.location);
+ { byte(boolean) or word(wordbool) or longint(longbool) must }
+ { be accepted for var parameters }
+ if not((nf_explicit in flags) and
+ (left.resulttype.def.size=resulttype.def.size) and
+ (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER])) then
+ location_force_reg(exprasmlist,location,def_cgsize(resulttype.def),false);
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ end;
+
+
+ procedure tcgtypeconvnode.second_bool_to_bool;
+ begin
+ { we can reuse the conversion already available
+ in bool_to_int to resize the value. But when the
+ size of the new boolean is smaller we need to calculate
+ the value as is done in int_to_bool. This is needed because
+ the bits that define the true status can be outside the limits
+ of the new size and truncating the register can result in a 0
+ value }
+ if resulttype.def.size<left.resulttype.def.size then
+ second_int_to_bool
+ else
+ second_bool_to_int;
+ end;
+
+
+ procedure tcgtypeconvnode.second_ansistring_to_pchar;
+ var
+ l1 : tasmlabel;
+ hr : treference;
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ objectlibrary.getjumplabel(l1);
+ case left.location.loc of
+ LOC_CREGISTER,LOC_REGISTER:
+ begin
+ {$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
+ left.location.register,location.register);
+ end
+ else
+ {$endif}
+ location.register := left.location.register;
+ end;
+ LOC_CREFERENCE,LOC_REFERENCE:
+ begin
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.register);
+ end;
+ else
+ internalerror(2002032214);
+ end;
+ cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_NE,0,location.register,l1);
+ reference_reset(hr);
+ hr.symbol:=objectlibrary.newasmsymbol('FPC_EMPTYCHAR',AB_EXTERNAL,AT_DATA);
+ cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
+ cg.a_label(exprasmlist,l1);
+ end;
+
+
+ procedure tcgtypeconvnode.second_class_to_intf;
+ var
+ l1 : tasmlabel;
+ hd : tobjectdef;
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.register);
+ location_freetemp(exprasmlist,left.location);
+ end;
+ LOC_CREGISTER:
+ begin
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,location.register);
+ end;
+ LOC_REGISTER:
+ location.register:=left.location.register;
+ else
+ internalerror(121120001);
+ end;
+ objectlibrary.getjumplabel(l1);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,location.register,l1);
+ hd:=tobjectdef(left.resulttype.def);
+ while assigned(hd) do
+ begin
+ if hd.implementedinterfaces.searchintf(resulttype.def)<>-1 then
+ begin
+ cg.a_op_const_reg(exprasmlist,OP_ADD,OS_ADDR,
+ hd.implementedinterfaces.ioffsets(
+ hd.implementedinterfaces.searchintf(resulttype.def)),location.register);
+ break;
+ end;
+ hd:=hd.childof;
+ end;
+ if hd=nil then
+ internalerror(2002081301);
+ cg.a_label(exprasmlist,l1);
+ end;
+
+
+ procedure tcgtypeconvnode.second_char_to_char;
+ begin
+{$ifdef fpc}
+ {$warning todo: add RTL routine for widechar-char conversion }
+{$endif}
+ { Quick hack to at least generate 'working' code (PFV) }
+ second_int_to_int;
+ end;
+
+
+ procedure tcgtypeconvnode.second_nothing;
+ var
+ newsize : tcgsize;
+ begin
+ { we reuse the old value }
+ location_copy(location,left.location);
+
+ { Floats should never be returned as LOC_CONSTANT, do the
+ moving to memory before the new size is set.
+ Also when converting from a float to a non-float
+ or the other way round, move to memory first to prevent
+ invalid LOC_FPUREGISTER locations }
+ if (
+ (resulttype.def.deftype=floatdef) and
+ (location.loc=LOC_CONSTANT)
+ ) or
+ (
+ (left.resulttype.def.deftype=floatdef) xor
+ (resulttype.def.deftype=floatdef)
+ ) then
+ location_force_mem(exprasmlist,location);
+
+ { but use the new size, but we don't know the size of all arrays }
+ newsize:=def_cgsize(resulttype.def);
+ location.size:=newsize;
+ end;
+
+
+{$ifdef TESTOBJEXT2}
+ procedure tcgtypeconvnode.checkobject;
+ begin
+ { no checking by default }
+ end;
+{$endif TESTOBJEXT2}
+
+
+ procedure tcgtypeconvnode.pass_2;
+ begin
+ { the boolean routines can be called with LOC_JUMP and
+ call secondpass themselves in the helper }
+ if not(convtype in [tc_bool_2_int,tc_bool_2_bool,tc_int_2_bool]) then
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ end;
+
+ second_call_helper(convtype);
+
+{$ifdef TESTOBJEXT2}
+ { Check explicit conversions to objects pointers !! }
+ if p^.explizit and
+ (p^.resulttype.def.deftype=pointerdef) and
+ (tpointerdef(p^.resulttype.def).definition.deftype=objectdef) and not
+ (tobjectdef(tpointerdef(p^.resulttype.def).definition).isclass) and
+ ((tobjectdef(tpointerdef(p^.resulttype.def).definition).options and oo_hasvmt)<>0) and
+ (cs_check_range in aktlocalswitches) then
+ checkobject;
+{$endif TESTOBJEXT2}
+ end;
+
+
+ procedure tcgasnode.pass_2;
+ begin
+ secondpass(call);
+ location_copy(location,call.location);
+ end;
+
+
+begin
+ ctypeconvnode := tcgtypeconvnode;
+ casnode := tcgasnode;
+end.
diff --git a/compiler/ncgcon.pas b/compiler/ncgcon.pas
new file mode 100644
index 0000000000..336cc65a1c
--- /dev/null
+++ b/compiler/ncgcon.pas
@@ -0,0 +1,617 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for constant nodes which are the same for
+ all (most) processors
+
+ 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 ncgcon;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncon;
+
+ type
+ tcgrealconstnode = class(trealconstnode)
+ procedure pass_2;override;
+ end;
+
+ tcgordconstnode = class(tordconstnode)
+ procedure pass_2;override;
+ end;
+
+ tcgpointerconstnode = class(tpointerconstnode)
+ procedure pass_2;override;
+ end;
+
+ tcgstringconstnode = class(tstringconstnode)
+ procedure pass_2;override;
+ end;
+
+ tcgsetconstnode = class(tsetconstnode)
+ procedure pass_2;override;
+ end;
+
+ tcgnilnode = class(tnilnode)
+ procedure pass_2;override;
+ end;
+
+ tcgguidconstnode = class(tguidconstnode)
+ procedure pass_2;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,widestr,systems,
+ verbose,globals,
+ symconst,symdef,aasmbase,aasmtai,aasmcpu,defutil,
+ cpuinfo,cpubase,
+ cgbase,cgobj,cgutils,
+ ncgutil
+ ;
+
+
+{*****************************************************************************
+ TCGREALCONSTNODE
+*****************************************************************************}
+
+ procedure tcgrealconstnode.pass_2;
+ { I suppose the parser/pass_1 must make sure the generated real }
+ { constants are actually supported by the target processor? (JM) }
+ const
+ floattype2ait:array[tfloattype] of taitype=
+ (ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_comp_64bit,ait_real_128bit);
+ var
+ hp1 : tai;
+ lastlabel : tasmlabel;
+ realait : taitype;
+{$ifdef ARM}
+ hiloswapped : boolean;
+{$endif ARM}
+
+ begin
+ location_reset(location,LOC_CREFERENCE,def_cgsize(resulttype.def));
+ lastlabel:=nil;
+ realait:=floattype2ait[tfloatdef(resulttype.def).typ];
+{$ifdef ARM}
+ hiloswapped:=aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11];
+{$endif ARM}
+ { const already used ? }
+ if not assigned(lab_real) then
+ begin
+ { tries to find an old entry }
+ hp1:=tai(asmlist[al_typedconsts].first);
+ while assigned(hp1) do
+ begin
+ if hp1.typ=ait_label then
+ lastlabel:=tai_label(hp1).l
+ else
+ begin
+ if (hp1.typ=realait) and (lastlabel<>nil) then
+ begin
+ if is_number_float(value_real) and
+ (
+ ((realait=ait_real_32bit) and (tai_real_32bit(hp1).value=value_real) and is_number_float(tai_real_32bit(hp1).value)) or
+ ((realait=ait_real_64bit) and
+{$ifdef ARM}
+ ((tai_real_64bit(hp1).formatoptions=fo_hiloswapped)=hiloswapped) and
+{$endif ARM}
+ (tai_real_64bit(hp1).value=value_real) and is_number_float(tai_real_64bit(hp1).value)) or
+ ((realait=ait_real_80bit) and (tai_real_80bit(hp1).value=value_real) and is_number_float(tai_real_80bit(hp1).value)) or
+{$ifdef cpufloat128}
+ ((realait=ait_real_128bit) and (tai_real_128bit(hp1).value=value_real) and is_number_float(tai_real_128bit(hp1).value)) or
+{$endif cpufloat128}
+ ((realait=ait_comp_64bit) and (tai_comp_64bit(hp1).value=value_real) and is_number_float(tai_comp_64bit(hp1).value))
+ ) then
+ begin
+ { found! }
+ lab_real:=lastlabel;
+ break;
+ end;
+ end;
+ lastlabel:=nil;
+ end;
+ hp1:=tai(hp1.next);
+ end;
+ { :-(, we must generate a new entry }
+ if not assigned(lab_real) then
+ begin
+ objectlibrary.getdatalabel(lastlabel);
+ lab_real:=lastlabel;
+ maybe_new_object_file(asmlist[al_typedconsts]);
+ new_section(asmlist[al_typedconsts],sec_rodata,lastlabel.name,const_align(resulttype.def.size));
+ asmlist[al_typedconsts].concat(Tai_label.Create(lastlabel));
+ case realait of
+ ait_real_32bit :
+ begin
+ asmlist[al_typedconsts].concat(Tai_real_32bit.Create(ts32real(value_real)));
+ { range checking? }
+ if ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) and
+ (tai_real_32bit(asmlist[al_typedconsts].last).value=double(MathInf)) then
+ Message(parser_e_range_check_error);
+ end;
+
+ ait_real_64bit :
+ begin
+{$ifdef ARM}
+ if hiloswapped then
+ asmlist[al_typedconsts].concat(Tai_real_64bit.Create_hiloswapped(ts64real(value_real)))
+ else
+{$endif ARM}
+ asmlist[al_typedconsts].concat(Tai_real_64bit.Create(ts64real(value_real)));
+
+ { range checking? }
+ if ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) and
+ (tai_real_64bit(asmlist[al_typedconsts].last).value=double(MathInf)) then
+ Message(parser_e_range_check_error);
+ end;
+
+ ait_real_80bit :
+ begin
+ asmlist[al_typedconsts].concat(Tai_real_80bit.Create(value_real));
+
+ { range checking? }
+ if ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) and
+ (tai_real_80bit(asmlist[al_typedconsts].last).value=double(MathInf)) then
+ Message(parser_e_range_check_error);
+ end;
+{$ifdef cpufloat128}
+ ait_real_128bit :
+ begin
+ asmlist[al_typedconsts].concat(Tai_real_128bit.Create(value_real));
+
+ { range checking? }
+ if ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) and
+ (tai_real_128bit(asmlist[al_typedconsts].last).value=double(MathInf)) then
+ Message(parser_e_range_check_error);
+ end;
+{$endif cpufloat128}
+
+ { the round is necessary for native compilers where comp isn't a float }
+ ait_comp_64bit :
+ if (value_real>9223372036854775807.0) or (value_real<-9223372036854775808.0) then
+ message(parser_e_range_check_error)
+ else
+ asmlist[al_typedconsts].concat(Tai_comp_64bit.Create(round(value_real)));
+ else
+ internalerror(10120);
+ end;
+ end;
+ end;
+ location.reference.symbol:=lab_real;
+ end;
+
+{*****************************************************************************
+ TCGORDCONSTNODE
+*****************************************************************************}
+
+ procedure tcgordconstnode.pass_2;
+ begin
+ location_reset(location,LOC_CONSTANT,def_cgsize(resulttype.def));
+{$ifdef cpu64bit}
+ location.value:=value;
+{$else cpu64bit}
+ location.value64:=int64(value);
+{$endif cpu64bit}
+ end;
+
+
+{*****************************************************************************
+ TCGPOINTERCONSTNODE
+*****************************************************************************}
+
+ procedure tcgpointerconstnode.pass_2;
+ begin
+ { an integer const. behaves as a memory reference }
+ location_reset(location,LOC_CONSTANT,OS_ADDR);
+ location.value:=aint(value);
+ end;
+
+
+{*****************************************************************************
+ TCGSTRINGCONSTNODE
+*****************************************************************************}
+
+ procedure tcgstringconstnode.pass_2;
+ var
+ hp1,hp2 : tai;
+ l1,l2,
+ lastlabel : tasmlabel;
+ lastlabelhp : tai;
+ pc : pchar;
+ same_string : boolean;
+ l,j,
+ i,mylength : longint;
+ begin
+ { for empty ansistrings we could return a constant 0 }
+ if (st_type in [st_ansistring,st_widestring]) and (len=0) then
+ begin
+ location_reset(location,LOC_CONSTANT,OS_ADDR);
+ location.value:=0;
+ exit;
+ end;
+ { return a constant reference in memory }
+ location_reset(location,LOC_CREFERENCE,def_cgsize(resulttype.def));
+ { const already used ? }
+ lastlabel:=nil;
+ lastlabelhp:=nil;
+ if not assigned(lab_str) then
+ begin
+ if is_shortstring(resulttype.def) then
+ mylength:=len+2
+ else
+ mylength:=len+1;
+ { widestrings can't be reused yet }
+ if not(is_widestring(resulttype.def)) then
+ begin
+ { tries to find an old entry }
+ hp1:=tai(asmlist[al_typedconsts].first);
+ while assigned(hp1) do
+ begin
+ if hp1.typ=ait_label then
+ begin
+ lastlabel:=tai_label(hp1).l;
+ lastlabelhp:=hp1;
+ end
+ else
+ begin
+ same_string:=false;
+ if (hp1.typ=ait_string) and
+ (lastlabel<>nil) and
+ (tai_string(hp1).len=mylength) then
+ begin
+ case st_type of
+ st_conststring:
+ begin
+ j:=0;
+ same_string:=true;
+ if len>0 then
+ begin
+ for i:=0 to len-1 do
+ begin
+ if tai_string(hp1).str[j]<>value_str[i] then
+ begin
+ same_string:=false;
+ break;
+ end;
+ inc(j);
+ end;
+ end;
+ end;
+ st_shortstring:
+ begin
+ { if shortstring then check the length byte first and
+ set the start index to 1 }
+ if len=ord(tai_string(hp1).str[0]) then
+ begin
+ j:=1;
+ same_string:=true;
+ if len>0 then
+ begin
+ for i:=0 to len-1 do
+ begin
+ if tai_string(hp1).str[j]<>value_str[i] then
+ begin
+ same_string:=false;
+ break;
+ end;
+ inc(j);
+ end;
+ end;
+ end;
+ end;
+ st_ansistring,
+ st_widestring :
+ begin
+ { before the string the following sequence must be found:
+ <label>
+ constsymbol <datalabel>
+ constint -1
+ constint <len>
+ we must then return <label> to reuse
+ }
+ hp2:=tai(lastlabelhp.previous);
+ if assigned(hp2) and
+ (hp2.typ=ait_const_aint) and
+ (tai_const(hp2).value=-1) and
+ assigned(hp2.previous) and
+ (tai(hp2.previous).typ=ait_const_aint) and
+ (tai_const(hp2.previous).value=len) and
+ assigned(hp2.previous.previous) and
+ (tai(hp2.previous.previous).typ=ait_const_ptr) and
+ assigned(hp2.previous.previous.previous) and
+ (tai(hp2.previous.previous.previous).typ=ait_label) then
+ begin
+ lastlabel:=tai_label(hp2.previous.previous.previous).l;
+ same_string:=true;
+ j:=0;
+ if len>0 then
+ begin
+ for i:=0 to len-1 do
+ begin
+ if tai_string(hp1).str[j]<>value_str[i] then
+ begin
+ same_string:=false;
+ break;
+ end;
+ inc(j);
+ end;
+ end;
+ end;
+ end;
+ end;
+ { found ? }
+ if same_string then
+ begin
+ lab_str:=lastlabel;
+ break;
+ end;
+ end;
+ lastlabel:=nil;
+ end;
+ hp1:=tai(hp1.next);
+ end;
+ end;
+ { :-(, we must generate a new entry }
+ if not assigned(lab_str) then
+ begin
+ objectlibrary.getdatalabel(lastlabel);
+ lab_str:=lastlabel;
+ maybe_new_object_file(asmlist[al_typedconsts]);
+ new_section(asmlist[al_typedconsts],sec_rodata,lastlabel.name,const_align(sizeof(aint)));
+ asmlist[al_typedconsts].concat(Tai_label.Create(lastlabel));
+ { generate an ansi string ? }
+ case st_type of
+ st_ansistring:
+ begin
+ { an empty ansi string is nil! }
+ if len=0 then
+ asmlist[al_typedconsts].concat(Tai_const.Create_sym(nil))
+ else
+ begin
+ objectlibrary.getdatalabel(l1);
+ objectlibrary.getdatalabel(l2);
+ asmlist[al_typedconsts].concat(Tai_label.Create(l2));
+ asmlist[al_typedconsts].concat(Tai_const.Create_sym(l1));
+ asmlist[al_typedconsts].concat(Tai_const.Create_aint(-1));
+ asmlist[al_typedconsts].concat(Tai_const.Create_aint(len));
+ asmlist[al_typedconsts].concat(Tai_label.Create(l1));
+ { include also terminating zero }
+ getmem(pc,len+1);
+ move(value_str^,pc^,len);
+ pc[len]:=#0;
+ asmlist[al_typedconsts].concat(Tai_string.Create_pchar(pc,len+1));
+ { return the offset of the real string }
+ lab_str:=l2;
+ end;
+ end;
+ st_widestring:
+ begin
+ { an empty wide string is nil! }
+ if len=0 then
+ asmlist[al_typedconsts].concat(Tai_const.Create_sym(nil))
+ else
+ begin
+ objectlibrary.getdatalabel(l1);
+ objectlibrary.getdatalabel(l2);
+ asmlist[al_typedconsts].concat(Tai_label.Create(l2));
+ asmlist[al_typedconsts].concat(Tai_const.Create_sym(l1));
+
+ { we use always UTF-16 coding for constants }
+ { at least for now }
+ { Consts.concat(Tai_const.Create_8bit(2)); }
+ asmlist[al_typedconsts].concat(Tai_const.Create_aint(-1));
+ asmlist[al_typedconsts].concat(Tai_const.Create_aint(len*cwidechartype.def.size));
+ asmlist[al_typedconsts].concat(Tai_label.Create(l1));
+ for i:=0 to len-1 do
+ asmlist[al_typedconsts].concat(Tai_const.Create_16bit(pcompilerwidestring(value_str)^.data[i]));
+ { terminating zero }
+ asmlist[al_typedconsts].concat(Tai_const.Create_16bit(0));
+ { return the offset of the real string }
+ lab_str:=l2;
+ end;
+ end;
+ st_shortstring:
+ begin
+ { truncate strings larger than 255 chars }
+ if len>255 then
+ l:=255
+ else
+ l:=len;
+ { include length and terminating zero for quick conversion to pchar }
+ getmem(pc,l+2);
+ move(value_str^,pc[1],l);
+ pc[0]:=chr(l);
+ pc[l+1]:=#0;
+ asmlist[al_typedconsts].concat(Tai_string.Create_pchar(pc,l+2));
+ end;
+ st_conststring:
+ begin
+ { include terminating zero }
+ getmem(pc,len+1);
+ move(value_str^,pc[0],len);
+ pc[len]:=#0;
+ asmlist[al_typedconsts].concat(Tai_string.Create_pchar(pc,len+1));
+ end;
+ end;
+ end;
+ end;
+ location.reference.symbol:=lab_str;
+ end;
+
+
+{*****************************************************************************
+ TCGSETCONSTNODE
+*****************************************************************************}
+
+ procedure tcgsetconstnode.pass_2;
+ var
+ hp1 : tai;
+ lastlabel : tasmlabel;
+ i : longint;
+ neededtyp : taitype;
+ indexadjust : longint;
+ type
+ setbytes=array[0..31] of byte;
+ Psetbytes=^setbytes;
+ begin
+ { xor indexadjust with indexes in a set typecasted to an array of }
+ { bytes to get the correct locations, also when endianess of source }
+ { and destiantion differs (JM) }
+ if (source_info.endian = target_info.endian) then
+ indexadjust := 0
+ else
+ indexadjust := 3;
+ { small sets are loaded as constants }
+ if tsetdef(resulttype.def).settype=smallset then
+ begin
+ location_reset(location,LOC_CONSTANT,OS_32);
+ location.value:=pLongint(value_set)^;
+ exit;
+ end;
+ location_reset(location,LOC_CREFERENCE,OS_NO);
+ neededtyp:=ait_const_8bit;
+ lastlabel:=nil;
+ { const already used ? }
+ if not assigned(lab_set) then
+ begin
+ { tries to found an old entry }
+ hp1:=tai(asmlist[al_typedconsts].first);
+ while assigned(hp1) do
+ begin
+ if hp1.typ=ait_label then
+ lastlabel:=tai_label(hp1).l
+ else
+ begin
+ if (lastlabel<>nil) and (hp1.typ=neededtyp) then
+ begin
+ if (hp1.typ=ait_const_8bit) then
+ begin
+ { compare normal set }
+ i:=0;
+ while assigned(hp1) and (i<32) do
+ begin
+ if tai_const(hp1).value<>Psetbytes(value_set)^[i xor indexadjust] then
+ break;
+ inc(i);
+ hp1:=tai(hp1.next);
+ end;
+ if i=32 then
+ begin
+ { found! }
+ lab_set:=lastlabel;
+ break;
+ end;
+ { leave when the end of consts is reached, so no
+ hp1.next is done }
+ if not assigned(hp1) then
+ break;
+ end
+ else
+ begin
+ { compare small set }
+ if paint(value_set)^=tai_const(hp1).value then
+ begin
+ { found! }
+ lab_set:=lastlabel;
+ break;
+ end;
+ end;
+ end;
+ lastlabel:=nil;
+ end;
+ hp1:=tai(hp1.next);
+ end;
+ { :-(, we must generate a new entry }
+ if not assigned(lab_set) then
+ begin
+ objectlibrary.getdatalabel(lastlabel);
+ lab_set:=lastlabel;
+ maybe_new_object_file(asmlist[al_typedconsts]);
+ new_section(asmlist[al_typedconsts],sec_rodata,lastlabel.name,const_align(sizeof(aint)));
+ asmlist[al_typedconsts].concat(Tai_label.Create(lastlabel));
+ { already handled at the start of this method?? (JM)
+ if tsetdef(resulttype.def).settype=smallset then
+ begin
+ move(value_set^,i,sizeof(longint));
+ Consts.concat(Tai_const.Create_32bit(i));
+ end
+ else
+ }
+ begin
+ for i:=0 to 31 do
+ asmlist[al_typedconsts].concat(Tai_const.Create_8bit(Psetbytes(value_set)^[i xor indexadjust]));
+ end;
+ end;
+ end;
+ location.reference.symbol:=lab_set;
+ end;
+
+
+{*****************************************************************************
+ TCGNILNODE
+*****************************************************************************}
+
+ procedure tcgnilnode.pass_2;
+ begin
+ location_reset(location,LOC_CONSTANT,OS_ADDR);
+ location.value:=0;
+ end;
+
+
+{*****************************************************************************
+ TCGPOINTERCONSTNODE
+*****************************************************************************}
+
+ procedure tcgguidconstnode.pass_2;
+ var
+ tmplabel : TAsmLabel;
+ i : integer;
+ begin
+ location_reset(location,LOC_CREFERENCE,OS_NO);
+ { label for GUID }
+ objectlibrary.getdatalabel(tmplabel);
+ asmlist[al_typedconsts].concat(tai_align.create(const_align(16)));
+ asmlist[al_typedconsts].concat(Tai_label.Create(tmplabel));
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit(longint(value.D1)));
+ asmlist[al_typedconsts].concat(Tai_const.Create_16bit(value.D2));
+ asmlist[al_typedconsts].concat(Tai_const.Create_16bit(value.D3));
+ for i:=low(value.D4) to high(value.D4) do
+ asmlist[al_typedconsts].concat(Tai_const.Create_8bit(value.D4[i]));
+ location.reference.symbol:=tmplabel;
+ end;
+
+
+begin
+ crealconstnode:=tcgrealconstnode;
+ cordconstnode:=tcgordconstnode;
+ cpointerconstnode:=tcgpointerconstnode;
+ cstringconstnode:=tcgstringconstnode;
+ csetconstnode:=tcgsetconstnode;
+ cnilnode:=tcgnilnode;
+ cguidconstnode:=tcgguidconstnode;
+end.
diff --git a/compiler/ncgflw.pas b/compiler/ncgflw.pas
new file mode 100644
index 0000000000..ca8ef23e08
--- /dev/null
+++ b/compiler/ncgflw.pas
@@ -0,0 +1,1469 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for nodes that influence the flow which are
+ the same for all (most?) processors
+
+ 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 ncgflw;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmbase,node,nflw;
+
+ type
+ tcgwhilerepeatnode = class(twhilerepeatnode)
+ procedure pass_2;override;
+ end;
+
+ tcgifnode = class(tifnode)
+ procedure pass_2;override;
+ end;
+
+ tcgfornode = class(tfornode)
+ procedure pass_2;override;
+ end;
+
+ tcgexitnode = class(texitnode)
+ procedure pass_2;override;
+ end;
+
+ tcgbreaknode = class(tbreaknode)
+ procedure pass_2;override;
+ end;
+
+ tcgcontinuenode = class(tcontinuenode)
+ procedure pass_2;override;
+ end;
+
+ tcggotonode = class(tgotonode)
+ procedure pass_2;override;
+ end;
+
+ tcglabelnode = class(tlabelnode)
+ private
+ asmlabel : tasmlabel;
+ public
+ function getasmlabel : tasmlabel;
+ procedure pass_2;override;
+ end;
+
+ tcgraisenode = class(traisenode)
+ procedure pass_2;override;
+ end;
+
+ tcgtryexceptnode = class(ttryexceptnode)
+ procedure pass_2;override;
+ end;
+
+ tcgtryfinallynode = class(ttryfinallynode)
+ procedure pass_2;override;
+ end;
+
+ tcgonnode = class(tonnode)
+ procedure pass_2;override;
+ end;
+
+implementation
+
+ uses
+ verbose,globals,systems,globtype,
+ symconst,symdef,symsym,aasmtai,aasmcpu,defutil,
+ procinfo,cgbase,pass_2,parabase,
+ cpubase,cpuinfo,
+ nld,ncon,
+ ncgutil,
+ tgobj,paramgr,
+ regvars,
+ cgutils,cgobj
+ ;
+
+{*****************************************************************************
+ Second_While_RepeatN
+*****************************************************************************}
+
+ procedure tcgwhilerepeatnode.pass_2;
+ var
+ lcont,lbreak,lloop,
+ oldclabel,oldblabel : tasmlabel;
+ otlabel,oflabel : tasmlabel;
+ oldflowcontrol : tflowcontrol;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ objectlibrary.getjumplabel(lloop);
+ objectlibrary.getjumplabel(lcont);
+ objectlibrary.getjumplabel(lbreak);
+ { arrange continue and breaklabels: }
+ oldflowcontrol:=flowcontrol;
+ oldclabel:=aktcontinuelabel;
+ oldblabel:=aktbreaklabel;
+
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ { handling code at the end as it is much more efficient, and makes
+ while equal to repeat loop, only the end true/false is swapped (PFV) }
+ if lnf_testatbegin in loopflags then
+ cg.a_jmp_always(exprasmlist,lcont);
+
+ if not(cs_littlesize in aktglobalswitches) then
+ { align loop target }
+ exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
+
+ cg.a_label(exprasmlist,lloop);
+
+ aktcontinuelabel:=lcont;
+ aktbreaklabel:=lbreak;
+ if assigned(right) then
+ secondpass(right);
+
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+
+ cg.a_label(exprasmlist,lcont);
+ otlabel:=truelabel;
+ oflabel:=falselabel;
+ if lnf_checknegate in loopflags then
+ begin
+ truelabel:=lbreak;
+ falselabel:=lloop;
+ end
+ else
+ begin
+ truelabel:=lloop;
+ falselabel:=lbreak;
+ end;
+ secondpass(left);
+
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ cg.a_label(exprasmlist,lbreak);
+ truelabel:=otlabel;
+ falselabel:=oflabel;
+
+ aktcontinuelabel:=oldclabel;
+ aktbreaklabel:=oldblabel;
+ { a break/continue in a while/repeat block can't be seen outside }
+ flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue]);
+ end;
+
+
+{*****************************************************************************
+ tcgIFNODE
+*****************************************************************************}
+
+ procedure tcgifnode.pass_2;
+
+ var
+ hl,otlabel,oflabel : tasmlabel;
+(*
+ org_regvar_loaded_other,
+ then_regvar_loaded_other,
+ else_regvar_loaded_other : regvarother_booleanarray;
+ org_regvar_loaded_int,
+ then_regvar_loaded_int,
+ else_regvar_loaded_int : Tsuperregisterset;
+ org_list,
+ then_list,
+ else_list : taasmoutput;
+*)
+
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ otlabel:=truelabel;
+ oflabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+
+(*
+ { save regvars loaded in the beginning so that we can restore them }
+ { when processing the else-block }
+ if cs_regvars in aktglobalswitches then
+ begin
+ org_list := exprasmlist;
+ exprasmlist := taasmoutput.create;
+ end;
+*)
+ maketojumpbool(exprasmlist,left,lr_dont_load_regvars);
+
+(*
+ if cs_regvars in aktglobalswitches then
+ begin
+ org_regvar_loaded_int := rg.regvar_loaded_int;
+ org_regvar_loaded_other := rg.regvar_loaded_other;
+ end;
+*)
+
+ if assigned(right) then
+ begin
+ cg.a_label(exprasmlist,truelabel);
+ secondpass(right);
+ end;
+
+ { save current asmlist (previous instructions + then-block) and }
+ { loaded regvar state and create new clean ones }
+ if cs_regvars in aktglobalswitches then
+ begin
+{ then_regvar_loaded_int := rg.regvar_loaded_int;
+ then_regvar_loaded_other := rg.regvar_loaded_other;
+ rg.regvar_loaded_int := org_regvar_loaded_int;
+ rg.regvar_loaded_other := org_regvar_loaded_other;
+ then_list := exprasmlist;
+ exprasmlist := taasmoutput.create;}
+ end;
+
+ if assigned(t1) then
+ begin
+ if assigned(right) then
+ begin
+ objectlibrary.getjumplabel(hl);
+ { do go back to if line !! }
+(*
+ if not(cs_regvars in aktglobalswitches) then
+*)
+ aktfilepos:=exprasmList.getlasttaifilepos^
+(*
+ else
+ aktfilepos:=then_list.getlasttaifilepos^
+*)
+ ;
+ cg.a_jmp_always(exprasmlist,hl);
+ end;
+ cg.a_label(exprasmlist,falselabel);
+ secondpass(t1);
+(*
+ { save current asmlist (previous instructions + else-block) }
+ { and loaded regvar state and create a new clean list }
+ if cs_regvars in aktglobalswitches then
+ begin
+{ else_regvar_loaded_int := rg.regvar_loaded_int;
+ else_regvar_loaded_other := rg.regvar_loaded_other;}
+ else_list := exprasmlist;
+ exprasmlist := taasmoutput.create;
+ end;
+*)
+ if assigned(right) then
+ cg.a_label(exprasmlist,hl);
+ end
+ else
+ begin
+(*
+ if cs_regvars in aktglobalswitches then
+ begin
+{ else_regvar_loaded_int := rg.regvar_loaded_int;
+ else_regvar_loaded_other := rg.regvar_loaded_other;}
+ else_list := exprasmlist;
+ exprasmlist := taasmoutput.create;
+ end;
+*)
+ cg.a_label(exprasmlist,falselabel);
+ end;
+ if not(assigned(right)) then
+ begin
+ cg.a_label(exprasmlist,truelabel);
+ end;
+
+(*
+ if cs_regvars in aktglobalswitches then
+ begin
+ { add loads of regvars at the end of the then- and else-blocks }
+ { so that at the end of both blocks the same regvars are loaded }
+
+ { no else block? }
+ if not assigned(t1) then
+ begin
+ sync_regvars_int(org_list,then_list,org_regvar_loaded_int,then_regvar_loaded_int);
+ sync_regvars_other(org_list,then_list,org_regvar_loaded_other,then_regvar_loaded_other);
+ end
+ { no then block? }
+ else if not assigned(right) then
+ begin
+ sync_regvars_int(org_list,else_list,org_regvar_loaded_int,else_regvar_loaded_int);
+ sync_regvars_other(org_list,else_list,org_regvar_loaded_other,else_regvar_loaded_other);
+ end
+ { both else and then blocks }
+ else
+ begin
+ sync_regvars_int(then_list,else_list,then_regvar_loaded_int,else_regvar_loaded_int);
+ sync_regvars_other(then_list,else_list,then_regvar_loaded_other,else_regvar_loaded_other);
+ end;
+ { add all lists together }
+ org_list.concatlist(then_list);
+ then_list.free;
+ org_list.concatlist(else_list);
+ else_list.free;
+ org_list.concatlist(exprasmlist);
+ exprasmlist.free;
+ exprasmlist := org_list;
+ end;
+*)
+
+ truelabel:=otlabel;
+ falselabel:=oflabel;
+ end;
+
+
+{*****************************************************************************
+ SecondFor
+*****************************************************************************}
+
+ procedure tcgfornode.pass_2;
+ var
+ l3,oldclabel,oldblabel : tasmlabel;
+ temptovalue : boolean;
+ temp1 : treference;
+ hop : topcg;
+ hcond : topcmp;
+ opsize : tcgsize;
+ count_var_is_signed,do_loopvar_at_end : boolean;
+ cmp_const:Tconstexprint;
+ oldflowcontrol : tflowcontrol;
+
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+ oldflowcontrol:=flowcontrol;
+ oldclabel:=aktcontinuelabel;
+ oldblabel:=aktbreaklabel;
+ objectlibrary.getjumplabel(aktcontinuelabel);
+ objectlibrary.getjumplabel(aktbreaklabel);
+ objectlibrary.getjumplabel(l3);
+
+ { only calculate reference }
+ opsize := def_cgsize(left.resulttype.def);
+ count_var_is_signed:=is_signed(left.resulttype.def);
+
+ { first set the to value
+ because the count var can be in the expression ! }
+ do_loopvar_at_end:=(lnf_dont_mind_loopvar_on_exit in loopflags)
+ { if the loop is unrolled and there is a jump into the loop,
+ then we can't do the trick with incrementing the loop var only at the
+ end
+ }
+ and not(assigned(entrylabel));
+
+ secondpass(t1);
+ { calculate pointer value and check if changeable and if so }
+ { load into temporary variable }
+ if t1.nodetype<>ordconstn then
+ begin
+ do_loopvar_at_end:=false;
+ tg.GetTemp(exprasmlist,t1.resulttype.def.size,tt_normal,temp1);
+ temptovalue:=true;
+ cg.a_load_loc_ref(exprasmlist,opsize,t1.location,temp1);
+ location_freetemp(exprasmlist,t1.location);
+ end
+ else
+ temptovalue:=false;
+
+ { produce start assignment }
+ secondpass(left);
+ secondpass(right);
+ case left.location.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ cg.a_load_loc_ref(exprasmlist,left.location.size,right.location,left.location.reference);
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ cg.a_load_loc_reg(exprasmlist,left.location.size,right.location,left.location.register);
+ else
+ internalerror(200501311);
+ end;
+
+ if lnf_backward in loopflags then
+ if count_var_is_signed then
+ hcond:=OC_LT
+ else
+ hcond:=OC_B
+ else
+ if count_var_is_signed then
+ hcond:=OC_GT
+ else
+ hcond:=OC_A;
+
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+
+ if temptovalue then
+ begin
+ cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,
+ temp1,left.location,aktbreaklabel);
+ end
+ else
+ begin
+ if lnf_testatbegin in loopflags then
+ begin
+ cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
+ tordconstnode(t1).value,
+ left.location,aktbreaklabel);
+ end;
+ end;
+
+ {If the loopvar doesn't mind on exit, we avoid this ugly
+ dec instruction and do the loopvar inc/dec after the loop
+ body.}
+ if not do_loopvar_at_end then
+ begin
+ if lnf_backward in loopflags then
+ hop:=OP_ADD
+ else
+ hop:=OP_SUB;
+ cg.a_op_const_loc(exprasmlist,hop,1,left.location);
+ end;
+
+ if assigned(entrylabel) then
+ cg.a_jmp_always(exprasmlist,tcglabelnode(entrylabel).getasmlabel);
+
+ { align loop target }
+ if not(cs_littlesize in aktglobalswitches) then
+ exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
+ cg.a_label(exprasmlist,l3);
+
+ {If the loopvar doesn't mind on exit, we avoid the loopvar inc/dec
+ after the loop body instead of here.}
+ if not do_loopvar_at_end then
+ begin
+ { according to count direction DEC or INC... }
+ if lnf_backward in loopflags then
+ hop:=OP_SUB
+ else
+ hop:=OP_ADD;
+ cg.a_op_const_loc(exprasmlist,hop,1,left.location);
+ end;
+
+ if assigned(t2) then
+ begin
+ secondpass(t2);
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ end;
+
+ {If the loopvar doesn't mind on exit, we do the loopvar inc/dec
+ after the loop body instead of here.}
+ if do_loopvar_at_end then
+ begin
+ { according to count direction DEC or INC... }
+ if lnf_backward in loopflags then
+ hop:=OP_SUB
+ else
+ hop:=OP_ADD;
+ cg.a_op_const_loc(exprasmlist,hop,1,left.location);
+ end;
+
+ cg.a_label(exprasmlist,aktcontinuelabel);
+
+ if do_loopvar_at_end then
+ if lnf_backward in loopflags then
+ if count_var_is_signed then
+ hcond:=OC_GTE
+ else
+ hcond:=OC_AE
+ else
+ if count_var_is_signed then
+ hcond:=OC_LTE
+ else
+ hcond:=OC_BE
+ else
+ if lnf_backward in loopflags then
+ if count_var_is_signed then
+ hcond:=OC_GT
+ else
+ hcond:=OC_A
+ else
+ if count_var_is_signed then
+ hcond:=OC_LT
+ else
+ hcond:=OC_B;
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+
+ { produce comparison and the corresponding }
+ { jump }
+ if temptovalue then
+ begin
+ cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,temp1,
+ left.location,l3);
+ tg.ungetiftemp(exprasmlist,temp1);
+ end
+ else
+ begin
+ cmp_const:=Tordconstnode(t1).value;
+ if do_loopvar_at_end then
+ begin
+ {Watch out for wrap around 255 -> 0.}
+ {Ugly: This code is way to long... Use tables?}
+ case opsize of
+ OS_8:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if byte(cmp_const)=low(byte) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(byte);
+ end
+ end
+ else
+ begin
+ if byte(cmp_const)=high(byte) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(byte);
+ end
+ end
+ end;
+ OS_16:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if word(cmp_const)=high(word) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(word);
+ end
+ end
+ else
+ begin
+ if word(cmp_const)=low(word) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(word);
+ end
+ end
+ end;
+ OS_32:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if cardinal(cmp_const)=high(cardinal) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(cardinal);
+ end
+ end
+ else
+ begin
+ if cardinal(cmp_const)=low(cardinal) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(cardinal);
+ end
+ end
+ end;
+ OS_64:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if qword(cmp_const)=high(qword) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(qword);
+ end
+ end
+ else
+ begin
+ if qword(cmp_const)=low(qword) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(qword);
+ end
+ end
+ end;
+ OS_S8:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if shortint(cmp_const)=low(shortint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(shortint);
+ end
+ end
+ else
+ begin
+ if shortint(cmp_const)=high(shortint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(shortint);
+ end
+ end
+ end;
+ OS_S16:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if integer(cmp_const)=high(smallint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(smallint);
+ end
+ end
+ else
+ begin
+ if integer(cmp_const)=low(smallint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(smallint);
+ end
+ end
+ end;
+ OS_S32:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if longint(cmp_const)=high(longint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(longint);
+ end
+ end
+ else
+ begin
+ if longint(cmp_const)=low(longint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(longint);
+ end
+ end
+ end;
+ OS_S64:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if int64(cmp_const)=high(int64) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(int64);
+ end
+ end
+ else
+ begin
+ if int64(cmp_const)=low(int64) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(int64);
+ end
+ end
+ end;
+ else
+ internalerror(200201021);
+ end;
+ end;
+
+ cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
+ cmp_const,left.location,l3);
+ end;
+
+ { this is the break label: }
+ cg.a_label(exprasmlist,aktbreaklabel);
+
+ aktcontinuelabel:=oldclabel;
+ aktbreaklabel:=oldblabel;
+ { a break/continue in a while/repeat block can't be seen outside }
+ flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue]);
+ end;
+
+
+{*****************************************************************************
+ SecondExitN
+*****************************************************************************}
+
+ procedure tcgexitnode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ include(flowcontrol,fc_exit);
+ if assigned(left) then
+ secondpass(left);
+
+ cg.a_jmp_always(exprasmlist,current_procinfo.aktexitlabel);
+ end;
+
+
+{*****************************************************************************
+ SecondBreakN
+*****************************************************************************}
+
+ procedure tcgbreaknode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ include(flowcontrol,fc_break);
+ if aktbreaklabel<>nil then
+ begin
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ cg.a_jmp_always(exprasmlist,aktbreaklabel)
+ end
+ else
+ CGMessage(cg_e_break_not_allowed);
+ end;
+
+
+{*****************************************************************************
+ SecondContinueN
+*****************************************************************************}
+
+ procedure tcgcontinuenode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ include(flowcontrol,fc_continue);
+ if aktcontinuelabel<>nil then
+ begin
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ cg.a_jmp_always(exprasmlist,aktcontinuelabel)
+ end
+ else
+ CGMessage(cg_e_continue_not_allowed);
+ end;
+
+
+{*****************************************************************************
+ SecondGoto
+*****************************************************************************}
+
+ procedure tcggotonode.pass_2;
+
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ cg.a_jmp_always(exprasmlist,tcglabelnode(labelnode).getasmlabel)
+ end;
+
+
+{*****************************************************************************
+ SecondLabel
+*****************************************************************************}
+
+ function tcglabelnode.getasmlabel : tasmlabel;
+ begin
+ if not(assigned(asmlabel)) then
+ objectlibrary.getjumplabel(asmlabel);
+ result:=asmlabel
+ end;
+
+
+ procedure tcglabelnode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ cg.a_label(exprasmlist,getasmlabel);
+ secondpass(left);
+ end;
+
+
+{*****************************************************************************
+ SecondRaise
+*****************************************************************************}
+
+ procedure tcgraisenode.pass_2;
+
+ var
+ a : tasmlabel;
+ href2: treference;
+ paraloc1,paraloc2,paraloc3 : tcgpara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ location_reset(location,LOC_VOID,OS_NO);
+
+ if assigned(left) then
+ begin
+ { multiple parameters? }
+ if assigned(right) then
+ begin
+ if assigned(frametree) then
+ secondpass(frametree);
+ secondpass(right);
+ end;
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { Push parameters }
+ if assigned(right) then
+ begin
+ paramanager.allocparaloc(exprasmlist,paraloc3);
+ if assigned(frametree) then
+ cg.a_param_loc(exprasmlist,frametree.location,paraloc3)
+ else
+ cg.a_param_const(exprasmlist,OS_INT,0,paraloc3);
+ { push address }
+ paramanager.allocparaloc(exprasmlist,paraloc2);
+ cg.a_param_loc(exprasmlist,right.location,paraloc2);
+ end
+ else
+ begin
+ { get current address }
+ objectlibrary.getaddrlabel(a);
+ cg.a_label(exprasmlist,a);
+ reference_reset_symbol(href2,a,0);
+ { push current frame }
+ paramanager.allocparaloc(exprasmlist,paraloc3);
+ cg.a_param_reg(exprasmlist,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3);
+ { push current address }
+ paramanager.allocparaloc(exprasmlist,paraloc2);
+ if target_info.system <> system_powerpc_macos then
+ cg.a_paramaddr_ref(exprasmlist,href2,paraloc2)
+ else
+ cg.a_param_const(exprasmlist,OS_INT,0,paraloc2);
+ end;
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_loc(exprasmlist,left.location,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc2);
+ paramanager.freeparaloc(exprasmlist,paraloc3);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_RAISEEXCEPTION');
+ cg.deallocallcpuregisters(exprasmlist);
+ end
+ else
+ begin
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
+ cg.a_call_name(exprasmlist,'FPC_RERAISE');
+ cg.deallocallcpuregisters(exprasmlist);
+ end;
+ paraloc1.done;
+ paraloc2.done;
+ paraloc3.done;
+ end;
+
+
+{*****************************************************************************
+ SecondTryExcept
+*****************************************************************************}
+
+ var
+ endexceptlabel : tasmlabel;
+
+
+ { does the necessary things to clean up the object stack }
+ { in the except block }
+ procedure cleanupobjectstack;
+ var
+ paraloc1 : tcgpara;
+ begin
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPOBJECTSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_reg(exprasmlist,OS_ADDR,NR_FUNCTION_RESULT_REG,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
+ cg.deallocallcpuregisters(exprasmlist);
+ paraloc1.done;
+ end;
+
+
+ procedure tcgtryexceptnode.pass_2;
+
+ var
+ exceptlabel,doexceptlabel,oldendexceptlabel,
+ lastonlabel,
+ exitexceptlabel,
+ continueexceptlabel,
+ breakexceptlabel,
+ exittrylabel,
+ continuetrylabel,
+ breaktrylabel,
+ doobjectdestroy,
+ doobjectdestroyandreraise,
+ oldaktexitlabel,
+ oldaktcontinuelabel,
+ oldaktbreaklabel : tasmlabel;
+ oldflowcontrol,tryflowcontrol,
+ exceptflowcontrol : tflowcontrol;
+ destroytemps,
+ excepttemps : texceptiontemps;
+ paraloc1 : tcgpara;
+ label
+ errorexit;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[];
+ { this can be called recursivly }
+ oldaktbreaklabel:=nil;
+ oldaktcontinuelabel:=nil;
+ oldendexceptlabel:=endexceptlabel;
+
+ { save the old labels for control flow statements }
+ oldaktexitlabel:=current_procinfo.aktexitlabel;
+ if assigned(aktbreaklabel) then
+ begin
+ oldaktcontinuelabel:=aktcontinuelabel;
+ oldaktbreaklabel:=aktbreaklabel;
+ end;
+
+ { get new labels for the control flow statements }
+ objectlibrary.getjumplabel(exittrylabel);
+ objectlibrary.getjumplabel(exitexceptlabel);
+ if assigned(aktbreaklabel) then
+ begin
+ objectlibrary.getjumplabel(breaktrylabel);
+ objectlibrary.getjumplabel(continuetrylabel);
+ objectlibrary.getjumplabel(breakexceptlabel);
+ objectlibrary.getjumplabel(continueexceptlabel);
+ end;
+
+ objectlibrary.getjumplabel(exceptlabel);
+ objectlibrary.getjumplabel(doexceptlabel);
+ objectlibrary.getjumplabel(endexceptlabel);
+ objectlibrary.getjumplabel(lastonlabel);
+
+ get_exception_temps(exprasmlist,excepttemps);
+ new_exception(exprasmlist,excepttemps,exceptlabel);
+
+ { try block }
+ { set control flow labels for the try block }
+ current_procinfo.aktexitlabel:=exittrylabel;
+ if assigned(oldaktbreaklabel) then
+ begin
+ aktcontinuelabel:=continuetrylabel;
+ aktbreaklabel:=breaktrylabel;
+ end;
+
+ flowcontrol:=[];
+ secondpass(left);
+ tryflowcontrol:=flowcontrol;
+ if codegenerror then
+ goto errorexit;
+
+ cg.a_label(exprasmlist,exceptlabel);
+
+ free_exception(exprasmlist, excepttemps, 0, endexceptlabel, false);
+
+ cg.a_label(exprasmlist,doexceptlabel);
+
+ { set control flow labels for the except block }
+ { and the on statements }
+ current_procinfo.aktexitlabel:=exitexceptlabel;
+ if assigned(oldaktbreaklabel) then
+ begin
+ aktcontinuelabel:=continueexceptlabel;
+ aktbreaklabel:=breakexceptlabel;
+ end;
+
+ flowcontrol:=[];
+ { on statements }
+ if assigned(right) then
+ secondpass(right);
+
+ cg.a_label(exprasmlist,lastonlabel);
+ { default handling except handling }
+ if assigned(t1) then
+ begin
+ { FPC_CATCHES must be called with
+ 'default handler' flag (=-1)
+ }
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_const(exprasmlist,OS_ADDR,-1,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_CATCHES');
+ cg.deallocallcpuregisters(exprasmlist);
+ paraloc1.done;
+
+ { the destruction of the exception object must be also }
+ { guarded by an exception frame }
+ objectlibrary.getjumplabel(doobjectdestroy);
+ objectlibrary.getjumplabel(doobjectdestroyandreraise);
+
+ get_exception_temps(exprasmlist,destroytemps);
+ new_exception(exprasmlist,destroytemps,doobjectdestroyandreraise);
+
+ { here we don't have to reset flowcontrol }
+ { the default and on flowcontrols are handled equal }
+ secondpass(t1);
+ exceptflowcontrol:=flowcontrol;
+
+ cg.a_label(exprasmlist,doobjectdestroyandreraise);
+
+ free_exception(exprasmlist,destroytemps,0,doobjectdestroy,false);
+
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_reg(exprasmlist, OS_ADDR, NR_FUNCTION_RESULT_REG, paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
+ cg.deallocallcpuregisters(exprasmlist);
+ paraloc1.done;
+ { we don't need to restore esi here because reraise never }
+ { returns }
+ cg.a_call_name(exprasmlist,'FPC_RERAISE');
+
+ cg.a_label(exprasmlist,doobjectdestroy);
+ cleanupobjectstack;
+ unget_exception_temps(exprasmlist,destroytemps);
+ cg.a_jmp_always(exprasmlist,endexceptlabel);
+ end
+ else
+ begin
+ cg.a_call_name(exprasmlist,'FPC_RERAISE');
+ exceptflowcontrol:=flowcontrol;
+ end;
+
+ if fc_exit in exceptflowcontrol then
+ begin
+ { do some magic for exit in the try block }
+ cg.a_label(exprasmlist,exitexceptlabel);
+ { we must also destroy the address frame which guards }
+ { exception object }
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cleanupobjectstack;
+ cg.a_jmp_always(exprasmlist,oldaktexitlabel);
+ end;
+
+ if fc_break in exceptflowcontrol then
+ begin
+ cg.a_label(exprasmlist,breakexceptlabel);
+ { we must also destroy the address frame which guards }
+ { exception object }
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cleanupobjectstack;
+ cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
+ end;
+
+ if fc_continue in exceptflowcontrol then
+ begin
+ cg.a_label(exprasmlist,continueexceptlabel);
+ { we must also destroy the address frame which guards }
+ { exception object }
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cleanupobjectstack;
+ cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
+ end;
+
+ if fc_exit in tryflowcontrol then
+ begin
+ { do some magic for exit in the try block }
+ cg.a_label(exprasmlist,exittrylabel);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cg.a_jmp_always(exprasmlist,oldaktexitlabel);
+ end;
+
+ if fc_break in tryflowcontrol then
+ begin
+ cg.a_label(exprasmlist,breaktrylabel);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
+ end;
+
+ if fc_continue in tryflowcontrol then
+ begin
+ cg.a_label(exprasmlist,continuetrylabel);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
+ end;
+ unget_exception_temps(exprasmlist,excepttemps);
+ cg.a_label(exprasmlist,endexceptlabel);
+
+ errorexit:
+ { restore all saved labels }
+ endexceptlabel:=oldendexceptlabel;
+
+ { restore the control flow labels }
+ current_procinfo.aktexitlabel:=oldaktexitlabel;
+ if assigned(oldaktbreaklabel) then
+ begin
+ aktcontinuelabel:=oldaktcontinuelabel;
+ aktbreaklabel:=oldaktbreaklabel;
+ end;
+
+ { return all used control flow statements }
+ flowcontrol:=oldflowcontrol+exceptflowcontrol+
+ tryflowcontrol;
+ end;
+
+
+ procedure tcgonnode.pass_2;
+ var
+ nextonlabel,
+ exitonlabel,
+ continueonlabel,
+ breakonlabel,
+ oldaktexitlabel,
+ oldaktcontinuelabel,
+ doobjectdestroyandreraise,
+ doobjectdestroy,
+ oldaktbreaklabel : tasmlabel;
+ oldflowcontrol : tflowcontrol;
+ excepttemps : texceptiontemps;
+ exceptref,
+ href2: treference;
+ paraloc1 : tcgpara;
+ begin
+ paraloc1.init;
+ location_reset(location,LOC_VOID,OS_NO);
+
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[];
+ objectlibrary.getjumplabel(nextonlabel);
+
+ { send the vmt parameter }
+ reference_reset_symbol(href2,objectlibrary.newasmsymbol(excepttype.vmt_mangledname,AB_EXTERNAL,AT_DATA),0);
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_paramaddr_ref(exprasmlist,href2,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_CATCHES');
+ cg.deallocallcpuregisters(exprasmlist);
+
+ { is it this catch? No. go to next onlabel }
+ cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,NR_FUNCTION_RESULT_REG,nextonlabel);
+
+ { what a hack ! }
+ if assigned(exceptsymtable) then
+ begin
+ tlocalvarsym(exceptsymtable.symindex.first).localloc.loc:=LOC_REFERENCE;
+ tlocalvarsym(exceptsymtable.symindex.first).localloc.size:=OS_ADDR;
+ tg.GetLocal(exprasmlist,sizeof(aint),voidpointertype.def,
+ tlocalvarsym(exceptsymtable.symindex.first).localloc.reference);
+ cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,tlocalvarsym(exceptsymtable.symindex.first).localloc.reference);
+ end
+ else
+ begin
+ tg.GetTemp(exprasmlist,sizeof(aint),tt_normal,exceptref);
+ cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,exceptref);
+ end;
+
+ { in the case that another exception is risen
+ we've to destroy the old one }
+ objectlibrary.getjumplabel(doobjectdestroyandreraise);
+
+ { call setjmp, and jump to finally label on non-zero result }
+ get_exception_temps(exprasmlist,excepttemps);
+ new_exception(exprasmlist,excepttemps,doobjectdestroyandreraise);
+
+ oldaktbreaklabel:=nil;
+ oldaktcontinuelabel:=nil;
+ if assigned(right) then
+ begin
+ oldaktexitlabel:=current_procinfo.aktexitlabel;
+ objectlibrary.getjumplabel(exitonlabel);
+ current_procinfo.aktexitlabel:=exitonlabel;
+ if assigned(aktbreaklabel) then
+ begin
+ oldaktcontinuelabel:=aktcontinuelabel;
+ oldaktbreaklabel:=aktbreaklabel;
+ objectlibrary.getjumplabel(breakonlabel);
+ objectlibrary.getjumplabel(continueonlabel);
+ aktcontinuelabel:=continueonlabel;
+ aktbreaklabel:=breakonlabel;
+ end;
+
+ secondpass(right);
+ end;
+ objectlibrary.getjumplabel(doobjectdestroy);
+ cg.a_label(exprasmlist,doobjectdestroyandreraise);
+
+ free_exception(exprasmlist,excepttemps,0,doobjectdestroy,false);
+
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
+ cg.deallocallcpuregisters(exprasmlist);
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_reg(exprasmlist, OS_ADDR, NR_FUNCTION_RESULT_REG, paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
+ cg.deallocallcpuregisters(exprasmlist);
+ { we don't need to store/restore registers here because reraise never
+ returns }
+ cg.a_call_name(exprasmlist,'FPC_RERAISE');
+
+ cg.a_label(exprasmlist,doobjectdestroy);
+ cleanupobjectstack;
+ { clear some stuff }
+ if assigned(exceptsymtable) then
+ begin
+ tg.UngetLocal(exprasmlist,tlocalvarsym(exceptsymtable.symindex.first).localloc.reference);
+ tlocalvarsym(exceptsymtable.symindex.first).localloc.loc:=LOC_INVALID;
+ end
+ else
+ tg.Ungettemp(exprasmlist,exceptref);
+ cg.a_jmp_always(exprasmlist,endexceptlabel);
+
+ if assigned(right) then
+ begin
+ { special handling for control flow instructions }
+ if fc_exit in flowcontrol then
+ begin
+ { the address and object pop does secondtryexcept }
+ cg.a_label(exprasmlist,exitonlabel);
+ cg.a_jmp_always(exprasmlist,oldaktexitlabel);
+ end;
+
+ if fc_break in flowcontrol then
+ begin
+ { the address and object pop does secondtryexcept }
+ cg.a_label(exprasmlist,breakonlabel);
+ cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
+ end;
+
+ if fc_continue in flowcontrol then
+ begin
+ { the address and object pop does secondtryexcept }
+ cg.a_label(exprasmlist,continueonlabel);
+ cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
+ end;
+
+ current_procinfo.aktexitlabel:=oldaktexitlabel;
+ if assigned(oldaktbreaklabel) then
+ begin
+ aktcontinuelabel:=oldaktcontinuelabel;
+ aktbreaklabel:=oldaktbreaklabel;
+ end;
+ end;
+
+ unget_exception_temps(exprasmlist,excepttemps);
+ cg.a_label(exprasmlist,nextonlabel);
+ flowcontrol:=oldflowcontrol+flowcontrol;
+ paraloc1.done;
+
+ { next on node }
+ if assigned(left) then
+ secondpass(left);
+ end;
+
+{*****************************************************************************
+ SecondTryFinally
+*****************************************************************************}
+
+ procedure tcgtryfinallynode.pass_2;
+ var
+ reraiselabel,
+ finallylabel,
+ endfinallylabel,
+ exitfinallylabel,
+ continuefinallylabel,
+ breakfinallylabel,
+ oldaktexitlabel,
+ oldaktcontinuelabel,
+ oldaktbreaklabel : tasmlabel;
+ oldflowcontrol,tryflowcontrol : tflowcontrol;
+ decconst : longint;
+ excepttemps : texceptiontemps;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { check if child nodes do a break/continue/exit }
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[];
+ objectlibrary.getjumplabel(finallylabel);
+ objectlibrary.getjumplabel(endfinallylabel);
+ objectlibrary.getjumplabel(reraiselabel);
+
+ { the finally block must catch break, continue and exit }
+ { statements }
+ oldaktexitlabel:=current_procinfo.aktexitlabel;
+ if implicitframe then
+ exitfinallylabel:=finallylabel
+ else
+ objectlibrary.getjumplabel(exitfinallylabel);
+ current_procinfo.aktexitlabel:=exitfinallylabel;
+ if assigned(aktbreaklabel) then
+ begin
+ oldaktcontinuelabel:=aktcontinuelabel;
+ oldaktbreaklabel:=aktbreaklabel;
+ if implicitframe then
+ begin
+ breakfinallylabel:=finallylabel;
+ continuefinallylabel:=finallylabel;
+ end
+ else
+ begin
+ objectlibrary.getjumplabel(breakfinallylabel);
+ objectlibrary.getjumplabel(continuefinallylabel);
+ end;
+ aktcontinuelabel:=continuefinallylabel;
+ aktbreaklabel:=breakfinallylabel;
+ end;
+
+ { call setjmp, and jump to finally label on non-zero result }
+ get_exception_temps(exprasmlist,excepttemps);
+ new_exception(exprasmlist,excepttemps,finallylabel);
+
+ { try code }
+ if assigned(left) then
+ begin
+ secondpass(left);
+ tryflowcontrol:=flowcontrol;
+ if codegenerror then
+ exit;
+ end;
+
+ cg.a_label(exprasmlist,finallylabel);
+ { just free the frame information }
+ free_exception(exprasmlist,excepttemps,1,finallylabel,true);
+
+ { finally code }
+ flowcontrol:=[];
+ secondpass(right);
+ if flowcontrol<>[] then
+ CGMessage(cg_e_control_flow_outside_finally);
+ if codegenerror then
+ exit;
+
+ { the value should now be in the exception handler }
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ if implicitframe then
+ begin
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,endfinallylabel);
+ { finally code only needed to be executed on exception }
+ flowcontrol:=[];
+ secondpass(t1);
+ if flowcontrol<>[] then
+ CGMessage(cg_e_control_flow_outside_finally);
+ if codegenerror then
+ exit;
+ cg.a_call_name(exprasmlist,'FPC_RERAISE');
+ end
+ else
+ begin
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,endfinallylabel);
+ cg.a_op_const_reg(exprasmlist,OP_SUB,OS_INT,1,NR_FUNCTION_RESULT_REG);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,reraiselabel);
+ if fc_exit in tryflowcontrol then
+ begin
+ cg.a_op_const_reg(exprasmlist,OP_SUB,OS_INT,1,NR_FUNCTION_RESULT_REG);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldaktexitlabel);
+ decconst:=1;
+ end
+ else
+ decconst:=2;
+ if fc_break in tryflowcontrol then
+ begin
+ cg.a_op_const_reg(exprasmlist,OP_SUB,OS_INT,decconst,NR_FUNCTION_RESULT_REG);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldaktbreaklabel);
+ decconst:=1;
+ end
+ else
+ inc(decconst);
+ if fc_continue in tryflowcontrol then
+ begin
+ cg.a_op_const_reg(exprasmlist,OP_SUB,OS_INT,decconst,NR_FUNCTION_RESULT_REG);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldaktcontinuelabel);
+ end;
+ cg.a_label(exprasmlist,reraiselabel);
+ cg.a_call_name(exprasmlist,'FPC_RERAISE');
+ { do some magic for exit,break,continue in the try block }
+ if fc_exit in tryflowcontrol then
+ begin
+ cg.a_label(exprasmlist,exitfinallylabel);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cg.g_exception_reason_save_const(exprasmlist,excepttemps.reasonbuf,2);
+ cg.a_jmp_always(exprasmlist,finallylabel);
+ end;
+ if fc_break in tryflowcontrol then
+ begin
+ cg.a_label(exprasmlist,breakfinallylabel);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cg.g_exception_reason_save_const(exprasmlist,excepttemps.reasonbuf,3);
+ cg.a_jmp_always(exprasmlist,finallylabel);
+ end;
+ if fc_continue in tryflowcontrol then
+ begin
+ cg.a_label(exprasmlist,continuefinallylabel);
+ cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
+ cg.g_exception_reason_save_const(exprasmlist,excepttemps.reasonbuf,4);
+ cg.a_jmp_always(exprasmlist,finallylabel);
+ end;
+ end;
+ unget_exception_temps(exprasmlist,excepttemps);
+ cg.a_label(exprasmlist,endfinallylabel);
+
+ current_procinfo.aktexitlabel:=oldaktexitlabel;
+ if assigned(aktbreaklabel) then
+ begin
+ aktcontinuelabel:=oldaktcontinuelabel;
+ aktbreaklabel:=oldaktbreaklabel;
+ end;
+ flowcontrol:=oldflowcontrol+tryflowcontrol;
+ end;
+
+
+begin
+ cwhilerepeatnode:=tcgwhilerepeatnode;
+ cifnode:=tcgifnode;
+ cfornode:=tcgfornode;
+ cexitnode:=tcgexitnode;
+ cbreaknode:=tcgbreaknode;
+ ccontinuenode:=tcgcontinuenode;
+ cgotonode:=tcggotonode;
+ clabelnode:=tcglabelnode;
+ craisenode:=tcgraisenode;
+ ctryexceptnode:=tcgtryexceptnode;
+ ctryfinallynode:=tcgtryfinallynode;
+ connode:=tcgonnode;
+end.
diff --git a/compiler/ncginl.pas b/compiler/ncginl.pas
new file mode 100644
index 0000000000..c32d6ccb32
--- /dev/null
+++ b/compiler/ncginl.pas
@@ -0,0 +1,688 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
+
+ Generate generic inline 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 ncginl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl;
+
+ type
+ tcginlinenode = class(tinlinenode)
+ procedure pass_2;override;
+ procedure second_assert;virtual;
+ procedure second_sizeoftypeof;virtual;
+ procedure second_length;virtual;
+ procedure second_predsucc;virtual;
+ procedure second_incdec;virtual;
+ procedure second_typeinfo;virtual;
+ procedure second_includeexclude;virtual;
+ procedure second_pi; virtual;
+ procedure second_arctan_real; virtual;
+ procedure second_abs_real; virtual;
+ procedure second_sqr_real; virtual;
+ procedure second_sqrt_real; virtual;
+ procedure second_ln_real; virtual;
+ procedure second_cos_real; virtual;
+ procedure second_sin_real; virtual;
+ procedure second_assigned; virtual;
+ procedure second_prefetch; virtual;
+ end;
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,fmodule,
+ symconst,symdef,defutil,symsym,
+ aasmbase,aasmtai,aasmcpu,parabase,
+ cgbase,pass_1,pass_2,
+ cpuinfo,cpubase,paramgr,procinfo,
+ nbas,ncon,ncal,ncnv,nld,
+ tgobj,ncgutil,
+ cgutils,cgobj
+{$ifndef cpu64bit}
+ ,cg64f32
+{$endif cpu64bit}
+ ;
+
+
+{*****************************************************************************
+ TCGINLINENODE
+*****************************************************************************}
+
+
+ procedure tcginlinenode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ case inlinenumber of
+ in_assert_x_y:
+ begin
+ second_Assert;
+ end;
+ in_sizeof_x,
+ in_typeof_x :
+ begin
+ second_SizeofTypeOf;
+ end;
+ in_length_x :
+ begin
+ second_Length;
+ end;
+ in_pred_x,
+ in_succ_x:
+ begin
+ second_PredSucc;
+ end;
+ in_dec_x,
+ in_inc_x :
+ begin
+ second_IncDec;
+ end;
+ in_typeinfo_x:
+ begin
+ second_TypeInfo;
+ end;
+ in_include_x_y,
+ in_exclude_x_y:
+ begin
+ second_IncludeExclude;
+ end;
+ in_pi_real:
+ begin
+ second_pi;
+ end;
+ in_sin_real:
+ begin
+ second_sin_real;
+ end;
+ in_arctan_real:
+ begin
+ second_arctan_real;
+ end;
+ in_abs_real:
+ begin
+ second_abs_real;
+ end;
+ in_sqr_real:
+ begin
+ second_sqr_real;
+ end;
+ in_sqrt_real:
+ begin
+ second_sqrt_real;
+ end;
+ in_ln_real:
+ begin
+ second_ln_real;
+ end;
+ in_cos_real:
+ begin
+ second_cos_real;
+ end;
+ in_prefetch_var:
+ begin
+ second_prefetch;
+ end;
+ in_assigned_x:
+ begin
+ second_assigned;
+ end;
+{$ifdef SUPPORT_MMX}
+ in_mmx_pcmpeqb..in_mmx_pcmpgtw:
+ begin
+ location_reset(location,LOC_MMXREGISTER,OS_NO);
+ if left.location.loc=LOC_REGISTER then
+ begin
+ {!!!!!!!}
+ end
+ else if tcallparanode(left).left.location.loc=LOC_REGISTER then
+ begin
+ {!!!!!!!}
+ end
+ else
+ begin
+ {!!!!!!!}
+ end;
+ end;
+{$endif SUPPORT_MMX}
+ else internalerror(9);
+ end;
+ end;
+
+
+{*****************************************************************************
+ ASSERT GENERIC HANDLING
+*****************************************************************************}
+ procedure tcginlinenode.second_Assert;
+ var
+ hp2,hp3 : tnode;
+ otlabel,oflabel : tasmlabel;
+ paraloc1,paraloc2,
+ paraloc3,paraloc4 : tcgpara;
+ begin
+ { the node should be removed in the firstpass }
+ if not (cs_do_assertion in aktlocalswitches) then
+ internalerror(7123458);
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paraloc4.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ paramanager.getintparaloc(pocall_default,4,paraloc4);
+ otlabel:=truelabel;
+ oflabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(tcallparanode(left).left);
+ maketojumpbool(exprasmlist,tcallparanode(left).left,lr_load_regvars);
+ cg.a_label(exprasmlist,falselabel);
+ { First call secondpass() before we can push the parameters, otherwise
+ parameters allocated in the registers can be destroyed }
+ { generate filename string parameter }
+ hp2:=cstringconstnode.createstr(current_module.sourcefiles.get_file_name(aktfilepos.fileindex),st_shortstring);
+ firstpass(hp2);
+ secondpass(hp2);
+ if codegenerror then
+ exit;
+ { message parameter }
+ hp3:=tcallparanode(tcallparanode(left).right).left;
+ secondpass(hp3);
+ if codegenerror then
+ exit;
+ { push erroraddr }
+ paramanager.allocparaloc(exprasmlist,paraloc4);
+ cg.a_param_reg(exprasmlist,OS_ADDR,NR_FRAME_POINTER_REG,paraloc4);
+ { push lineno }
+ paramanager.allocparaloc(exprasmlist,paraloc3);
+ cg.a_param_const(exprasmlist,OS_INT,aktfilepos.line,paraloc3);
+ { push filename }
+ paramanager.allocparaloc(exprasmlist,paraloc2);
+ cg.a_paramaddr_ref(exprasmlist,hp2.location.reference,paraloc2);
+ { push msg }
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_paramaddr_ref(exprasmlist,hp3.location.reference,paraloc1);
+ { call }
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc2);
+ paramanager.freeparaloc(exprasmlist,paraloc3);
+ paramanager.freeparaloc(exprasmlist,paraloc4);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_ASSERT');
+ cg.deallocallcpuregisters(exprasmlist);
+ location_freetemp(exprasmlist,hp3.location);
+ location_freetemp(exprasmlist,hp2.location);
+ cg.a_label(exprasmlist,truelabel);
+ truelabel:=otlabel;
+ falselabel:=oflabel;
+ paraloc1.done;
+ paraloc2.done;
+ paraloc3.done;
+ paraloc4.done;
+ hp2.free;
+ end;
+
+
+{*****************************************************************************
+ SIZEOF / TYPEOF GENERIC HANDLING
+*****************************************************************************}
+
+ { second_handle_ the sizeof and typeof routines }
+ procedure tcginlinenode.second_SizeOfTypeOf;
+ var
+ href,
+ hrefvmt : treference;
+ hregister : tregister;
+ begin
+ if inlinenumber=in_sizeof_x then
+ location_reset(location,LOC_REGISTER,OS_INT)
+ else
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ { for both cases load vmt }
+ if left.nodetype=typen then
+ begin
+ hregister:=cg.getaddressregister(exprasmlist);
+ reference_reset_symbol(href,objectlibrary.newasmsymbol(tobjectdef(left.resulttype.def).vmt_mangledname,AB_EXTERNAL,AT_DATA),0);
+ cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
+ end
+ else
+ begin
+ secondpass(left);
+ hregister:=cg.getaddressregister(exprasmlist);
+
+ { handle self inside a method of a class }
+ case left.location.loc of
+ LOC_CREGISTER,
+ LOC_REGISTER :
+ begin
+ if (left.resulttype.def.deftype=classrefdef) or
+ (po_staticmethod in current_procinfo.procdef.procoptions) then
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,hregister)
+ else
+ begin
+ { load VMT pointer }
+ reference_reset_base(hrefvmt,left.location.register,tobjectdef(left.resulttype.def).vmt_offset);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,hrefvmt,hregister);
+ end
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if is_class(left.resulttype.def) then
+ begin
+ { deref class }
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,hregister);
+ cg.g_maybe_testself(exprasmlist,hregister);
+ { load VMT pointer }
+ reference_reset_base(hrefvmt,hregister,tobjectdef(left.resulttype.def).vmt_offset);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,hrefvmt,hregister);
+ end
+ else
+ begin
+ { load VMT pointer, but not for classrefdefs }
+ if (left.resulttype.def.deftype=objectdef) then
+ inc(left.location.reference.offset,tobjectdef(left.resulttype.def).vmt_offset);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,hregister);
+ end;
+ end;
+ else
+ internalerror(200301301);
+ end;
+ end;
+ { in sizeof load size }
+ if inlinenumber=in_sizeof_x then
+ begin
+ reference_reset_base(href,hregister,0);
+ hregister:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_ref_reg(exprasmlist,OS_INT,OS_INT,href,hregister);
+ end;
+ location.register:=hregister;
+ end;
+
+
+
+{*****************************************************************************
+ LENGTH GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tcginlinenode.second_Length;
+ var
+ lengthlab : tasmlabel;
+ hregister : tregister;
+ href : treference;
+ begin
+ secondpass(left);
+ if is_shortstring(left.resulttype.def) then
+ begin
+ location_copy(location,left.location);
+ location.size:=OS_8;
+ end
+ else
+ begin
+ { length in ansi/wide strings is at offset -sizeof(aint) }
+ location_force_reg(exprasmlist,left.location,OS_ADDR,false);
+ objectlibrary.getjumplabel(lengthlab);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,left.location.register,lengthlab);
+ reference_reset_base(href,left.location.register,-sizeof(aint));
+ hregister:=cg.makeregsize(exprasmlist,left.location.register,OS_INT);
+ cg.a_load_ref_reg(exprasmlist,OS_INT,OS_INT,href,hregister);
+ if is_widestring(left.resulttype.def) then
+ cg.a_op_const_reg(exprasmlist,OP_SHR,OS_INT,1,hregister);
+ cg.a_label(exprasmlist,lengthlab);
+ location_reset(location,LOC_REGISTER,OS_INT);
+ location.register:=hregister;
+ end;
+ end;
+
+
+{*****************************************************************************
+ PRED/SUCC GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tcginlinenode.second_PredSucc;
+ var
+ cgsize : TCGSize;
+ cgop : topcg;
+ begin
+ secondpass(left);
+ if inlinenumber=in_pred_x then
+ cgop:=OP_SUB
+ else
+ cgop:=OP_ADD;
+ cgsize:=def_cgsize(resulttype.def);
+
+ { we need a value in a register }
+ location_copy(location,left.location);
+ location_force_reg(exprasmlist,location,cgsize,false);
+
+{$ifndef cpu64bit}
+ if cgsize in [OS_64,OS_S64] then
+ cg64.a_op64_const_reg(exprasmlist,cgop,cgsize,1,location.register64)
+ else
+{$endif cpu64bit}
+ cg.a_op_const_reg(exprasmlist,cgop,location.size,1,location.register);
+
+ cg.g_rangecheck(exprasmlist,location,resulttype.def,resulttype.def);
+ end;
+
+
+{*****************************************************************************
+ INC/DEC GENERIC HANDLING
+*****************************************************************************}
+ procedure tcginlinenode.second_IncDec;
+ const
+ addsubop:array[in_inc_x..in_dec_x] of TOpCG=(OP_ADD,OP_SUB);
+ var
+ addvalue : TConstExprInt;
+ addconstant : boolean;
+{$ifndef cpu64bit}
+ hregisterhi,
+{$endif cpu64bit}
+ hregister : tregister;
+ cgsize : tcgsize;
+ begin
+ { set defaults }
+ addconstant:=true;
+ { load first parameter, must be a reference }
+ secondpass(tcallparanode(left).left);
+ cgsize:=def_cgsize(tcallparanode(left).left.resulttype.def);
+ { get addvalue }
+ case tcallparanode(left).left.resulttype.def.deftype of
+ orddef,
+ enumdef :
+ addvalue:=1;
+ pointerdef :
+ begin
+ if is_void(tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def) then
+ addvalue:=1
+ else
+ addvalue:=tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def.size;
+ end;
+ else
+ internalerror(10081);
+ end;
+ { second_ argument specified?, must be a s32bit in register }
+ if assigned(tcallparanode(left).right) then
+ begin
+ secondpass(tcallparanode(tcallparanode(left).right).left);
+ { when constant, just multiply the addvalue }
+ if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
+ addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
+ else
+ begin
+ location_force_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,cgsize,addvalue<=1);
+ hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
+{$ifndef cpu64bit}
+ hregisterhi:=tcallparanode(tcallparanode(left).right).left.location.register64.reghi;
+{$endif cpu64bit}
+ { insert multiply with addvalue if its >1 }
+ if addvalue>1 then
+ cg.a_op_const_reg(exprasmlist,OP_IMUL,cgsize,addvalue,hregister);
+ addconstant:=false;
+ end;
+ end;
+ { write the add instruction }
+ if addconstant then
+ begin
+{$ifndef cpu64bit}
+ if cgsize in [OS_64,OS_S64] then
+ cg64.a_op64_const_loc(exprasmlist,addsubop[inlinenumber],cgsize,addvalue,tcallparanode(left).left.location)
+ else
+{$endif cpu64bit}
+ cg.a_op_const_loc(exprasmlist,addsubop[inlinenumber],
+ aint(addvalue),tcallparanode(left).left.location);
+ end
+ else
+ begin
+{$ifndef cpu64bit}
+ if cgsize in [OS_64,OS_S64] then
+ cg64.a_op64_reg_loc(exprasmlist,addsubop[inlinenumber],cgsize,
+ joinreg64(hregister,hregisterhi),tcallparanode(left).left.location)
+ else
+{$endif cpu64bit}
+ cg.a_op_reg_loc(exprasmlist,addsubop[inlinenumber],
+ hregister,tcallparanode(left).left.location);
+ end;
+ cg.g_overflowcheck(exprasmlist,tcallparanode(left).left.location,tcallparanode(left).resulttype.def);
+ cg.g_rangecheck(exprasmlist,tcallparanode(left).left.location,tcallparanode(left).left.resulttype.def,
+ tcallparanode(left).left.resulttype.def);
+ end;
+
+
+{*****************************************************************************
+ TYPEINFO GENERIC HANDLING
+*****************************************************************************}
+ procedure tcginlinenode.second_typeinfo;
+ var
+ href : treference;
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(exprasmlist);
+ reference_reset_symbol(href,tstoreddef(left.resulttype.def).get_rtti_label(fullrtti),0);
+ cg.a_loadaddr_ref_reg(exprasmlist,href,location.register);
+ end;
+
+
+{*****************************************************************************
+ INCLUDE/EXCLUDE GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tcginlinenode.second_IncludeExclude;
+ var
+ bitsperop,l : longint;
+ opsize : tcgsize;
+ cgop : topcg;
+ addrreg2,addrreg,
+ hregister,hregister2: tregister;
+ use_small : boolean;
+ href : treference;
+ begin
+ opsize:=OS_32;
+ bitsperop:=(8*tcgsize2size[opsize]);
+ secondpass(tcallparanode(left).left);
+ if tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn then
+ begin
+ { calculate bit position }
+ l:=1 shl (tordconstnode(tcallparanode(tcallparanode(left).right).left).value mod bitsperop);
+
+ { determine operator }
+ if inlinenumber=in_include_x_y then
+ cgop:=OP_OR
+ else
+ begin
+ cgop:=OP_AND;
+ l:=not(l);
+ end;
+ case tcallparanode(left).left.location.loc of
+ LOC_REFERENCE :
+ begin
+ inc(tcallparanode(left).left.location.reference.offset,
+ (tordconstnode(tcallparanode(tcallparanode(left).right).left).value div bitsperop)*tcgsize2size[opsize]);
+ cg.a_op_const_ref(exprasmlist,cgop,opsize,l,tcallparanode(left).left.location.reference);
+ end;
+ LOC_CREGISTER :
+ cg.a_op_const_reg(exprasmlist,cgop,tcallparanode(left).left.location.size,l,tcallparanode(left).left.location.register);
+ else
+ internalerror(200405021);
+ end;
+ end
+ else
+ begin
+ use_small:=
+ { set type }
+ (tsetdef(tcallparanode(left).left.resulttype.def).settype=smallset)
+ and
+ { elemenut number between 1 and 32 }
+ ((tcallparanode(tcallparanode(left).right).left.resulttype.def.deftype=orddef) and
+ (torddef(tcallparanode(tcallparanode(left).right).left.resulttype.def).high<=32) or
+ (tcallparanode(tcallparanode(left).right).left.resulttype.def.deftype=enumdef) and
+ (tenumdef(tcallparanode(tcallparanode(left).right).left.resulttype.def).max<=32));
+
+ { generate code for the element to set }
+ secondpass(tcallparanode(tcallparanode(left).right).left);
+
+ { bitnumber - which must be loaded into register }
+ hregister:=cg.getintregister(exprasmlist,opsize);
+ hregister2:=cg.getintregister(exprasmlist,opsize);
+
+ cg.a_load_loc_reg(exprasmlist,opsize,
+ tcallparanode(tcallparanode(left).right).left.location,hregister);
+
+ if use_small then
+ begin
+ { hregister contains the bitnumber to add }
+ cg.a_load_const_reg(exprasmlist, opsize, 1, hregister2);
+ cg.a_op_reg_reg(exprasmlist, OP_SHL, opsize, hregister, hregister2);
+
+ { possiblities :
+ bitnumber : LOC_REFERENCE, LOC_REGISTER, LOC_CREGISTER
+ set value : LOC_REFERENCE, LOC_REGISTER
+ }
+ { location of set }
+ if inlinenumber=in_include_x_y then
+ begin
+ cg.a_op_reg_loc(exprasmlist, OP_OR, hregister2,
+ tcallparanode(left).left.location);
+ end
+ else
+ begin
+ cg.a_op_reg_reg(exprasmlist, OP_NOT, opsize, hregister2,hregister2);
+ cg.a_op_reg_loc(exprasmlist, OP_AND, hregister2,
+ tcallparanode(left).left.location);
+ end;
+ end
+ else
+ begin
+ { possiblities :
+ bitnumber : LOC_REFERENCE, LOC_REGISTER, LOC_CREGISTER
+ set value : LOC_REFERENCE
+ }
+ { hregister contains the bitnumber (div 32 to get the correct offset) }
+ { hregister contains the bitnumber to add }
+
+ cg.a_op_const_reg_reg(exprasmlist, OP_SHR, opsize, 5, hregister,hregister2);
+ cg.a_op_const_reg(exprasmlist, OP_SHL, opsize, 2, hregister2);
+ addrreg:=cg.getaddressregister(exprasmlist);
+ { we need an extra address register to be able to do an ADD operation }
+ addrreg2:=cg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,opsize,OS_ADDR,hregister2,addrreg2);
+ { calculate the correct address of the operand }
+ cg.a_loadaddr_ref_reg(exprasmlist, tcallparanode(left).left.location.reference,addrreg);
+ cg.a_op_reg_reg(exprasmlist, OP_ADD, OS_ADDR, addrreg2, addrreg);
+
+ { hregister contains the bitnumber to add }
+ cg.a_load_const_reg(exprasmlist, opsize, 1, hregister2);
+ cg.a_op_const_reg(exprasmlist, OP_AND, opsize, 31, hregister);
+ cg.a_op_reg_reg(exprasmlist, OP_SHL, opsize, hregister, hregister2);
+
+ reference_reset_base(href,addrreg,0);
+
+ if inlinenumber=in_include_x_y then
+ cg.a_op_reg_ref(exprasmlist, OP_OR, opsize, hregister2, href)
+ else
+ begin
+ cg.a_op_reg_reg(exprasmlist, OP_NOT, opsize, hregister2, hregister2);
+ cg.a_op_reg_ref(exprasmlist, OP_AND, opsize, hregister2, href);
+ end;
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ FLOAT GENERIC HANDLING
+*****************************************************************************}
+
+{
+ These routines all call internal RTL routines, so if they are
+ called here, they give an internal error
+}
+ procedure tcginlinenode.second_pi;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_arctan_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_abs_real;
+ begin
+ internalerror(20020718);
+ end;
+
+
+ procedure tcginlinenode.second_sqr_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_sqrt_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_ln_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_cos_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_sin_real;
+ begin
+ internalerror(20020718);
+ end;
+
+
+ procedure tcginlinenode.second_prefetch;
+ begin
+ end;
+
+
+{*****************************************************************************
+ ASSIGNED GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tcginlinenode.second_assigned;
+ begin
+ secondpass(tcallparanode(left).left);
+ { force left to be an OS_ADDR, since in case of method procvars }
+ { the size is 2*OS_ADDR (JM) }
+ cg.a_cmp_const_loc_label(exprasmlist,OS_ADDR,OC_NE,0,tcallparanode(left).left.location,truelabel);
+ cg.a_jmp_always(exprasmlist,falselabel);
+ location_reset(location,LOC_JUMP,OS_NO);
+ end;
+
+
+begin
+ cinlinenode:=tcginlinenode;
+end.
diff --git a/compiler/ncgld.pas b/compiler/ncgld.pas
new file mode 100644
index 0000000000..c97ffbeed3
--- /dev/null
+++ b/compiler/ncgld.pas
@@ -0,0 +1,940 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for nodes that handle loads and assignments which
+ are the same for all (most) processors
+
+ 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 ncgld;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nld;
+
+ type
+ tcgloadnode = class(tloadnode)
+ procedure pass_2;override;
+ procedure generate_picvaraccess;virtual;
+ end;
+
+ tcgassignmentnode = class(tassignmentnode)
+ procedure pass_2;override;
+ end;
+
+ tcgarrayconstructornode = class(tarrayconstructornode)
+ procedure pass_2;override;
+ end;
+
+ tcgrttinode = class(trttinode)
+ procedure pass_2;override;
+ end;
+
+
+implementation
+
+ uses
+ cutils,
+ systems,
+ verbose,globtype,globals,
+ symconst,symtype,symdef,symsym,defutil,paramgr,
+ ncnv,ncon,nmem,nbas,
+ aasmbase,aasmtai,aasmcpu,
+ cgbase,pass_2,
+ procinfo,
+ cpubase,parabase,
+ tgobj,ncgutil,
+ cgutils,cgobj,
+ ncgbas,ncgflw;
+
+{*****************************************************************************
+ SecondLoad
+*****************************************************************************}
+
+ procedure tcgloadnode.generate_picvaraccess;
+ begin
+{$ifndef sparc}
+ location.reference.base:=current_procinfo.got;
+ location.reference.symbol:=objectlibrary.newasmsymbol(tglobalvarsym(symtableentry).mangledname+'@GOT',AB_EXTERNAL,AT_DATA);
+{$endif sparc}
+ end;
+
+
+ procedure tcgloadnode.pass_2;
+ var
+ hregister : tregister;
+ symtabletype : tsymtabletype;
+ href : treference;
+ newsize : tcgsize;
+ endrelocatelab,
+ norelocatelab : tasmlabel;
+ paraloc1 : tcgpara;
+ begin
+ { we don't know the size of all arrays }
+ newsize:=def_cgsize(resulttype.def);
+ location_reset(location,LOC_REFERENCE,newsize);
+ case symtableentry.typ of
+ absolutevarsym :
+ begin
+ { this is only for toasm and toaddr }
+ case tabsolutevarsym(symtableentry).abstyp of
+ toaddr :
+ begin
+{$ifdef i386}
+ if tabsolutevarsym(symtableentry).absseg then
+ location.reference.segment:=NR_FS;
+{$endif i386}
+ location.reference.offset:=tabsolutevarsym(symtableentry).addroffset;
+ end;
+ toasm :
+ location.reference.symbol:=objectlibrary.newasmsymbol(tabsolutevarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
+ else
+ internalerror(200310283);
+ end;
+ end;
+ constsym:
+ begin
+ if tconstsym(symtableentry).consttyp=constresourcestring then
+ begin
+ location_reset(location,LOC_CREFERENCE,OS_ADDR);
+ location.reference.symbol:=objectlibrary.newasmsymbol(make_mangledname('RESOURCESTRINGLIST',tconstsym(symtableentry).owner,''),AB_EXTERNAL,AT_DATA);
+ location.reference.offset:=tconstsym(symtableentry).resstrindex*(4+sizeof(aint)*3)+4+sizeof(aint);
+ end
+ else
+ internalerror(22798);
+ end;
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ symtabletype:=symtable.symtabletype;
+ hregister:=NR_NO;
+ if (target_info.system=system_powerpc_darwin) and
+ ([vo_is_dll_var,vo_is_external] * tabstractvarsym(symtableentry).varoptions <> []) then
+ begin
+ if not(pi_needs_got in current_procinfo.flags) then
+ internalerror(200403022);
+ generate_picvaraccess;
+ end
+ else if (vo_is_dll_var in tabstractvarsym(symtableentry).varoptions) then
+ { DLL variable }
+ begin
+ hregister:=cg.getaddressregister(exprasmlist);
+ location.reference.symbol:=objectlibrary.newasmsymbol(tglobalvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,location.reference,hregister);
+ reference_reset_base(location.reference,hregister,0);
+ end
+{$ifndef segment_threadvars}
+ { Thread variable }
+ else if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
+ begin
+ {
+ Thread var loading is optimized to first check if
+ a relocate function is available. When the function
+ is available it is called to retrieve the address.
+ Otherwise the address is loaded with the symbol
+
+ The code needs to be in the order to first handle the
+ call and then the address load to be sure that the
+ register that is used for returning is the same (PFV)
+ }
+ objectlibrary.getjumplabel(norelocatelab);
+ objectlibrary.getjumplabel(endrelocatelab);
+ { make sure hregister can't allocate the register necessary for the parameter }
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ hregister:=cg.getaddressregister(exprasmlist);
+ reference_reset_symbol(href,objectlibrary.newasmsymbol('FPC_THREADVAR_RELOCATE',AB_EXTERNAL,AT_DATA),0);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
+ { don't save the allocated register else the result will be destroyed later }
+ reference_reset_symbol(href,objectlibrary.newasmsymbol(tglobalvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_ref(exprasmlist,OS_ADDR,href,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ paraloc1.done;
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_reg(exprasmlist,hregister);
+ cg.deallocallcpuregisters(exprasmlist);
+ cg.getcpuregister(exprasmlist,NR_FUNCTION_RESULT_REG);
+ cg.ungetcpuregister(exprasmlist,NR_FUNCTION_RESULT_REG);
+ hregister:=cg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
+ cg.a_jmp_always(exprasmlist,endrelocatelab);
+ cg.a_label(exprasmlist,norelocatelab);
+ { no relocation needed, load the address of the variable only, the
+ layout of a threadvar is (4 bytes pointer):
+ 0 - Threadvar index
+ 4 - Threadvar value in single threading }
+ reference_reset_symbol(href,objectlibrary.newasmsymbol(tglobalvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),sizeof(aint));
+ cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
+ cg.a_label(exprasmlist,endrelocatelab);
+ location.reference.base:=hregister;
+ end
+{$endif}
+ { Nested variable }
+ else if assigned(left) then
+ begin
+ if not(symtabletype in [localsymtable,parasymtable]) then
+ internalerror(200309285);
+ secondpass(left);
+ if left.location.loc<>LOC_REGISTER then
+ internalerror(200309286);
+ if tabstractnormalvarsym(symtableentry).localloc.loc<>LOC_REFERENCE then
+ internalerror(200409241);
+ hregister:=left.location.register;
+ reference_reset_base(location.reference,hregister,tabstractnormalvarsym(symtableentry).localloc.reference.offset);
+ end
+ { Normal (or external) variable }
+ else
+ begin
+{$ifdef OLDREGVARS}
+ { in case it is a register variable: }
+ if tvarsym(symtableentry).localloc.loc in [LOC_REGISTER,LOC_FPUREGISTER] then
+ begin
+ case getregtype(tvarsym(symtableentry).localloc.register) of
+ R_FPUREGISTER :
+ begin
+ location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
+ location.register:=tvarsym(symtableentry).localloc.register;
+ end;
+ R_INTREGISTER :
+ begin
+ location_reset(location,LOC_CREGISTER,def_cgsize(resulttype.def));
+ location.register:=tvarsym(symtableentry).localloc.register;
+ hregister := location.register;
+ end;
+ else
+ internalerror(200301172);
+ end;
+ end
+ else
+{$endif OLDREGVARS}
+ begin
+ case symtabletype of
+ stt_exceptsymtable,
+ localsymtable,
+ parasymtable :
+ location:=tabstractnormalvarsym(symtableentry).localloc;
+ globalsymtable,
+ staticsymtable :
+ begin
+ if (target_info.system=system_powerpc_darwin) and
+ (cs_create_pic in aktmoduleswitches) then
+ begin
+ generate_picvaraccess;
+ if not(pi_needs_got in current_procinfo.flags) then
+ internalerror(200403023);
+ end
+ else
+ begin
+ if tabstractnormalvarsym(symtableentry).localloc.loc=LOC_INVALID then
+ reference_reset_symbol(location.reference,objectlibrary.newasmsymbol(tglobalvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0)
+ else
+ location:=tglobalvarsym(symtableentry).localloc;
+{$ifdef segment_threadvars}
+ if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
+ location.reference.segment:=NR_GS;
+{$endif}
+ end;
+ end;
+ else
+ internalerror(200305102);
+ end;
+ end;
+ end;
+
+ { handle call by reference variables when they are not
+ alreayd copied to local copies. Also ignore the reference
+ when we need to load the self pointer for objects }
+ if is_addr_param_load then
+ begin
+ if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+ hregister:=location.register
+ else
+ begin
+ hregister:=cg.getaddressregister(exprasmlist);
+ { we need to load only an address }
+ location.size:=OS_ADDR;
+ cg.a_load_loc_reg(exprasmlist,location.size,location,hregister);
+ end;
+ location_reset(location,LOC_REFERENCE,newsize);
+ location.reference.base:=hregister;
+ end;
+
+ { make const a LOC_CREFERENCE }
+ if (tabstractvarsym(symtableentry).varspez=vs_const) and
+ (location.loc=LOC_REFERENCE) then
+ location.loc:=LOC_CREFERENCE;
+ end;
+ procsym:
+ begin
+ if not assigned(procdef) then
+ internalerror(200312011);
+ if assigned(left) then
+ begin
+ {
+ THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
+ ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
+ CONSISTS OF TWO OS_ADDR, so you cannot set it
+ to OS_64 - how to solve?? Carl
+ Solved. Florian
+ }
+ if (sizeof(aint) = 4) then
+ location_reset(location,LOC_CREFERENCE,OS_64)
+ else if (sizeof(aint) = 8) then
+ location_reset(location,LOC_CREFERENCE,OS_128)
+ else
+ internalerror(20020520);
+ tg.GetTemp(exprasmlist,2*sizeof(aint),tt_normal,location.reference);
+ secondpass(left);
+
+ { load class instance address }
+ case left.location.loc of
+ LOC_CREGISTER,
+ LOC_REGISTER:
+ begin
+ { this is not possible for objects }
+ if is_object(left.resulttype.def) then
+ internalerror(200304234);
+ hregister:=left.location.register;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ hregister:=cg.getaddressregister(exprasmlist);
+ if is_class_or_interface(left.resulttype.def) then
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,hregister)
+ else
+ cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
+ location_freetemp(exprasmlist,left.location);
+ end;
+ else
+ internalerror(26019);
+ end;
+
+ { store the class instance address }
+ href:=location.reference;
+ inc(href.offset,sizeof(aint));
+ cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,href);
+
+ { virtual method ? }
+ if (po_virtualmethod in procdef.procoptions) then
+ begin
+ { load vmt pointer }
+ reference_reset_base(href,hregister,0);
+ hregister:=cg.getaddressregister(exprasmlist);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
+ { load method address }
+ reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
+ hregister:=cg.getaddressregister(exprasmlist);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
+ { ... and store it }
+ cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
+ end
+ else
+ begin
+ { load address of the function }
+ reference_reset_symbol(href,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION),0);
+ hregister:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
+ cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
+ end;
+ end
+ else
+ begin
+ {!!!!! Be aware, work on virtual methods too }
+ location.reference.symbol:=objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION);
+ end;
+ end;
+ typedconstsym :
+ location.reference.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
+ labelsym :
+ location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
+ else internalerror(200510032);
+ end;
+ end;
+
+
+{*****************************************************************************
+ SecondAssignment
+*****************************************************************************}
+
+ procedure tcgassignmentnode.pass_2;
+ var
+ otlabel,hlabel,oflabel : tasmlabel;
+ fputyp : tfloattype;
+ href : treference;
+ releaseright : boolean;
+ len : aint;
+ r:Tregister;
+
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ otlabel:=truelabel;
+ oflabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+
+ {
+ in most cases we can process first the right node which contains
+ the most complex code. Exceptions for this are:
+ - result is in flags, loading left will then destroy the flags
+ - result is a jump, loading left must be already done before the jump is made
+ - result need reference count, when left points to a value used in
+ right then decreasing the refcnt on left can possibly release
+ the memory before right increased the refcnt, result is that an
+ empty value is assigned
+ - calln, call destroys most registers and is therefor 'complex'
+
+ But not when the result is in the flags, then
+ loading the left node afterwards can destroy the flags.
+ }
+ if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
+ ((right.nodetype=calln) or
+ (right.resulttype.def.needs_inittable) or
+ (right.registersint>=left.registersint)) then
+ begin
+ secondpass(right);
+ { increment source reference counter, this is
+ useless for string constants}
+ if (right.resulttype.def.needs_inittable) and
+ (right.nodetype<>stringconstn) then
+ begin
+ location_force_mem(exprasmlist,right.location);
+ location_get_data_ref(exprasmlist,right.location,href,false);
+ cg.g_incrrefcount(exprasmlist,right.resulttype.def,href);
+ end;
+ if codegenerror then
+ exit;
+
+ if not(nf_concat_string in flags) then
+ begin
+ { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
+ { can be false }
+ secondpass(left);
+ { decrement destination reference counter }
+ if (left.resulttype.def.needs_inittable) then
+ begin
+ location_get_data_ref(exprasmlist,left.location,href,false);
+ cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
+ end;
+ if codegenerror then
+ exit;
+ end;
+ end
+ else
+ begin
+ { calculate left sides }
+ { don't do it yet if it's a crgister (JM) }
+ if not(nf_concat_string in flags) then
+ begin
+ secondpass(left);
+ { decrement destination reference counter }
+ if (left.resulttype.def.needs_inittable) then
+ begin
+ location_get_data_ref(exprasmlist,left.location,href,false);
+ cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
+ end;
+ if codegenerror then
+ exit;
+ end;
+
+ { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
+ { can be false }
+ secondpass(right);
+ { increment source reference counter, this is
+ useless for string constants}
+ if (right.resulttype.def.needs_inittable) and
+ (right.nodetype<>stringconstn) then
+ begin
+ location_force_mem(exprasmlist,right.location);
+ location_get_data_ref(exprasmlist,right.location,href,false);
+ cg.g_incrrefcount(exprasmlist,right.resulttype.def,href);
+ end;
+
+ if codegenerror then
+ exit;
+ end;
+
+ releaseright:=true;
+
+ { optimize temp to temp copies }
+(* if (left.nodetype = temprefn) and
+ { we may store certain temps in registers in the future, then this }
+ { optimization will have to be adapted }
+ (left.location.loc = LOC_REFERENCE) and
+ (right.location.loc = LOC_REFERENCE) and
+ tg.istemp(right.location.reference) and
+ (tg.sizeoftemp(exprasmlist,right.location.reference) = tg.sizeoftemp(exprasmlist,left.location.reference)) then
+ begin
+ { in theory, we should also make sure the left temp type is }
+ { already more or less of the same kind (ie. we must not }
+ { assign an ansistring to a normaltemp). In practice, the }
+ { assignment node will have already taken care of this for us }
+ tcgtemprefnode(left).changelocation(right.location.reference);
+ end
+ { shortstring assignments are handled separately }
+ else *)
+ if is_shortstring(left.resulttype.def) then
+ begin
+ {
+ we can get here only in the following situations
+ for the right node:
+ - empty constant string
+ - char
+ }
+
+ { empty constant string }
+ if (right.nodetype=stringconstn) and
+ (tstringconstnode(right).len=0) then
+ begin
+ cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
+ end
+ { char loading }
+ else if is_char(right.resulttype.def) then
+ begin
+ if right.nodetype=ordconstn then
+ begin
+ if (target_info.endian = endian_little) then
+ cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
+ left.location.reference)
+ else
+ cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
+ left.location.reference);
+ end
+ else
+ begin
+ href:=left.location.reference;
+ cg.a_load_const_ref(exprasmlist,OS_8,1,href);
+ inc(href.offset,1);
+ case right.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ r:=cg.makeregsize(exprasmlist,right.location.register,OS_8);
+ cg.a_load_reg_ref(exprasmlist,OS_8,OS_8,r,href);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ cg.a_load_ref_ref(exprasmlist,OS_8,OS_8,right.location.reference,href);
+ else
+ internalerror(200205111);
+ end;
+ end;
+ end
+ else
+ internalerror(200204249);
+ end
+ else
+ begin
+ case right.location.loc of
+ LOC_CONSTANT :
+ begin
+{$ifndef cpu64bit}
+ if right.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_const_loc(exprasmlist,right.location.value64,left.location)
+ else
+{$endif cpu64bit}
+ cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifndef cpu64bit}
+ if left.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_ref_reg(exprasmlist,right.location.reference,left.location.register64)
+ else
+{$endif cpu64bit}
+ cg.a_load_ref_reg(exprasmlist,right.location.size,left.location.size,right.location.reference,left.location.register);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ cg.a_loadfpu_ref_reg(exprasmlist,
+ right.location.size,
+ right.location.reference,
+ left.location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+{$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
+ { Use unaligned copy when the offset is not aligned }
+ len:=left.resulttype.def.size;
+ if (right.location.reference.offset mod sizeof(aint)<>0) or
+ (left.location.reference.offset mod sizeof(aint)<>0) or
+ (right.resulttype.def.alignment<sizeof(aint)) then
+ cg.g_concatcopy_unaligned(exprasmlist,right.location.reference,left.location.reference,len)
+ else
+ cg.g_concatcopy(exprasmlist,right.location.reference,left.location.reference,len);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ cg.a_loadmm_ref_reg(exprasmlist,
+ right.location.size,
+ left.location.size,
+ right.location.reference,
+ left.location.register,mms_movescalar);
+ else
+ internalerror(200203284);
+ end;
+ end;
+{$ifdef SUPPORT_MMX}
+ LOC_CMMXREGISTER,
+ LOC_MMXREGISTER:
+ begin
+ if left.location.loc=LOC_CMMXREGISTER then
+ cg.a_loadmm_reg_reg(exprasmlist,OS_M64,OS_M64,right.location.register,left.location.register,nil)
+ else
+ cg.a_loadmm_reg_ref(exprasmlist,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
+ end;
+{$endif SUPPORT_MMX}
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ if left.resulttype.def.deftype=arraydef then
+ begin
+ end
+ else
+ begin
+ if left.location.loc=LOC_CMMREGISTER then
+ cg.a_loadmm_reg_reg(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
+ else
+ cg.a_loadmm_reg_ref(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
+ end;
+ end;
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifndef cpu64bit}
+ if left.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_reg_loc(exprasmlist,
+ right.location.register64,left.location)
+ else
+{$endif cpu64bit}
+ cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ if (left.resulttype.def.deftype=floatdef) then
+ fputyp:=tfloatdef(left.resulttype.def).typ
+ else
+ if (right.resulttype.def.deftype=floatdef) then
+ fputyp:=tfloatdef(right.resulttype.def).typ
+ else
+ if (right.nodetype=typeconvn) and
+ (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
+ fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
+ else
+ fputyp:=s32real;
+ { we can't do direct moves between fpu and mm registers }
+ if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
+ begin
+ location_force_mmregscalar(exprasmlist,right.location,false);
+ cg.a_loadmm_reg_reg(exprasmlist,
+ tfloat2tcgsize[fputyp],tfloat2tcgsize[fputyp],
+ right.location.register,left.location.register,mms_movescalar);
+ end
+ else
+ cg.a_loadfpu_reg_loc(exprasmlist,
+ tfloat2tcgsize[fputyp],
+ right.location.register,left.location);
+ end;
+ LOC_JUMP :
+ begin
+ objectlibrary.getjumplabel(hlabel);
+ cg.a_label(exprasmlist,truelabel);
+ cg.a_load_const_loc(exprasmlist,1,left.location);
+ cg.a_jmp_always(exprasmlist,hlabel);
+ cg.a_label(exprasmlist,falselabel);
+ cg.a_load_const_loc(exprasmlist,0,left.location);
+ cg.a_label(exprasmlist,hlabel);
+ end;
+{$ifdef cpuflags}
+ LOC_FLAGS :
+ begin
+ {This can be a wordbool or longbool too, no?}
+ if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
+ else
+ begin
+ if not(left.location.loc = LOC_REFERENCE) then
+ internalerror(200203273);
+ cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
+ end;
+ end;
+{$endif cpuflags}
+ end;
+ end;
+
+ if releaseright then
+ location_freetemp(exprasmlist,right.location);
+
+ truelabel:=otlabel;
+ falselabel:=oflabel;
+ end;
+
+
+{*****************************************************************************
+ SecondArrayConstruct
+*****************************************************************************}
+
+ const
+ vtInteger = 0;
+ vtBoolean = 1;
+ vtChar = 2;
+ vtExtended = 3;
+ vtString = 4;
+ vtPointer = 5;
+ vtPChar = 6;
+ vtObject = 7;
+ vtClass = 8;
+ vtWideChar = 9;
+ vtPWideChar = 10;
+ vtAnsiString32 = 11;
+ vtCurrency = 12;
+ vtVariant = 13;
+ vtInterface = 14;
+ vtWideString = 15;
+ vtInt64 = 16;
+ vtQWord = 17;
+ vtAnsiString16 = 18;
+ vtAnsiString64 = 19;
+
+ procedure tcgarrayconstructornode.pass_2;
+ var
+ hp : tarrayconstructornode;
+ href : treference;
+ lt : tdef;
+ vaddr : boolean;
+ vtype : longint;
+ freetemp,
+ dovariant : boolean;
+ elesize : longint;
+ tmpreg : tregister;
+ paraloc : tcgparalocation;
+ begin
+ dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
+ if dovariant then
+ elesize:=sizeof(aint)+sizeof(aint)
+ else
+ elesize:=tarraydef(resulttype.def).elesize;
+ location_reset(location,LOC_CREFERENCE,OS_NO);
+ fillchar(paraloc,sizeof(paraloc),0);
+ { Allocate always a temp, also if no elements are required, to
+ be sure that location is valid (PFV) }
+ if tarraydef(resulttype.def).highrange=-1 then
+ tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
+ else
+ tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
+ href:=location.reference;
+ { Process nodes in array constructor }
+ hp:=self;
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ freetemp:=true;
+ secondpass(hp.left);
+ if codegenerror then
+ exit;
+ { Move flags and jump in register }
+ if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(exprasmlist,hp.left.location,def_cgsize(hp.left.resulttype.def),false);
+ if dovariant then
+ begin
+ { find the correct vtype value }
+ vtype:=$ff;
+ vaddr:=false;
+ lt:=hp.left.resulttype.def;
+ case lt.deftype of
+ enumdef,
+ orddef :
+ begin
+ if is_64bit(lt) then
+ begin
+ case torddef(lt).typ of
+ scurrency:
+ vtype:=vtCurrency;
+ s64bit:
+ vtype:=vtInt64;
+ u64bit:
+ vtype:=vtQWord;
+ end;
+ freetemp:=false;
+ vaddr:=true;
+ end
+ else if (lt.deftype=enumdef) or
+ is_integer(lt) then
+ vtype:=vtInteger
+ else
+ if is_boolean(lt) then
+ vtype:=vtBoolean
+ else
+ if (lt.deftype=orddef) then
+ begin
+ case torddef(lt).typ of
+ uchar:
+ vtype:=vtChar;
+ uwidechar:
+ vtype:=vtWideChar;
+ end;
+ end;
+ end;
+ floatdef :
+ begin
+ if is_currency(lt) then
+ vtype:=vtCurrency
+ else
+ vtype:=vtExtended;
+ freetemp:=false;
+ vaddr:=true;
+ end;
+ procvardef,
+ pointerdef :
+ begin
+ if is_pchar(lt) then
+ vtype:=vtPChar
+ else if is_pwidechar(lt) then
+ vtype:=vtPWideChar
+ else
+ vtype:=vtPointer;
+ end;
+ variantdef :
+ begin
+ vtype:=vtVariant;
+ vaddr:=true;
+ freetemp:=false;
+ end;
+ classrefdef :
+ vtype:=vtClass;
+ objectdef :
+ if is_interface(lt) then
+ vtype:=vtInterface
+ { vtObject really means a class based on TObject }
+ else if is_class(lt) then
+ vtype:=vtObject
+ else
+ internalerror(200505171);
+ stringdef :
+ begin
+ if is_shortstring(lt) then
+ begin
+ vtype:=vtString;
+ vaddr:=true;
+ freetemp:=false;
+ end
+ else
+ if is_ansistring(lt) then
+ begin
+ vtype:=vtAnsiString;
+ freetemp:=false;
+ end
+ else
+ if is_widestring(lt) then
+ begin
+ vtype:=vtWideString;
+ freetemp:=false;
+ end;
+ end;
+ end;
+ if vtype=$ff then
+ internalerror(14357);
+ { write changing field update href to the next element }
+ inc(href.offset,sizeof(aint));
+ if vaddr then
+ begin
+ location_force_mem(exprasmlist,hp.left.location);
+ tmpreg:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
+ cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
+ end
+ else
+ cg.a_load_loc_ref(exprasmlist,OS_ADDR,hp.left.location,href);
+ { update href to the vtype field and write it }
+ dec(href.offset,sizeof(aint));
+ cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
+ { goto next array element }
+ inc(href.offset,sizeof(aint)*2);
+ end
+ else
+ { normal array constructor of the same type }
+ begin
+ if resulttype.def.needs_inittable then
+ freetemp:=false;
+ case hp.left.location.loc of
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if is_shortstring(hp.left.resulttype.def) then
+ cg.g_copyshortstring(exprasmlist,hp.left.location.reference,href,
+ Tstringdef(hp.left.resulttype.def).len)
+ else
+ cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize);
+ end;
+ else
+ begin
+{$ifndef cpu64bit}
+ if hp.left.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
+ else
+{$endif cpu64bit}
+ cg.a_load_loc_ref(exprasmlist,hp.left.location.size,hp.left.location,href);
+ end;
+ end;
+ inc(href.offset,elesize);
+ end;
+ if freetemp then
+ location_freetemp(exprasmlist,hp.left.location);
+ end;
+ { load next entry }
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+
+
+{*****************************************************************************
+ SecondRTTI
+*****************************************************************************}
+
+ procedure tcgrttinode.pass_2;
+ begin
+ location_reset(location,LOC_CREFERENCE,OS_NO);
+ location.reference.symbol:=rttidef.get_rtti_label(rttitype);
+ end;
+
+
+
+begin
+ cloadnode:=tcgloadnode;
+ cassignmentnode:=tcgassignmentnode;
+ carrayconstructornode:=tcgarrayconstructornode;
+ crttinode:=tcgrttinode;
+end.
diff --git a/compiler/ncgmat.pas b/compiler/ncgmat.pas
new file mode 100644
index 0000000000..af03b0876a
--- /dev/null
+++ b/compiler/ncgmat.pas
@@ -0,0 +1,472 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate generic mathematical 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 ncgmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,cpubase,cgbase;
+
+ type
+ tcgunaryminusnode = class(tunaryminusnode)
+ protected
+ { This routine is called to change the sign of the
+ floating point value in the floating point
+ register r.
+
+ This routine should be overriden, since
+ the generic version is not optimal at all. The
+ generic version assumes that floating
+ point values are stored in the register
+ in IEEE-754 format.
+ }
+ procedure emit_float_sign_change(r: tregister; _size : tcgsize);virtual;
+{$ifdef SUPPORT_MMX}
+ procedure second_mmx;virtual;abstract;
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bit}
+ procedure second_64bit;virtual;
+{$endif cpu64bit}
+ procedure second_integer;virtual;
+ procedure second_float;virtual;
+ public
+ procedure pass_2;override;
+ end;
+
+ tcgmoddivnode = class(tmoddivnode)
+ procedure pass_2;override;
+ protected
+ { This routine must do an actual 32-bit division, be it
+ signed or unsigned. The result must set into the the
+ @var(num) register.
+
+ @param(signed Indicates if the division must be signed)
+ @param(denum Register containing the denominator
+ @param(num Register containing the numerator, will also receive result)
+
+ The actual optimizations regarding shifts have already
+ been done and emitted, so this should really a do a divide.
+ }
+ procedure emit_div_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract;
+ { This routine must do an actual 32-bit modulo, be it
+ signed or unsigned. The result must set into the the
+ @var(num) register.
+
+ @param(signed Indicates if the modulo must be signed)
+ @param(denum Register containing the denominator
+ @param(num Register containing the numerator, will also receive result)
+
+ The actual optimizations regarding shifts have already
+ been done and emitted, so this should really a do a modulo.
+ }
+ procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract;
+{$ifndef cpu64bit}
+ { This routine must do an actual 64-bit division, be it
+ signed or unsigned. The result must set into the the
+ @var(num) register.
+
+ @param(signed Indicates if the division must be signed)
+ @param(denum Register containing the denominator
+ @param(num Register containing the numerator, will also receive result)
+
+ The actual optimizations regarding shifts have already
+ been done and emitted, so this should really a do a divide.
+ Currently, this routine should only be implemented on
+ 64-bit systems, otherwise a helper is called in 1st pass.
+ }
+ procedure emit64_div_reg_reg(signed: boolean;denum,num : tregister64);virtual;
+{$endif cpu64bit}
+ end;
+
+ tcgshlshrnode = class(tshlshrnode)
+{$ifndef cpu64bit}
+ procedure second_64bit;virtual;
+{$endif cpu64bit}
+ procedure second_integer;virtual;
+ procedure pass_2;override;
+ end;
+
+ tcgnotnode = class(tnotnode)
+ protected
+ procedure second_boolean;virtual;abstract;
+{$ifdef SUPPORT_MMX}
+ procedure second_mmx;virtual;abstract;
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bit}
+ procedure second_64bit;virtual;
+{$endif cpu64bit}
+ procedure second_integer;virtual;
+ public
+ procedure pass_2;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,aasmbase,aasmtai,aasmcpu,defutil,
+ parabase,
+ pass_2,
+ ncon,
+ tgobj,ncgutil,cgobj,cgutils,paramgr
+{$ifndef cpu64bit}
+ ,cg64f32
+{$endif cpu64bit}
+ ;
+
+{*****************************************************************************
+ TCGUNARYMINUSNODE
+*****************************************************************************}
+
+ procedure tcgunaryminusnode.emit_float_sign_change(r: tregister; _size : tcgsize);
+ var
+ href,
+ href2 : treference;
+ begin
+ { get a temporary memory reference to store the floating
+ point value
+ }
+ tg.gettemp(exprasmlist,tcgsize2size[_size],tt_normal,href);
+ { store the floating point value in the temporary memory area }
+ cg.a_loadfpu_reg_ref(exprasmlist,_size,r,href);
+ { only single and double ieee are supported, for little endian
+ the signed bit is in the second dword }
+ href2:=href;
+ case _size of
+ OS_F64 :
+ if target_info.endian = endian_little then
+ inc(href2.offset,4);
+ OS_F32 :
+ ;
+ else
+ internalerror(200406021);
+ end;
+ { flip sign-bit (bit 31/63) of single/double }
+ cg.a_op_const_ref(exprasmlist,OP_XOR,OS_32,aint($80000000),href2);
+ cg.a_loadfpu_ref_reg(exprasmlist,_size,href,r);
+ tg.ungetiftemp(exprasmlist,href);
+ end;
+
+
+{$ifndef cpu64bit}
+ procedure tcgunaryminusnode.second_64bit;
+ begin
+ secondpass(left);
+ { load left operator in a register }
+ location_copy(location,left.location);
+ location_force_reg(exprasmlist,location,OS_64,false);
+ cg64.a_op64_loc_reg(exprasmlist,OP_NEG,OS_64,
+ location,joinreg64(location.register64.reglo,location.register64.reghi));
+ end;
+{$endif cpu64bit}
+
+ procedure tcgunaryminusnode.second_float;
+ begin
+ secondpass(left);
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ case left.location.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location.register:=cg.getfpuregister(exprasmlist,location.size);
+ cg.a_loadfpu_ref_reg(exprasmlist,
+ def_cgsize(left.resulttype.def),
+ left.location.reference,location.register);
+ emit_float_sign_change(location.register,def_cgsize(left.resulttype.def));
+ end;
+ LOC_FPUREGISTER:
+ begin
+ location.register:=left.location.register;
+ emit_float_sign_change(location.register,def_cgsize(left.resulttype.def));
+ end;
+ LOC_CFPUREGISTER:
+ begin
+ location.register:=cg.getfpuregister(exprasmlist,location.size);
+ cg.a_loadfpu_reg_reg(exprasmlist,left.location.size,left.location.register,location.register);
+ emit_float_sign_change(location.register,def_cgsize(left.resulttype.def));
+ end;
+ else
+ internalerror(200306021);
+ end;
+ end;
+
+
+ procedure tcgunaryminusnode.second_integer;
+ begin
+ secondpass(left);
+ { load left operator in a register }
+ location_copy(location,left.location);
+ location_force_reg(exprasmlist,location,OS_SINT,false);
+ cg.a_op_reg_reg(exprasmlist,OP_NEG,OS_SINT,location.register,location.register);
+ end;
+
+
+ procedure tcgunaryminusnode.pass_2;
+ begin
+{$ifndef cpu64bit}
+ if is_64bit(left.resulttype.def) then
+ second_64bit
+ else
+{$endif cpu64bit}
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
+ second_mmx
+ else
+{$endif SUPPORT_MMX}
+ if (left.resulttype.def.deftype=floatdef) then
+ second_float
+ else
+ second_integer;
+ end;
+
+
+{*****************************************************************************
+ TCGMODDIVNODE
+*****************************************************************************}
+
+{$ifndef cpu64bit}
+ procedure tcgmoddivnode.emit64_div_reg_reg(signed: boolean; denum,num:tregister64);
+ begin
+ { handled in pass_1 already, unless pass_1 is
+ overriden
+ }
+ { should be handled in pass_1 (JM) }
+ internalerror(200109052);
+ end;
+{$endif cpu64bit}
+
+
+ procedure tcgmoddivnode.pass_2;
+ var
+ hreg1 : tregister;
+ hdenom : tregister;
+ power : longint;
+ hl : tasmlabel;
+ paraloc1 : tcgpara;
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ secondpass(right);
+ if codegenerror then
+ exit;
+ location_copy(location,left.location);
+
+{$ifndef cpu64bit}
+ if is_64bit(resulttype.def) then
+ begin
+ { this code valid for 64-bit cpu's only ,
+ otherwise helpers are called in pass_1
+ }
+ location_force_reg(exprasmlist,location,OS_64,false);
+ location_copy(location,left.location);
+ location_force_reg(exprasmlist,right.location,OS_64,false);
+ emit64_div_reg_reg(is_signed(left.resulttype.def),
+ joinreg64(right.location.register64.reglo,right.location.register64.reghi),
+ joinreg64(location.register64.reglo,location.register64.reghi));
+ end
+ else
+{$endif cpu64bit}
+ begin
+ { put numerator in register }
+ location_force_reg(exprasmlist,left.location,OS_INT,false);
+ hreg1:=left.location.register;
+
+ if (nodetype=divn) and
+ (right.nodetype=ordconstn) and
+ ispowerof2(tordconstnode(right).value,power) then
+ Begin
+ { for signed numbers, the numerator must be adjusted before the
+ shift instruction, but not wih unsigned numbers! Otherwise,
+ "Cardinal($ffffffff) div 16" overflows! (JM) }
+ If is_signed(left.resulttype.def) Then
+ Begin
+ objectlibrary.getjumplabel(hl);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_GT,0,hreg1,hl);
+ if power=1 then
+ cg.a_op_const_reg(exprasmlist,OP_ADD,OS_INT,1,hreg1)
+ else
+ cg.a_op_const_reg(exprasmlist,OP_ADD,OS_INT,tordconstnode(right).value-1,hreg1);
+ cg.a_label(exprasmlist,hl);
+ cg.a_op_const_reg(exprasmlist,OP_SAR,OS_INT,power,hreg1);
+ End
+ Else { not signed }
+ cg.a_op_const_reg(exprasmlist,OP_SHR,OS_INT,power,hreg1);
+ End
+ else
+ begin
+ { bring denominator to hdenom }
+ { hdenom is always free, it's }
+ { only used for temporary }
+ { purposes }
+ hdenom := cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_loc_reg(exprasmlist,right.location.size,right.location,hdenom);
+ { verify if the divisor is zero, if so return an error
+ immediately
+ }
+ objectlibrary.getjumplabel(hl);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_NE,0,hdenom,hl);
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_const(exprasmlist,OS_S32,200,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.a_call_name(exprasmlist,'FPC_HANDLERROR');
+ paraloc1.done;
+ cg.a_label(exprasmlist,hl);
+ if nodetype = modn then
+ emit_mod_reg_reg(is_signed(left.resulttype.def),hdenom,hreg1)
+ else
+ emit_div_reg_reg(is_signed(left.resulttype.def),hdenom,hreg1);
+ end;
+ location_reset(location,LOC_REGISTER,OS_INT);
+ location.register:=hreg1;
+ end;
+ cg.g_overflowcheck(exprasmlist,location,resulttype.def);
+ end;
+
+
+{*****************************************************************************
+ TCGSHLRSHRNODE
+*****************************************************************************}
+
+
+{$ifndef cpu64bit}
+ procedure tcgshlshrnode.second_64bit;
+ begin
+ { already hanled in 1st pass }
+ internalerror(2002081501);
+ end;
+{$endif cpu64bit}
+
+
+ procedure tcgshlshrnode.second_integer;
+ var
+ op : topcg;
+ hcountreg : tregister;
+ begin
+ { determine operator }
+ case nodetype of
+ shln: op:=OP_SHL;
+ shrn: op:=OP_SHR;
+ end;
+ { load left operators in a register }
+ location_copy(location,left.location);
+ location_force_reg(exprasmlist,location,OS_INT,false);
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ begin
+ { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)
+ if right.value<=31 then
+ }
+ cg.a_op_const_reg(exprasmlist,op,location.size,
+ tordconstnode(right).value and 31,location.register);
+ {
+ else
+ emit_reg_reg(A_XOR,S_L,hregister1,
+ hregister1);
+ }
+ end
+ else
+ begin
+ { load right operators in a register - this
+ is done since most target cpu which will use this
+ node do not support a shift count in a mem. location (cec)
+ }
+ if right.location.loc<>LOC_REGISTER then
+ begin
+ hcountreg:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_loc_reg(exprasmlist,right.location.size,right.location,hcountreg);
+ end
+ else
+ hcountreg:=right.location.register;
+ cg.a_op_reg_reg(exprasmlist,op,OS_INT,hcountreg,location.register);
+ end;
+ end;
+
+
+ procedure tcgshlshrnode.pass_2;
+ begin
+ secondpass(left);
+ secondpass(right);
+{$ifndef cpu64bit}
+ if is_64bit(left.resulttype.def) then
+ second_64bit
+ else
+{$endif cpu64bit}
+ second_integer;
+ end;
+
+
+{*****************************************************************************
+ TCGNOTNODE
+*****************************************************************************}
+
+{$ifndef cpu64bit}
+ procedure tcgnotnode.second_64bit;
+ begin
+ secondpass(left);
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
+ location_copy(location,left.location);
+ { perform the NOT operation }
+ cg64.a_op64_reg_reg(exprasmlist,OP_NOT,location.size,left.location.register64,location.register64);
+ end;
+{$endif cpu64bit}
+
+
+ procedure tcgnotnode.second_integer;
+ begin
+ secondpass(left);
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
+ location_copy(location,left.location);
+ { perform the NOT operation }
+ cg.a_op_reg_reg(exprasmlist,OP_NOT,location.size,location.register,location.register);
+ end;
+
+
+ procedure tcgnotnode.pass_2;
+ begin
+ if is_boolean(resulttype.def) then
+ second_boolean
+{$ifdef SUPPORT_MMX}
+ else if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
+ second_mmx
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bit}
+ else if is_64bit(left.resulttype.def) then
+ second_64bit
+{$endif cpu64bit}
+ else
+ second_integer;
+ end;
+
+begin
+ cmoddivnode:=tcgmoddivnode;
+ cunaryminusnode:=tcgunaryminusnode;
+ cshlshrnode:=tcgshlshrnode;
+ cnotnode:=tcgnotnode;
+end.
diff --git a/compiler/ncgmem.pas b/compiler/ncgmem.pas
new file mode 100644
index 0000000000..db342e3c7b
--- /dev/null
+++ b/compiler/ncgmem.pas
@@ -0,0 +1,768 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for memory related nodes which are
+ the same for all (most?) processors
+
+ 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 ncgmem;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,cgbase,cpuinfo,cpubase,
+ node,nmem;
+
+ type
+ tcgloadvmtaddrnode = class(tloadvmtaddrnode)
+ procedure pass_2;override;
+ end;
+
+ tcgloadparentfpnode = class(tloadparentfpnode)
+ procedure pass_2;override;
+ end;
+
+ tcgaddrnode = class(taddrnode)
+ procedure pass_2;override;
+ end;
+
+ tcgderefnode = class(tderefnode)
+ procedure pass_2;override;
+ end;
+
+ tcgsubscriptnode = class(tsubscriptnode)
+ procedure pass_2;override;
+ end;
+
+ tcgwithnode = class(twithnode)
+ procedure pass_2;override;
+ end;
+
+ tcgvecnode = class(tvecnode)
+ private
+ procedure rangecheck_array;
+ protected
+ function get_mul_size : aint;
+ {# This routine is used to calculate the address of the reference.
+ On entry reg contains the index in the array,
+ and l contains the size of each element in the array.
+ This routine should update location.reference correctly,
+ so it points to the correct address.
+ }
+ procedure update_reference_reg_mul(reg:tregister;l:aint);virtual;
+ procedure second_wideansistring;virtual;
+ procedure second_dynamicarray;virtual;
+ public
+ procedure pass_2;override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ cutils,verbose,globals,
+ symconst,symdef,symsym,defutil,paramgr,
+ aasmbase,aasmtai,
+ procinfo,pass_2,parabase,
+ pass_1,nld,ncon,nadd,nutils,
+ cgutils,cgobj,
+ tgobj,ncgutil
+ ;
+
+
+{*****************************************************************************
+ TCGLOADVMTADDRNODE
+*****************************************************************************}
+
+ procedure tcgloadvmtaddrnode.pass_2;
+ var
+ href : treference;
+
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ if (left.nodetype=typen) then
+ begin
+ reference_reset_symbol(href,
+ objectlibrary.newasmsymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname,AB_EXTERNAL,AT_DATA),0);
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,href,location.register);
+ end
+ else
+ begin
+ { left contains self, load vmt from self }
+ secondpass(left);
+ gen_load_vmt_register(exprasmlist,tobjectdef(left.resulttype.def),left.location,location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TCGLOADPARENTFPNODE
+*****************************************************************************}
+
+ procedure tcgloadparentfpnode.pass_2;
+ var
+ currpi : tprocinfo;
+ hsym : tparavarsym;
+ href : treference;
+ begin
+ if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=current_procinfo.framepointer;
+ end
+ else
+ begin
+ currpi:=current_procinfo;
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(exprasmlist);
+ { load framepointer of current proc }
+ hsym:=tparavarsym(currpi.procdef.parast.search('parentfp'));
+ if not assigned(hsym) then
+ internalerror(200309281);
+ cg.a_load_loc_reg(exprasmlist,OS_ADDR,hsym.localloc,location.register);
+ { walk parents }
+ while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
+ begin
+ currpi:=currpi.parent;
+ if not assigned(currpi) then
+ internalerror(200311201);
+ hsym:=tparavarsym(currpi.procdef.parast.search('parentfp'));
+ if not assigned(hsym) then
+ internalerror(200309282);
+
+ if hsym.localloc.loc<>LOC_REFERENCE then
+ internalerror(200309283);
+
+ reference_reset_base(href,location.register,hsym.localloc.reference.offset);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TCGADDRNODE
+*****************************************************************************}
+
+ procedure tcgaddrnode.pass_2;
+ begin
+ secondpass(left);
+
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
+ end;
+
+
+{*****************************************************************************
+ TCGDEREFNODE
+*****************************************************************************}
+
+ procedure tcgderefnode.pass_2;
+ var
+ paraloc1 : tcgpara;
+ begin
+ secondpass(left);
+ location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
+ case left.location.loc of
+ LOC_REGISTER:
+ begin
+ {$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ location.reference.base := cg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,
+ location.reference.base);
+ end
+ else
+ {$endif}
+ location.reference.base := left.location.register;
+ end;
+ LOC_CREGISTER,
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ location.reference.base:=cg.getaddressregister(exprasmlist);
+ cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,location.reference.base);
+ end;
+ LOC_CONSTANT:
+ begin
+ location.reference.offset:=left.location.value;
+ end;
+ else
+ internalerror(200507031);
+ end;
+ if (cs_use_heaptrc in aktglobalswitches) and
+ (cs_checkpointer in aktlocalswitches) and
+ not(cs_compilesystem in aktmoduleswitches) and
+ not(tpointerdef(left.resulttype.def).is_far) and
+ not(nf_no_checkpointer in flags) then
+ begin
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ paraloc1.done;
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
+ cg.deallocallcpuregisters(exprasmlist);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TCGSUBSCRIPTNODE
+*****************************************************************************}
+
+ procedure tcgsubscriptnode.pass_2;
+ var
+ paraloc1 : tcgpara;
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ paraloc1.init;
+ { classes and interfaces must be dereferenced implicit }
+ if is_class_or_interface(left.resulttype.def) then
+ begin
+ location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
+ case left.location.loc of
+ LOC_CREGISTER,
+ LOC_REGISTER:
+ begin
+ {$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ location.reference.base:=rg.getaddressregister(exprasmlist);
+ cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
+ left.location.register,location.reference.base);
+ end
+ else
+ {$endif}
+ location.reference.base := left.location.register;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ location.reference.base:=cg.getaddressregister(exprasmlist);
+ cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,location.reference.base);
+ end;
+ end;
+ { implicit deferencing }
+ if (cs_use_heaptrc in aktglobalswitches) and
+ (cs_checkpointer in aktlocalswitches) and
+ not(cs_compilesystem in aktmoduleswitches) then
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
+ cg.deallocallcpuregisters(exprasmlist);
+ end;
+ end
+ else if is_interfacecom(left.resulttype.def) then
+ begin
+ tg.GetTempTyped(exprasmlist,left.resulttype.def,tt_normal,location.reference);
+ cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,location.reference);
+ { implicit deferencing also for interfaces }
+ if (cs_use_heaptrc in aktglobalswitches) and
+ (cs_checkpointer in aktlocalswitches) and
+ not(cs_compilesystem in aktmoduleswitches) then
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
+ cg.deallocallcpuregisters(exprasmlist);
+ end;
+ end
+ else
+ location_copy(location,left.location);
+
+ inc(location.reference.offset,vs.fieldoffset);
+ { also update the size of the location }
+ location.size:=def_cgsize(resulttype.def);
+ paraloc1.done;
+ end;
+
+
+{*****************************************************************************
+ TCGWITHNODE
+*****************************************************************************}
+
+ procedure tcgwithnode.pass_2;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ if assigned(left) then
+ secondpass(left);
+ end;
+
+
+{*****************************************************************************
+ TCGVECNODE
+*****************************************************************************}
+
+ function tcgvecnode.get_mul_size : aint;
+ begin
+ if nf_memindex in flags then
+ get_mul_size:=1
+ else
+ begin
+ if (left.resulttype.def.deftype=arraydef) then
+ get_mul_size:=tarraydef(left.resulttype.def).elesize
+ else
+ get_mul_size:=resulttype.def.size;
+ end
+ end;
+
+
+ procedure tcgvecnode.update_reference_reg_mul(reg:tregister;l:aint);
+ var
+ hreg: tregister;
+ begin
+ if location.reference.base=NR_NO then
+ begin
+ if l<>1 then
+ cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
+ location.reference.base:=reg;
+ end
+ else if location.reference.index=NR_NO then
+ begin
+ if l<>1 then
+ cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
+ location.reference.index:=reg;
+ end
+ else
+ begin
+ hreg := cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,location.reference,hreg);
+ reference_reset_base(location.reference,hreg,0);
+ { insert new index register }
+ if l<>1 then
+ cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
+ location.reference.index:=reg;
+ end;
+ end;
+
+
+ procedure tcgvecnode.second_wideansistring;
+ begin
+ end;
+
+ procedure tcgvecnode.second_dynamicarray;
+ begin
+ end;
+
+
+ procedure tcgvecnode.rangecheck_array;
+ var
+ hightree : tnode;
+ poslabel,
+ neglabel : tasmlabel;
+ hreg : tregister;
+ paraloc1,paraloc2 : tcgpara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ if is_open_array(left.resulttype.def) or
+ is_array_of_const(left.resulttype.def) then
+ begin
+ { cdecl functions don't have high() so we can not check the range }
+ if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ begin
+ { Get high value }
+ hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ { it must be available }
+ if not assigned(hightree) then
+ internalerror(200212201);
+ firstpass(hightree);
+ secondpass(hightree);
+ { generate compares }
+ if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ hreg:=cg.makeregsize(exprasmlist,right.location.register,OS_INT)
+ else
+ begin
+ hreg:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,hreg);
+ end;
+ objectlibrary.getjumplabel(neglabel);
+ objectlibrary.getjumplabel(poslabel);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
+ cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
+ cg.a_label(exprasmlist,poslabel);
+ cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
+ cg.a_label(exprasmlist,neglabel);
+ { release hightree }
+ hightree.free;
+ end;
+ end
+ else
+ if is_dynamic_array(left.resulttype.def) then
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.allocparaloc(exprasmlist,paraloc2);
+ cg.a_param_loc(exprasmlist,right.location,paraloc2);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_loc(exprasmlist,left.location,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc2);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_DYNARRAY_RANGECHECK');
+ cg.deallocallcpuregisters(exprasmlist);
+ end
+ else
+ cg.g_rangecheck(exprasmlist,right.location,right.resulttype.def,left.resulttype.def);
+ paraloc1.done;
+ paraloc2.done;
+ end;
+
+
+ procedure tcgvecnode.pass_2;
+
+ var
+ offsetdec,
+ extraoffset : aint;
+ t : tnode;
+ href : treference;
+ otl,ofl : tasmlabel;
+ newsize : tcgsize;
+ mulsize : aint;
+ isjump : boolean;
+ paraloc1,
+ paraloc2 : tcgpara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ mulsize := get_mul_size;
+
+ newsize:=def_cgsize(resulttype.def);
+ secondpass(left);
+ if left.location.loc=LOC_CREFERENCE then
+ location_reset(location,LOC_CREFERENCE,newsize)
+ else
+ location_reset(location,LOC_REFERENCE,newsize);
+
+ { an ansistring needs to be dereferenced }
+ if is_ansistring(left.resulttype.def) or
+ is_widestring(left.resulttype.def) then
+ begin
+ if nf_callunique in flags then
+ internalerror(200304236);
+
+ {DM!!!!!}
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ location.reference.base:=left.location.register;
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ location.reference.base:=cg.getaddressregister(exprasmlist);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.reference.base);
+ end;
+ else
+ internalerror(2002032218);
+ end;
+
+ { check for a zero length string,
+ we can use the ansistring routine here }
+ if (cs_check_range in aktlocalswitches) then
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
+ cg.deallocallcpuregisters(exprasmlist);
+ end;
+
+ { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
+ if is_ansistring(left.resulttype.def) then
+ offsetdec:=1
+ else
+ offsetdec:=2;
+ dec(location.reference.offset,offsetdec);
+ end
+ else if is_dynamic_array(left.resulttype.def) then
+ begin
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ location.reference.base:=left.location.register;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location.reference.base:=cg.getaddressregister(exprasmlist);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,
+ left.location.reference,location.reference.base);
+ end;
+ else
+ internalerror(2002032219);
+ end;
+ end
+ else
+ location_copy(location,left.location);
+
+ { location must be memory }
+ if not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200411013);
+
+ { offset can only differ from 0 if arraydef }
+ if (left.resulttype.def.deftype=arraydef) and
+ not(is_dynamic_array(left.resulttype.def)) then
+ dec(location.reference.offset,mulsize*tarraydef(left.resulttype.def).lowrange);
+
+ if right.nodetype=ordconstn then
+ begin
+ { offset can only differ from 0 if arraydef }
+ case left.resulttype.def.deftype of
+ arraydef :
+ begin
+ if not(is_open_array(left.resulttype.def)) and
+ not(is_array_of_const(left.resulttype.def)) and
+ not(is_dynamic_array(left.resulttype.def)) then
+ begin
+ if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
+ (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
+ begin
+ { this should be caught in the resulttypepass! (JM) }
+ if (cs_check_range in aktlocalswitches) then
+ CGMessage(parser_e_range_check_error)
+ else
+ CGMessage(parser_w_range_check_error);
+ end;
+ end
+ else
+ begin
+ { range checking for open and dynamic arrays needs
+ runtime code }
+ secondpass(right);
+ if (cs_check_range in aktlocalswitches) then
+ rangecheck_array;
+ end;
+ end;
+ stringdef :
+ begin
+ if (cs_check_range in aktlocalswitches) then
+ begin
+ case tstringdef(left.resulttype.def).string_typ of
+ { it's the same for ansi- and wide strings }
+ st_widestring,
+ {$ifdef ansistring_bits}
+ st_ansistring16,st_ansistring32,st_ansistring64:
+ {$else}
+ st_ansistring:
+ {$endif}
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.allocparaloc(exprasmlist,paraloc2);
+ cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paraloc2);
+ href:=location.reference;
+ dec(href.offset,sizeof(aint)-offsetdec);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_ref(exprasmlist,OS_INT,href,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc2);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
+ cg.deallocallcpuregisters(exprasmlist);
+ end;
+
+ st_shortstring:
+ begin
+ {!!!!!!!!!!!!!!!!!}
+ end;
+
+ st_longstring:
+ begin
+ {!!!!!!!!!!!!!!!!!}
+ end;
+ end;
+ end;
+ end;
+ end;
+ inc(location.reference.offset,
+ mulsize*tordconstnode(right).value);
+ end
+ else
+ { not nodetype=ordconstn }
+ begin
+ if (cs_regvars in aktglobalswitches) and
+ { if we do range checking, we don't }
+ { need that fancy code (it would be }
+ { buggy) }
+ not(cs_check_range in aktlocalswitches) and
+ (left.resulttype.def.deftype=arraydef) then
+ begin
+ extraoffset:=0;
+ if (right.nodetype=addn) then
+ begin
+ if taddnode(right).right.nodetype=ordconstn then
+ begin
+ extraoffset:=tordconstnode(taddnode(right).right).value;
+ t:=taddnode(right).left;
+ { First pass processed this with the assumption }
+ { that there was an add node which may require an }
+ { extra register. Fake it or die with IE10 (JM) }
+ t.registersint := taddnode(right).registersint;
+ taddnode(right).left:=nil;
+ right.free;
+ right:=t;
+ end
+ else if taddnode(right).left.nodetype=ordconstn then
+ begin
+ extraoffset:=tordconstnode(taddnode(right).left).value;
+ t:=taddnode(right).right;
+ t.registersint := right.registersint;
+ taddnode(right).right:=nil;
+ right.free;
+ right:=t;
+ end;
+ end
+ else if (right.nodetype=subn) then
+ begin
+ if taddnode(right).right.nodetype=ordconstn then
+ begin
+ extraoffset:=-tordconstnode(taddnode(right).right).value;
+ t:=taddnode(right).left;
+ t.registersint := right.registersint;
+ taddnode(right).left:=nil;
+ right.free;
+ right:=t;
+ end
+{ You also have to negate right.right in this case! I can't add an
+ unaryminusn without causing a crash, so I've disabled it (JM)
+ else if right.left.nodetype=ordconstn then
+ begin
+ extraoffset:=right.left.value;
+ t:=right.right;
+ t^.registersint := right.registersint;
+ putnode(right);
+ putnode(right.left);
+ right:=t;
+ end;}
+ end;
+ inc(location.reference.offset,
+ mulsize*extraoffset);
+ end;
+ { calculate from left to right }
+ if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ internalerror(200304237);
+ isjump:=(right.location.loc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(right);
+
+ if cs_check_range in aktlocalswitches then
+ begin
+ if left.resulttype.def.deftype=arraydef then
+ rangecheck_array;
+ end;
+
+ { if mulsize = 1, we won't have to modify the index }
+ location_force_reg(exprasmlist,right.location,OS_ADDR,(mulsize = 1));
+
+ if isjump then
+ begin
+ truelabel:=otl;
+ falselabel:=ofl;
+ end;
+
+ { produce possible range check code: }
+ if cs_check_range in aktlocalswitches then
+ begin
+ if left.resulttype.def.deftype=arraydef then
+ begin
+ { done defore (PM) }
+ end
+ else if (left.resulttype.def.deftype=stringdef) then
+ begin
+ case tstringdef(left.resulttype.def).string_typ of
+ { it's the same for ansi- and wide strings }
+ st_widestring,
+ {$ifdef ansistring_bits}
+ st_ansistring16,st_ansistring32,st_ansistring64:
+ {$else}
+ st_ansistring:
+ {$endif}
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.allocparaloc(exprasmlist,paraloc2);
+ cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paraloc2);
+ href:=location.reference;
+ dec(href.offset,sizeof(aint)-offsetdec);
+ //dec(href.offset,7);
+ paramanager.allocparaloc(exprasmlist,paraloc1);
+ cg.a_param_ref(exprasmlist,OS_INT,href,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc1);
+ paramanager.freeparaloc(exprasmlist,paraloc2);
+ cg.allocallcpuregisters(exprasmlist);
+ cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
+ cg.deallocallcpuregisters(exprasmlist);
+ end;
+ st_shortstring:
+ begin
+ {!!!!!!!!!!!!!!!!!}
+ end;
+ st_longstring:
+ begin
+ {!!!!!!!!!!!!!!!!!}
+ end;
+ end;
+ end;
+ end;
+
+ { insert the register and the multiplication factor in the
+ reference }
+ update_reference_reg_mul(right.location.register,mulsize);
+ end;
+
+ location.size:=newsize;
+ paraloc1.done;
+ paraloc2.done;
+ end;
+
+
+begin
+ cloadvmtaddrnode:=tcgloadvmtaddrnode;
+ cloadparentfpnode:=tcgloadparentfpnode;
+ caddrnode:=tcgaddrnode;
+ cderefnode:=tcgderefnode;
+ csubscriptnode:=tcgsubscriptnode;
+ cwithnode:=tcgwithnode;
+ cvecnode:=tcgvecnode;
+end.
diff --git a/compiler/ncgopt.pas b/compiler/ncgopt.pas
new file mode 100644
index 0000000000..133fb025b3
--- /dev/null
+++ b/compiler/ncgopt.pas
@@ -0,0 +1,194 @@
+{
+ Copyright (c) 1998-2003 by Jonas Maebe
+
+ This unit implements the generic implementation of optimized 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 ncgopt;
+
+{$i fpcdefs.inc}
+
+interface
+uses node, nopt;
+
+type
+ tcgaddsstringcharoptnode = class(taddsstringcharoptnode)
+ function det_resulttype: tnode; override;
+ function pass_1: tnode; override;
+ procedure pass_2; override;
+ end;
+
+
+implementation
+
+uses
+ globtype,globals,
+ pass_1,defutil,htypechk,
+ symdef,paramgr,
+ aasmbase,aasmtai,
+ ncnv, ncon, pass_2,
+ cgbase, cpubase,
+ tgobj, cgobj, cgutils,ncgutil;
+
+
+{*****************************************************************************
+ TCGADDOPTNODE
+*****************************************************************************}
+
+function tcgaddsstringcharoptnode.det_resulttype: tnode;
+begin
+ det_resulttype := nil;
+ resulttypepass(left);
+ resulttypepass(right);
+ if codegenerror then
+ exit;
+ { update the curmaxlen field (before converting to a string!) }
+ updatecurmaxlen;
+ if not is_shortstring(left.resulttype.def) then
+ inserttypeconv(left,cshortstringtype);
+ resulttype:=left.resulttype;
+end;
+
+
+function tcgaddsstringcharoptnode.pass_1: tnode;
+begin
+ pass_1 := nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+ expectloc:=LOC_REFERENCE;
+ if not is_constcharnode(right) then
+ { it's not sure we need the register, but we can't know it here yet }
+ calcregisters(self,2,0,0)
+ else
+ calcregisters(self,1,0,0);
+end;
+
+
+procedure tcgaddsstringcharoptnode.pass_2;
+var
+ l: tasmlabel;
+ href,href2 : treference;
+ hreg, lengthreg: tregister;
+ checklength: boolean;
+ len : integer;
+begin
+ { first, we have to more or less replicate some code from }
+ { ti386addnode.pass_2 }
+ secondpass(left);
+ if not(tg.istemp(left.location.reference) and
+ (tg.sizeoftemp(exprasmlist,left.location.reference) = 256)) and
+ not(nf_use_strconcat in flags) then
+ begin
+ tg.Gettemp(exprasmlist,256,tt_normal,href);
+ cg.g_copyshortstring(exprasmlist,left.location.reference,href,255);
+ location_freetemp(exprasmlist,left.location);
+ { return temp reference }
+ location_reset(left.location,LOC_REFERENCE,def_cgsize(resulttype.def));
+ left.location.reference:=href;
+ end;
+ secondpass(right);
+ { special case for string := string + char (JM) }
+ hreg:=NR_NO;
+
+ { we have to load the char before checking the length, because we }
+ { may need registers from the reference }
+
+ { is it a constant char? }
+ if not is_constcharnode(right) then
+ { no, make sure it is in a register }
+ if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ begin
+ { get register for the char }
+ hreg := cg.getintregister(exprasmlist,OS_8);
+ cg.a_load_ref_reg(exprasmlist,OS_8,OS_8,right.location.reference,hreg);
+ { I don't think a temp char exists, but it won't hurt (JM) }
+ tg.ungetiftemp(exprasmlist,right.location.reference);
+ end
+ else hreg := right.location.register;
+
+ { load the current string length }
+ lengthreg := cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_ref_reg(exprasmlist,OS_8,OS_INT,left.location.reference,lengthreg);
+
+ { do we have to check the length ? }
+ if tg.istemp(left.location.reference) then
+ checklength := curmaxlen = 255
+ else
+ checklength := curmaxlen >= tstringdef(left.resulttype.def).len;
+ if checklength then
+ begin
+ { is it already maximal? }
+ objectlibrary.getjumplabel(l);
+ if tg.istemp(left.location.reference) then
+ len:=255
+ else
+ len:=tstringdef(left.resulttype.def).len;
+ cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,len,lengthreg,l)
+ end;
+
+ { no, so increase the length and add the new character }
+ href2 := left.location.reference;
+
+ { we need a new reference to store the character }
+ { at the end of the string. Check if the base or }
+ { index register is still free }
+ if (href2.base <> NR_NO) and
+ (href2.index <> NR_NO) then
+ begin
+ { they're not free, so add the base reg to }
+ { the string length (since the index can }
+ { have a scalefactor) and use lengthreg as base }
+ cg.a_op_reg_reg(exprasmlist,OP_ADD,OS_INT,href2.base,lengthreg);
+ href2.base := lengthreg;
+ end
+ else
+ { at least one is still free, so put EDI there }
+ if href2.base = NR_NO then
+ href2.base := lengthreg
+ else
+ begin
+ href2.index := lengthreg;
+{$ifdef x86}
+ href2.scalefactor := 1;
+{$endif x86}
+ end;
+ { we need to be one position after the last char }
+ inc(href2.offset);
+ { store the character at the end of the string }
+ if (right.nodetype <> ordconstn) then
+ begin
+ { no new_reference(href2) because it's only }
+ { used once (JM) }
+ cg.a_load_reg_ref(exprasmlist,OS_8,OS_8,hreg,href2);
+ end
+ else
+ cg.a_load_const_ref(exprasmlist,OS_8,tordconstnode(right).value,href2);
+ lengthreg:=cg.makeregsize(exprasmlist,lengthreg,OS_8);
+ { increase the string length }
+ cg.a_op_const_reg(exprasmlist,OP_ADD,OS_8,1,lengthreg);
+ cg.a_load_reg_ref(exprasmlist,OS_8,OS_8,lengthreg,left.location.reference);
+ if checklength then
+ cg.a_label(exprasmlist,l);
+ location_copy(location,left.location);
+end;
+
+begin
+ caddsstringcharoptnode := tcgaddsstringcharoptnode;
+end.
diff --git a/compiler/ncgset.pas b/compiler/ncgset.pas
new file mode 100644
index 0000000000..b9e9753c61
--- /dev/null
+++ b/compiler/ncgset.pas
@@ -0,0 +1,869 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
+
+ Generate generic assembler for in set/case labels
+
+ 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 ncgset;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,globals,
+ node,nset,cpubase,cgbase,cgobj,aasmbase,aasmtai;
+
+ type
+ tcgsetelementnode = class(tsetelementnode)
+ procedure pass_2;override;
+ end;
+
+ tcginnode = class(tinnode)
+ procedure pass_2;override;
+ protected
+ {# Routine to test bitnumber in bitnumber register on value
+ in value register. The __result register should be set
+ to one if the bit is set, otherwise __result register
+ should be set to zero.
+
+ Should be overriden on processors which have specific
+ instructions to do bit tests.
+ }
+
+ procedure emit_bit_test_reg_reg(list : taasmoutput;
+ bitsize: tcgsize; bitnumber,value : tregister;
+ ressize: tcgsize; res :tregister);virtual;
+ end;
+
+ tcgcasenode = class(tcasenode)
+ {
+ Emits the case node statement. Contrary to the intel
+ 80x86 version, this version does not emit jump tables,
+ because of portability problems.
+ }
+ procedure pass_2;override;
+
+ protected
+ with_sign : boolean;
+ opsize : tcgsize;
+ jmp_gt,jmp_lt,jmp_le : topcmp;
+ { register with case expression }
+ hregister,hregister2 : tregister;
+ endlabel,elselabel : tasmlabel;
+
+ { true, if we can omit the range check of the jump table }
+ jumptable_no_range : boolean;
+ { has the implementation jumptable support }
+ min_label : tconstexprint;
+
+ function blocklabel(id:longint):tasmlabel;
+ procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);virtual;
+ function has_jumptable : boolean;virtual;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint); virtual;
+ procedure genlinearlist(hp : pcaselabel); virtual;
+ procedure genlinearcmplist(hp : pcaselabel); virtual;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,
+ symconst,symdef,defutil,
+ paramgr,
+ pass_2,tgobj,
+ nbas,ncon,nflw,
+ ncgutil,regvars,
+ cgutils;
+
+
+{*****************************************************************************
+ TCGSETELEMENTNODE
+*****************************************************************************}
+
+ procedure tcgsetelementnode.pass_2;
+ begin
+ { load first value in 32bit register }
+ secondpass(left);
+ if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ location_force_reg(exprasmlist,left.location,OS_32,false);
+
+ { also a second value ? }
+ if assigned(right) then
+ begin
+ secondpass(right);
+ if codegenerror then
+ exit;
+ if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ location_force_reg(exprasmlist,right.location,OS_32,false);
+ end;
+
+ { we doesn't modify the left side, we check only the type }
+ location_copy(location,left.location);
+ end;
+
+
+{*****************************************************************************
+*****************************************************************************}
+
+ {**********************************************************************}
+ { Description: Emit operation to do a bit test, where the bitnumber }
+ { to test is in the bitnumber register. The value to test against is }
+ { located in the value register. }
+ { WARNING: Bitnumber register value is DESTROYED! }
+ { __Result register is set to 1, if the bit is set otherwise, __Result}
+ { is set to zero. __RESULT register is also used as scratch. }
+ {**********************************************************************}
+ procedure tcginnode.emit_bit_test_reg_reg(list : taasmoutput;
+ bitsize: tcgsize; bitnumber,value : tregister;
+ ressize: tcgsize; res :tregister);
+ begin
+ { first make sure that the bit number is modulo 32 }
+
+ { not necessary, since if it's > 31, we have a range error -> will }
+ { be caught when range checking is on! (JM) }
+ { cg.a_op_const_reg(list,OP_AND,31,bitnumber); }
+
+ if bitsize<>ressize then
+ begin
+ { FIX ME! We're not allowed to modify the value register here! }
+
+ { shift value register "bitnumber" bits to the right }
+ cg.a_op_reg_reg(list,OP_SHR,bitsize,bitnumber,value);
+ { extract the bit we want }
+ cg.a_op_const_reg(list,OP_AND,bitsize,1,value);
+ cg.a_load_reg_reg(list,bitsize,ressize,value,res);
+ end
+ else
+ begin
+ { rotate value register "bitnumber" bits to the right }
+ cg.a_op_reg_reg_reg(list,OP_SHR,bitsize,bitnumber,value,res);
+ { extract the bit we want }
+ cg.a_op_const_reg(list,OP_AND,bitsize,1,res);
+ end;
+ end;
+
+
+ procedure tcginnode.pass_2;
+ type
+ Tsetpart=record
+ range : boolean; {Part is a range.}
+ start,stop : byte; {Start/stop when range; Stop=element when an element.}
+ end;
+ var
+ l,l3 : tasmlabel;
+ adjustment : aint;
+ href : treference;
+ hr,hr2,
+ pleftreg : tregister;
+ setparts : array[1..8] of Tsetpart;
+ opsize : tcgsize;
+ genjumps,
+ use_small : boolean;
+ i,numparts : byte;
+
+ function analizeset(const Aset:Tconstset;is_small:boolean):boolean;
+ var
+ compares,maxcompares:word;
+ i:byte;
+ begin
+ analizeset:=false;
+ numparts:=0;
+ compares:=0;
+ { Lots of comparisions take a lot of time, so do not allow
+ too much comparisions. 8 comparisions are, however, still
+ smalller than emitting the set }
+ if cs_littlesize in aktglobalswitches then
+ maxcompares:=8
+ else
+ maxcompares:=5;
+ { when smallset is possible allow only 3 compares the smallset
+ code is for littlesize also smaller when more compares are used }
+ if is_small then
+ maxcompares:=3;
+ for i:=0 to 255 do
+ if i in Aset then
+ begin
+ if (numparts=0) or (i<>setparts[numparts].stop+1) then
+ begin
+ {Set element is a separate element.}
+ inc(compares);
+ if compares>maxcompares then
+ exit;
+ inc(numparts);
+ setparts[numparts].range:=false;
+ setparts[numparts].stop:=i;
+ end
+ else
+ {Set element is part of a range.}
+ if not setparts[numparts].range then
+ begin
+ {Transform an element into a range.}
+ setparts[numparts].range:=true;
+ setparts[numparts].start:=setparts[numparts].stop;
+ setparts[numparts].stop:=i;
+ { there's only one compare per range anymore. Only a }
+ { sub is added, but that's much faster than a }
+ { cmp/jcc combo so neglect its effect }
+{ inc(compares);
+ if compares>maxcompares then
+ exit; }
+ end
+ else
+ begin
+ {Extend a range.}
+ setparts[numparts].stop:=i;
+ end;
+ end;
+ analizeset:=true;
+ end;
+
+ begin
+ { We check first if we can generate jumps, this can be done
+ because the resulttype.def is already set in firstpass }
+
+ { check if we can use smallset operation using btl which is limited
+ to 32 bits, the left side may also not contain higher values !! }
+ use_small:=(tsetdef(right.resulttype.def).settype=smallset) and
+ ((left.resulttype.def.deftype=orddef) and (torddef(left.resulttype.def).high<=32) or
+ (left.resulttype.def.deftype=enumdef) and (tenumdef(left.resulttype.def).max<=32));
+
+ { Can we generate jumps? Possible for all types of sets }
+ genjumps:=(right.nodetype=setconstn) and
+ analizeset(Tsetconstnode(right).value_set^,use_small);
+
+ opsize:=OS_32;
+
+ { calculate both operators }
+ { the complex one first }
+ firstcomplex(self);
+ secondpass(left);
+ { Only process the right if we are not generating jumps }
+ if not genjumps then
+ secondpass(right);
+ if codegenerror then
+ exit;
+
+ { ofcourse not commutative }
+ if nf_swaped in flags then
+ swapleftright;
+
+ { location is always LOC_JUMP }
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
+
+ if genjumps then
+ begin
+ { allocate a register for the result }
+ location.register := cg.getintregister(exprasmlist,location.size);
+ { Get a label to jump to the end }
+ objectlibrary.getjumplabel(l);
+
+ { clear the register value, indicating result is FALSE }
+ cg.a_load_const_reg(exprasmlist,location.size,0,location.register);
+ { If register is used, use only lower 8 bits }
+ location_force_reg(exprasmlist,left.location,opsize,false);
+ pleftreg := left.location.register;
+
+ { how much have we already substracted from the x in the }
+ { "x in [y..z]" expression }
+ adjustment := 0;
+ hr:=NR_NO;
+
+ for i:=1 to numparts do
+ if setparts[i].range then
+ { use fact that a <= x <= b <=> aword(x-a) <= aword(b-a) }
+ begin
+ { is the range different from all legal values? }
+ if (setparts[i].stop-setparts[i].start <> 255) then
+ begin
+ { yes, is the lower bound <> 0? }
+ if (setparts[i].start <> 0) then
+ { we're going to substract from the left register, }
+ { so in case of a LOC_CREGISTER first move the value }
+ { to edi (not done before because now we can do the }
+ { move and substract in one instruction with LEA) }
+ if (left.location.loc = LOC_CREGISTER) and
+ (hr<>pleftreg) then
+ begin
+ cg.a_op_const_reg(exprasmlist,OP_SUB,opsize,setparts[i].start,pleftreg);
+ hr:=cg.getintregister(exprasmlist,opsize);
+ cg.a_load_reg_reg(exprasmlist,opsize,opsize,pleftreg,hr);
+ pleftreg:=hr;
+ end
+ else
+ begin
+ { otherwise, the value is already in a register }
+ { that can be modified }
+ cg.a_op_const_reg(exprasmlist,OP_SUB,opsize,
+ setparts[i].start-adjustment,pleftreg)
+ end;
+ { new total value substracted from x: }
+ { adjustment + (setparts[i].start - adjustment) }
+ adjustment := setparts[i].start;
+
+ { check if result < b-a+1 (not "result <= b-a", since }
+ { we need a carry in case the element is in the range }
+ { (this will never overflow since we check at the }
+ { beginning whether stop-start <> 255) }
+ cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_B,
+ setparts[i].stop-setparts[i].start+1,pleftreg,l);
+ end
+ else
+ { if setparts[i].start = 0 and setparts[i].stop = 255, }
+ { it's always true since "in" is only allowed for bytes }
+ begin
+ cg.a_jmp_always(exprasmlist,l);
+ end;
+ end
+ else
+ begin
+ { Emit code to check if left is an element }
+ cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ,
+ setparts[i].stop-adjustment,pleftreg,l);
+ end;
+ { To compensate for not doing a second pass }
+ right.location.reference.symbol:=nil;
+ objectlibrary.getjumplabel(l3);
+ cg.a_jmp_always(exprasmlist,l3);
+ { Now place the end label if IN success }
+ cg.a_label(exprasmlist,l);
+ { result register is 1 }
+ cg.a_load_const_reg(exprasmlist,location.size,1,location.register);
+ { in case value is not found }
+ cg.a_label(exprasmlist,l3);
+ end
+ else
+ {*****************************************************************}
+ { NO JUMP TABLE GENERATION }
+ {*****************************************************************}
+ begin
+ { We will now generated code to check the set itself, no jmps,
+ handle smallsets separate, because it allows faster checks }
+ if use_small then
+ begin
+ {**************************** SMALL SET **********************}
+ if left.nodetype=ordconstn then
+ begin
+ location_force_reg(exprasmlist,right.location,opsize,true);
+ location.register:=cg.getintregister(exprasmlist,location.size);
+ { first SHR the register }
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHR,opsize,tordconstnode(left).value and 31,right.location.register,location.register);
+ { then extract the lowest bit }
+ cg.a_op_const_reg(exprasmlist,OP_AND,opsize,1,location.register);
+ end
+ else
+ begin
+ location_force_reg(exprasmlist,left.location,opsize,false);
+ location_force_reg(exprasmlist,right.location,opsize,false);
+ { allocate a register for the result }
+ location.register:=cg.getintregister(exprasmlist,location.size);
+ { emit bit test operation }
+ emit_bit_test_reg_reg(exprasmlist,left.location.size,left.location.register,
+ right.location.register,location.size,location.register);
+ end;
+ end
+ else
+ {************************** NOT SMALL SET ********************}
+ begin
+ if right.location.loc=LOC_CONSTANT then
+ begin
+ { can it actually occur currently? CEC }
+ { yes: "if bytevar in [1,3,5,7,9,11,13,15]" (JM) }
+
+ { note: this code assumes that left in [0..255], which is a valid }
+ { assumption (other cases will be caught by range checking) (JM) }
+
+ { load left in register }
+ location_force_reg(exprasmlist,left.location,opsize,true);
+ if left.location.loc = LOC_CREGISTER then
+ hr := cg.getintregister(exprasmlist,opsize)
+ else
+ hr := left.location.register;
+ { load right in register }
+ hr2:=cg.getintregister(exprasmlist,opsize);
+ cg.a_load_const_reg(exprasmlist,opsize,right.location.value,hr2);
+
+ { emit bit test operation }
+ emit_bit_test_reg_reg(exprasmlist,left.location.size,left.location.register,hr2,opsize,hr2);
+
+ { if left > 31 then hr := 0 else hr := $ffffffff }
+ cg.a_op_const_reg_reg(exprasmlist,OP_SUB,opsize,32,left.location.register,hr);
+ cg.a_op_const_reg(exprasmlist,OP_SAR,opsize,31,hr);
+
+ { if left > 31, then result := 0 else result := result of bit test }
+ cg.a_op_reg_reg(exprasmlist,OP_AND,opsize,hr,hr2);
+ { allocate a register for the result }
+ location.register := cg.getintregister(exprasmlist,location.size);
+ cg.a_load_reg_reg(exprasmlist,opsize,location.size,hr2,location.register);
+ end { of right.location.loc=LOC_CONSTANT }
+ { do search in a normal set which could have >32 elementsm
+ but also used if the left side contains higher values > 32 }
+ else if left.nodetype=ordconstn then
+ begin
+ { use location.register as scratch register here }
+ if (target_info.endian = endian_little) then
+ inc(right.location.reference.offset,tordconstnode(left).value shr 3)
+ else
+ { adjust for endianess differences }
+ inc(right.location.reference.offset,(tordconstnode(left).value shr 3) xor 3);
+ { allocate a register for the result }
+ location.register := cg.getintregister(exprasmlist,location.size);
+ cg.a_load_ref_reg(exprasmlist,OS_8,location.size,right.location.reference, location.register);
+ cg.a_op_const_reg(exprasmlist,OP_SHR,location.size,tordconstnode(left).value and 7,
+ location.register);
+ cg.a_op_const_reg(exprasmlist,OP_AND,location.size,1,location.register);
+ end
+ else
+ begin
+ location_force_reg(exprasmlist,left.location,OS_INT,true);
+ pleftreg := left.location.register;
+
+ location_freetemp(exprasmlist,left.location);
+ hr := cg.getaddressregister(exprasmlist);
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHR,OS_INT,5,pleftreg,hr);
+ cg.a_op_const_reg(exprasmlist,OP_SHL,OS_INT,2,hr);
+
+ href := right.location.reference;
+ if (href.base = NR_NO) then
+ href.base := hr
+ else if (right.location.reference.index = NR_NO) then
+ href.index := hr
+ else
+ begin
+ hr2 := cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,href, hr2);
+ reference_reset_base(href,hr2,0);
+ href.index := hr;
+ end;
+ { allocate a register for the result }
+ location.register := cg.getintregister(exprasmlist,opsize);
+ cg.a_load_ref_reg(exprasmlist,opsize,opsize,href,location.register);
+
+ hr := cg.getintregister(exprasmlist,opsize);
+ cg.a_op_const_reg_reg(exprasmlist,OP_AND,opsize,31,pleftreg,hr);
+ cg.a_op_reg_reg(exprasmlist,OP_SHR,opsize,hr,location.register);
+ cg.a_op_const_reg(exprasmlist,OP_AND,opsize,1,location.register);
+ end;
+ end;
+ end;
+ location_freetemp(exprasmlist,right.location);
+ end;
+
+{*****************************************************************************
+ TCGCASENODE
+*****************************************************************************}
+
+ function tcgcasenode.blocklabel(id:longint):tasmlabel;
+ begin
+ if not assigned(blocks[id]) then
+ internalerror(200411301);
+ result:=pcaseblock(blocks[id])^.blocklabel;
+ end;
+
+
+ procedure tcgcasenode.optimizevalues(var max_linear_list:aint;var max_dist:aword);
+ begin
+ { no changes by default }
+ end;
+
+
+ function tcgcasenode.has_jumptable : boolean;
+ begin
+ { No jumptable support in the default implementation }
+ has_jumptable:=false;
+ end;
+
+
+ procedure tcgcasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ begin
+ internalerror(200209161);
+ end;
+
+
+ procedure tcgcasenode.genlinearlist(hp : pcaselabel);
+
+ var
+ first : boolean;
+ last : TConstExprInt;
+ scratch_reg: tregister;
+
+ procedure genitem(t : pcaselabel);
+
+ procedure gensub(value:aint);
+ begin
+ { here, since the sub and cmp are separate we need
+ to move the result before subtract to help
+ the register allocator
+ }
+ cg.a_load_reg_reg(exprasmlist, opsize, opsize, hregister, scratch_reg);
+ cg.a_op_const_reg(exprasmlist, OP_SUB, opsize, value, hregister);
+ end;
+
+ begin
+ if assigned(t^.less) then
+ genitem(t^.less);
+ { do we need to test the first value? }
+ if first and (t^._low>get_min_value(left.resulttype.def)) then
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_lt,aint(t^._low),hregister,elselabel);
+ if t^._low=t^._high then
+ begin
+ if t^._low-last=0 then
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,OC_EQ,0,hregister,blocklabel(t^.blockid))
+ else
+ begin
+ gensub(aint(t^._low-last));
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,OC_EQ,aint(t^._low-last),scratch_reg,blocklabel(t^.blockid));
+ end;
+ last:=t^._low;
+ 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(aint(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(aint(t^._low-last));
+ cg.a_cmp_const_reg_label(exprasmlist, opsize,jmp_lt,aint(t^._low-last),scratch_reg,elselabel);
+ end;
+ gensub(aint(t^._high-t^._low));
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_le,aint(t^._high-t^._low),scratch_reg,blocklabel(t^.blockid));
+ 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)) then
+ genlinearcmplist(hp)
+ else
+ begin
+ last:=0;
+ first:=true;
+ scratch_reg:=cg.getintregister(exprasmlist,opsize);
+ genitem(hp);
+ cg.a_jmp_always(exprasmlist,elselabel);
+ end;
+ end;
+
+
+ procedure tcgcasenode.genlinearcmplist(hp : pcaselabel);
+
+ var
+ last : TConstExprInt;
+ lastwasrange: boolean;
+
+ procedure genitem(t : pcaselabel);
+
+{$ifndef cpu64bit}
+ var
+ l1 : tasmlabel;
+{$endif cpu64bit}
+
+ begin
+ if assigned(t^.less) then
+ genitem(t^.less);
+ if t^._low=t^._high then
+ begin
+{$ifndef cpu64bit}
+ if opsize in [OS_S64,OS_64] then
+ begin
+ objectlibrary.getjumplabel(l1);
+ cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_NE, aint(hi(int64(t^._low))),hregister2,l1);
+ cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_EQ, aint(lo(int64(t^._low))),hregister, blocklabel(t^.blockid));
+ cg.a_label(exprasmlist,l1);
+ end
+ else
+{$endif cpu64bit}
+ begin
+ cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ, aint(t^._low),hregister, blocklabel(t^.blockid));
+ end;
+ { Reset last here, because we've only checked for one value and need to compare
+ for the next range both the lower and upper bound }
+ lastwasrange := false;
+ end
+ else
+ begin
+ { it begins with the smallest label, if the value }
+ { is even smaller then jump immediately to the }
+ { ELSE-label }
+ if not lastwasrange or (t^._low-last>1) then
+ begin
+{$ifndef cpu64bit}
+ if opsize in [OS_64,OS_S64] then
+ begin
+ objectlibrary.getjumplabel(l1);
+ cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_lt, aint(hi(int64(t^._low))),
+ hregister2, elselabel);
+ cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_gt, aint(hi(int64(t^._low))),
+ hregister2, l1);
+ { the comparisation of the low dword must be always unsigned! }
+ cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_B, aint(lo(int64(t^._low))), hregister, elselabel);
+ cg.a_label(exprasmlist,l1);
+ end
+ else
+{$endif cpu64bit}
+ begin
+ cg.a_cmp_const_reg_label(exprasmlist, opsize, jmp_lt, aint(t^._low), hregister,
+ elselabel);
+ end;
+ end;
+{$ifndef cpu64bit}
+ if opsize in [OS_S64,OS_64] then
+ begin
+ objectlibrary.getjumplabel(l1);
+ cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_lt, aint(hi(int64(t^._high))), hregister2,
+ blocklabel(t^.blockid));
+ cg.a_cmp_const_reg_label(exprasmlist, OS_32, jmp_gt, aint(hi(int64(t^._high))), hregister2,
+ l1);
+ cg.a_cmp_const_reg_label(exprasmlist, OS_32, OC_BE, aint(lo(int64(t^._high))), hregister, blocklabel(t^.blockid));
+ cg.a_label(exprasmlist,l1);
+ end
+ else
+{$endif cpu64bit}
+ begin
+ cg.a_cmp_const_reg_label(exprasmlist, opsize, jmp_le, aint(t^._high), hregister, blocklabel(t^.blockid));
+ end;
+
+ last:=t^._high;
+ lastwasrange := true;
+ end;
+ if assigned(t^.greater) then
+ genitem(t^.greater);
+ end;
+
+ begin
+ last:=0;
+ lastwasrange:=false;
+ genitem(hp);
+ cg.a_jmp_always(exprasmlist,elselabel);
+ end;
+
+
+ procedure ReLabel(var p:tasmsymbol);
+ begin
+ if p.defbind = AB_LOCAL then
+ begin
+ if not assigned(p.altsymbol) then
+ objectlibrary.GenerateAltSymbol(p);
+ p:=p.altsymbol;
+ p.increfs;
+ end;
+ end;
+
+
+ procedure tcgcasenode.pass_2;
+ var
+ i : longint;
+ lv,hv,
+ max_label: tconstexprint;
+ labelcnt : aint;
+ max_linear_list : aint;
+ otl, ofl: tasmlabel;
+ isjump : boolean;
+ max_dist,
+ dist : aword;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { Allocate labels }
+ objectlibrary.getjumplabel(endlabel);
+ objectlibrary.getjumplabel(elselabel);
+ for i:=0 to blocks.count-1 do
+ objectlibrary.getjumplabel(pcaseblock(blocks[i])^.blocklabel);
+
+ with_sign:=is_signed(left.resulttype.def);
+ if with_sign then
+ begin
+ jmp_gt:=OC_GT;
+ jmp_lt:=OC_LT;
+ jmp_le:=OC_LTE;
+ end
+ else
+ begin
+ jmp_gt:=OC_A;
+ jmp_lt:=OC_B;
+ jmp_le:=OC_BE;
+ end;
+
+ { save current truelabel and falselabel }
+ isjump:=false;
+ if left.location.loc=LOC_JUMP then
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ isjump:=true;
+ end;
+ secondpass(left);
+ { determines the size of the operand }
+ opsize:=def_cgsize(left.resulttype.def);
+ { copy the case expression to a register }
+ location_force_reg(exprasmlist,left.location,opsize,false);
+{$ifndef cpu64bit}
+ if opsize in [OS_S64,OS_64] then
+ begin
+ hregister:=left.location.register64.reglo;
+ hregister2:=left.location.register64.reghi;
+ end
+ else
+{$endif cpu64bit}
+ hregister:=left.location.register;
+ if isjump then
+ begin
+ truelabel:=otl;
+ falselabel:=ofl;
+ end;
+
+ { we need the min_label always to choose between }
+ { cmps and subs/decs }
+ min_label:=case_get_min(labels);
+
+ { Generate the jumps }
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+{$ifndef cpu64bit}
+ if opsize in [OS_64,OS_S64] then
+ genlinearcmplist(labels)
+ else
+{$endif cpu64bit}
+ begin
+ if cs_optimize in aktglobalswitches then
+ begin
+ { procedures are empirically passed on }
+ { consumption can also be calculated }
+ { but does it pay on the different }
+ { processors? }
+ { moreover can the size only be appro- }
+ { ximated as it is not known if rel8, }
+ { rel16 or rel32 jumps are used }
+ max_label:=case_get_max(labels);
+ labelcnt:=case_count_labels(labels);
+ { can we omit the range check of the jump table ? }
+ getrange(left.resulttype.def,lv,hv);
+ jumptable_no_range:=(lv=min_label) and (hv=max_label);
+ { hack a little bit, because the range can be greater }
+ { than the positive range of a aint }
+
+ if (min_label<0) and (max_label>0) then
+ begin
+ if min_label=TConstExprInt(low(aint)) then
+ dist:=aword(max_label)+aword(low(aint))
+ else
+ dist:=aword(max_label)+aword(-min_label)
+ end
+ else
+ dist:=max_label-min_label;
+
+ { optimize for size ? }
+ if cs_littlesize in aktglobalswitches then
+ begin
+ if has_jumptable and
+ not((labelcnt<=2) or
+ ((max_label-min_label)<0) or
+ ((max_label-min_label)>3*labelcnt)) then
+ begin
+ { if the labels less or more a continuum then }
+ genjumptable(labels,min_label,max_label);
+ end
+ else
+ begin
+ { a linear list is always smaller than a jump tree }
+ genlinearlist(labels);
+ end;
+ end
+ else
+ begin
+ max_dist:=4*labelcnt;
+ if jumptable_no_range then
+ max_linear_list:=4
+ else
+ max_linear_list:=2;
+
+ { allow processor specific values }
+ optimizevalues(max_linear_list,max_dist);
+
+ if (labelcnt<=max_linear_list) then
+ genlinearlist(labels)
+ else
+ begin
+ if (has_jumptable) and
+ (dist<max_dist) and
+ (min_label>=low(aint)) and
+ (max_label<=high(aint)) then
+ genjumptable(labels,min_label,max_label)
+ else
+ genlinearlist(labels);
+ end;
+ end;
+ end
+ else
+ { it's always not bad }
+ genlinearlist(labels);
+ end;
+
+ { generate the instruction blocks }
+ for i:=0 to blocks.count-1 do
+ begin
+ cg.a_label(exprasmlist,pcaseblock(blocks[i])^.blocklabel);
+ secondpass(pcaseblock(blocks[i])^.statement);
+ { don't come back to case line }
+ aktfilepos:=exprasmList.getlasttaifilepos^;
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ cg.a_jmp_always(exprasmlist,endlabel);
+ end;
+ { ...and the else block }
+ cg.a_label(exprasmlist,elselabel);
+ if assigned(elseblock) then
+ begin
+ secondpass(elseblock);
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ end;
+ cg.a_label(exprasmlist,endlabel);
+
+ { Reset labels }
+ for i:=0 to blocks.count-1 do
+ pcaseblock(blocks[i])^.blocklabel:=nil;
+ end;
+
+
+begin
+ csetelementnode:=tcgsetelementnode;
+ cinnode:=tcginnode;
+ ccasenode:=tcgcasenode;
+end.
diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas
new file mode 100644
index 0000000000..ec63a7ce58
--- /dev/null
+++ b/compiler/ncgutil.pas
@@ -0,0 +1,2205 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Helper routines for all code generators
+
+ 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 ncgutil;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,cpuinfo,
+ globtype,
+ cpubase,cgbase,parabase,cgutils,
+ aasmbase,aasmtai,aasmcpu,
+ symconst,symbase,symdef,symsym,symtype,symtable
+{$ifndef cpu64bit}
+ ,cg64f32
+{$endif cpu64bit}
+ ;
+
+ type
+ tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
+
+ procedure firstcomplex(p : tbinarynode);
+ procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
+// procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsuperregisterset);
+
+ procedure location_force_reg(list:TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
+ procedure location_force_fpureg(list:TAAsmoutput;var l: tlocation;maybeconst:boolean);
+ procedure location_force_mem(list:TAAsmoutput;var l:tlocation);
+ procedure location_force_mmregscalar(list:TAAsmoutput;var l: tlocation;maybeconst:boolean);
+
+ { Retrieve the location of the data pointed to in location l, when the location is
+ a register it is expected to contain the address of the data }
+ procedure location_get_data_ref(list:TAAsmoutput;const l:tlocation;var ref:treference;loadref:boolean);
+
+ function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
+
+ procedure gen_proc_symbol(list:Taasmoutput);
+ procedure gen_proc_symbol_end(list:Taasmoutput);
+ procedure gen_proc_entry_code(list:Taasmoutput);
+ procedure gen_proc_exit_code(list:Taasmoutput);
+ procedure gen_stack_check_size_para(list:Taasmoutput);
+ procedure gen_stack_check_call(list:Taasmoutput);
+ procedure gen_save_used_regs(list:TAAsmoutput);
+ procedure gen_restore_used_regs(list:TAAsmoutput);
+ procedure gen_initialize_code(list:TAAsmoutput);
+ procedure gen_finalize_code(list:TAAsmoutput);
+ procedure gen_entry_code(list:TAAsmoutput);
+ procedure gen_exit_code(list:TAAsmoutput);
+ procedure gen_load_para_value(list:TAAsmoutput);
+ procedure gen_load_return_value(list:TAAsmoutput);
+
+ procedure gen_external_stub(list:taasmoutput;pd:tprocdef;const externalname:string);
+ procedure gen_intf_wrappers(list:taasmoutput;st:tsymtable);
+ procedure gen_load_vmt_register(list:taasmoutput;objdef:tobjectdef;selfloc:tlocation;var vmtreg:tregister);
+
+ {#
+ Allocate the buffers for exception management and setjmp environment.
+ Return a pointer to these buffers, send them to the utility routine
+ so they are registered, and then call setjmp.
+
+ Then compare the result of setjmp with 0, and if not equal
+ to zero, then jump to exceptlabel.
+
+ Also store the result of setjmp to a temporary space by calling g_save_exception_reason
+
+ It is to note that this routine may be called *after* the stackframe of a
+ routine has been called, therefore on machines where the stack cannot
+ be modified, all temps should be allocated on the heap instead of the
+ stack.
+ }
+
+ const
+
+ EXCEPT_BUF_SIZE = 3*sizeof(aint);
+ type
+ texceptiontemps=record
+ jmpbuf,
+ envbuf,
+ reasonbuf : treference;
+ end;
+
+ procedure get_exception_temps(list:taasmoutput;var t:texceptiontemps);
+ procedure unget_exception_temps(list:taasmoutput;const t:texceptiontemps);
+ procedure new_exception(list:TAAsmoutput;const t:texceptiontemps;exceptlabel:tasmlabel);
+ procedure free_exception(list:TAAsmoutput;const t:texceptiontemps;a:aint;endexceptlabel:tasmlabel;onlyfree:boolean);
+
+ procedure insertbssdata(sym : tglobalvarsym);
+
+ procedure gen_alloc_symtable(list:TAAsmoutput;st:tsymtable);
+ procedure gen_free_symtable(list:TAAsmoutput;st:tsymtable);
+
+ { rtti and init/final }
+ procedure generate_rtti(p:Ttypesym);
+ procedure generate_inittable(p:tsym);
+
+ procedure location_free(list: taasmoutput; const location : TLocation);
+
+implementation
+
+ uses
+ version,
+ cutils,cclasses,
+ globals,systems,verbose,
+ ppu,defutil,
+ procinfo,paramgr,fmodule,
+ regvars,dwarf,dbgbase,
+ pass_1,pass_2,
+ ncon,nld,nutils,
+ tgobj,cgobj;
+
+
+{*****************************************************************************
+ Misc Helpers
+*****************************************************************************}
+
+ procedure location_free(list: taasmoutput; const location : TLocation);
+ begin
+ case location.loc of
+ LOC_VOID:
+ ;
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ if getsupreg(location.register)<first_int_imreg then
+ cg.ungetcpuregister(list,location.register);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ if getsupreg(location.register)<first_fpu_imreg then
+ cg.ungetcpuregister(list,location.register);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER :
+ begin
+ if getsupreg(location.register)<first_mm_imreg then
+ cg.ungetcpuregister(list,location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+{$ifdef cputargethasfixedstack}
+ location_freetemp(list,location);
+{$endif cputargethasfixedstack}
+ end;
+ else
+ internalerror(2004110211);
+ end;
+ end;
+
+
+
+ { DO NOT RELY on the fact that the tnode is not yet swaped
+ because of inlining code PM }
+ procedure firstcomplex(p : tbinarynode);
+ var
+ hp : tnode;
+ begin
+ { always calculate boolean AND and OR from left to right }
+ if (p.nodetype in [orn,andn]) and
+ is_boolean(p.left.resulttype.def) then
+ begin
+ if nf_swaped in p.flags then
+ internalerror(234234);
+ end
+ else
+ if (
+ (p.expectloc=LOC_FPUREGISTER) and
+ (p.right.registersfpu > p.left.registersfpu)
+ ) or
+ (
+ (
+ (
+ ((p.left.registersfpu = 0) and (p.right.registersfpu = 0)) or
+ (p.expectloc<>LOC_FPUREGISTER)
+ ) and
+ (p.left.registersint<p.right.registersint)
+ )
+ ) then
+ begin
+ hp:=p.left;
+ p.left:=p.right;
+ p.right:=hp;
+ if nf_swaped in p.flags then
+ exclude(p.flags,nf_swaped)
+ else
+ include(p.flags,nf_swaped);
+ end;
+ end;
+
+
+ procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
+ {
+ produces jumps to true respectively false labels using boolean expressions
+
+ depending on whether the loading of regvars is currently being
+ synchronized manually (such as in an if-node) or automatically (most of
+ the other cases where this procedure is called), loadregvars can be
+ "lr_load_regvars" or "lr_dont_load_regvars"
+ }
+ var
+ opsize : tcgsize;
+ storepos : tfileposinfo;
+ begin
+ if nf_error in p.flags then
+ exit;
+ storepos:=aktfilepos;
+ aktfilepos:=p.fileinfo;
+ if is_boolean(p.resulttype.def) then
+ begin
+{$ifdef OLDREGVARS}
+ if loadregvars = lr_load_regvars then
+ load_all_regvars(list);
+{$endif OLDREGVARS}
+ if is_constboolnode(p) then
+ begin
+ if tordconstnode(p).value<>0 then
+ cg.a_jmp_always(list,truelabel)
+ else
+ cg.a_jmp_always(list,falselabel)
+ end
+ else
+ begin
+ opsize:=def_cgsize(p.resulttype.def);
+ case p.location.loc of
+ LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
+ begin
+{$ifdef OLDREGVARS}
+ if (p.location.loc = LOC_CREGISTER) then
+ load_regvar_reg(list,p.location.register);
+{$endif OLDREGVARS}
+ cg.a_cmp_const_loc_label(list,opsize,OC_NE,0,p.location,truelabel);
+ cg.a_jmp_always(list,falselabel);
+ end;
+ LOC_JUMP:
+ ;
+{$ifdef cpuflags}
+ LOC_FLAGS :
+ begin
+ cg.a_jmp_flags(list,p.location.resflags,truelabel);
+ cg.a_jmp_always(list,falselabel);
+ end;
+{$endif cpuflags}
+ else
+ begin
+ printnode(output,p);
+ internalerror(200308241);
+ end;
+ end;
+ end;
+ end
+ else
+ internalerror(200112305);
+ aktfilepos:=storepos;
+ end;
+
+
+ (*
+ This code needs fixing. It is not safe to use rgint; on the m68000 it
+ would be rgaddr.
+
+ procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsuperregisterset);
+ begin
+ case t.loc of
+ LOC_REGISTER:
+ begin
+ { can't be a regvar, since it would be LOC_CREGISTER then }
+ exclude(regs,getsupreg(t.register));
+ if t.register64.reghi<>NR_NO then
+ exclude(regs,getsupreg(t.register64.reghi));
+ end;
+ LOC_CREFERENCE,LOC_REFERENCE:
+ begin
+ if not(cs_regvars in aktglobalswitches) or
+ (getsupreg(t.reference.base) in cg.rgint.usableregs) then
+ exclude(regs,getsupreg(t.reference.base));
+ if not(cs_regvars in aktglobalswitches) or
+ (getsupreg(t.reference.index) in cg.rgint.usableregs) then
+ exclude(regs,getsupreg(t.reference.index));
+ end;
+ end;
+ end;
+ *)
+
+
+{*****************************************************************************
+ EXCEPTION MANAGEMENT
+*****************************************************************************}
+
+ procedure get_exception_temps(list:taasmoutput;var t:texceptiontemps);
+ var
+ sym : ttypesym;
+ begin
+ if jmp_buf_size=-1 then
+ begin
+ searchsystype('JMP_BUF',sym);
+ jmp_buf_size:=sym.restype.def.size;
+ end;
+ tg.GetTemp(list,EXCEPT_BUF_SIZE,tt_persistent,t.envbuf);
+ tg.GetTemp(list,jmp_buf_size,tt_persistent,t.jmpbuf);
+ tg.GetTemp(list,sizeof(aint),tt_persistent,t.reasonbuf);
+ end;
+
+
+ procedure unget_exception_temps(list:taasmoutput;const t:texceptiontemps);
+ begin
+ tg.Ungettemp(list,t.jmpbuf);
+ tg.ungettemp(list,t.envbuf);
+ tg.ungettemp(list,t.reasonbuf);
+ end;
+
+
+ procedure new_exception(list:TAAsmoutput;const t:texceptiontemps;exceptlabel:tasmlabel);
+ var
+ paraloc1,paraloc2,paraloc3 : tcgpara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ paramanager.allocparaloc(list,paraloc3);
+ cg.a_paramaddr_ref(list,t.envbuf,paraloc3);
+ paramanager.allocparaloc(list,paraloc2);
+ cg.a_paramaddr_ref(list,t.jmpbuf,paraloc2);
+ { push type of exceptionframe }
+ paramanager.allocparaloc(list,paraloc1);
+ cg.a_param_const(list,OS_S32,1,paraloc1);
+ paramanager.freeparaloc(list,paraloc3);
+ paramanager.freeparaloc(list,paraloc2);
+ paramanager.freeparaloc(list,paraloc1);
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_PUSHEXCEPTADDR');
+ cg.deallocallcpuregisters(list);
+
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(list,paraloc1);
+ cg.a_param_reg(list,OS_ADDR,NR_FUNCTION_RESULT_REG,paraloc1);
+ paramanager.freeparaloc(list,paraloc1);
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_SETJMP');
+ cg.deallocallcpuregisters(list);
+
+ cg.g_exception_reason_save(list, t.reasonbuf);
+ cg.a_cmp_const_reg_label(list,OS_S32,OC_NE,0,cg.makeregsize(list,NR_FUNCTION_RESULT_REG,OS_S32),exceptlabel);
+ paraloc1.done;
+ paraloc2.done;
+ paraloc3.done;
+ end;
+
+
+ procedure free_exception(list:TAAsmoutput;const t:texceptiontemps;a:aint;endexceptlabel:tasmlabel;onlyfree:boolean);
+ begin
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_POPADDRSTACK');
+ cg.deallocallcpuregisters(list);
+
+ if not onlyfree then
+ begin
+ cg.g_exception_reason_load(list, t.reasonbuf);
+ cg.a_cmp_const_reg_label(list,OS_INT,OC_EQ,a,NR_FUNCTION_RESULT_REG,endexceptlabel);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TLocation
+*****************************************************************************}
+
+{$ifndef cpu64bit}
+ { 32-bit version }
+ procedure location_force_reg(list:TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
+ var
+ hregister,
+ hregisterhi : tregister;
+ hreg64 : tregister64;
+ hl : tasmlabel;
+ oldloc : tlocation;
+ const_location: boolean;
+ begin
+ oldloc:=l;
+ if dst_size=OS_NO then
+ internalerror(200309144);
+ { handle transformations to 64bit separate }
+ if dst_size in [OS_64,OS_S64] then
+ begin
+ if not (l.size in [OS_64,OS_S64]) then
+ begin
+ { load a smaller size to OS_64 }
+ if l.loc=LOC_REGISTER then
+ begin
+ hregister:=cg.makeregsize(list,l.register64.reglo,OS_32);
+ cg.a_load_reg_reg(list,l.size,OS_32,l.register64.reglo,hregister);
+ end
+ else
+ hregister:=cg.getintregister(list,OS_INT);
+ { load value in low register }
+ case l.loc of
+ LOC_FLAGS :
+ cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
+ LOC_JUMP :
+ begin
+ cg.a_label(list,truelabel);
+ cg.a_load_const_reg(list,OS_INT,1,hregister);
+ objectlibrary.getjumplabel(hl);
+ cg.a_jmp_always(list,hl);
+ cg.a_label(list,falselabel);
+ cg.a_load_const_reg(list,OS_INT,0,hregister);
+ cg.a_label(list,hl);
+ end;
+ else
+ cg.a_load_loc_reg(list,OS_INT,l,hregister);
+ end;
+ { reset hi part, take care of the signed bit of the current value }
+ hregisterhi:=cg.getintregister(list,OS_INT);
+ if (l.size in [OS_S8,OS_S16,OS_S32]) then
+ begin
+ if l.loc=LOC_CONSTANT then
+ begin
+ if (longint(l.value)<0) then
+ cg.a_load_const_reg(list,OS_32,aint($ffffffff),hregisterhi)
+ else
+ cg.a_load_const_reg(list,OS_32,0,hregisterhi);
+ end
+ else
+ begin
+ cg.a_op_const_reg_reg(list,OP_SAR,OS_32,31,hregister,
+ hregisterhi);
+ end;
+ end
+ else
+ cg.a_load_const_reg(list,OS_32,0,hregisterhi);
+ location_reset(l,LOC_REGISTER,dst_size);
+ l.register64.reglo:=hregister;
+ l.register64.reghi:=hregisterhi;
+ end
+ else
+ begin
+ { 64bit to 64bit }
+ if ((l.loc=LOC_CREGISTER) and maybeconst) then
+ begin
+ hregister:=l.register64.reglo;
+ hregisterhi:=l.register64.reghi;
+ const_location := true;
+ end
+ else
+ begin
+ hregister:=cg.getintregister(list,OS_INT);
+ hregisterhi:=cg.getintregister(list,OS_INT);
+ const_location := false;
+ end;
+ hreg64.reglo:=hregister;
+ hreg64.reghi:=hregisterhi;
+ { load value in new register }
+ cg64.a_load64_loc_reg(list,l,hreg64);
+ if not const_location then
+ location_reset(l,LOC_REGISTER,dst_size)
+ else
+ location_reset(l,LOC_CREGISTER,dst_size);
+ l.register64.reglo:=hregister;
+ l.register64.reghi:=hregisterhi;
+ end;
+ end
+ else
+ begin
+ {Do not bother to recycle the existing register. The register
+ allocator eliminates unnecessary moves, so it's not needed
+ and trying to recycle registers can cause problems because
+ the registers changes size and may need aditional constraints.
+
+ Not if it's about LOC_CREGISTER's (JM)
+ }
+ const_location :=
+ (maybeconst) and
+ (l.loc = LOC_CREGISTER) and
+ (TCGSize2Size[l.size] = TCGSize2Size[dst_size]) and
+ ((l.size = dst_size) or
+ (TCGSize2Size[l.size] = TCGSize2Size[OS_INT]));
+ if not const_location then
+ hregister:=cg.getintregister(list,dst_size)
+ else
+ hregister := l.register;
+ { load value in new register }
+ case l.loc of
+ LOC_FLAGS :
+ cg.g_flags2reg(list,dst_size,l.resflags,hregister);
+ LOC_JUMP :
+ begin
+ cg.a_label(list,truelabel);
+ cg.a_load_const_reg(list,dst_size,1,hregister);
+ objectlibrary.getjumplabel(hl);
+ cg.a_jmp_always(list,hl);
+ cg.a_label(list,falselabel);
+ cg.a_load_const_reg(list,dst_size,0,hregister);
+ cg.a_label(list,hl);
+ end;
+ else
+ begin
+ { load_loc_reg can only handle size >= l.size, when the
+ new size is smaller then we need to adjust the size
+ of the orignal and maybe recalculate l.register for i386 }
+ if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
+ begin
+ if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ l.register:=cg.makeregsize(list,l.register,dst_size);
+ { for big endian systems, the reference's offset must }
+ { be increased in this case, since they have the }
+ { MSB first in memory and e.g. byte(word_var) should }
+ { return the second byte in this case (JM) }
+ if (target_info.endian = ENDIAN_BIG) and
+ (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
+{$ifdef x86}
+ l.size:=dst_size;
+{$endif x86}
+ end;
+ cg.a_load_loc_reg(list,dst_size,l,hregister);
+{$ifndef x86}
+ if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
+ l.size:=dst_size;
+{$endif not x86}
+ end;
+ end;
+ if not const_location then
+ location_reset(l,LOC_REGISTER,dst_size)
+ else
+ location_reset(l,LOC_CREGISTER,dst_size);
+ l.register:=hregister;
+ end;
+ { Release temp when it was a reference }
+ if oldloc.loc=LOC_REFERENCE then
+ location_freetemp(list,oldloc);
+ end;
+
+{$else cpu64bit}
+
+ { 64-bit version }
+ procedure location_force_reg(list:TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
+ var
+ hregister : tregister;
+ hl : tasmlabel;
+ oldloc : tlocation;
+ begin
+ oldloc:=l;
+ hregister:=cg.getintregister(list,dst_size);
+ { load value in new register }
+ case l.loc of
+ LOC_FLAGS :
+ cg.g_flags2reg(list,dst_size,l.resflags,hregister);
+ LOC_JUMP :
+ begin
+ cg.a_label(list,truelabel);
+ cg.a_load_const_reg(list,dst_size,1,hregister);
+ objectlibrary.getjumplabel(hl);
+ cg.a_jmp_always(list,hl);
+ cg.a_label(list,falselabel);
+ cg.a_load_const_reg(list,dst_size,0,hregister);
+ cg.a_label(list,hl);
+ end;
+ else
+ begin
+ { load_loc_reg can only handle size >= l.size, when the
+ new size is smaller then we need to adjust the size
+ of the orignal and maybe recalculate l.register for i386 }
+ if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
+ begin
+ if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ l.register:=cg.makeregsize(list,l.register,dst_size);
+ { for big endian systems, the reference's offset must }
+ { be increased in this case, since they have the }
+ { MSB first in memory and e.g. byte(word_var) should }
+ { return the second byte in this case (JM) }
+ if (target_info.endian = ENDIAN_BIG) and
+ (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
+{$ifdef x86}
+ l.size:=dst_size;
+{$endif x86}
+ end;
+ cg.a_load_loc_reg(list,dst_size,l,hregister);
+{$ifndef x86}
+ if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
+ l.size:=dst_size;
+{$endif not x86}
+ end;
+ end;
+ if (l.loc <> LOC_CREGISTER) or
+ not maybeconst then
+ location_reset(l,LOC_REGISTER,dst_size)
+ else
+ location_reset(l,LOC_CREGISTER,dst_size);
+ l.register:=hregister;
+ { Release temp when it was a reference }
+ if oldloc.loc=LOC_REFERENCE then
+ location_freetemp(list,oldloc);
+ end;
+{$endif cpu64bit}
+
+
+ procedure location_force_fpureg(list:TAAsmoutput;var l: tlocation;maybeconst:boolean);
+ var
+ reg : tregister;
+ href : treference;
+ begin
+ if (l.loc<>LOC_FPUREGISTER) and
+ ((l.loc<>LOC_CFPUREGISTER) or (not maybeconst)) then
+ begin
+ { if it's in an mm register, store to memory first }
+ if (l.loc in [LOC_MMREGISTER,LOC_CMMREGISTER]) then
+ begin
+ tg.GetTemp(list,tcgsize2size[l.size],tt_normal,href);
+ cg.a_loadmm_reg_ref(list,l.size,l.size,l.register,href,mms_movescalar);
+ location_reset(l,LOC_REFERENCE,l.size);
+ l.reference:=href;
+ end;
+ reg:=cg.getfpuregister(list,l.size);
+ cg.a_loadfpu_loc_reg(list,l,reg);
+ location_freetemp(list,l);
+ location_reset(l,LOC_FPUREGISTER,l.size);
+ l.register:=reg;
+ end;
+ end;
+
+
+ procedure location_force_mmregscalar(list:TAAsmoutput;var l: tlocation;maybeconst:boolean);
+ var
+ reg : tregister;
+ href : treference;
+ begin
+ if (l.loc<>LOC_MMREGISTER) and
+ ((l.loc<>LOC_CMMREGISTER) or (not maybeconst)) then
+ begin
+ { if it's in an fpu register, store to memory first }
+ if (l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
+ begin
+ tg.GetTemp(list,tcgsize2size[l.size],tt_normal,href);
+ cg.a_loadfpu_reg_ref(list,l.size,l.register,href);
+ location_reset(l,LOC_REFERENCE,l.size);
+ l.reference:=href;
+ end;
+ reg:=cg.getmmregister(list,l.size);
+ cg.a_loadmm_loc_reg(list,l.size,l,reg,mms_movescalar);
+ location_freetemp(list,l);
+ location_reset(l,LOC_MMREGISTER,l.size);
+ l.register:=reg;
+ end;
+ end;
+
+
+ procedure location_force_mem(list:TAAsmoutput;var l:tlocation);
+ var
+ r : treference;
+ begin
+ case l.loc of
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
+ cg.a_loadfpu_reg_ref(list,l.size,l.register,r);
+ location_reset(l,LOC_REFERENCE,l.size);
+ l.reference:=r;
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
+ cg.a_loadmm_reg_ref(list,l.size,l.size,l.register,r,mms_movescalar);
+ location_reset(l,LOC_REFERENCE,l.size);
+ l.reference:=r;
+ end;
+ LOC_CONSTANT,
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
+{$ifndef cpu64bit}
+ if l.size in [OS_64,OS_S64] then
+ cg64.a_load64_loc_ref(list,l,r)
+ else
+{$endif cpu64bit}
+ cg.a_load_loc_ref(list,l.size,l,r);
+ location_reset(l,LOC_REFERENCE,l.size);
+ l.reference:=r;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE : ;
+ else
+ internalerror(200203219);
+ end;
+ end;
+
+
+ procedure location_get_data_ref(list:TAAsmoutput;const l:tlocation;var ref:treference;loadref:boolean);
+ begin
+ case l.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ if not loadref then
+ internalerror(200410231);
+ reference_reset_base(ref,l.register,0);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if loadref then
+ begin
+ reference_reset_base(ref,cg.getaddressregister(list),0);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,l.reference,ref.base);
+ end
+ else
+ ref:=l.reference;
+ end;
+ else
+ internalerror(200309181);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Maybe_Save
+*****************************************************************************}
+
+ function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
+ begin
+{$ifdef i386}
+ if (needed>=maxfpuregs) and
+ (l.loc = LOC_FPUREGISTER) then
+ begin
+ location_force_mem(list,l);
+ maybe_pushfpu:=true;
+ end
+ else
+ maybe_pushfpu:=false;
+{$else i386}
+ maybe_pushfpu:=false;
+{$endif i386}
+ end;
+
+
+{****************************************************************************
+ Init/Finalize Code
+****************************************************************************}
+
+ procedure copyvalueparas(p : tnamedindexitem;arg:pointer);
+ var
+ href : treference;
+ hreg : tregister;
+ list : TAAsmoutput;
+ hsym : tparavarsym;
+ l : longint;
+ localcopyloc : tlocation;
+ begin
+ list:=taasmoutput(arg);
+ if (tsym(p).typ=paravarsym) and
+ (tparavarsym(p).varspez=vs_value) and
+ (paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vartype.def,current_procinfo.procdef.proccalloption)) then
+ begin
+ location_get_data_ref(list,tparavarsym(p).localloc,href,true);
+ if is_open_array(tparavarsym(p).vartype.def) or
+ is_array_of_const(tparavarsym(p).vartype.def) then
+ begin
+ { cdecl functions don't have a high pointer so it is not possible to generate
+ a local copy }
+ if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ begin
+ hsym:=tparavarsym(tsym(p).owner.search('high'+p.name));
+ if not assigned(hsym) then
+ internalerror(200306061);
+ hreg:=cg.getaddressregister(list);
+ cg.g_copyvaluepara_openarray(list,href,hsym.localloc,tarraydef(tparavarsym(p).vartype.def).elesize,hreg);
+ cg.a_load_reg_loc(list,OS_ADDR,hreg,tparavarsym(p).localloc);
+ end;
+ end
+ else
+ begin
+ { Allocate space for the local copy }
+ l:=tparavarsym(p).getsize;
+ localcopyloc.loc:=LOC_REFERENCE;
+ localcopyloc.size:=int_cgsize(l);
+ tg.GetLocal(list,l,tparavarsym(p).vartype.def,localcopyloc.reference);
+ { Copy data }
+ if is_shortstring(tparavarsym(p).vartype.def) then
+ begin
+ { this code is only executed before the code for the body and the entry/exit code is generated
+ so we're allowed to include pi_do_call here; after pass1 is run, this isn't allowed anymore
+ }
+ include(current_procinfo.flags,pi_do_call);
+ cg.g_copyshortstring(list,href,localcopyloc.reference,tstringdef(tparavarsym(p).vartype.def).len)
+ end
+ else
+ cg.g_concatcopy(list,href,localcopyloc.reference,tparavarsym(p).vartype.def.size);
+ { update localloc of varsym }
+ tg.Ungetlocal(list,tparavarsym(p).localloc.reference);
+ tparavarsym(p).localloc:=localcopyloc;
+ end;
+ end;
+ end;
+
+
+ { initializes the regvars from staticsymtable with 0 }
+ procedure initialize_regvars(p : tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ=globalvarsym) then
+ begin
+ case tglobalvarsym(p).localloc.loc of
+ LOC_CREGISTER :
+ cg.a_load_const_reg(taasmoutput(arg),reg_cgsize(tglobalvarsym(p).localloc.register),0,
+ tglobalvarsym(p).localloc.register);
+ LOC_REFERENCE : ;
+ LOC_CMMREGISTER :
+ { clear the whole register }
+ cg.a_opmm_reg_reg(taasmoutput(arg),OP_XOR,reg_cgsize(tglobalvarsym(p).localloc.register),
+ tglobalvarsym(p).localloc.register,
+ tglobalvarsym(p).localloc.register,
+ nil);
+ LOC_CFPUREGISTER :
+ ;
+ else
+ internalerror(200410124);
+ end;
+ end;
+ end;
+
+
+ { generates the code for initialisation of local data }
+ procedure initialize_data(p : tnamedindexitem;arg:pointer);
+ var
+ oldexprasmlist : TAAsmoutput;
+ hp : tnode;
+ begin
+ if (tsym(p).typ in [globalvarsym,localvarsym]) and
+ (tabstractvarsym(p).refs>0) and
+ not(is_class(tabstractvarsym(p).vartype.def)) and
+ tabstractvarsym(p).vartype.def.needs_inittable then
+ begin
+ oldexprasmlist:=exprasmlist;
+ exprasmlist:=taasmoutput(arg);
+ hp:=initialize_data_node(cloadnode.create(tsym(p),tsym(p).owner));
+ firstpass(hp);
+ secondpass(hp);
+ hp.free;
+ exprasmlist:=oldexprasmlist;
+ end;
+ end;
+
+
+ procedure finalize_sym(asmlist:taasmoutput;sym:tsym);
+ var
+ hp : tnode;
+ oldexprasmlist : TAAsmoutput;
+ begin
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ oldexprasmlist:=exprasmlist;
+ exprasmlist:=asmlist;
+ hp:=finalize_data_node(cloadnode.create(sym,sym.owner));
+ firstpass(hp);
+ secondpass(hp);
+ hp.free;
+ exprasmlist:=oldexprasmlist;
+ end;
+
+
+ { generates the code for finalisation of local variables }
+ procedure finalize_local_vars(p : tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ=localvarsym) and
+ (tlocalvarsym(p).refs>0) and
+ not(vo_is_funcret in tlocalvarsym(p).varoptions) and
+ not(is_class(tlocalvarsym(p).vartype.def)) and
+ tlocalvarsym(p).vartype.def.needs_inittable then
+ finalize_sym(taasmoutput(arg),tsym(p));
+ end;
+
+
+ { generates the code for finalisation of local typedconsts }
+ procedure finalize_local_typedconst(p : tnamedindexitem;arg:pointer);
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ case tsym(p).typ of
+ typedconstsym :
+ begin
+ if ttypedconstsym(p).is_writable and
+ ttypedconstsym(p).typedconsttype.def.needs_inittable then
+ finalize_sym(taasmoutput(arg),tsym(p));
+ end;
+ procsym :
+ begin
+ for i:=1 to tprocsym(p).procdef_count do
+ begin
+ pd:=tprocsym(p).procdef[i];
+ if assigned(pd.localst) and
+ (pd.procsym=tprocsym(p)) and
+ (pd.localst.symtabletype<>staticsymtable) then
+ pd.localst.foreach_static(@finalize_local_typedconst,arg);
+ end;
+ end;
+ end;
+ end;
+
+
+ { generates the code for finalization of static symtable and
+ all local (static) typedconsts }
+ procedure finalize_static_data(p : tnamedindexitem;arg:pointer);
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ case tsym(p).typ of
+ globalvarsym :
+ begin
+ if (tglobalvarsym(p).refs>0) and
+ not(vo_is_funcret in tglobalvarsym(p).varoptions) and
+ not(is_class(tglobalvarsym(p).vartype.def)) and
+ tglobalvarsym(p).vartype.def.needs_inittable then
+ finalize_sym(taasmoutput(arg),tsym(p));
+ end;
+ typedconstsym :
+ begin
+ if ttypedconstsym(p).is_writable and
+ ttypedconstsym(p).typedconsttype.def.needs_inittable then
+ finalize_sym(taasmoutput(arg),tsym(p));
+ end;
+ procsym :
+ begin
+ for i:=1 to tprocsym(p).procdef_count do
+ begin
+ pd:=tprocsym(p).procdef[i];
+ if assigned(pd.localst) and
+ (pd.procsym=tprocsym(p)) and
+ (pd.localst.symtabletype<>staticsymtable) then
+ pd.localst.foreach_static(@finalize_local_typedconst,arg);
+ end;
+ end;
+ end;
+ end;
+
+
+ { generates the code for incrementing the reference count of parameters and
+ initialize out parameters }
+ procedure init_paras(p : tnamedindexitem;arg:pointer);
+ var
+ href : treference;
+ tmpreg : tregister;
+ list : TAAsmoutput;
+ begin
+ list:=taasmoutput(arg);
+ if (tsym(p).typ=paravarsym) and
+ not is_class_or_interface(tparavarsym(p).vartype.def) and
+ tparavarsym(p).vartype.def.needs_inittable then
+ begin
+ case tparavarsym(p).varspez of
+ vs_value :
+ begin
+ location_get_data_ref(list,tparavarsym(p).localloc,href,is_open_array(tparavarsym(p).vartype.def));
+ cg.g_incrrefcount(list,tparavarsym(p).vartype.def,href);
+ end;
+ vs_out :
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_loc_reg(list,OS_ADDR,tparavarsym(p).localloc,tmpreg);
+ reference_reset_base(href,tmpreg,0);
+ cg.g_initialize(list,tparavarsym(p).vartype.def,href);
+ end;
+ end;
+ end;
+ end;
+
+
+ { generates the code for decrementing the reference count of parameters }
+ procedure final_paras(p : tnamedindexitem;arg:pointer);
+ var
+ list : TAAsmoutput;
+ href : treference;
+ begin
+ if not(tsym(p).typ=paravarsym) then
+ exit;
+ list:=taasmoutput(arg);
+ if not is_class_or_interface(tparavarsym(p).vartype.def) and
+ tparavarsym(p).vartype.def.needs_inittable then
+ begin
+ if (tparavarsym(p).varspez=vs_value) then
+ begin
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ location_get_data_ref(list,tparavarsym(p).localloc,href,is_open_array(tparavarsym(p).vartype.def));
+ cg.g_decrrefcount(list,tparavarsym(p).vartype.def,href);
+ end;
+ end
+ else
+ if (tparavarsym(p).varspez=vs_value) and
+ (is_open_array(tparavarsym(p).vartype.def) or
+ is_array_of_const(tparavarsym(p).vartype.def)) then
+ begin
+ { cdecl functions don't have a high pointer so it is not possible to generate
+ a local copy }
+ if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ cg.g_releasevaluepara_openarray(list,tparavarsym(p).localloc);
+ end;
+ end;
+
+
+ { Initialize temp ansi/widestrings,interfaces }
+ procedure inittempvariables(list:taasmoutput);
+ var
+ hp : ptemprecord;
+ href : treference;
+ begin
+ hp:=tg.templist;
+ while assigned(hp) do
+ begin
+ if assigned(hp^.def) and
+ hp^.def.needs_inittable then
+ begin
+ reference_reset_base(href,current_procinfo.framepointer,hp^.pos);
+ cg.g_initialize(list,hp^.def,href);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure finalizetempvariables(list:taasmoutput);
+ var
+ hp : ptemprecord;
+ href : treference;
+ begin
+ hp:=tg.templist;
+ while assigned(hp) do
+ begin
+ if assigned(hp^.def) and
+ hp^.def.needs_inittable then
+ begin
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ reference_reset_base(href,current_procinfo.framepointer,hp^.pos);
+ cg.g_finalize(list,hp^.def,href);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure gen_load_return_value(list:TAAsmoutput);
+ var
+{$ifndef cpu64bit}
+ href : treference;
+{$endif cpu64bit}
+ ressym : tabstractnormalvarsym;
+ resloc,
+ restmploc : tlocation;
+ hreg : tregister;
+ funcretloc : tlocation;
+ begin
+ { Is the loading needed? }
+ if (current_procinfo.procdef.funcretloc[calleeside].loc=LOC_VOID) or
+ (
+ (po_assembler in current_procinfo.procdef.procoptions) and
+ (not(assigned(current_procinfo.procdef.funcretsym)) or
+ (tabstractvarsym(current_procinfo.procdef.funcretsym).refs=0))
+ ) then
+ exit;
+
+ funcretloc:=current_procinfo.procdef.funcretloc[calleeside];
+
+ { constructors return self }
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) then
+ ressym:=tabstractnormalvarsym(current_procinfo.procdef.parast.search('self'))
+ else
+ ressym:=tabstractnormalvarsym(current_procinfo.procdef.funcretsym);
+ if (ressym.refs>0) then
+ begin
+{$ifdef OLDREGVARS}
+ case ressym.localloc.loc of
+ LOC_CFPUREGISTER,
+ LOC_FPUREGISTER:
+ begin
+ location_reset(restmploc,LOC_CFPUREGISTER,funcretloc^.size);
+ restmploc.register:=ressym.localloc.register;
+ end;
+
+ LOC_CREGISTER,
+ LOC_REGISTER:
+ begin
+ location_reset(restmploc,LOC_CREGISTER,funcretloc^.size);
+ restmploc.register:=ressym.localloc.register;
+ end;
+
+ LOC_MMREGISTER:
+ begin
+ location_reset(restmploc,LOC_CMMREGISTER,funcretloc^.size);
+ restmploc.register:=ressym.localloc.register;
+ end;
+
+ LOC_REFERENCE:
+ begin
+ location_reset(restmploc,LOC_REFERENCE,funcretloc^.size);
+ restmploc.reference:=ressym.localloc.reference;
+ end;
+ else
+ internalerror(200309184);
+ end;
+{$else}
+ restmploc:=ressym.localloc;
+{$endif}
+
+ { Here, we return the function result. In most architectures, the value is
+ passed into the FUNCTION_RETURN_REG, but in a windowed architecure like sparc a
+ function returns in a register and the caller receives it in an other one }
+ case funcretloc.loc of
+ LOC_REGISTER:
+ begin
+{$ifndef cpu64bit}
+ if current_procinfo.procdef.funcretloc[calleeside].size in [OS_64,OS_S64] then
+ begin
+ resloc:=current_procinfo.procdef.funcretloc[calleeside];
+ if resloc.loc<>LOC_REGISTER then
+ internalerror(200409141);
+ { Load low and high register separate to generate better register
+ allocation info }
+ if getsupreg(resloc.register64.reglo)<first_int_imreg then
+ begin
+ cg.getcpuregister(list,resloc.register64.reglo);
+ cg.ungetcpuregister(list,resloc.register64.reglo);
+ { for the optimizer }
+ cg.a_reg_alloc(list,resloc.register64.reglo);
+ end;
+ case restmploc.loc of
+ LOC_REFERENCE :
+ begin
+ href:=restmploc.reference;
+ if target_info.endian=ENDIAN_BIG then
+ inc(href.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,href,resloc.register64.reglo);
+ end;
+ LOC_CREGISTER :
+ cg.a_load_reg_reg(list,OS_32,OS_32,restmploc.register64.reglo,resloc.register64.reglo);
+ else
+ internalerror(200409203);
+ end;
+ if getsupreg(resloc.register64.reghi)<first_int_imreg then
+ begin
+ cg.getcpuregister(list,resloc.register64.reghi);
+ cg.ungetcpuregister(list,resloc.register64.reghi);
+ { for the optimizer }
+ cg.a_reg_alloc(list,resloc.register64.reghi);
+ end;
+ case restmploc.loc of
+ LOC_REFERENCE :
+ begin
+ href:=restmploc.reference;
+ if target_info.endian=ENDIAN_LITTLE then
+ inc(href.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,href,resloc.register64.reghi);
+ end;
+ LOC_CREGISTER :
+ cg.a_load_reg_reg(list,OS_32,OS_32,restmploc.register64.reghi,resloc.register64.reghi);
+ else
+ internalerror(200409204);
+ end;
+ end
+ else
+{$endif cpu64bit}
+ begin
+ hreg:=cg.makeregsize(list,funcretloc.register,funcretloc.size);
+ if getsupreg(funcretloc.register)<first_int_imreg then
+ begin
+ cg.getcpuregister(list,funcretloc.register);
+ cg.ungetcpuregister(list,hreg);
+ { for the optimizer }
+ cg.a_reg_alloc(list,funcretloc.register);
+ end;
+ { it could be that a structure is passed in memory but the function is expected to
+ return a pointer to this memory }
+ if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption) then
+ cg.a_load_loc_reg(list,OS_ADDR,restmploc,hreg)
+ else
+ cg.a_load_loc_reg(list,restmploc.size,restmploc,hreg);
+ end;
+ end;
+ LOC_FPUREGISTER:
+ begin
+ if getsupreg(funcretloc.register)<first_fpu_imreg then
+ begin
+ cg.getcpuregister(list,funcretloc.register);
+ cg.ungetcpuregister(list,funcretloc.register);
+ end;
+ { we can't do direct moves between fpu and mm registers }
+ if restmploc.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
+ location_force_fpureg(list,restmploc,false);
+ cg.a_loadfpu_loc_reg(list,restmploc,funcretloc.register);
+ end;
+ LOC_MMREGISTER:
+ begin
+ if getsupreg(funcretloc.register)<first_mm_imreg then
+ begin
+ cg.getcpuregister(list,funcretloc.register);
+ cg.ungetcpuregister(list,funcretloc.register);
+ end;
+ cg.a_loadmm_loc_reg(list,restmploc.size,restmploc,funcretloc.register,mms_movescalar);
+ end;
+ LOC_INVALID,
+ LOC_REFERENCE:
+ ;
+ else
+ internalerror(200405025);
+ end;
+ end;
+ end;
+
+
+ procedure gen_load_para_value(list:TAAsmoutput);
+
+
+ procedure get_para(const paraloc:TCGParaLocation);
+ begin
+ case paraloc.loc of
+ LOC_REGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_int_imreg then
+ cg.getcpuregister(list,paraloc.register);
+ end;
+ LOC_MMREGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_mm_imreg then
+ cg.getcpuregister(list,paraloc.register);
+ end;
+ LOC_FPUREGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_fpu_imreg then
+ cg.getcpuregister(list,paraloc.register);
+ end;
+ end;
+ end;
+
+
+ procedure unget_para(const paraloc:TCGParaLocation);
+ begin
+ case paraloc.loc of
+ LOC_REGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_int_imreg then
+ cg.ungetcpuregister(list,paraloc.register);
+ end;
+ LOC_MMREGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_mm_imreg then
+ cg.ungetcpuregister(list,paraloc.register);
+ end;
+ LOC_FPUREGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_fpu_imreg then
+ cg.ungetcpuregister(list,paraloc.register);
+ end;
+ end;
+ end;
+
+
+ procedure gen_load_ref(const paraloc:TCGParaLocation;const ref:treference;sizeleft:aint);
+ var
+ href : treference;
+ begin
+ case paraloc.loc of
+ LOC_REGISTER :
+ cg.a_load_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
+ LOC_MMREGISTER :
+ cg.a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,mms_movescalar);
+ LOC_FPUREGISTER :
+ cg.a_loadfpu_reg_ref(list,paraloc.size,paraloc.register,ref);
+ LOC_REFERENCE :
+ begin
+ reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset);
+ { use concatcopy, because it can also be a float which fails when
+ load_ref_ref is used. Don't copy data when the references are equal }
+ if not((href.base=ref.base) and (href.offset=ref.offset)) then
+ cg.g_concatcopy(list,href,ref,sizeleft);
+ end;
+ else
+ internalerror(2002081302);
+ end;
+ end;
+
+
+ procedure gen_load_reg(const paraloc:TCGParaLocation;reg:tregister);
+ var
+ href : treference;
+ begin
+ case paraloc.loc of
+ LOC_REGISTER :
+ cg.a_load_reg_reg(list,paraloc.size,paraloc.size,paraloc.register,reg);
+ LOC_MMREGISTER :
+ cg.a_loadmm_reg_reg(list,paraloc.size,paraloc.size,paraloc.register,reg,mms_movescalar);
+ LOC_FPUREGISTER :
+ cg.a_loadfpu_reg_reg(list,paraloc.size,paraloc.register,reg);
+ LOC_REFERENCE :
+ begin
+ reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset);
+ case getregtype(reg) of
+ R_INTREGISTER :
+ cg.a_load_ref_reg(list,paraloc.size,paraloc.size,href,reg);
+ R_FPUREGISTER :
+ cg.a_loadfpu_ref_reg(list,paraloc.size,href,reg);
+ R_MMREGISTER :
+ cg.a_loadmm_ref_reg(list,paraloc.size,paraloc.size,href,reg,mms_movescalar);
+ else
+ internalerror(2004101012);
+ end;
+ end;
+ else
+ internalerror(2002081302);
+ end;
+ end;
+
+ var
+ i : longint;
+ currpara : tparavarsym;
+ paraloc : pcgparalocation;
+ href : treference;
+ sizeleft : aint;
+{$ifdef sparc}
+ tempref : treference;
+{$endif sparc}
+ begin
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ exit;
+
+ { Allocate registers used by parameters }
+ for i:=0 to current_procinfo.procdef.paras.count-1 do
+ begin
+ currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+ paraloc:=currpara.paraloc[calleeside].location;
+ while assigned(paraloc) do
+ begin
+ if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then
+ get_para(paraloc^);
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+ { Copy parameters to local references/registers }
+ for i:=0 to current_procinfo.procdef.paras.count-1 do
+ begin
+ currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+ paraloc:=currpara.paraloc[calleeside].location;
+ { skip e.g. empty records }
+ if (paraloc^.loc = LOC_VOID) then
+ continue;
+ if not assigned(paraloc) then
+ internalerror(200408203);
+ case currpara.localloc.loc of
+ LOC_REFERENCE :
+ begin
+ { If the parameter location is reused we don't need to copy
+ anything }
+ if not paramanager.param_use_paraloc(currpara.paraloc[calleeside]) then
+ begin
+ href:=currpara.localloc.reference;
+ sizeleft:=currpara.paraloc[calleeside].intsize;
+ while assigned(paraloc) do
+ begin
+ unget_para(paraloc^);
+ if (paraloc^.size=OS_NO) then
+ begin
+ { Can only be a reference that contains the rest
+ of the parameter }
+ if (paraloc^.loc<>LOC_REFERENCE) or
+ assigned(paraloc^.next) then
+ internalerror(2005013010);
+ gen_load_ref(paraloc^,href,sizeleft);
+ inc(href.offset,sizeleft);
+ sizeleft:=0;
+ end
+ else
+ begin
+ gen_load_ref(paraloc^,href,tcgsize2size[paraloc^.size]);
+ inc(href.offset,TCGSize2Size[paraloc^.size]);
+ dec(sizeleft,TCGSize2Size[paraloc^.size]);
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+ end;
+ LOC_CREGISTER :
+ begin
+{$ifndef cpu64bit}
+ if (currpara.paraloc[calleeside].size in [OS_64,OS_S64]) and
+ is_64bit(currpara.vartype.def) then
+ begin
+ case paraloc^.loc of
+ LOC_REGISTER:
+ begin
+ if not assigned(paraloc^.next) then
+ internalerror(200410104);
+ if (target_info.endian=ENDIAN_BIG) then
+ begin
+ { paraloc^ -> high
+ paraloc^.next -> low }
+ unget_para(paraloc^);
+ gen_load_reg(paraloc^,currpara.localloc.register64.reghi);
+ unget_para(paraloc^.next^);
+ gen_load_reg(paraloc^.next^,currpara.localloc.register64.reglo);
+ end
+ else
+ begin
+ { paraloc^ -> low
+ paraloc^.next -> high }
+ unget_para(paraloc^);
+ gen_load_reg(paraloc^,currpara.localloc.register64.reglo);
+ unget_para(paraloc^.next^);
+ gen_load_reg(paraloc^.next^,currpara.localloc.register64.reghi);
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset);
+ cg64.a_load64_ref_reg(list,href,currpara.localloc.register64);
+ unget_para(paraloc^);
+ end;
+ else
+ internalerror(2005101501);
+ end
+ end
+ else
+{$endif cpu64bit}
+ begin
+ if assigned(paraloc^.next) then
+ internalerror(200410105);
+ unget_para(paraloc^);
+ gen_load_reg(paraloc^,currpara.localloc.register);
+ end;
+ end;
+ LOC_CFPUREGISTER :
+ begin
+{$ifdef sparc}
+ { Sparc passes floats in int registers, when loading to fpu register
+ we need a temp }
+ sizeleft := TCGSize2Size[currpara.localloc.size];
+ tg.GetTemp(list,sizeleft,tt_normal,tempref);
+ href:=tempref;
+ while assigned(paraloc) do
+ begin
+ unget_para(paraloc^);
+ gen_load_ref(paraloc^,href,sizeleft);
+ inc(href.offset,TCGSize2Size[paraloc^.size]);
+ dec(sizeleft,TCGSize2Size[paraloc^.size]);
+ paraloc:=paraloc^.next;
+ end;
+ cg.a_loadfpu_ref_reg(list,currpara.localloc.size,tempref,currpara.localloc.register);
+ tg.UnGetTemp(list,tempref);
+{$else sparc}
+ unget_para(paraloc^);
+ gen_load_reg(paraloc^,currpara.localloc.register);
+ if assigned(paraloc^.next) then
+ internalerror(200410109);
+{$endif sparc}
+ end;
+ LOC_CMMREGISTER :
+ begin
+ unget_para(paraloc^);
+ gen_load_reg(paraloc^,currpara.localloc.register);
+ { data could come in two memory locations, for now
+ we simply ignore the sanity check (FK)
+ if assigned(paraloc^.next) then
+ internalerror(200410108);
+ }
+ end;
+ end;
+ end;
+
+ { generate copies of call by value parameters, must be done before
+ the initialization and body is parsed because the refcounts are
+ incremented using the local copies }
+ current_procinfo.procdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
+{$ifdef powerpc}
+ { unget the register that contains the stack pointer before the procedure entry, }
+ { which is used to access the parameters in their original callee-side location }
+ cg.a_reg_dealloc(list,NR_R12);
+{$endif powerpc}
+ end;
+
+
+ procedure gen_initialize_code(list:TAAsmoutput);
+ begin
+ { initialize local data like ansistrings }
+ case current_procinfo.procdef.proctypeoption of
+ potype_unitinit:
+ begin
+ { this is also used for initialization of variables in a
+ program which does not have a globalsymtable }
+ if assigned(current_module.globalsymtable) then
+ tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
+ tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
+ tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_regvars,list);
+ end;
+ { units have seperate code for initilization and finalization }
+ potype_unitfinalize: ;
+ { program init/final is generated in separate procedure }
+ potype_proginit:
+ begin
+ tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_regvars,list);
+ end;
+ else
+ current_procinfo.procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
+ end;
+
+ { initialisizes temp. ansi/wide string data }
+ inittempvariables(list);
+
+ { initialize ansi/widesstring para's }
+ if not(po_assembler in current_procinfo.procdef.procoptions) then
+ current_procinfo.procdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
+
+{$ifdef OLDREGVARS}
+ load_regvars(list,nil);
+{$endif OLDREGVARS}
+ end;
+
+
+ procedure gen_finalize_code(list:TAAsmoutput);
+ begin
+{$ifdef OLDREGVARS}
+ cleanup_regvars(list);
+{$endif OLDREGVARS}
+
+ { finalize temporary data }
+ finalizetempvariables(list);
+
+ { finalize local data like ansistrings}
+ case current_procinfo.procdef.proctypeoption of
+ potype_unitfinalize:
+ begin
+ { this is also used for initialization of variables in a
+ program which does not have a globalsymtable }
+ if assigned(current_module.globalsymtable) then
+ tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_static_data,list);
+ tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_static_data,list);
+ end;
+ { units/progs have separate code for initialization and finalization }
+ potype_unitinit: ;
+ { program init/final is generated in separate procedure }
+ potype_proginit: ;
+ else
+ current_procinfo.procdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_local_vars,list);
+ end;
+
+ { finalize paras data }
+ if assigned(current_procinfo.procdef.parast) and
+ not(po_assembler in current_procinfo.procdef.procoptions) then
+ current_procinfo.procdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
+ end;
+
+
+ procedure gen_entry_code(list:TAAsmoutput);
+ var
+ paraloc1,
+ paraloc2 : tcgpara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+
+ { the actual profile code can clobber some registers,
+ therefore if the context must be saved, do it before
+ the actual call to the profile code
+ }
+ if (cs_profile in aktmoduleswitches) and
+ not(po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { non-win32 can call mcout even in main }
+ if not (target_info.system in [system_i386_win32,system_i386_wdosx]) or
+ not (current_procinfo.procdef.proctypeoption=potype_proginit) then
+ begin
+ cg.allocallcpuregisters(list);
+ cg.g_profilecode(list);
+ cg.deallocallcpuregisters(list);
+ end;
+ end;
+
+ { call startup helpers from main program }
+ if (current_procinfo.procdef.proctypeoption=potype_proginit) then
+ begin
+ if (target_info.system = system_powerpc_darwin) or
+ (target_info.system = system_powerpc_macos) then
+ begin
+ { the parameters are already in the right registers }
+ cg.a_call_name(list,target_info.cprefix+'FPC_SYSTEMMAIN');
+ end;
+
+ { initialize units }
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_INITIALIZEUNITS');
+ cg.deallocallcpuregisters(list);
+ end;
+
+ list.concat(Tai_force_line.Create);
+
+{$ifdef OLDREGVARS}
+ load_regvars(list,nil);
+{$endif OLDREGVARS}
+
+ paraloc1.done;
+ paraloc2.done;
+ end;
+
+
+ procedure gen_exit_code(list:TAAsmoutput);
+ begin
+ { call __EXIT for main program }
+ if (not DLLsource) and
+ (current_procinfo.procdef.proctypeoption=potype_proginit) then
+ cg.a_call_name(list,'FPC_DO_EXIT');
+ end;
+
+
+{****************************************************************************
+ Entry/Exit
+****************************************************************************}
+
+ procedure gen_proc_symbol(list:Taasmoutput);
+ var
+ hs : string;
+ begin
+ repeat
+ hs:=current_procinfo.procdef.aliasnames.getfirst;
+ if hs='' then
+ break;
+ if (cs_profile in aktmoduleswitches) or
+ (po_global in current_procinfo.procdef.procoptions) then
+ list.concat(Tai_symbol.createname_global(hs,AT_FUNCTION,0))
+ else
+ list.concat(Tai_symbol.createname(hs,AT_FUNCTION,0));
+ if target_info.use_function_relative_addresses then
+ list.concat(Tai_function_name.create(hs));
+ until false;
+
+ current_procinfo.procdef.procstarttai:=tai(list.last);
+ end;
+
+
+
+ procedure gen_proc_symbol_end(list:Taasmoutput);
+ begin
+ if (current_procinfo.procdef.proctypeoption=potype_proginit) then
+ begin
+ { Insert Ident of the compiler in the main .text section }
+ if (not (cs_create_smart in aktmoduleswitches)) then
+ begin
+ list.insert(Tai_align.Create(const_align(32)));
+ list.insert(Tai_string.Create('FPC '+full_version_string+
+ ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname));
+ end;
+
+ { Reference all DEBUGINFO sections from the main .text section }
+ if (cs_debuginfo in aktmoduleswitches) then
+ debuginfo.referencesections(list);
+ end;
+
+ list.concat(Tai_symbol_end.Createname(current_procinfo.procdef.mangledname));
+
+ current_procinfo.procdef.procendtai:=tai(list.last);
+ end;
+
+
+ procedure gen_proc_entry_code(list:Taasmoutput);
+ var
+ hitemp,
+ lotemp : longint;
+ begin
+ { generate call frame marker for dwarf call frame info }
+ dwarfcfi.start_frame(list);
+
+ { All temps are know, write offsets used for information }
+ if (cs_asm_source in aktglobalswitches) then
+ begin
+ if tg.direction>0 then
+ begin
+ lotemp:=current_procinfo.tempstart;
+ hitemp:=tg.lasttemp;
+ end
+ else
+ begin
+ lotemp:=tg.lasttemp;
+ hitemp:=current_procinfo.tempstart;
+ end;
+ list.concat(Tai_comment.Create(strpnew('Temps allocated between '+std_regname(current_procinfo.framepointer)+
+ tostr_with_plus(lotemp)+' and '+std_regname(current_procinfo.framepointer)+tostr_with_plus(hitemp))));
+ end;
+
+ { generate target specific proc entry code }
+ cg.g_proc_entry(list,current_procinfo.calc_stackframe_size,(po_nostackframe in current_procinfo.procdef.procoptions));
+ end;
+
+
+ procedure gen_proc_exit_code(list:Taasmoutput);
+ var
+ parasize : longint;
+ begin
+ { c style clearstack does not need to remove parameters from the stack, only the
+ return value when it was pushed by arguments }
+ if current_procinfo.procdef.proccalloption in clearstack_pocalls then
+ begin
+ parasize:=0;
+ if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption) then
+ inc(parasize,sizeof(aint));
+ end
+ else
+ parasize:=current_procinfo.para_stack_size;
+
+ { generate target specific proc exit code }
+ cg.g_proc_exit(list,parasize,(po_nostackframe in current_procinfo.procdef.procoptions));
+
+ { release return registers, needed for optimizer }
+ if not is_void(current_procinfo.procdef.rettype.def) then
+ location_free(list,current_procinfo.procdef.funcretloc[calleeside]);
+
+ { end of frame marker for call frame info }
+ dwarfcfi.end_frame(list);
+ end;
+
+
+ procedure gen_stack_check_size_para(list:Taasmoutput);
+ var
+ paraloc1 : tcgpara;
+ begin
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(list,paraloc1);
+ cg.a_param_const(list,OS_INT,current_procinfo.calc_stackframe_size,paraloc1);
+ paramanager.freeparaloc(list,paraloc1);
+ paraloc1.done;
+ end;
+
+
+ procedure gen_stack_check_call(list:Taasmoutput);
+ var
+ paraloc1 : tcgpara;
+ begin
+ paraloc1.init;
+ { Also alloc the register needed for the parameter }
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.allocparaloc(list,paraloc1);
+ paramanager.freeparaloc(list,paraloc1);
+ { Call the helper }
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_STACKCHECK');
+ cg.deallocallcpuregisters(list);
+ paraloc1.done;
+ end;
+
+
+ procedure gen_save_used_regs(list:TAAsmoutput);
+ begin
+ { Pure assembler routines need to save the registers themselves }
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ exit;
+
+ { oldfpccall expects all registers to be destroyed }
+ if current_procinfo.procdef.proccalloption<>pocall_oldfpccall then
+ cg.g_save_standard_registers(list);
+ end;
+
+
+ procedure gen_restore_used_regs(list:TAAsmoutput);
+ begin
+ { Pure assembler routines need to save the registers themselves }
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ exit;
+
+ { oldfpccall expects all registers to be destroyed }
+ if current_procinfo.procdef.proccalloption<>pocall_oldfpccall then
+ cg.g_restore_standard_registers(list);
+ end;
+
+
+{****************************************************************************
+ External handling
+****************************************************************************}
+
+ procedure gen_external_stub(list:taasmoutput;pd:tprocdef;const externalname:string);
+ begin
+ { add the procedure to the al_procedures }
+ maybe_new_object_file(list);
+ new_section(list,sec_code,lower(pd.mangledname),aktalignment.procalign);
+ list.concat(Tai_align.create(aktalignment.procalign));
+ if (po_global in pd.procoptions) then
+ list.concat(Tai_symbol.createname_global(pd.mangledname,AT_FUNCTION,0))
+ else
+ list.concat(Tai_symbol.createname(pd.mangledname,AT_FUNCTION,0));
+ cg.a_jmp_name(list,externalname);
+ end;
+
+{****************************************************************************
+ Const Data
+****************************************************************************}
+
+ procedure insertbssdata(sym : tglobalvarsym);
+ var
+ l,varalign : longint;
+ storefilepos : tfileposinfo;
+ list : Taasmoutput;
+ sectype : Tasmsectiontype;
+ begin
+ storefilepos:=aktfilepos;
+ aktfilepos:=sym.fileinfo;
+ l:=sym.getsize;
+ {$ifndef segment_threadvars}
+ if (vo_is_thread_var in sym.varoptions) then
+ inc(l,sizeof(aint));
+ list:=asmlist[al_globals];
+ sectype:=sec_bss;
+ {$else}
+ if (vo_is_thread_var in sym.varoptions) then
+ begin
+ list:=asmlist[al_threadvars];
+ sectype:=sec_threadvar;
+ end
+ else
+ begin
+ list:=asmlist[al_globals];
+ sectype:=sec_bss;
+ end;
+ {$endif}
+ varalign:=var_align(l);
+ maybe_new_object_file(list);
+ new_section(list,sectype,lower(sym.mangledname),varalign);
+ if (sym.owner.symtabletype=globalsymtable) or
+ maybe_smartlink_symbol or
+ DLLSource or
+ (assigned(current_procinfo) and
+ (po_inline in current_procinfo.procdef.procoptions)) or
+ (vo_is_exported in sym.varoptions) or
+ (vo_is_C_var in sym.varoptions) then
+ list.concat(Tai_datablock.create_global(sym.mangledname,l))
+ else
+ list.concat(Tai_datablock.create(sym.mangledname,l));
+ aktfilepos:=storefilepos;
+ end;
+
+
+ procedure gen_alloc_symtable(list:TAAsmoutput;st:tsymtable);
+ var
+ sym : tsym;
+ isaddr : boolean;
+ cgsize : tcgsize;
+ begin
+ sym:=tsym(st.symindex.first);
+ while assigned(sym) do
+ begin
+ if (sym.typ in [globalvarsym,localvarsym,paravarsym]) then
+ begin
+ with tabstractnormalvarsym(sym) do
+ begin
+ { Parameters passed to assembler procedures need to be kept
+ in the original location }
+ if (sym.typ=paravarsym) and
+ (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ tparavarsym(sym).paraloc[calleeside].get_location(localloc);
+ end
+ else
+ begin
+ isaddr:=(st.symtabletype=parasymtable) and
+ paramanager.push_addr_param(varspez,vartype.def,current_procinfo.procdef.proccalloption);
+ if isaddr then
+ cgsize:=OS_ADDR
+ else
+ cgsize:=def_cgsize(vartype.def);
+{$ifndef OLDREGVARS}
+ { When there is assembler code we can't use regvars }
+ if is_regvar then
+ begin
+ localloc.size:=cgsize;
+ case varregable of
+ vr_intreg :
+ begin
+ localloc.loc:=LOC_CREGISTER;
+{$ifndef cpu64bit}
+ if cgsize in [OS_64,OS_S64] then
+ begin
+ localloc.register64.reglo:=cg.getintregister(list,OS_32);
+ localloc.register64.reghi:=cg.getintregister(list,OS_32);
+ end
+ else
+{$endif cpu64bit}
+ localloc.register:=cg.getintregister(list,cgsize);
+ end;
+ vr_fpureg :
+ begin
+ localloc.loc:=LOC_CFPUREGISTER;
+ localloc.register:=cg.getfpuregister(list,cgsize);
+ end;
+ vr_mmreg :
+ begin
+ localloc.loc:=LOC_CMMREGISTER;
+ localloc.register:=cg.getmmregister(list,cgsize);
+ end;
+ else
+ internalerror(2004101010);
+ end;
+ { Allocate register already, to prevent first allocation to be
+ inside a loop }
+{$ifndef cpu64bit}
+ if cgsize in [OS_64,OS_S64] then
+ begin
+ cg.a_reg_sync(list,localloc.register64.reglo);
+ cg.a_reg_sync(list,localloc.register64.reghi);
+ end
+ else
+{$endif cpu64bit}
+ cg.a_reg_sync(list,localloc.register);
+ end
+ else
+{$endif NOT OLDREGVARS}
+ begin
+ localloc.loc:=LOC_REFERENCE;
+ localloc.size:=cgsize;
+ case st.symtabletype of
+ parasymtable :
+ begin
+ { Reuse the parameter location for values to are at a single location on the stack }
+ if paramanager.param_use_paraloc(tparavarsym(sym).paraloc[calleeside]) then
+ begin
+ reference_reset_base(localloc.reference,tparavarsym(sym).paraloc[calleeside].location^.reference.index,
+ tparavarsym(sym).paraloc[calleeside].location^.reference.offset);
+ end
+ else
+ begin
+ if isaddr then
+ tg.GetLocal(list,sizeof(aint),voidpointertype.def,localloc.reference)
+ else
+ tg.GetLocal(list,getsize,vartype.def,localloc.reference);
+ end;
+ end;
+ localsymtable,
+ stt_exceptsymtable :
+ begin
+ tg.GetLocal(list,getsize,vartype.def,localloc.reference);
+ end;
+ staticsymtable :
+ begin
+ { PIC, DLL and Threadvar need extra code and are handled in ncgld }
+ if not((target_info.system=system_powerpc_darwin) and
+ (cs_create_pic in aktmoduleswitches)) and
+ not(vo_is_dll_var in varoptions) {$ifndef segment_threadvars} and
+ not(vo_is_thread_var in varoptions) {$endif} then
+ reference_reset_symbol(localloc.reference,objectlibrary.newasmsymbol(mangledname,AB_EXTERNAL,AT_DATA),0);
+ end;
+ else
+ internalerror(200410103);
+ end;
+ end;
+ end;
+ if cs_asm_source in aktglobalswitches then
+ begin
+ case localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ if (cs_no_regalloc in aktglobalswitches) then
+ list.concat(Tai_comment.Create(strpnew('Var '+realname+' located in register '+
+ std_regname(localloc.register))))
+ else
+ list.concat(Tai_comment.Create(strpnew('Var '+realname+' located in register')));
+ end;
+ LOC_REFERENCE :
+ begin
+ if not assigned(localloc.reference.symbol) then
+ list.concat(Tai_comment.Create(strpnew('Var '+realname+' located at '+
+ std_regname(localloc.reference.base)+tostr_with_plus(localloc.reference.offset))));
+ end;
+ end;
+ end;
+ end;
+ end;
+ sym:=tsym(sym.indexnext);
+ end;
+ end;
+
+
+ procedure gen_free_symtable(list:TAAsmoutput;st:tsymtable);
+ var
+ sym : tsym;
+ begin
+ sym:=tsym(st.symindex.first);
+ while assigned(sym) do
+ begin
+ if (sym.typ in [globalvarsym,localvarsym,paravarsym]) then
+ begin
+ with tabstractnormalvarsym(sym) do
+ begin
+ { Note: We need to keep the data available in memory
+ for the sub procedures that can access local data
+ in the parent procedures }
+ case localloc.loc of
+ LOC_CREGISTER :
+{$ifndef cpu64bit}
+ if def_cgsize(vartype.def) in [OS_64,OS_S64] then
+ begin
+ cg.a_reg_sync(list,localloc.register64.reglo);
+ cg.a_reg_sync(list,localloc.register64.reghi);
+ end
+ else
+{$endif cpu64bit}
+ cg.a_reg_sync(list,localloc.register);
+ LOC_REFERENCE :
+ begin
+ case st.symtabletype of
+ localsymtable,
+ parasymtable,
+ stt_exceptsymtable :
+ tg.Ungetlocal(list,localloc.reference);
+ end;
+ end;
+ end;
+ end;
+ end;
+ sym:=tsym(sym.indexnext);
+ end;
+ end;
+
+
+ { persistent rtti generation }
+ procedure generate_rtti(p:Ttypesym);
+ var
+ rsym : trttisym;
+ def : tstoreddef;
+ begin
+ { rtti can only be generated for classes that are always typesyms }
+ def:=tstoreddef(ttypesym(p).restype.def);
+ { there is an error, skip rtti info }
+ if (def.deftype=errordef) or (Errorcount>0) then
+ exit;
+ { only create rtti once for each definition }
+ if not(df_has_rttitable in def.defoptions) then
+ begin
+ { definition should be in the same symtable as the symbol }
+ if p.owner<>def.owner then
+ internalerror(200108262);
+ { create rttisym }
+ rsym:=trttisym.create(p.name,fullrtti);
+ p.owner.insert(rsym);
+ { register rttisym in definition }
+ include(def.defoptions,df_has_rttitable);
+ def.rttitablesym:=rsym;
+ { write rtti data }
+ def.write_child_rtti_data(fullrtti);
+ maybe_new_object_file(asmlist[al_rtti]);
+ new_section(asmlist[al_rtti],sec_rodata,rsym.get_label.name,const_align(sizeof(aint)));
+ asmlist[al_rtti].concat(Tai_symbol.Create_global(rsym.get_label,0));
+ def.write_rtti_data(fullrtti);
+ asmlist[al_rtti].concat(Tai_symbol_end.Create(rsym.get_label));
+ end;
+ end;
+
+
+ { persistent init table generation }
+ procedure generate_inittable(p:tsym);
+ var
+ rsym : trttisym;
+ def : tstoreddef;
+ begin
+ { anonymous types are also allowed for records that can be varsym }
+ case p.typ of
+ typesym :
+ def:=tstoreddef(ttypesym(p).restype.def);
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ def:=tstoreddef(tabstractvarsym(p).vartype.def);
+ else
+ internalerror(200108263);
+ end;
+ { only create inittable once for each definition }
+ if not(df_has_inittable in def.defoptions) then
+ begin
+ { definition should be in the same symtable as the symbol }
+ if p.owner<>def.owner then
+ internalerror(200108264);
+ { create rttisym }
+ rsym:=trttisym.create(p.name,initrtti);
+ p.owner.insert(rsym);
+ { register rttisym in definition }
+ include(def.defoptions,df_has_inittable);
+ def.inittablesym:=rsym;
+ { write inittable data }
+ def.write_child_rtti_data(initrtti);
+ maybe_new_object_file(asmlist[al_rtti]);
+ new_section(asmlist[al_rtti],sec_rodata,rsym.get_label.name,const_align(sizeof(aint)));
+ asmlist[al_rtti].concat(Tai_symbol.Create_global(rsym.get_label,0));
+ def.write_rtti_data(initrtti);
+ asmlist[al_rtti].concat(Tai_symbol_end.Create(rsym.get_label));
+ end;
+ end;
+
+
+
+ procedure gen_intf_wrapper(list:taasmoutput;_class:tobjectdef);
+ var
+ i,j,
+ proccount : longint;
+ tmps : string;
+ begin
+ for i:=1 to _class.implementedinterfaces.count do
+ begin
+ { only if implemented by this class }
+ if _class.implementedinterfaces.implindex(i)=i then
+ begin
+ proccount:=_class.implementedinterfaces.implproccount(i);
+ for j:=1 to proccount do
+ begin
+ tmps:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+
+ _class.implementedinterfaces.interfaces(i).objname^+'_$_'+
+ tostr(j)+'_$_'+_class.implementedinterfaces.implprocs(i,j).mangledname);
+ { create wrapper code }
+ new_section(list,sec_code,lower(tmps),0);
+ cg.g_intf_wrapper(list,_class.implementedinterfaces.implprocs(i,j),tmps,_class.implementedinterfaces.ioffsets(i));
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure gen_intf_wrappers(list:taasmoutput;st:tsymtable);
+ var
+ def : tstoreddef;
+ begin
+ def:=tstoreddef(st.defindex.first);
+ while assigned(def) do
+ begin
+ if is_class(def) then
+ gen_intf_wrapper(list,tobjectdef(def));
+ def:=tstoreddef(def.indexnext);
+ end;
+ end;
+
+
+ procedure gen_load_vmt_register(list:taasmoutput;objdef:tobjectdef;selfloc:tlocation;var vmtreg:tregister);
+ var
+ href : treference;
+ begin
+ if is_object(objdef) then
+ begin
+ case selfloc.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(href,cg.getaddressregister(list),objdef.vmt_offset);
+ cg.a_loadaddr_ref_reg(list,selfloc.reference,href.base);
+ end;
+ else
+ internalerror(200305056);
+ end;
+ end
+ else
+ begin
+ case selfloc.loc of
+ LOC_REGISTER:
+ begin
+{$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ reference_reset_base(href,cg.getaddressregister(list),objdef.vmt_offset);
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,selfloc.register,href.base);
+ end
+ else
+{$endif cpu_uses_separate_address_registers}
+ reference_reset_base(href,selfloc.register,objdef.vmt_offset);
+ end;
+ LOC_CREGISTER,
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(href,cg.getaddressregister(list),objdef.vmt_offset);
+ cg.a_load_loc_reg(list,OS_ADDR,selfloc,href.base);
+ end;
+ else
+ internalerror(200305057);
+ end;
+ end;
+ vmtreg:=cg.getaddressregister(list);
+ cg.g_maybe_testself(list,href.base);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,vmtreg);
+ end;
+
+end.
diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas
new file mode 100644
index 0000000000..3fcb23a15a
--- /dev/null
+++ b/compiler/ncnv.pas
@@ -0,0 +1,2687 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for type converting 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 ncnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,
+ symtype,
+ defutil,defcmp,
+ nld
+ ;
+
+ type
+ ttypeconvnode = class(tunarynode)
+ totype : ttype;
+ convtype : tconverttype;
+ constructor create(node : tnode;const t : ttype);virtual;
+ constructor create_explicit(node : tnode;const t : ttype);
+ constructor create_internal(node : tnode;const t : ttype);
+ constructor create_proc_to_procvar(node : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ procedure printnodeinfo(var t : text);override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ procedure mark_write;override;
+ function docompare(p: tnode) : boolean; override;
+ function assign_allowed:boolean;
+ procedure second_call_helper(c : tconverttype);
+ private
+ function resulttype_int_to_int : tnode;
+ function resulttype_cord_to_pointer : tnode;
+ function resulttype_chararray_to_string : tnode;
+ function resulttype_string_to_chararray : tnode;
+ function resulttype_string_to_string : tnode;
+ function resulttype_char_to_string : tnode;
+ function resulttype_char_to_chararray : tnode;
+ function resulttype_int_to_real : tnode;
+ function resulttype_real_to_real : tnode;
+ function resulttype_real_to_currency : tnode;
+ function resulttype_cchar_to_pchar : tnode;
+ function resulttype_cstring_to_pchar : tnode;
+ function resulttype_cstring_to_int : tnode;
+ function resulttype_char_to_char : tnode;
+ function resulttype_arrayconstructor_to_set : tnode;
+ function resulttype_pchar_to_string : tnode;
+ function resulttype_interface_to_guid : tnode;
+ function resulttype_dynarray_to_openarray : tnode;
+ function resulttype_pwchar_to_string : tnode;
+ function resulttype_variant_to_dynarray : tnode;
+ function resulttype_dynarray_to_variant : tnode;
+ function resulttype_call_helper(c : tconverttype) : tnode;
+ function resulttype_variant_to_enum : tnode;
+ function resulttype_enum_to_variant : tnode;
+ function resulttype_proc_to_procvar : tnode;
+ function resulttype_variant_to_interface : tnode;
+ function resulttype_interface_to_variant : tnode;
+ function resulttype_array_2_dynarray : tnode;
+ protected
+ function first_int_to_int : tnode;virtual;
+ function first_cstring_to_pchar : tnode;virtual;
+ function first_cstring_to_int : tnode;virtual;
+ function first_string_to_chararray : tnode;virtual;
+ function first_char_to_string : tnode;virtual;
+ function first_nothing : tnode;virtual;
+ function first_array_to_pointer : tnode;virtual;
+ function first_int_to_real : tnode;virtual;
+ function first_real_to_real : tnode;virtual;
+ function first_pointer_to_array : tnode;virtual;
+ function first_cchar_to_pchar : tnode;virtual;
+ function first_bool_to_int : tnode;virtual;
+ function first_int_to_bool : tnode;virtual;
+ function first_bool_to_bool : tnode;virtual;
+ function first_proc_to_procvar : tnode;virtual;
+ function first_load_smallset : tnode;virtual;
+ function first_cord_to_pointer : tnode;virtual;
+ function first_ansistring_to_pchar : tnode;virtual;
+ function first_arrayconstructor_to_set : tnode;virtual;
+ function first_class_to_intf : tnode;virtual;
+ function first_char_to_char : tnode;virtual;
+ function first_call_helper(c : tconverttype) : tnode;
+
+ { these wrapper are necessary, because the first_* stuff is called }
+ { through a table. Without the wrappers override wouldn't have }
+ { any effect }
+ function _first_int_to_int : tnode;
+ function _first_cstring_to_pchar : tnode;
+ function _first_cstring_to_int : tnode;
+ function _first_string_to_chararray : tnode;
+ function _first_char_to_string : tnode;
+ function _first_nothing : tnode;
+ function _first_array_to_pointer : tnode;
+ function _first_int_to_real : tnode;
+ function _first_real_to_real: tnode;
+ function _first_pointer_to_array : tnode;
+ function _first_cchar_to_pchar : tnode;
+ function _first_bool_to_int : tnode;
+ function _first_int_to_bool : tnode;
+ function _first_bool_to_bool : tnode;
+ function _first_proc_to_procvar : tnode;
+ function _first_load_smallset : tnode;
+ function _first_cord_to_pointer : tnode;
+ function _first_ansistring_to_pchar : tnode;
+ function _first_arrayconstructor_to_set : tnode;
+ function _first_class_to_intf : tnode;
+ function _first_char_to_char : tnode;
+
+ procedure _second_int_to_int;virtual;
+ procedure _second_string_to_string;virtual;
+ procedure _second_cstring_to_pchar;virtual;
+ procedure _second_cstring_to_int;virtual;
+ procedure _second_string_to_chararray;virtual;
+ procedure _second_array_to_pointer;virtual;
+ procedure _second_pointer_to_array;virtual;
+ procedure _second_chararray_to_string;virtual;
+ procedure _second_char_to_string;virtual;
+ procedure _second_int_to_real;virtual;
+ procedure _second_real_to_real;virtual;
+ procedure _second_cord_to_pointer;virtual;
+ procedure _second_proc_to_procvar;virtual;
+ procedure _second_bool_to_int;virtual;
+ procedure _second_int_to_bool;virtual;
+ procedure _second_bool_to_bool;virtual;
+ procedure _second_load_smallset;virtual;
+ procedure _second_ansistring_to_pchar;virtual;
+ procedure _second_class_to_intf;virtual;
+ procedure _second_char_to_char;virtual;
+ procedure _second_nothing; virtual;
+
+ procedure second_int_to_int;virtual;abstract;
+ procedure second_string_to_string;virtual;abstract;
+ procedure second_cstring_to_pchar;virtual;abstract;
+ procedure second_cstring_to_int;virtual;abstract;
+ procedure second_string_to_chararray;virtual;abstract;
+ procedure second_array_to_pointer;virtual;abstract;
+ procedure second_pointer_to_array;virtual;abstract;
+ procedure second_chararray_to_string;virtual;abstract;
+ procedure second_char_to_string;virtual;abstract;
+ procedure second_int_to_real;virtual;abstract;
+ procedure second_real_to_real;virtual;abstract;
+ procedure second_cord_to_pointer;virtual;abstract;
+ procedure second_proc_to_procvar;virtual;abstract;
+ procedure second_bool_to_int;virtual;abstract;
+ procedure second_int_to_bool;virtual;abstract;
+ procedure second_bool_to_bool;virtual;abstract;
+ procedure second_load_smallset;virtual;abstract;
+ procedure second_ansistring_to_pchar;virtual;abstract;
+ procedure second_class_to_intf;virtual;abstract;
+ procedure second_char_to_char;virtual;abstract;
+ procedure second_nothing; virtual;abstract;
+ end;
+ ttypeconvnodeclass = class of ttypeconvnode;
+
+ tasnode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function _getcopy: tnode;override;
+ destructor destroy; override;
+ protected
+ call: tnode;
+ end;
+ tasnodeclass = class of tasnode;
+
+ tisnode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ procedure pass_2;override;
+ end;
+ tisnodeclass = class of tisnode;
+
+ var
+ ctypeconvnode : ttypeconvnodeclass;
+ casnode : tasnodeclass;
+ cisnode : tisnodeclass;
+
+ procedure inserttypeconv(var p:tnode;const t:ttype);
+ procedure inserttypeconv_internal(var p:tnode;const t:ttype);
+ procedure arrayconstructor_to_set(var p : tnode);
+
+
+implementation
+
+ uses
+ cclasses,globtype,systems,
+ cutils,verbose,globals,widestr,
+ symconst,symdef,symsym,symbase,symtable,
+ ncon,ncal,nset,nadd,ninl,nmem,nmat,nbas,nutils,
+ cgbase,procinfo,
+ htypechk,pass_1,cpuinfo;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure inserttypeconv(var p:tnode;const t:ttype);
+
+ begin
+ if not assigned(p.resulttype.def) then
+ begin
+ resulttypepass(p);
+ if codegenerror then
+ exit;
+ end;
+
+ { don't insert obsolete type conversions }
+ if equal_defs(p.resulttype.def,t.def) and
+ not ((p.resulttype.def.deftype=setdef) and
+ (tsetdef(p.resulttype.def).settype <>
+ tsetdef(t.def).settype)) then
+ begin
+ p.resulttype:=t;
+ end
+ else
+ begin
+ p:=ctypeconvnode.create(p,t);
+ resulttypepass(p);
+ end;
+ end;
+
+
+ procedure inserttypeconv_internal(var p:tnode;const t:ttype);
+
+ begin
+ if not assigned(p.resulttype.def) then
+ begin
+ resulttypepass(p);
+ if codegenerror then
+ exit;
+ end;
+
+ { don't insert obsolete type conversions }
+ if equal_defs(p.resulttype.def,t.def) and
+ not ((p.resulttype.def.deftype=setdef) and
+ (tsetdef(p.resulttype.def).settype <>
+ tsetdef(t.def).settype)) then
+ begin
+ p.resulttype:=t;
+ end
+ else
+ begin
+ p:=ctypeconvnode.create_internal(p,t);
+ resulttypepass(p);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Array constructor to Set Conversion
+*****************************************************************************}
+
+ procedure arrayconstructor_to_set(var p : tnode);
+
+ var
+ constp : tsetconstnode;
+ buildp,
+ p2,p3,p4 : tnode;
+ htype : ttype;
+ constset : Pconstset;
+ constsetlo,
+ constsethi : TConstExprInt;
+
+ procedure update_constsethi(t:ttype);
+ begin
+ if ((t.def.deftype=orddef) and
+ (torddef(t.def).high>=constsethi)) then
+ begin
+ if torddef(t.def).typ=uwidechar then
+ begin
+ constsethi:=255;
+ if htype.def=nil then
+ htype:=t;
+ end
+ else
+ begin
+ constsethi:=torddef(t.def).high;
+ if htype.def=nil then
+ begin
+ if (constsethi>255) or
+ (torddef(t.def).low<0) then
+ htype:=u8inttype
+ else
+ htype:=t;
+ end;
+ if constsethi>255 then
+ constsethi:=255;
+ end;
+ end
+ else if ((t.def.deftype=enumdef) and
+ (tenumdef(t.def).max>=constsethi)) then
+ begin
+ if htype.def=nil then
+ htype:=t;
+ constsethi:=tenumdef(t.def).max;
+ end;
+ end;
+
+ procedure do_set(pos : longint);
+ begin
+ if (pos and not $ff)<>0 then
+ Message(parser_e_illegal_set_expr);
+ if pos>constsethi then
+ constsethi:=pos;
+ if pos<constsetlo then
+ constsetlo:=pos;
+ if pos in constset^ then
+ Message(parser_e_illegal_set_expr);
+ include(constset^,pos);
+ end;
+
+ var
+ l : Longint;
+ lr,hr : TConstExprInt;
+ hp : tarrayconstructornode;
+ begin
+ if p.nodetype<>arrayconstructorn then
+ internalerror(200205105);
+ new(constset);
+ constset^:=[];
+ htype.reset;
+ constsetlo:=0;
+ constsethi:=0;
+ constp:=csetconstnode.create(nil,htype);
+ constp.value_set:=constset;
+ buildp:=constp;
+ hp:=tarrayconstructornode(p);
+ if assigned(hp.left) then
+ begin
+ while assigned(hp) do
+ begin
+ p4:=nil; { will contain the tree to create the set }
+ {split a range into p2 and p3 }
+ if hp.left.nodetype=arrayconstructorrangen then
+ begin
+ p2:=tarrayconstructorrangenode(hp.left).left;
+ p3:=tarrayconstructorrangenode(hp.left).right;
+ tarrayconstructorrangenode(hp.left).left:=nil;
+ tarrayconstructorrangenode(hp.left).right:=nil;
+ end
+ else
+ begin
+ p2:=hp.left;
+ hp.left:=nil;
+ p3:=nil;
+ end;
+ resulttypepass(p2);
+ set_varstate(p2,vs_used,[vsf_must_be_valid]);
+ if assigned(p3) then
+ begin
+ resulttypepass(p3);
+ set_varstate(p3,vs_used,[vsf_must_be_valid]);
+ end;
+ if codegenerror then
+ break;
+ case p2.resulttype.def.deftype of
+ enumdef,
+ orddef:
+ begin
+ getrange(p2.resulttype.def,lr,hr);
+ if assigned(p3) then
+ begin
+ { this isn't good, you'll get problems with
+ type t010 = 0..10;
+ ts = set of t010;
+ var s : ts;b : t010
+ begin s:=[1,2,b]; end.
+ if is_integer(p3^.resulttype.def) then
+ begin
+ inserttypeconv(p3,u8bitdef);
+ end;
+ }
+ if assigned(htype.def) and not(equal_defs(htype.def,p3.resulttype.def)) then
+ begin
+ aktfilepos:=p3.fileinfo;
+ CGMessage(type_e_typeconflict_in_set);
+ end
+ else
+ begin
+ if (p2.nodetype=ordconstn) and (p3.nodetype=ordconstn) then
+ begin
+ if not(is_integer(p3.resulttype.def)) then
+ htype:=p3.resulttype
+ else
+ begin
+ inserttypeconv(p3,u8inttype);
+ inserttypeconv(p2,u8inttype);
+ end;
+
+ for l:=tordconstnode(p2).value to tordconstnode(p3).value do
+ do_set(l);
+ p2.free;
+ p3.free;
+ end
+ else
+ begin
+ update_constsethi(p2.resulttype);
+ inserttypeconv(p2,htype);
+
+ update_constsethi(p3.resulttype);
+ inserttypeconv(p3,htype);
+
+ if assigned(htype.def) then
+ inserttypeconv(p3,htype)
+ else
+ inserttypeconv(p3,u8inttype);
+ p4:=csetelementnode.create(p2,p3);
+ end;
+ end;
+ end
+ else
+ begin
+ { Single value }
+ if p2.nodetype=ordconstn then
+ begin
+ if not(is_integer(p2.resulttype.def)) then
+ begin
+ { for constant set elements, delphi allows the usage of elements of enumerations which
+ have value>255 if there is no element with a value > 255 used }
+ if (m_delphi in aktmodeswitches) and (p2.resulttype.def.deftype=enumdef) then
+ begin
+ if tordconstnode(p2).value>constsethi then
+ constsethi:=tordconstnode(p2).value;
+ if htype.def=nil then
+ htype:=p2.resulttype;
+ end
+ else
+ update_constsethi(p2.resulttype);
+ end;
+
+ if assigned(htype.def) then
+ inserttypeconv(p2,htype)
+ else
+ inserttypeconv(p2,u8inttype);
+
+ do_set(tordconstnode(p2).value);
+ p2.free;
+ end
+ else
+ begin
+ update_constsethi(p2.resulttype);
+
+ if assigned(htype.def) then
+ inserttypeconv(p2,htype)
+ else
+ inserttypeconv(p2,u8inttype);
+
+ p4:=csetelementnode.create(p2,nil);
+ end;
+ end;
+ end;
+
+ stringdef :
+ begin
+ { if we've already set elements which are constants }
+ { throw an error }
+ if ((htype.def=nil) and assigned(buildp)) or
+ not(is_char(htype.def)) then
+ CGMessage(type_e_typeconflict_in_set)
+ else
+ for l:=1 to length(pstring(tstringconstnode(p2).value_str)^) do
+ do_set(ord(pstring(tstringconstnode(p2).value_str)^[l]));
+ if htype.def=nil then
+ htype:=cchartype;
+ p2.free;
+ end;
+
+ else
+ CGMessage(type_e_ordinal_expr_expected);
+ end;
+ { insert the set creation tree }
+ if assigned(p4) then
+ buildp:=caddnode.create(addn,buildp,p4);
+ { load next and dispose current node }
+ p2:=hp;
+ hp:=tarrayconstructornode(tarrayconstructornode(p2).right);
+ tarrayconstructornode(p2).right:=nil;
+ p2.free;
+ end;
+ if (htype.def=nil) then
+ htype:=u8inttype;
+ end
+ else
+ begin
+ { empty set [], only remove node }
+ p.free;
+ end;
+ { set the initial set type }
+ constp.resulttype.setdef(tsetdef.create(htype,constsethi));
+ { determine the resulttype for the tree }
+ resulttypepass(buildp);
+ { set the new tree }
+ p:=buildp;
+ end;
+
+
+{*****************************************************************************
+ TTYPECONVNODE
+*****************************************************************************}
+
+
+ constructor ttypeconvnode.create(node : tnode;const t:ttype);
+
+ begin
+ inherited create(typeconvn,node);
+ convtype:=tc_none;
+ totype:=t;
+ if t.def=nil then
+ internalerror(200103281);
+ fileinfo:=node.fileinfo;
+ end;
+
+
+ constructor ttypeconvnode.create_explicit(node : tnode;const t:ttype);
+
+ begin
+ self.create(node,t);
+ include(flags,nf_explicit);
+ end;
+
+
+ constructor ttypeconvnode.create_internal(node : tnode;const t:ttype);
+
+ begin
+ self.create(node,t);
+ { handle like explicit conversions }
+ include(flags,nf_explicit);
+ include(flags,nf_internal);
+ end;
+
+
+ constructor ttypeconvnode.create_proc_to_procvar(node : tnode);
+
+ begin
+ self.create(node,voidtype);
+ convtype:=tc_proc_2_procvar;
+ end;
+
+
+ constructor ttypeconvnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.gettype(totype);
+ convtype:=tconverttype(ppufile.getbyte);
+ end;
+
+
+ procedure ttypeconvnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(totype);
+ ppufile.putbyte(byte(convtype));
+ end;
+
+
+ procedure ttypeconvnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ totype.buildderef;
+ end;
+
+
+ procedure ttypeconvnode.derefimpl;
+ begin
+ inherited derefimpl;
+ totype.resolve;
+ end;
+
+
+ function ttypeconvnode._getcopy : tnode;
+ var
+ n : ttypeconvnode;
+ begin
+ n:=ttypeconvnode(inherited _getcopy);
+ n.convtype:=convtype;
+ n.totype:=totype;
+ _getcopy:=n;
+ end;
+
+ procedure ttypeconvnode.printnodeinfo(var t : text);
+ const
+ convtyp2str : array[tconverttype] of pchar = (
+ 'tc_none',
+ 'tc_equal',
+ 'tc_not_possible',
+ 'tc_string_2_string',
+ 'tc_char_2_string',
+ 'tc_char_2_chararray',
+ 'tc_pchar_2_string',
+ 'tc_cchar_2_pchar',
+ 'tc_cstring_2_pchar',
+ 'tc_cstring_2_int',
+ 'tc_ansistring_2_pchar',
+ 'tc_string_2_chararray',
+ 'tc_chararray_2_string',
+ 'tc_array_2_pointer',
+ 'tc_pointer_2_array',
+ 'tc_int_2_int',
+ 'tc_int_2_bool',
+ 'tc_bool_2_bool',
+ 'tc_bool_2_int',
+ 'tc_real_2_real',
+ 'tc_int_2_real',
+ 'tc_real_2_currency',
+ 'tc_proc_2_procvar',
+ 'tc_arrayconstructor_2_set',
+ 'tc_load_smallset',
+ 'tc_cord_2_pointer',
+ 'tc_intf_2_string',
+ 'tc_intf_2_guid',
+ 'tc_class_2_intf',
+ 'tc_char_2_char',
+ 'tc_normal_2_smallset',
+ 'tc_dynarray_2_openarray',
+ 'tc_pwchar_2_string',
+ 'tc_variant_2_dynarray',
+ 'tc_dynarray_2_variant',
+ 'tc_variant_2_enum',
+ 'tc_enum_2_variant',
+ 'tc_interface_2_variant',
+ 'tc_variant_2_interface',
+ 'tc_array_2_dynarray'
+ );
+ begin
+ inherited printnodeinfo(t);
+ write(t,', convtype = ',strpas(convtyp2str[convtype]));
+ end;
+
+
+ function ttypeconvnode.resulttype_cord_to_pointer : tnode;
+
+ var
+ t : tnode;
+
+ begin
+ result:=nil;
+ if left.nodetype=ordconstn then
+ begin
+ { check if we have a valid pointer constant (JM) }
+ if (sizeof(pointer) > sizeof(TConstPtrUInt)) then
+ if (sizeof(TConstPtrUInt) = 4) then
+ begin
+ if (tordconstnode(left).value < low(longint)) or
+ (tordconstnode(left).value > high(cardinal)) then
+ CGMessage(parser_e_range_check_error);
+ end
+ else if (sizeof(TConstPtrUInt) = 8) then
+ begin
+ if (tordconstnode(left).value < low(int64)) or
+ (tordconstnode(left).value > high(qword)) then
+ CGMessage(parser_e_range_check_error);
+ end
+ else
+ internalerror(2001020801);
+ t:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value),resulttype);
+ result:=t;
+ end
+ else
+ internalerror(200104023);
+ end;
+
+
+ function ttypeconvnode.resulttype_chararray_to_string : tnode;
+ var
+ chartype : string[8];
+ begin
+ if is_widechar(tarraydef(left.resulttype.def).elementtype.def) then
+ chartype:='widechar'
+ else
+ chartype:='char';
+ result := ccallnode.createinternres(
+ 'fpc_'+chartype+'array_to_'+tstringdef(resulttype.def).stringtypname,
+ ccallparanode.create(left,nil),resulttype);
+ left := nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_string_to_chararray : tnode;
+ var
+ arrsize : aint;
+ chartype : string[8];
+ begin
+ result := nil;
+ with tarraydef(resulttype.def) do
+ begin
+ if highrange<lowrange then
+ internalerror(200501051);
+ arrsize := highrange-lowrange+1;
+ end;
+ if (left.nodetype = stringconstn) and
+ (tstringdef(left.resulttype.def).string_typ=st_conststring) then
+ begin
+ { if the array of char is large enough we can use the string
+ constant directly. This is handled in ncgcnv }
+ if (arrsize>=tstringconstnode(left).len) and
+ is_char(tarraydef(resulttype.def).elementtype.def) then
+ exit;
+ { Convert to wide/short/ansistring and call default helper }
+ if is_widechar(tarraydef(resulttype.def).elementtype.def) then
+ inserttypeconv(left,cwidestringtype)
+ else
+ begin
+ if tstringconstnode(left).len>255 then
+ inserttypeconv(left,cansistringtype)
+ else
+ inserttypeconv(left,cshortstringtype);
+ end;
+ end;
+ if is_widechar(tarraydef(resulttype.def).elementtype.def) then
+ chartype:='widechar'
+ else
+ chartype:='char';
+ result := ccallnode.createinternres(
+ 'fpc_'+tstringdef(left.resulttype.def).stringtypname+
+ '_to_'+chartype+'array',ccallparanode.create(left,ccallparanode.create(
+ cordconstnode.create(arrsize,s32inttype,true),nil)),resulttype);
+ left := nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_string_to_string : tnode;
+
+ var
+ procname: string[31];
+ stringpara : tcallparanode;
+
+ begin
+ result:=nil;
+ if left.nodetype=stringconstn then
+ begin
+ tstringconstnode(left).changestringtype(resulttype);
+ result:=left;
+ left:=nil;
+ end
+ else
+ begin
+ { get the correct procedure name }
+ procname := 'fpc_'+tstringdef(left.resulttype.def).stringtypname+
+ '_to_'+tstringdef(resulttype.def).stringtypname;
+
+ { create parameter (and remove left node from typeconvnode }
+ { since it's reused as parameter) }
+ stringpara := ccallparanode.create(left,nil);
+ left := nil;
+
+ { when converting to shortstrings, we have to pass high(destination) too }
+ if (tstringdef(resulttype.def).string_typ = st_shortstring) then
+ stringpara.right := ccallparanode.create(cinlinenode.create(
+ in_high_x,false,self.getcopy),nil);
+
+ { and create the callnode }
+ result := ccallnode.createinternres(procname,stringpara,resulttype);
+ end;
+ end;
+
+
+ function ttypeconvnode.resulttype_char_to_string : tnode;
+
+ var
+ procname: string[31];
+ para : tcallparanode;
+ hp : tstringconstnode;
+ ws : pcompilerwidestring;
+
+ begin
+ result:=nil;
+ if left.nodetype=ordconstn then
+ begin
+ if tstringdef(resulttype.def).string_typ=st_widestring then
+ begin
+ initwidestring(ws);
+ if torddef(left.resulttype.def).typ=uwidechar then
+ concatwidestringchar(ws,tcompilerwidechar(tordconstnode(left).value))
+ else
+ concatwidestringchar(ws,tcompilerwidechar(chr(tordconstnode(left).value)));
+ hp:=cstringconstnode.createwstr(ws);
+ donewidestring(ws);
+ end
+ else
+ hp:=cstringconstnode.createstr(chr(tordconstnode(left).value),tstringdef(resulttype.def).string_typ);
+ result:=hp;
+ end
+ else
+ { shortstrings are handled 'inline' }
+ if tstringdef(resulttype.def).string_typ <> st_shortstring then
+ begin
+ { create the parameter }
+ para := ccallparanode.create(left,nil);
+ left := nil;
+
+ { and the procname }
+ procname := 'fpc_char_to_' +tstringdef(resulttype.def).stringtypname;
+
+ { and finally the call }
+ result := ccallnode.createinternres(procname,para,resulttype);
+ end
+ else
+ begin
+ { create word(byte(char) shl 8 or 1) for litte endian machines }
+ { and word(byte(char) or 256) for big endian machines }
+ left := ctypeconvnode.create_internal(left,u8inttype);
+ if (target_info.endian = endian_little) then
+ left := caddnode.create(orn,
+ cshlshrnode.create(shln,left,cordconstnode.create(8,s32inttype,false)),
+ cordconstnode.create(1,s32inttype,false))
+ else
+ left := caddnode.create(orn,left,
+ cordconstnode.create(1 shl 8,s32inttype,false));
+ left := ctypeconvnode.create_internal(left,u16inttype);
+ resulttypepass(left);
+ end;
+ end;
+
+
+ function ttypeconvnode.resulttype_char_to_chararray : tnode;
+
+ begin
+ if resulttype.def.size <> 1 then
+ begin
+ { convert first to string, then to chararray }
+ inserttypeconv(left,cshortstringtype);
+ inserttypeconv(left,resulttype);
+ result:=left;
+ left := nil;
+ exit;
+ end;
+ result := nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_char_to_char : tnode;
+
+ var
+ hp : tordconstnode;
+
+ begin
+ result:=nil;
+ if left.nodetype=ordconstn then
+ begin
+ if (torddef(resulttype.def).typ=uchar) and
+ (torddef(left.resulttype.def).typ=uwidechar) then
+ begin
+ hp:=cordconstnode.create(
+ ord(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value))),
+ cchartype,true);
+ result:=hp;
+ end
+ else if (torddef(resulttype.def).typ=uwidechar) and
+ (torddef(left.resulttype.def).typ=uchar) then
+ begin
+ hp:=cordconstnode.create(
+ asciichar2unicode(chr(tordconstnode(left).value)),
+ cwidechartype,true);
+ result:=hp;
+ end
+ else
+ internalerror(200105131);
+ exit;
+ end;
+ end;
+
+
+ function ttypeconvnode.resulttype_int_to_int : tnode;
+ var
+ v : TConstExprInt;
+ begin
+ result:=nil;
+ if left.nodetype=ordconstn then
+ begin
+ v:=tordconstnode(left).value;
+ if is_currency(resulttype.def) then
+ v:=v*10000;
+ if (resulttype.def.deftype=pointerdef) then
+ result:=cpointerconstnode.create(TConstPtrUInt(v),resulttype)
+ else
+ begin
+ if is_currency(left.resulttype.def) then
+ v:=v div 10000;
+ result:=cordconstnode.create(v,resulttype,false);
+ end;
+ end
+ else if left.nodetype=pointerconstn then
+ begin
+ v:=tpointerconstnode(left).value;
+ if (resulttype.def.deftype=pointerdef) then
+ result:=cpointerconstnode.create(v,resulttype)
+ else
+ begin
+ if is_currency(resulttype.def) then
+ v:=v*10000;
+ result:=cordconstnode.create(v,resulttype,false);
+ end;
+ end
+ else
+ begin
+ { multiply by 10000 for currency. We need to use getcopy to pass
+ the argument because the current node is always disposed. Only
+ inserting the multiply in the left node is not possible because
+ it'll get in an infinite loop to convert int->currency }
+ if is_currency(resulttype.def) then
+ begin
+ result:=caddnode.create(muln,getcopy,cordconstnode.create(10000,resulttype,false));
+ include(result.flags,nf_is_currency);
+ end
+ else if is_currency(left.resulttype.def) then
+ begin
+ result:=cmoddivnode.create(divn,getcopy,cordconstnode.create(10000,resulttype,false));
+ include(result.flags,nf_is_currency);
+ end;
+ end;
+ end;
+
+
+ function ttypeconvnode.resulttype_int_to_real : tnode;
+ var
+ rv : bestreal;
+ begin
+ result:=nil;
+ if left.nodetype=ordconstn then
+ begin
+ rv:=tordconstnode(left).value;
+ if is_currency(resulttype.def) then
+ rv:=rv*10000.0
+ else if is_currency(left.resulttype.def) then
+ rv:=rv/10000.0;
+ result:=crealconstnode.create(rv,resulttype);
+ end
+ else
+ begin
+ { multiply by 10000 for currency. We need to use getcopy to pass
+ the argument because the current node is always disposed. Only
+ inserting the multiply in the left node is not possible because
+ it'll get in an infinite loop to convert int->currency }
+ if is_currency(resulttype.def) then
+ begin
+ result:=caddnode.create(muln,getcopy,crealconstnode.create(10000.0,resulttype));
+ include(result.flags,nf_is_currency);
+ end
+ else if is_currency(left.resulttype.def) then
+ begin
+ result:=caddnode.create(slashn,getcopy,crealconstnode.create(10000.0,resulttype));
+ include(result.flags,nf_is_currency);
+ end;
+ end;
+ end;
+
+
+ function ttypeconvnode.resulttype_real_to_currency : tnode;
+ begin
+ if not is_currency(resulttype.def) then
+ internalerror(200304221);
+ result:=nil;
+ left:=caddnode.create(muln,left,crealconstnode.create(10000.0,left.resulttype));
+ include(left.flags,nf_is_currency);
+ resulttypepass(left);
+ { Convert constants directly, else call Round() }
+ if left.nodetype=realconstn then
+ result:=cordconstnode.create(round(trealconstnode(left).value_real),resulttype,false)
+ else
+ result:=ccallnode.createinternres('fpc_round_real',
+ ccallparanode.create(left,nil),resulttype);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_real_to_real : tnode;
+ begin
+ result:=nil;
+ if is_currency(left.resulttype.def) and not(is_currency(resulttype.def)) then
+ begin
+ left:=caddnode.create(slashn,left,crealconstnode.create(10000.0,left.resulttype));
+ include(left.flags,nf_is_currency);
+ resulttypepass(left);
+ end
+ else
+ if is_currency(resulttype.def) and not(is_currency(left.resulttype.def)) then
+ begin
+ left:=caddnode.create(muln,left,crealconstnode.create(10000.0,left.resulttype));
+ include(left.flags,nf_is_currency);
+ resulttypepass(left);
+ end;
+ if left.nodetype=realconstn then
+ result:=crealconstnode.create(trealconstnode(left).value_real,resulttype);
+ end;
+
+
+ function ttypeconvnode.resulttype_cchar_to_pchar : tnode;
+
+ begin
+ result:=nil;
+ if is_pwidechar(resulttype.def) then
+ inserttypeconv(left,cwidestringtype)
+ else
+ inserttypeconv(left,cshortstringtype);
+ { evaluate again, reset resulttype so the convert_typ
+ will be calculated again and cstring_to_pchar will
+ be used for futher conversion }
+ convtype:=tc_none;
+ result:=det_resulttype;
+ end;
+
+
+ function ttypeconvnode.resulttype_cstring_to_pchar : tnode;
+
+ begin
+ result:=nil;
+ if is_pwidechar(resulttype.def) then
+ inserttypeconv(left,cwidestringtype)
+ else
+ if is_pchar(resulttype.def) and
+ is_widestring(left.resulttype.def) then
+ inserttypeconv(left,cansistringtype);
+ end;
+
+
+ function ttypeconvnode.resulttype_cstring_to_int : tnode;
+ var
+ fcc : cardinal;
+ pb : pbyte;
+ begin
+ result:=nil;
+ if left.nodetype<>stringconstn then
+ internalerror(200510012);
+ if tstringconstnode(left).len=4 then
+ begin
+ pb:=pbyte(tstringconstnode(left).value_str);
+ fcc:=(pb[0] shl 24) or (pb[1] shl 16) or (pb[2] shl 8) or pb[3];
+ result:=cordconstnode.create(fcc,u32inttype,false);
+ end
+ else
+ CGMessage2(type_e_illegal_type_conversion,left.resulttype.def.gettypename,resulttype.def.gettypename);
+ end;
+
+
+ function ttypeconvnode.resulttype_arrayconstructor_to_set : tnode;
+
+ var
+ hp : tnode;
+
+ begin
+ result:=nil;
+ if left.nodetype<>arrayconstructorn then
+ internalerror(5546);
+ { remove typeconv node }
+ hp:=left;
+ left:=nil;
+ { create a set constructor tree }
+ arrayconstructor_to_set(hp);
+ result:=hp;
+ end;
+
+
+ function ttypeconvnode.resulttype_pchar_to_string : tnode;
+
+ begin
+ result := ccallnode.createinternres(
+ 'fpc_pchar_to_'+tstringdef(resulttype.def).stringtypname,
+ ccallparanode.create(left,nil),resulttype);
+ left := nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_interface_to_guid : tnode;
+
+ begin
+ if assigned(tobjectdef(left.resulttype.def).iidguid) then
+ result:=cguidconstnode.create(tobjectdef(left.resulttype.def).iidguid^);
+ end;
+
+
+ function ttypeconvnode.resulttype_dynarray_to_openarray : tnode;
+
+ begin
+ { a dynamic array is a pointer to an array, so to convert it to }
+ { an open array, we have to dereference it (JM) }
+ result := ctypeconvnode.create_internal(left,voidpointertype);
+ resulttypepass(result);
+ { left is reused }
+ left := nil;
+ result := cderefnode.create(result);
+ include(result.flags,nf_no_checkpointer);
+ result.resulttype := resulttype;
+ end;
+
+
+ function ttypeconvnode.resulttype_pwchar_to_string : tnode;
+
+ begin
+ result := ccallnode.createinternres(
+ 'fpc_pwidechar_to_'+tstringdef(resulttype.def).stringtypname,
+ ccallparanode.create(left,nil),resulttype);
+ left := nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_variant_to_dynarray : tnode;
+
+ begin
+ result := ccallnode.createinternres(
+ 'fpc_variant_to_dynarray',
+ ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(resulttype.def),initrtti)),
+ ccallparanode.create(left,nil)
+ ),resulttype);
+ resulttypepass(result);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_dynarray_to_variant : tnode;
+
+ begin
+ result := ccallnode.createinternres(
+ 'fpc_dynarray_to_variant',
+ ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(resulttype.def),initrtti)),
+ ccallparanode.create(ctypeconvnode.create_explicit(left,voidpointertype),nil)
+ ),resulttype);
+ resulttypepass(result);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_variant_to_interface : tnode;
+ begin
+ result := ccallnode.createinternres(
+ 'fpc_variant_to_interface',
+ ccallparanode.create(left,nil)
+ ,resulttype);
+ resulttypepass(result);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_interface_to_variant : tnode;
+ begin
+ result := ccallnode.createinternres(
+ 'fpc_interface_to_variant',
+ ccallparanode.create(left,nil)
+ ,resulttype);
+ resulttypepass(result);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_variant_to_enum : tnode;
+
+ begin
+ result := ctypeconvnode.create_internal(left,sinttype);
+ result := ctypeconvnode.create_internal(result,resulttype);
+ resulttypepass(result);
+ { left is reused }
+ left := nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_enum_to_variant : tnode;
+
+ begin
+ result := ctypeconvnode.create_internal(left,sinttype);
+ result := ctypeconvnode.create_internal(result,cvarianttype);
+ resulttypepass(result);
+ { left is reused }
+ left := nil;
+ end;
+
+
+ function ttypeconvnode.resulttype_array_2_dynarray : tnode;
+ var
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ temp2 : ttempcreatenode;
+ begin
+ { create statements with call to getmem+initialize }
+ result:=internalstatements(newstatement);
+
+ { create temp for result }
+ temp:=ctempcreatenode.create(resulttype,resulttype.def.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ { get temp for array of lengths }
+ temp2:=ctempcreatenode.create(sinttype,sinttype.def.size,tt_persistent,false);
+ addstatement(newstatement,temp2);
+
+ { one dimensional }
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create_offset(temp2,0),
+ cordconstnode.create
+ (tarraydef(left.resulttype.def).highrange+1,s32inttype,true)));
+ { create call to fpc_dynarr_setlength }
+ addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',
+ ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp2)),
+ ccallparanode.create(cordconstnode.create
+ (1,s32inttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(resulttype.def),initrtti)),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ ctemprefnode.create(temp),voidpointertype),
+ nil))))
+
+ ));
+ addstatement(newstatement,ctempdeletenode.create(temp2));
+
+ { copy ... }
+ addstatement(newstatement,cassignmentnode.create(
+ ctypeconvnode.create_internal(cderefnode.create(ctypeconvnode.create_internal(ctemprefnode.create(temp),voidpointertype)),left.resulttype),
+ left
+ ));
+ { left is reused }
+ left:=nil;
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+ end;
+
+
+ procedure copyparasym(p:TNamedIndexItem;arg:pointer);
+ var
+ newparast : tsymtable absolute arg;
+ vs : tparavarsym;
+ begin
+ if tsym(p).typ<>paravarsym then
+ exit;
+ with tparavarsym(p) do
+ begin
+ vs:=tparavarsym.create(realname,paranr,varspez,vartype,varoptions);
+ vs.defaultconstsym:=defaultconstsym;
+ newparast.insert(vs);
+ end;
+ end;
+
+
+ function ttypeconvnode.resulttype_proc_to_procvar : tnode;
+ var
+ pd : tabstractprocdef;
+ begin
+ result:=nil;
+ pd:=tabstractprocdef(left.resulttype.def);
+
+ { create procvardef }
+ resulttype.setdef(tprocvardef.create(pd.parast.symtablelevel));
+ tprocvardef(resulttype.def).proctypeoption:=pd.proctypeoption;
+ tprocvardef(resulttype.def).proccalloption:=pd.proccalloption;
+ tprocvardef(resulttype.def).procoptions:=pd.procoptions;
+ tprocvardef(resulttype.def).rettype:=pd.rettype;
+
+ { method ? then set the methodpointer flag }
+ if (pd.owner.symtabletype=objectsymtable) then
+ include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
+
+ { was it a local procedure? }
+ if (pd.owner.symtabletype=localsymtable) then
+ include(tprocvardef(resulttype.def).procoptions,po_local);
+
+ { only need the address of the method? this is needed
+ for @tobject.create. In this case there will be a loadn without
+ a methodpointer. }
+ if (left.nodetype=loadn) and
+ not assigned(tloadnode(left).left) then
+ include(tprocvardef(resulttype.def).procoptions,po_addressonly);
+
+ { Add parameters use only references, we don't need to keep the
+ parast. We use the parast from the original function to calculate
+ our parameter data and reset it afterwards }
+ pd.parast.foreach_static(@copyparasym,tprocvardef(resulttype.def).parast);
+ tprocvardef(resulttype.def).calcparas;
+ end;
+
+
+ function ttypeconvnode.resulttype_call_helper(c : tconverttype) : tnode;
+ const
+ resulttypeconvert : array[tconverttype] of pointer = (
+ {none} nil,
+ {equal} nil,
+ {not_possible} nil,
+ { string_2_string } @ttypeconvnode.resulttype_string_to_string,
+ { char_2_string } @ttypeconvnode.resulttype_char_to_string,
+ { char_2_chararray } @ttypeconvnode.resulttype_char_to_chararray,
+ { pchar_2_string } @ttypeconvnode.resulttype_pchar_to_string,
+ { cchar_2_pchar } @ttypeconvnode.resulttype_cchar_to_pchar,
+ { cstring_2_pchar } @ttypeconvnode.resulttype_cstring_to_pchar,
+ { cstring_2_int } @ttypeconvnode.resulttype_cstring_to_int,
+ { ansistring_2_pchar } nil,
+ { string_2_chararray } @ttypeconvnode.resulttype_string_to_chararray,
+ { chararray_2_string } @ttypeconvnode.resulttype_chararray_to_string,
+ { array_2_pointer } nil,
+ { pointer_2_array } nil,
+ { int_2_int } @ttypeconvnode.resulttype_int_to_int,
+ { int_2_bool } nil,
+ { bool_2_bool } nil,
+ { bool_2_int } nil,
+ { real_2_real } @ttypeconvnode.resulttype_real_to_real,
+ { int_2_real } @ttypeconvnode.resulttype_int_to_real,
+ { real_2_currency } @ttypeconvnode.resulttype_real_to_currency,
+ { proc_2_procvar } @ttypeconvnode.resulttype_proc_to_procvar,
+ { arrayconstructor_2_set } @ttypeconvnode.resulttype_arrayconstructor_to_set,
+ { load_smallset } nil,
+ { cord_2_pointer } @ttypeconvnode.resulttype_cord_to_pointer,
+ { intf_2_string } nil,
+ { intf_2_guid } @ttypeconvnode.resulttype_interface_to_guid,
+ { class_2_intf } nil,
+ { char_2_char } @ttypeconvnode.resulttype_char_to_char,
+ { normal_2_smallset} nil,
+ { dynarray_2_openarray} @ttypeconvnode.resulttype_dynarray_to_openarray,
+ { pwchar_2_string} @ttypeconvnode.resulttype_pwchar_to_string,
+ { variant_2_dynarray} @ttypeconvnode.resulttype_variant_to_dynarray,
+ { dynarray_2_variant} @ttypeconvnode.resulttype_dynarray_to_variant,
+ { variant_2_enum} @ttypeconvnode.resulttype_variant_to_enum,
+ { enum_2_variant} @ttypeconvnode.resulttype_enum_to_variant,
+ { variant_2_interface} @ttypeconvnode.resulttype_interface_to_variant,
+ { interface_2_variant} @ttypeconvnode.resulttype_variant_to_interface,
+ { array_2_dynarray} @ttypeconvnode.resulttype_array_2_dynarray
+ );
+ type
+ tprocedureofobject = function : tnode of object;
+ var
+ r : packed record
+ proc : pointer;
+ obj : pointer;
+ end;
+ begin
+ result:=nil;
+ { this is a little bit dirty but it works }
+ { and should be quite portable too }
+ r.proc:=resulttypeconvert[c];
+ r.obj:=self;
+ if assigned(r.proc) then
+ result:=tprocedureofobject(r)();
+ end;
+
+
+ function ttypeconvnode.det_resulttype:tnode;
+
+ var
+ htype : ttype;
+ hp : tnode;
+ currprocdef : tabstractprocdef;
+ aprocdef : tprocdef;
+ eq : tequaltype;
+ cdoptions : tcompare_defs_options;
+ begin
+ result:=nil;
+ resulttype:=totype;
+
+ resulttypepass(left);
+ if codegenerror then
+ exit;
+
+ { When absolute force tc_equal }
+ if (nf_absolute in flags) then
+ begin
+ convtype:=tc_equal;
+ if not(tstoreddef(resulttype.def).is_intregable) and
+ not(tstoreddef(resulttype.def).is_fpuregable) then
+ make_not_regable(left);
+ exit;
+ end;
+
+ { tp procvar support. Skip typecasts to procvar, record or set. Those
+ convert on the procvar value. This is used to access the
+ fields of a methodpointer }
+ if not(nf_load_procvar in flags) and
+ not(resulttype.def.deftype in [procvardef,recorddef,setdef]) then
+ maybe_call_procvar(left,true);
+
+ { convert array constructors to sets, because there is no conversion
+ possible for array constructors }
+ if (resulttype.def.deftype<>arraydef) and
+ is_array_constructor(left.resulttype.def) then
+ begin
+ arrayconstructor_to_set(left);
+ resulttypepass(left);
+ end;
+
+ if convtype=tc_none then
+ begin
+ cdoptions:=[cdo_check_operator,cdo_allow_variant];
+ if nf_explicit in flags then
+ include(cdoptions,cdo_explicit);
+ if nf_internal in flags then
+ include(cdoptions,cdo_internal);
+ eq:=compare_defs_ext(left.resulttype.def,resulttype.def,left.nodetype,convtype,aprocdef,cdoptions);
+ case eq of
+ te_exact,
+ te_equal :
+ begin
+ { because is_equal only checks the basetype for sets we need to
+ check here if we are loading a smallset into a normalset }
+ if (resulttype.def.deftype=setdef) and
+ (left.resulttype.def.deftype=setdef) and
+ ((tsetdef(resulttype.def).settype = smallset) xor
+ (tsetdef(left.resulttype.def).settype = smallset)) then
+ begin
+ { constant sets can be converted by changing the type only }
+ if (left.nodetype=setconstn) then
+ begin
+ left.resulttype:=resulttype;
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+
+ if (tsetdef(resulttype.def).settype <> smallset) then
+ convtype:=tc_load_smallset
+ else
+ convtype := tc_normal_2_smallset;
+ exit;
+ end
+ else
+ begin
+ { Only leave when there is no conversion to do.
+ We can still need to call a conversion routine,
+ like the routine to convert a stringconstnode }
+ if convtype in [tc_equal,tc_not_possible] then
+ begin
+ left.resulttype:=resulttype;
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+ end;
+
+ te_convert_l1,
+ te_convert_l2,
+ te_convert_l3 :
+ begin
+ { nothing to do }
+ end;
+
+ te_convert_operator :
+ begin
+ include(current_procinfo.flags,pi_do_call);
+ inc(aprocdef.procsym.refs);
+ hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[]);
+ { tell explicitly which def we must use !! (PM) }
+ tcallnode(hp).procdefinition:=aprocdef;
+ left:=nil;
+ result:=hp;
+ exit;
+ end;
+
+ te_incompatible :
+ begin
+ { Procedures have a resulttype.def of voiddef and functions of their
+ own resulttype.def. They will therefore always be incompatible with
+ a procvar. Because isconvertable cannot check for procedures we
+ use an extra check for them.}
+ if (left.nodetype=calln) and
+ (tcallnode(left).para_count=0) and
+ (resulttype.def.deftype=procvardef) and
+ (
+ (m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches)
+ ) then
+ begin
+ if assigned(tcallnode(left).right) then
+ begin
+ { this is already a procvar, if it is really equal
+ is checked below }
+ convtype:=tc_equal;
+ hp:=tcallnode(left).right.getcopy;
+ currprocdef:=tabstractprocdef(hp.resulttype.def);
+ end
+ else
+ begin
+ convtype:=tc_proc_2_procvar;
+ currprocdef:=Tprocsym(Tcallnode(left).symtableprocentry).search_procdef_byprocvardef(Tprocvardef(resulttype.def));
+ hp:=cloadnode.create_procvar(tprocsym(tcallnode(left).symtableprocentry),
+ tprocdef(currprocdef),tcallnode(left).symtableproc);
+ if (tcallnode(left).symtableprocentry.owner.symtabletype=objectsymtable) then
+ begin
+ if assigned(tcallnode(left).methodpointer) then
+ tloadnode(hp).set_mp(tcallnode(left).get_load_methodpointer)
+ else
+ tloadnode(hp).set_mp(load_self_node);
+ end;
+ resulttypepass(hp);
+ end;
+ left.free;
+ left:=hp;
+ { Now check if the procedure we are going to assign to
+ the procvar, is compatible with the procvar's type }
+ if not(nf_explicit in flags) and
+ (proc_to_procvar_equal(currprocdef,tprocvardef(resulttype.def))=te_incompatible) then
+ IncompatibleTypes(left.resulttype.def,resulttype.def);
+ exit;
+ end;
+
+ { Handle explicit type conversions }
+ if nf_explicit in flags then
+ begin
+ { do common tc_equal cast }
+ convtype:=tc_equal;
+
+ { ordinal constants can be resized to 1,2,4,8 bytes }
+ if (left.nodetype=ordconstn) then
+ begin
+ { Insert typeconv for ordinal to the correct size first on left, after
+ that the other conversion can be done }
+ htype.reset;
+ case longint(resulttype.def.size) of
+ 1 :
+ htype:=s8inttype;
+ 2 :
+ htype:=s16inttype;
+ 4 :
+ htype:=s32inttype;
+ 8 :
+ htype:=s64inttype;
+ end;
+ { we need explicit, because it can also be an enum }
+ if assigned(htype.def) then
+ inserttypeconv_internal(left,htype)
+ else
+ CGMessage2(type_e_illegal_type_conversion,left.resulttype.def.gettypename,resulttype.def.gettypename);
+ end;
+
+ { check if the result could be in a register }
+ if (not(tstoreddef(resulttype.def).is_intregable) and
+ not(tstoreddef(resulttype.def).is_fpuregable)) or
+ ((left.resulttype.def.deftype = floatdef) and
+ (resulttype.def.deftype <> floatdef)) then
+ make_not_regable(left);
+
+ { class/interface to class/interface, with checkobject support }
+ if is_class_or_interface(resulttype.def) and
+ is_class_or_interface(left.resulttype.def) then
+ begin
+ { check if the types are related }
+ if not(nf_internal in flags) and
+ (not(tobjectdef(left.resulttype.def).is_related(tobjectdef(resulttype.def)))) and
+ (not(tobjectdef(resulttype.def).is_related(tobjectdef(left.resulttype.def)))) then
+ begin
+ { Give an error when typecasting class to interface, this is compatible
+ with delphi }
+ if is_interface(resulttype.def) and
+ not is_interface(left.resulttype.def) then
+ CGMessage2(type_e_classes_not_related,
+ FullTypeName(left.resulttype.def,resulttype.def),
+ FullTypeName(resulttype.def,left.resulttype.def))
+ else
+ CGMessage2(type_w_classes_not_related,
+ FullTypeName(left.resulttype.def,resulttype.def),
+ FullTypeName(resulttype.def,left.resulttype.def))
+ end;
+
+ { Add runtime check? }
+ if (cs_check_object in aktlocalswitches) then
+ begin
+ { we can translate the typeconvnode to 'as' when
+ typecasting to a class or interface }
+ hp:=casnode.create(left,cloadvmtaddrnode.create(ctypenode.create(resulttype)));
+ left:=nil;
+ result:=hp;
+ exit;
+ end;
+ end
+
+ else
+ begin
+ { only if the same size or formal def }
+ if not(
+ (left.resulttype.def.deftype=formaldef) or
+ (
+ not(is_open_array(left.resulttype.def)) and
+ (left.resulttype.def.size=resulttype.def.size)
+ ) or
+ (
+ is_void(left.resulttype.def) and
+ (left.nodetype=derefn)
+ )
+ ) then
+ CGMessage2(type_e_illegal_type_conversion,left.resulttype.def.gettypename,resulttype.def.gettypename);
+ end;
+ end
+ else
+ IncompatibleTypes(left.resulttype.def,resulttype.def);
+ end;
+
+ else
+ internalerror(200211231);
+ end;
+ end;
+ { Give hint or warning for unportable code, exceptions are
+ - typecasts from constants
+ - void }
+ if not(nf_internal in flags) and
+ (left.nodetype<>ordconstn) and
+ not(is_void(left.resulttype.def)) and
+ (((left.resulttype.def.deftype=orddef) and
+ (resulttype.def.deftype in [pointerdef,procvardef,classrefdef])) or
+ ((resulttype.def.deftype=orddef) and
+ (left.resulttype.def.deftype in [pointerdef,procvardef,classrefdef]))) then
+ begin
+ { Give a warning when sizes don't match, because then info will be lost }
+ if left.resulttype.def.size=resulttype.def.size then
+ CGMessage(type_h_pointer_to_longint_conv_not_portable)
+ else
+ CGMessage(type_w_pointer_to_longint_conv_not_portable);
+ end;
+
+ { Constant folding and other node transitions to
+ remove the typeconv node }
+ case left.nodetype of
+ niln :
+ begin
+ { nil to ordinal node }
+ if (resulttype.def.deftype=orddef) then
+ begin
+ hp:=cordconstnode.create(0,resulttype,true);
+ result:=hp;
+ exit;
+ end
+ else
+ { fold nil to any pointer type }
+ if (resulttype.def.deftype=pointerdef) then
+ begin
+ hp:=cnilnode.create;
+ hp.resulttype:=resulttype;
+ result:=hp;
+ exit;
+ end
+ else
+ { remove typeconv after niln, but not when the result is a
+ methodpointer. The typeconv of the methodpointer will then
+ take care of updateing size of niln to OS_64 }
+ if not((resulttype.def.deftype=procvardef) and
+ (po_methodpointer in tprocvardef(resulttype.def).procoptions)) then
+ begin
+ left.resulttype:=resulttype;
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+
+ ordconstn :
+ begin
+ { ordinal contants can be directly converted }
+ { but not char to char because it is a widechar to char or via versa }
+ { which needs extra code to do the code page transistion }
+ { constant ordinal to pointer }
+ if (resulttype.def.deftype=pointerdef) and
+ (convtype<>tc_cchar_2_pchar) then
+ begin
+ hp:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value),resulttype);
+ result:=hp;
+ exit;
+ end
+ else if is_ordinal(resulttype.def) and
+ not(convtype=tc_char_2_char) then
+ begin
+ { replace the resulttype and recheck the range }
+ left.resulttype:=resulttype;
+ testrange(left.resulttype.def,tordconstnode(left).value,(nf_explicit in flags));
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+
+ pointerconstn :
+ begin
+ { pointerconstn to any pointer is folded too }
+ if (resulttype.def.deftype=pointerdef) then
+ begin
+ left.resulttype:=resulttype;
+ result:=left;
+ left:=nil;
+ exit;
+ end
+ { constant pointer to ordinal }
+ else if is_ordinal(resulttype.def) then
+ begin
+ hp:=cordconstnode.create(TConstExprInt(tpointerconstnode(left).value),
+ resulttype,not(nf_explicit in flags));
+ result:=hp;
+ exit;
+ end;
+ end;
+ end;
+
+ { now call the resulttype helper to do constant folding }
+ result:=resulttype_call_helper(convtype);
+ end;
+
+ procedure Ttypeconvnode.mark_write;
+
+ begin
+ left.mark_write;
+ end;
+
+ function ttypeconvnode.first_cord_to_pointer : tnode;
+
+ begin
+ result:=nil;
+ internalerror(200104043);
+ end;
+
+
+ function ttypeconvnode.first_int_to_int : tnode;
+
+ begin
+ first_int_to_int:=nil;
+ expectloc:=left.expectloc;
+ if not is_void(left.resulttype.def) then
+ begin
+ if (left.expectloc<>LOC_REGISTER) and
+ (resulttype.def.size>left.resulttype.def.size) then
+ expectloc:=LOC_REGISTER
+ else
+ if (left.expectloc=LOC_CREGISTER) and
+ (resulttype.def.size<left.resulttype.def.size) then
+ expectloc:=LOC_REGISTER;
+ end;
+{$ifndef cpu64bit}
+ if is_64bit(resulttype.def) then
+ registersint:=max(registersint,2)
+ else
+{$endif cpu64bit}
+ registersint:=max(registersint,1);
+ end;
+
+
+ function ttypeconvnode.first_cstring_to_pchar : tnode;
+
+ begin
+ result:=nil;
+ registersint:=1;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ function ttypeconvnode.first_cstring_to_int : tnode;
+
+ begin
+ result:=nil;
+ internalerror(200510014);
+ end;
+
+
+ function ttypeconvnode.first_string_to_chararray : tnode;
+
+ begin
+ first_string_to_chararray:=nil;
+ expectloc:=left.expectloc;
+ end;
+
+
+ function ttypeconvnode.first_char_to_string : tnode;
+
+ begin
+ first_char_to_string:=nil;
+ expectloc:=LOC_REFERENCE;
+ end;
+
+
+ function ttypeconvnode.first_nothing : tnode;
+ begin
+ first_nothing:=nil;
+ end;
+
+
+ function ttypeconvnode.first_array_to_pointer : tnode;
+
+ begin
+ first_array_to_pointer:=nil;
+ if registersint<1 then
+ registersint:=1;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ function ttypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[32];
+ typname : string[12];
+ begin
+ { Get the type name }
+ { Normally the typename should be one of the following:
+ single, double - carl
+ }
+ typname := lower(pbestrealtype^.def.gettypename);
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bit(left.resulttype.def) then
+ begin
+ if is_signed(left.resulttype.def) then
+ fname := 'fpc_int64_to_'+typname
+ else
+{$warning generic conversion from int to float does not support unsigned integers}
+ fname := 'fpc_int64_to_'+typname;
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+{$warning generic conversion from int to float does not support unsigned integers}
+ if is_signed(left.resulttype.def) then
+ fname := 'fpc_longint_to_'+typname
+ else
+ fname := 'fpc_longint_to_'+typname;
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end;
+ end;
+
+
+ function ttypeconvnode.first_real_to_real : tnode;
+ begin
+{$ifdef cpufpemu}
+ if cs_fp_emulation in aktmoduleswitches then
+ begin
+ if target_info.system in system_wince then
+ begin
+ case tfloatdef(left.resulttype.def).typ of
+ s32real:
+ case tfloatdef(resulttype.def).typ of
+ s64real:
+ result:=ccallnode.createintern('STOD',ccallparanode.create(left,nil));
+ else
+ internalerror(2005082704);
+ end;
+ s64real:
+ case tfloatdef(resulttype.def).typ of
+ s32real:
+ result:=ccallnode.createintern('DTOS',ccallparanode.create(left,nil));
+ else
+ internalerror(2005082703);
+ end;
+ else
+ internalerror(2005082702);
+ end;
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ begin
+ {!! FIXME }
+ internalerror(2005082701);
+ end;
+ end
+ else
+{$endif cpufpemu}
+ begin
+ first_real_to_real:=nil;
+ { comp isn't a floating type }
+ if registersfpu<1 then
+ registersfpu:=1;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+ end;
+
+
+ function ttypeconvnode.first_pointer_to_array : tnode;
+
+ begin
+ first_pointer_to_array:=nil;
+ if registersint<1 then
+ registersint:=1;
+ expectloc:=LOC_REFERENCE;
+ end;
+
+
+ function ttypeconvnode.first_cchar_to_pchar : tnode;
+
+ begin
+ first_cchar_to_pchar:=nil;
+ internalerror(200104021);
+ end;
+
+
+ function ttypeconvnode.first_bool_to_int : tnode;
+
+ begin
+ first_bool_to_int:=nil;
+ { byte(boolean) or word(wordbool) or longint(longbool) must
+ be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resulttype.def.size=resulttype.def.size) and
+ (left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ exit;
+ { when converting to 64bit, first convert to a 32bit int and then }
+ { convert to a 64bit int (only necessary for 32bit processors) (JM) }
+ if resulttype.def.size > sizeof(aint) then
+ begin
+ result := ctypeconvnode.create_internal(left,u32inttype);
+ result := ctypeconvnode.create(result,resulttype);
+ left := nil;
+ firstpass(result);
+ exit;
+ end;
+ expectloc:=LOC_REGISTER;
+ if registersint<1 then
+ registersint:=1;
+ end;
+
+
+ function ttypeconvnode.first_int_to_bool : tnode;
+
+ begin
+ first_int_to_bool:=nil;
+ { byte(boolean) or word(wordbool) or longint(longbool) must
+ be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resulttype.def.size=resulttype.def.size) and
+ (left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ exit;
+ expectloc:=LOC_REGISTER;
+ { need if bool to bool !!
+ not very nice !!
+ insertypeconv(left,s32inttype);
+ left.explizit:=true;
+ firstpass(left); }
+ if registersint<1 then
+ registersint:=1;
+ end;
+
+
+ function ttypeconvnode.first_bool_to_bool : tnode;
+ begin
+ first_bool_to_bool:=nil;
+ expectloc:=LOC_REGISTER;
+ if registersint<1 then
+ registersint:=1;
+ end;
+
+
+ function ttypeconvnode.first_char_to_char : tnode;
+
+ begin
+ first_char_to_char:=first_int_to_int;
+ end;
+
+
+ function ttypeconvnode.first_proc_to_procvar : tnode;
+ begin
+ first_proc_to_procvar:=nil;
+ if tabstractprocdef(resulttype.def).is_addressonly then
+ begin
+ registersint:=left.registersint;
+ if registersint<1 then
+ registersint:=1;
+ expectloc:=LOC_REGISTER;
+ end
+ else
+ begin
+ if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ CGMessage(parser_e_illegal_expression);
+ registersint:=left.registersint;
+ expectloc:=left.expectloc
+ end
+ end;
+
+
+ function ttypeconvnode.first_load_smallset : tnode;
+
+ var
+ srsym: ttypesym;
+ p: tcallparanode;
+
+ begin
+ if not searchsystype('FPC_SMALL_SET',srsym) then
+ internalerror(200108313);
+ p := ccallparanode.create(left,nil);
+ { reused }
+ left := nil;
+ { convert parameter explicitely to fpc_small_set }
+ p.left := ctypeconvnode.create_internal(p.left,srsym.restype);
+ { create call, adjust resulttype }
+ result :=
+ ccallnode.createinternres('fpc_set_load_small',p,resulttype);
+ firstpass(result);
+ end;
+
+
+ function ttypeconvnode.first_ansistring_to_pchar : tnode;
+
+ begin
+ first_ansistring_to_pchar:=nil;
+ expectloc:=LOC_REGISTER;
+ if registersint<1 then
+ registersint:=1;
+ end;
+
+
+ function ttypeconvnode.first_arrayconstructor_to_set : tnode;
+ begin
+ first_arrayconstructor_to_set:=nil;
+ internalerror(200104022);
+ end;
+
+ function ttypeconvnode.first_class_to_intf : tnode;
+
+ begin
+ first_class_to_intf:=nil;
+ expectloc:=LOC_REGISTER;
+ if registersint<1 then
+ registersint:=1;
+ end;
+
+ function ttypeconvnode._first_int_to_int : tnode;
+ begin
+ result:=first_int_to_int;
+ end;
+
+ function ttypeconvnode._first_cstring_to_pchar : tnode;
+ begin
+ result:=first_cstring_to_pchar;
+ end;
+
+ function ttypeconvnode._first_cstring_to_int : tnode;
+ begin
+ result:=first_cstring_to_int;
+ end;
+
+ function ttypeconvnode._first_string_to_chararray : tnode;
+ begin
+ result:=first_string_to_chararray;
+ end;
+
+ function ttypeconvnode._first_char_to_string : tnode;
+ begin
+ result:=first_char_to_string;
+ end;
+
+ function ttypeconvnode._first_nothing : tnode;
+ begin
+ result:=first_nothing;
+ end;
+
+ function ttypeconvnode._first_array_to_pointer : tnode;
+ begin
+ result:=first_array_to_pointer;
+ end;
+
+ function ttypeconvnode._first_int_to_real : tnode;
+ begin
+ result:=first_int_to_real;
+ end;
+
+ function ttypeconvnode._first_real_to_real : tnode;
+ begin
+ result:=first_real_to_real;
+ end;
+
+ function ttypeconvnode._first_pointer_to_array : tnode;
+ begin
+ result:=first_pointer_to_array;
+ end;
+
+ function ttypeconvnode._first_cchar_to_pchar : tnode;
+ begin
+ result:=first_cchar_to_pchar;
+ end;
+
+ function ttypeconvnode._first_bool_to_int : tnode;
+ begin
+ result:=first_bool_to_int;
+ end;
+
+ function ttypeconvnode._first_int_to_bool : tnode;
+ begin
+ result:=first_int_to_bool;
+ end;
+
+ function ttypeconvnode._first_bool_to_bool : tnode;
+ begin
+ result:=first_bool_to_bool;
+ end;
+
+ function ttypeconvnode._first_proc_to_procvar : tnode;
+ begin
+ result:=first_proc_to_procvar;
+ end;
+
+ function ttypeconvnode._first_load_smallset : tnode;
+ begin
+ result:=first_load_smallset;
+ end;
+
+ function ttypeconvnode._first_cord_to_pointer : tnode;
+ begin
+ result:=first_cord_to_pointer;
+ end;
+
+ function ttypeconvnode._first_ansistring_to_pchar : tnode;
+ begin
+ result:=first_ansistring_to_pchar;
+ end;
+
+ function ttypeconvnode._first_arrayconstructor_to_set : tnode;
+ begin
+ result:=first_arrayconstructor_to_set;
+ end;
+
+ function ttypeconvnode._first_class_to_intf : tnode;
+ begin
+ result:=first_class_to_intf;
+ end;
+
+ function ttypeconvnode._first_char_to_char : tnode;
+ begin
+ result:=first_char_to_char;
+ end;
+
+ function ttypeconvnode.first_call_helper(c : tconverttype) : tnode;
+
+ const
+ firstconvert : array[tconverttype] of pointer = (
+ nil, { none }
+ @ttypeconvnode._first_nothing, {equal}
+ @ttypeconvnode._first_nothing, {not_possible}
+ nil, { removed in resulttype_string_to_string }
+ @ttypeconvnode._first_char_to_string,
+ @ttypeconvnode._first_nothing, { char_2_chararray, needs nothing extra }
+ nil, { removed in resulttype_chararray_to_string }
+ @ttypeconvnode._first_cchar_to_pchar,
+ @ttypeconvnode._first_cstring_to_pchar,
+ @ttypeconvnode._first_cstring_to_int,
+ @ttypeconvnode._first_ansistring_to_pchar,
+ @ttypeconvnode._first_string_to_chararray,
+ nil, { removed in resulttype_chararray_to_string }
+ @ttypeconvnode._first_array_to_pointer,
+ @ttypeconvnode._first_pointer_to_array,
+ @ttypeconvnode._first_int_to_int,
+ @ttypeconvnode._first_int_to_bool,
+ @ttypeconvnode._first_bool_to_bool,
+ @ttypeconvnode._first_bool_to_int,
+ @ttypeconvnode._first_real_to_real,
+ @ttypeconvnode._first_int_to_real,
+ nil, { removed in resulttype_real_to_currency }
+ @ttypeconvnode._first_proc_to_procvar,
+ @ttypeconvnode._first_arrayconstructor_to_set,
+ @ttypeconvnode._first_load_smallset,
+ @ttypeconvnode._first_cord_to_pointer,
+ @ttypeconvnode._first_nothing,
+ @ttypeconvnode._first_nothing,
+ @ttypeconvnode._first_class_to_intf,
+ @ttypeconvnode._first_char_to_char,
+ @ttypeconvnode._first_nothing,
+ @ttypeconvnode._first_nothing,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil
+ );
+ type
+ tprocedureofobject = function : tnode of object;
+
+ var
+ r : packed record
+ proc : pointer;
+ obj : pointer;
+ end;
+
+ begin
+ { this is a little bit dirty but it works }
+ { and should be quite portable too }
+ r.proc:=firstconvert[c];
+ r.obj:=self;
+ if not assigned(r.proc) then
+ internalerror(200312081);
+ first_call_helper:=tprocedureofobject(r){$ifdef FPC}(){$endif FPC}
+ end;
+
+
+ function ttypeconvnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ { load the value_str from the left part }
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif}
+ expectloc:=left.expectloc;
+
+ result:=first_call_helper(convtype);
+ end;
+
+
+ function ttypeconvnode.assign_allowed:boolean;
+ begin
+ result:=(convtype=tc_equal) or
+ { typecasting from void is always allowed }
+ is_void(left.resulttype.def) or
+ (left.resulttype.def.deftype=formaldef) or
+ { int 2 int with same size reuses same location, or for
+ tp7 mode also allow size < orignal size }
+ (
+ (convtype=tc_int_2_int) and
+ (
+ (resulttype.def.size=left.resulttype.def.size) or
+ ((m_tp7 in aktmodeswitches) and
+ (resulttype.def.size<left.resulttype.def.size))
+ )
+ ) or
+ { int 2 bool/bool 2 int, explicit typecast, see also nx86cnv }
+ ((convtype in [tc_int_2_bool,tc_bool_2_int]) and
+ (nf_explicit in flags) and
+ (resulttype.def.size=left.resulttype.def.size));
+
+ { When using only a part of the value it can't be in a register since
+ that will load the value in a new register first }
+ if (resulttype.def.size<left.resulttype.def.size) then
+ make_not_regable(left);
+ end;
+
+
+ function ttypeconvnode.docompare(p: tnode) : boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (convtype = ttypeconvnode(p).convtype);
+ end;
+
+
+ procedure ttypeconvnode._second_int_to_int;
+ begin
+ second_int_to_int;
+ end;
+
+
+ procedure ttypeconvnode._second_string_to_string;
+ begin
+ second_string_to_string;
+ end;
+
+
+ procedure ttypeconvnode._second_cstring_to_pchar;
+ begin
+ second_cstring_to_pchar;
+ end;
+
+
+ procedure ttypeconvnode._second_cstring_to_int;
+ begin
+ second_cstring_to_int;
+ end;
+
+
+ procedure ttypeconvnode._second_string_to_chararray;
+ begin
+ second_string_to_chararray;
+ end;
+
+
+ procedure ttypeconvnode._second_array_to_pointer;
+ begin
+ second_array_to_pointer;
+ end;
+
+
+ procedure ttypeconvnode._second_pointer_to_array;
+ begin
+ second_pointer_to_array;
+ end;
+
+
+ procedure ttypeconvnode._second_chararray_to_string;
+ begin
+ second_chararray_to_string;
+ end;
+
+
+ procedure ttypeconvnode._second_char_to_string;
+ begin
+ second_char_to_string;
+ end;
+
+
+ procedure ttypeconvnode._second_int_to_real;
+ begin
+ second_int_to_real;
+ end;
+
+
+ procedure ttypeconvnode._second_real_to_real;
+ begin
+ second_real_to_real;
+ end;
+
+
+ procedure ttypeconvnode._second_cord_to_pointer;
+ begin
+ second_cord_to_pointer;
+ end;
+
+
+ procedure ttypeconvnode._second_proc_to_procvar;
+ begin
+ second_proc_to_procvar;
+ end;
+
+
+ procedure ttypeconvnode._second_bool_to_int;
+ begin
+ second_bool_to_int;
+ end;
+
+
+ procedure ttypeconvnode._second_int_to_bool;
+ begin
+ second_int_to_bool;
+ end;
+
+
+ procedure ttypeconvnode._second_bool_to_bool;
+ begin
+ second_bool_to_bool;
+ end;
+
+ procedure ttypeconvnode._second_load_smallset;
+ begin
+ second_load_smallset;
+ end;
+
+
+ procedure ttypeconvnode._second_ansistring_to_pchar;
+ begin
+ second_ansistring_to_pchar;
+ end;
+
+
+ procedure ttypeconvnode._second_class_to_intf;
+ begin
+ second_class_to_intf;
+ end;
+
+
+ procedure ttypeconvnode._second_char_to_char;
+ begin
+ second_char_to_char;
+ end;
+
+
+ procedure ttypeconvnode._second_nothing;
+ begin
+ second_nothing;
+ end;
+
+
+ procedure ttypeconvnode.second_call_helper(c : tconverttype);
+ const
+ secondconvert : array[tconverttype] of pointer = (
+ @ttypeconvnode._second_nothing, {none}
+ @ttypeconvnode._second_nothing, {equal}
+ @ttypeconvnode._second_nothing, {not_possible}
+ @ttypeconvnode._second_nothing, {second_string_to_string, handled in resulttype pass }
+ @ttypeconvnode._second_char_to_string,
+ @ttypeconvnode._second_nothing, {char_to_charray}
+ @ttypeconvnode._second_nothing, { pchar_to_string, handled in resulttype pass }
+ @ttypeconvnode._second_nothing, {cchar_to_pchar}
+ @ttypeconvnode._second_cstring_to_pchar,
+ @ttypeconvnode._second_cstring_to_int,
+ @ttypeconvnode._second_ansistring_to_pchar,
+ @ttypeconvnode._second_string_to_chararray,
+ @ttypeconvnode._second_nothing, { chararray_to_string, handled in resulttype pass }
+ @ttypeconvnode._second_array_to_pointer,
+ @ttypeconvnode._second_pointer_to_array,
+ @ttypeconvnode._second_int_to_int,
+ @ttypeconvnode._second_int_to_bool,
+ @ttypeconvnode._second_bool_to_bool,
+ @ttypeconvnode._second_bool_to_int,
+ @ttypeconvnode._second_real_to_real,
+ @ttypeconvnode._second_int_to_real,
+ @ttypeconvnode._second_nothing, { real_to_currency, handled in resulttype pass }
+ @ttypeconvnode._second_proc_to_procvar,
+ @ttypeconvnode._second_nothing, { arrayconstructor_to_set }
+ @ttypeconvnode._second_nothing, { second_load_smallset, handled in first pass }
+ @ttypeconvnode._second_cord_to_pointer,
+ @ttypeconvnode._second_nothing, { interface 2 string }
+ @ttypeconvnode._second_nothing, { interface 2 guid }
+ @ttypeconvnode._second_class_to_intf,
+ @ttypeconvnode._second_char_to_char,
+ @ttypeconvnode._second_nothing, { normal_2_smallset }
+ @ttypeconvnode._second_nothing, { dynarray_2_openarray }
+ @ttypeconvnode._second_nothing, { pwchar_2_string }
+ @ttypeconvnode._second_nothing, { variant_2_dynarray }
+ @ttypeconvnode._second_nothing, { dynarray_2_variant}
+ @ttypeconvnode._second_nothing, { variant_2_enum }
+ @ttypeconvnode._second_nothing, { enum_2_variant }
+ @ttypeconvnode._second_nothing, { variant_2_interface }
+ @ttypeconvnode._second_nothing, { interface_2_variant }
+ @ttypeconvnode._second_nothing { array_2_dynarray }
+ );
+ type
+ tprocedureofobject = procedure of object;
+
+ var
+ r : packed record
+ proc : pointer;
+ obj : pointer;
+ end;
+
+ begin
+ { this is a little bit dirty but it works }
+ { and should be quite portable too }
+ r.proc:=secondconvert[c];
+ r.obj:=self;
+ tprocedureofobject(r)();
+ end;
+
+
+{*****************************************************************************
+ TISNODE
+*****************************************************************************}
+
+ constructor tisnode.create(l,r : tnode);
+
+ begin
+ inherited create(isn,l,r);
+ end;
+
+
+ function tisnode.det_resulttype:tnode;
+ var
+ paras: tcallparanode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ resulttypepass(right);
+
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+
+ if codegenerror then
+ exit;
+
+ if (right.resulttype.def.deftype=classrefdef) then
+ begin
+ { left must be a class }
+ if is_class(left.resulttype.def) then
+ begin
+ { the operands must be related }
+ if (not(tobjectdef(left.resulttype.def).is_related(
+ tobjectdef(tclassrefdef(right.resulttype.def).pointertype.def)))) and
+ (not(tobjectdef(tclassrefdef(right.resulttype.def).pointertype.def).is_related(
+ tobjectdef(left.resulttype.def)))) then
+ CGMessage2(type_e_classes_not_related,left.resulttype.def.typename,
+ tclassrefdef(right.resulttype.def).pointertype.def.typename);
+ end
+ else
+ CGMessage1(type_e_class_type_expected,left.resulttype.def.typename);
+
+ { call fpc_do_is helper }
+ paras := ccallparanode.create(
+ left,
+ ccallparanode.create(
+ right,nil));
+ result := ccallnode.createintern('fpc_do_is',paras);
+ left := nil;
+ right := nil;
+ end
+ else if is_interface(right.resulttype.def) then
+ begin
+ { left is a class }
+ if is_class(left.resulttype.def) then
+ begin
+ { the operands must be related }
+ if not(assigned(tobjectdef(left.resulttype.def).implementedinterfaces) and
+ (tobjectdef(left.resulttype.def).implementedinterfaces.searchintf(right.resulttype.def)<>-1)) then
+ CGMessage2(type_e_classes_not_related,
+ FullTypeName(left.resulttype.def,right.resulttype.def),
+ FullTypeName(right.resulttype.def,left.resulttype.def))
+ end
+ { left is an interface }
+ else if is_interface(left.resulttype.def) then
+ begin
+ { the operands must be related }
+ if (not(tobjectdef(left.resulttype.def).is_related(tobjectdef(right.resulttype.def)))) and
+ (not(tobjectdef(right.resulttype.def).is_related(tobjectdef(left.resulttype.def)))) then
+ CGMessage2(type_e_classes_not_related,
+ FullTypeName(left.resulttype.def,right.resulttype.def),
+ FullTypeName(right.resulttype.def,left.resulttype.def));
+ end
+ else
+ CGMessage1(type_e_class_type_expected,left.resulttype.def.typename);
+ { call fpc_do_is helper }
+ paras := ccallparanode.create(
+ left,
+ ccallparanode.create(
+ right,nil));
+ result := ccallnode.createintern('fpc_do_is',paras);
+ left := nil;
+ right := nil;
+ end
+ else
+ CGMessage1(type_e_class_or_interface_type_expected,right.resulttype.def.typename);
+
+ resulttype:=booltype;
+ end;
+
+
+ function tisnode.pass_1 : tnode;
+ begin
+ internalerror(200204254);
+ result:=nil;
+ end;
+
+ { dummy pass_2, it will never be called, but we need one since }
+ { you can't instantiate an abstract class }
+ procedure tisnode.pass_2;
+ begin
+ end;
+
+
+{*****************************************************************************
+ TASNODE
+*****************************************************************************}
+
+ constructor tasnode.create(l,r : tnode);
+
+ begin
+ inherited create(asn,l,r);
+ call := nil;
+ end;
+
+
+ destructor tasnode.destroy;
+
+ begin
+ call.free;
+ inherited destroy;
+ end;
+
+
+ function tasnode.det_resulttype:tnode;
+ var
+ hp : tnode;
+ begin
+ result:=nil;
+ resulttypepass(right);
+ resulttypepass(left);
+
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+
+ if codegenerror then
+ exit;
+
+ if (right.resulttype.def.deftype=classrefdef) then
+ begin
+ { left must be a class }
+ if is_class(left.resulttype.def) then
+ begin
+ { the operands must be related }
+ if (not(tobjectdef(left.resulttype.def).is_related(
+ tobjectdef(tclassrefdef(right.resulttype.def).pointertype.def)))) and
+ (not(tobjectdef(tclassrefdef(right.resulttype.def).pointertype.def).is_related(
+ tobjectdef(left.resulttype.def)))) then
+ CGMessage2(type_e_classes_not_related,
+ FullTypeName(left.resulttype.def,tclassrefdef(right.resulttype.def).pointertype.def),
+ FullTypeName(tclassrefdef(right.resulttype.def).pointertype.def,left.resulttype.def));
+ end
+ else
+ CGMessage1(type_e_class_type_expected,left.resulttype.def.typename);
+ resulttype:=tclassrefdef(right.resulttype.def).pointertype;
+ end
+ else if is_interface(right.resulttype.def) then
+ begin
+ { left is a class }
+ if not(is_class(left.resulttype.def) or
+ is_interface(left.resulttype.def)) then
+ CGMessage1(type_e_class_type_expected,left.resulttype.def.typename);
+
+ resulttype:=right.resulttype;
+
+ { load the GUID of the interface }
+ if (right.nodetype=typen) then
+ begin
+ if assigned(tobjectdef(right.resulttype.def).iidguid) then
+ begin
+ hp:=cguidconstnode.create(tobjectdef(right.resulttype.def).iidguid^);
+ right.free;
+ right:=hp;
+ end
+ else
+ internalerror(200206282);
+ resulttypepass(right);
+ end;
+ end
+ else
+ CGMessage1(type_e_class_or_interface_type_expected,right.resulttype.def.typename);
+ end;
+
+
+ function tasnode._getcopy: tnode;
+
+ begin
+ result := inherited _getcopy;
+ if assigned(call) then
+ tasnode(result).call := call.getcopy
+ else
+ tasnode(result).call := nil;
+ end;
+
+
+ function tasnode.pass_1 : tnode;
+
+ var
+ procname: string;
+ begin
+ result:=nil;
+ if not assigned(call) then
+ begin
+ if is_class(left.resulttype.def) and
+ (right.resulttype.def.deftype=classrefdef) then
+ call := ccallnode.createinternres('fpc_do_as',
+ ccallparanode.create(left,ccallparanode.create(right,nil)),
+ resulttype)
+ else
+ begin
+ if is_class(left.resulttype.def) then
+ procname := 'fpc_class_as_intf'
+ else
+ procname := 'fpc_intf_as';
+ call := ccallnode.createinternres(procname,
+ ccallparanode.create(right,ccallparanode.create(left,nil)),
+ resulttype);
+ end;
+ left := nil;
+ right := nil;
+ firstpass(call);
+ if codegenerror then
+ exit;
+ expectloc:=call.expectloc;
+ registersint:=call.registersint;
+ registersfpu:=call.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=call.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+
+begin
+ ctypeconvnode:=ttypeconvnode;
+ casnode:=tasnode;
+ cisnode:=tisnode;
+end.
diff --git a/compiler/ncon.pas b/compiler/ncon.pas
new file mode 100644
index 0000000000..492d8832fa
--- /dev/null
+++ b/compiler/ncon.pas
@@ -0,0 +1,917 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for constants
+
+ 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 ncon;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,widestr,
+ node,
+ aasmbase,aasmtai,cpuinfo,globals,
+ symconst,symtype,symdef,symsym;
+
+ type
+ trealconstnode = class(tnode)
+ restype : ttype;
+ value_real : bestreal;
+ lab_real : tasmlabel;
+ constructor create(v : bestreal;const t:ttype);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ procedure printnodedata(var t:text);override;
+ end;
+ trealconstnodeclass = class of trealconstnode;
+
+ tordconstnode = class(tnode)
+ restype : ttype;
+ value : TConstExprInt;
+ rangecheck : boolean;
+ { create an ordinal constant node of the specified type and value.
+ _rangecheck determines if the value of the ordinal should be checked
+ against the ranges of the type definition.
+ }
+ constructor create(v : tconstexprint;const t:ttype; _rangecheck : boolean);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ procedure printnodedata(var t:text);override;
+ end;
+ tordconstnodeclass = class of tordconstnode;
+
+ tpointerconstnode = class(tnode)
+ restype : ttype;
+ value : TConstPtrUInt;
+ constructor create(v : TConstPtrUInt;const t:ttype);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ end;
+ tpointerconstnodeclass = class of tpointerconstnode;
+
+ tstringconstnode = class(tnode)
+ value_str : pchar;
+ len : longint;
+ lab_str : tasmlabel;
+ st_type : tstringtype;
+ constructor createstr(const s : string;st:tstringtype);virtual;
+ constructor createpchar(s : pchar;l : longint;st:tstringtype);virtual;
+ constructor createwstr(w : pcompilerwidestring);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ destructor destroy;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function getpcharcopy : pchar;
+ function docompare(p: tnode) : boolean; override;
+ procedure changestringtype(const newtype:ttype);
+ end;
+ tstringconstnodeclass = class of tstringconstnode;
+
+ tsetconstnode = class(tunarynode)
+ restype : ttype;
+ value_set : pconstset;
+ lab_set : tasmlabel;
+ constructor create(s : pconstset;const t:ttype);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ end;
+ tsetconstnodeclass = class of tsetconstnode;
+
+ tnilnode = class(tnode)
+ constructor create;virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ end;
+ tnilnodeclass = class of tnilnode;
+
+ tguidconstnode = class(tnode)
+ value : tguid;
+ constructor create(const g:tguid);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ end;
+ tguidconstnodeclass = class of tguidconstnode;
+
+ var
+ crealconstnode : trealconstnodeclass;
+ cordconstnode : tordconstnodeclass;
+ cpointerconstnode : tpointerconstnodeclass;
+ cstringconstnode : tstringconstnodeclass;
+ csetconstnode : tsetconstnodeclass;
+ cguidconstnode : tguidconstnodeclass;
+ cnilnode : tnilnodeclass;
+
+ function genintconstnode(v : TConstExprInt) : tordconstnode;
+ function genenumnode(v : tenumsym) : tordconstnode;
+
+ { some helper routines }
+ function get_ordinal_value(p : tnode) : TConstExprInt;
+ function is_constresourcestringnode(p : tnode) : boolean;
+ function str_length(p : tnode) : longint;
+ function is_emptyset(p : tnode):boolean;
+ function genconstsymtree(p : tconstsym) : tnode;
+
+implementation
+
+ uses
+ cutils,
+ verbose,systems,
+ defutil,
+ cpubase,cgbase,
+ nld;
+
+ function genintconstnode(v : TConstExprInt) : tordconstnode;
+ var
+ htype : ttype;
+ begin
+ int_to_type(v,htype);
+ genintconstnode:=cordconstnode.create(v,htype,true);
+ end;
+
+
+ function genenumnode(v : tenumsym) : tordconstnode;
+ var
+ htype : ttype;
+ begin
+ htype.setdef(v.definition);
+ genenumnode:=cordconstnode.create(v.value,htype,true);
+ end;
+
+
+ function get_ordinal_value(p : tnode) : TConstExprInt;
+ begin
+ get_ordinal_value:=0;
+ if is_constnode(p) then
+ begin
+ if p.nodetype=ordconstn then
+ get_ordinal_value:=tordconstnode(p).value
+ else
+ Message(type_e_ordinal_expr_expected);
+ end
+ else
+ Message(type_e_constant_expr_expected);
+ end;
+
+
+ function is_constresourcestringnode(p : tnode) : boolean;
+ begin
+ is_constresourcestringnode:=(p.nodetype=loadn) and
+ (tloadnode(p).symtableentry.typ=constsym) and
+ (tconstsym(tloadnode(p).symtableentry).consttyp=constresourcestring);
+ end;
+
+
+ function str_length(p : tnode) : longint;
+
+ begin
+ str_length:=tstringconstnode(p).len;
+ end;
+
+ function is_emptyset(p : tnode):boolean;
+ begin
+ is_emptyset:=(p.nodetype=setconstn) and
+ (Tsetconstnode(p).value_set^=[]);
+ end;
+
+
+ function genconstsymtree(p : tconstsym) : tnode;
+ var
+ p1 : tnode;
+ len : longint;
+ pc : pchar;
+ begin
+ p1:=nil;
+ case p.consttyp of
+ constord :
+ p1:=cordconstnode.create(p.value.valueord,p.consttype,true);
+ conststring :
+ begin
+ len:=p.value.len;
+ getmem(pc,len+1);
+ move(pchar(p.value.valueptr)^,pc^,len);
+ pc[len]:=#0;
+ p1:=cstringconstnode.createpchar(pc,len,st_conststring);
+ end;
+ constreal :
+ p1:=crealconstnode.create(pbestreal(p.value.valueptr)^,pbestrealtype^);
+ constset :
+ p1:=csetconstnode.create(pconstset(p.value.valueptr),p.consttype);
+ constpointer :
+ p1:=cpointerconstnode.create(p.value.valueordptr,p.consttype);
+ constnil :
+ p1:=cnilnode.create;
+ else
+ internalerror(200205103);
+ end;
+ genconstsymtree:=p1;
+ end;
+
+{*****************************************************************************
+ TREALCONSTNODE
+*****************************************************************************}
+
+ { generic code }
+ { overridden by: }
+ { i386 }
+ constructor trealconstnode.create(v : bestreal;const t:ttype);
+ begin
+ inherited create(realconstn);
+ restype:=t;
+ value_real:=v;
+ lab_real:=nil;
+ end;
+
+ constructor trealconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.gettype(restype);
+ value_real:=ppufile.getreal;
+ lab_real:=tasmlabel(ppufile.getasmsymbol);
+ end;
+
+
+ procedure trealconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(restype);
+ ppufile.putreal(value_real);
+ ppufile.putasmsymbol(lab_real);
+ end;
+
+
+ procedure trealconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ restype.buildderef;
+ end;
+
+
+ procedure trealconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ restype.resolve;
+ objectlibrary.derefasmsymbol(tasmsymbol(lab_real));
+ end;
+
+
+ function trealconstnode._getcopy : tnode;
+
+ var
+ n : trealconstnode;
+
+ begin
+ n:=trealconstnode(inherited _getcopy);
+ n.value_real:=value_real;
+ n.lab_real:=lab_real;
+ _getcopy:=n;
+ end;
+
+ function trealconstnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=restype;
+ end;
+
+ function trealconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CREFERENCE;
+ { needs to be loaded into an FPU register }
+ registersfpu:=1;
+ end;
+
+ function trealconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (value_real = trealconstnode(p).value_real) and
+ { floating point compares for non-numbers give strange results usually }
+ is_number_float(value_real) and
+ is_number_float(trealconstnode(p).value_real);
+ end;
+
+
+ procedure Trealconstnode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'value = ',value_real);
+ end;
+
+
+{*****************************************************************************
+ TORDCONSTNODE
+*****************************************************************************}
+
+ constructor tordconstnode.create(v : tconstexprint;const t:ttype;_rangecheck : boolean);
+
+ begin
+ inherited create(ordconstn);
+ value:=v;
+ restype:=t;
+ rangecheck := _rangecheck;
+ end;
+
+
+ constructor tordconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.gettype(restype);
+ value:=ppufile.getexprint;
+ { normally, the value is already compiled, so we don't need
+ to do once again a range check
+ }
+ rangecheck := false;
+ end;
+
+
+ procedure tordconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(restype);
+ ppufile.putexprint(value);
+ end;
+
+
+ procedure tordconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ restype.buildderef;
+ end;
+
+
+ procedure tordconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ restype.resolve;
+ end;
+
+
+ function tordconstnode._getcopy : tnode;
+
+ var
+ n : tordconstnode;
+
+ begin
+ n:=tordconstnode(inherited _getcopy);
+ n.value:=value;
+ n.restype := restype;
+ _getcopy:=n;
+ end;
+
+ function tordconstnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=restype;
+ { only do range checking when explicitly asked for it }
+ if rangecheck then
+ testrange(resulttype.def,value,false);
+ end;
+
+ function tordconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CONSTANT;
+ end;
+
+ function tordconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (value = tordconstnode(p).value);
+ end;
+
+
+ procedure Tordconstnode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'value = ',value);
+ end;
+
+
+{*****************************************************************************
+ TPOINTERCONSTNODE
+*****************************************************************************}
+
+ constructor tpointerconstnode.create(v : TConstPtrUInt;const t:ttype);
+
+ begin
+ inherited create(pointerconstn);
+ value:=v;
+ restype:=t;
+ end;
+
+
+ constructor tpointerconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.gettype(restype);
+ value:=ppufile.getptruint;
+ end;
+
+
+ procedure tpointerconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(restype);
+ ppufile.putptruint(value);
+ end;
+
+
+ procedure tpointerconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ restype.buildderef;
+ end;
+
+
+ procedure tpointerconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ restype.resolve;
+ end;
+
+
+ function tpointerconstnode._getcopy : tnode;
+
+ var
+ n : tpointerconstnode;
+
+ begin
+ n:=tpointerconstnode(inherited _getcopy);
+ n.value:=value;
+ n.restype := restype;
+ _getcopy:=n;
+ end;
+
+ function tpointerconstnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=restype;
+ end;
+
+ function tpointerconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CONSTANT;
+ end;
+
+ function tpointerconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (value = tpointerconstnode(p).value);
+ end;
+
+
+{*****************************************************************************
+ TSTRINGCONSTNODE
+*****************************************************************************}
+
+ constructor tstringconstnode.createstr(const s : string;st:tstringtype);
+ var
+ l : longint;
+ begin
+ inherited create(stringconstn);
+ l:=length(s);
+ len:=l;
+ { stringdup write even past a #0 }
+ getmem(value_str,l+1);
+ move(s[1],value_str^,l);
+ value_str[l]:=#0;
+ lab_str:=nil;
+ st_type:=st;
+ end;
+
+
+ constructor tstringconstnode.createwstr(w : pcompilerwidestring);
+ begin
+ inherited create(stringconstn);
+ len:=getlengthwidestring(w);
+ initwidestring(pcompilerwidestring(value_str));
+ copywidestring(w,pcompilerwidestring(value_str));
+ lab_str:=nil;
+ st_type:=st_widestring;
+ end;
+
+
+ constructor tstringconstnode.createpchar(s : pchar;l : longint;st:tstringtype);
+ begin
+ inherited create(stringconstn);
+ len:=l;
+ value_str:=s;
+ st_type:=st;
+ lab_str:=nil;
+ end;
+
+
+ destructor tstringconstnode.destroy;
+ begin
+ if st_type=st_widestring then
+ donewidestring(pcompilerwidestring(value_str))
+ else
+ ansistringdispose(value_str,len);
+ inherited destroy;
+ end;
+
+
+ constructor tstringconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ var
+ pw : pcompilerwidestring;
+ begin
+ inherited ppuload(t,ppufile);
+ st_type:=tstringtype(ppufile.getbyte);
+ len:=ppufile.getlongint;
+ if st_type=st_widestring then
+ begin
+ initwidestring(pw);
+ setlengthwidestring(pw,len);
+ ppufile.getdata(pw^.data,pw^.len*sizeof(tcompilerwidechar));
+ pcompilerwidestring(value_str):=pw
+ end
+ else
+ begin
+ getmem(value_str,len+1);
+ ppufile.getdata(value_str^,len);
+ value_str[len]:=#0;
+ end;
+ lab_str:=tasmlabel(ppufile.getasmsymbol);
+ end;
+
+
+ procedure tstringconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(st_type));
+ ppufile.putlongint(len);
+ if st_type=st_widestring then
+ ppufile.putdata(pcompilerwidestring(value_str)^.data,len*sizeof(tcompilerwidechar))
+ else
+ ppufile.putdata(value_str^,len);
+ ppufile.putasmsymbol(lab_str);
+ end;
+
+
+ procedure tstringconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ end;
+
+
+ procedure tstringconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ objectlibrary.derefasmsymbol(tasmsymbol(lab_str));
+ end;
+
+
+ function tstringconstnode._getcopy : tnode;
+
+ var
+ n : tstringconstnode;
+
+ begin
+ n:=tstringconstnode(inherited _getcopy);
+ n.st_type:=st_type;
+ n.len:=len;
+ n.lab_str:=lab_str;
+ if st_type=st_widestring then
+ begin
+ initwidestring(pcompilerwidestring(n.value_str));
+ copywidestring(pcompilerwidestring(value_str),pcompilerwidestring(n.value_str));
+ end
+ else
+ n.value_str:=getpcharcopy;
+ _getcopy:=n;
+ end;
+
+ function tstringconstnode.det_resulttype:tnode;
+ var
+ l : aint;
+ begin
+ result:=nil;
+ case st_type of
+ st_conststring :
+ begin
+ { handle and store as array[0..len-1] of char }
+ if len>0 then
+ l:=len-1
+ else
+ l:=0;
+ resulttype.setdef(tarraydef.create(0,l,s32inttype));
+ tarraydef(resulttype.def).setelementtype(cchartype);
+ end;
+ st_shortstring :
+ resulttype:=cshortstringtype;
+ st_ansistring :
+ resulttype:=cansistringtype;
+ st_widestring :
+ resulttype:=cwidestringtype;
+ st_longstring :
+ resulttype:=clongstringtype;
+ end;
+ end;
+
+ function tstringconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ if (st_type in [st_ansistring,st_widestring]) and
+ (len=0) then
+ expectloc:=LOC_CONSTANT
+ else
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+ function tstringconstnode.getpcharcopy : pchar;
+ var
+ pc : pchar;
+ begin
+ pc:=nil;
+ getmem(pc,len+1);
+ if pc=nil then
+ Message(general_f_no_memory_left);
+ move(value_str^,pc^,len+1);
+ getpcharcopy:=pc;
+ end;
+
+ function tstringconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (len = tstringconstnode(p).len) and
+ { Don't compare the pchars, since they may contain null chars }
+ { Since all equal constant strings are replaced by the same }
+ { label, the following compare should be enough (JM) }
+ (lab_str = tstringconstnode(p).lab_str);
+ end;
+
+
+ procedure tstringconstnode.changestringtype(const newtype:ttype);
+ var
+ pw : pcompilerwidestring;
+ pc : pchar;
+ begin
+ if newtype.def.deftype<>stringdef then
+ internalerror(200510011);
+ { convert ascii 2 unicode }
+ if (tstringdef(newtype.def).string_typ=st_widestring) and
+ (st_type<>st_widestring) then
+ begin
+ initwidestring(pw);
+ ascii2unicode(value_str,len,pw);
+ ansistringdispose(value_str,len);
+ pcompilerwidestring(value_str):=pw;
+ end
+ else
+ { convert unicode 2 ascii }
+ if (st_type=st_widestring) and
+ (tstringdef(newtype.def).string_typ<>st_widestring) then
+ begin
+ pw:=pcompilerwidestring(value_str);
+ getmem(pc,getlengthwidestring(pw)+1);
+ unicode2ascii(pw,pc);
+ donewidestring(pw);
+ value_str:=pc;
+ end;
+ st_type:=tstringdef(newtype.def).string_typ;
+ resulttype:=newtype;
+ end;
+
+
+{*****************************************************************************
+ TSETCONSTNODE
+*****************************************************************************}
+
+ constructor tsetconstnode.create(s : pconstset;const t:ttype);
+
+ begin
+ inherited create(setconstn,nil);
+ restype:=t;
+ if assigned(s) then
+ begin
+ new(value_set);
+ value_set^:=s^;
+ end
+ else
+ value_set:=nil;
+ end;
+
+ destructor tsetconstnode.destroy;
+ begin
+ if assigned(value_set) then
+ dispose(value_set);
+ inherited destroy;
+ end;
+
+
+ constructor tsetconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.gettype(restype);
+ new(value_set);
+ ppufile.getdata(value_set^,sizeof(tconstset));
+ end;
+
+
+ procedure tsetconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(restype);
+ ppufile.putdata(value_set^,sizeof(tconstset));
+ end;
+
+
+ procedure tsetconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ restype.buildderef;
+ end;
+
+
+ procedure tsetconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ restype.resolve;
+ end;
+
+
+ function tsetconstnode._getcopy : tnode;
+
+ var
+ n : tsetconstnode;
+
+ begin
+ n:=tsetconstnode(inherited _getcopy);
+ if assigned(value_set) then
+ begin
+ new(n.value_set);
+ n.value_set^:=value_set^
+ end
+ else
+ n.value_set:=nil;
+ n.restype := restype;
+ n.lab_set:=lab_set;
+ _getcopy:=n;
+ end;
+
+ function tsetconstnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=restype;
+ end;
+
+ function tsetconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ if tsetdef(resulttype.def).settype=smallset then
+ expectloc:=LOC_CONSTANT
+ else
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+ function tsetconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare:=(inherited docompare(p)) and
+ (value_set^=Tsetconstnode(p).value_set^);
+ end;
+
+
+{*****************************************************************************
+ TNILNODE
+*****************************************************************************}
+
+ constructor tnilnode.create;
+
+ begin
+ inherited create(niln);
+ end;
+
+ function tnilnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidpointertype;
+ end;
+
+ function tnilnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CONSTANT;
+ end;
+
+{*****************************************************************************
+ TGUIDCONSTNODE
+*****************************************************************************}
+
+ constructor tguidconstnode.create(const g:tguid);
+
+ begin
+ inherited create(guidconstn);
+ value:=g;
+ end;
+
+ constructor tguidconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getguid(value);
+ end;
+
+
+ procedure tguidconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putguid(value);
+ end;
+
+
+ function tguidconstnode._getcopy : tnode;
+
+ var
+ n : tguidconstnode;
+
+ begin
+ n:=tguidconstnode(inherited _getcopy);
+ n.value:=value;
+ _getcopy:=n;
+ end;
+
+ function tguidconstnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype.setdef(rec_tguid);
+ end;
+
+ function tguidconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+ function tguidconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (guid2string(value) = guid2string(tguidconstnode(p).value));
+ end;
+
+
+begin
+ crealconstnode:=trealconstnode;
+ cordconstnode:=tordconstnode;
+ cpointerconstnode:=tpointerconstnode;
+ cstringconstnode:=tstringconstnode;
+ csetconstnode:=tsetconstnode;
+ cnilnode:=tnilnode;
+ cguidconstnode:=tguidconstnode;
+end.
diff --git a/compiler/nflw.pas b/compiler/nflw.pas
new file mode 100644
index 0000000000..ec078951cc
--- /dev/null
+++ b/compiler/nflw.pas
@@ -0,0 +1,1444 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Type checking and register allocation for nodes that influence
+ the flow
+
+ 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 nflw;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ node,cpubase,
+ symnot,
+ symtype,symbase,symdef,symsym,
+ optunrol;
+
+ type
+ { flags used by loop nodes }
+ tloopflag = (
+ { set if it is a for ... downto ... do loop }
+ lnf_backward,
+ { Do we need to parse childs to set var state? }
+ lnf_varstate,
+ { Do a test at the begin of the loop?}
+ lnf_testatbegin,
+ { Negate the loop test? }
+ lnf_checknegate,
+ { Should the value of the loop variable on exit be correct. }
+ lnf_dont_mind_loopvar_on_exit);
+ tloopflags = set of tloopflag;
+
+ const
+ { loop flags which must match to consider loop nodes equal regarding the flags }
+ loopflagsequal = [lnf_backward];
+
+ type
+ tlabelnode = class;
+
+ tloopnode = class(tbinarynode)
+ t1,t2 : tnode;
+ loopflags : tloopflags;
+ constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual;
+ destructor destroy;override;
+ function _getcopy : tnode;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure printnodetree(var t:text);override;
+ function docompare(p: tnode): boolean; override;
+ end;
+
+ twhilerepeatnode = class(tloopnode)
+ constructor create(l,r:Tnode;tab,cn:boolean);virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+{$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+{$endif}
+ end;
+ twhilerepeatnodeclass = class of twhilerepeatnode;
+
+ tifnode = class(tloopnode)
+ constructor create(l,r,_t1 : tnode);virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tifnodeclass = class of tifnode;
+
+ tfornode = class(tloopnode)
+ { if count isn divisable by unrolls then
+ the for loop must jump to this label to get the correct
+ number of executions }
+ entrylabel : tnode;
+ loopvar_notid:cardinal;
+ constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;
+ procedure loop_var_access(not_type:Tnotification_flag;symbol:Tsym);
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tfornodeclass = class of tfornode;
+
+ texitnode = class(tunarynode)
+ constructor create(l:tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ texitnodeclass = class of texitnode;
+
+ tbreaknode = class(tnode)
+ constructor create;virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tbreaknodeclass = class of tbreaknode;
+
+ tcontinuenode = class(tnode)
+ constructor create;virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tcontinuenodeclass = class of tcontinuenode;
+
+ tgotonode = class(tnode)
+ { we still need this for resolving forward gotos }
+ labelsym : tlabelsym;
+ labelnode : tlabelnode;
+ exceptionblock : integer;
+{ internlab : tinterngotolabel;}
+ constructor create(p : tlabelnode);virtual;
+ { as long as we don't know the label node we can't resolve it }
+ constructor create_sym(p : tlabelsym);virtual;
+{ constructor createintern(g:tinterngotolabel);}
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ tgotonodeclass = class of tgotonode;
+
+ tlabelnode = class(tunarynode)
+ exceptionblock : integer;
+ { when copying trees, this points to the newly created copy of a label }
+ copiedto : tlabelnode;
+ { contains all goto nodesrefering to this label }
+ referinggotonodes : tlist;
+ constructor create(l:tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ tlabelnodeclass = class of tlabelnode;
+
+ traisenode = class(tbinarynode)
+ frametree : tnode;
+ constructor create(l,taddr,tframe:tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ traisenodeclass = class of traisenode;
+
+ ttryexceptnode = class(tloopnode)
+ constructor create(l,r,_t1 : tnode);virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ ttryexceptnodeclass = class of ttryexceptnode;
+
+ ttryfinallynode = class(tloopnode)
+ implicitframe : boolean;
+ constructor create(l,r:tnode);virtual;
+ constructor create_implicit(l,r,_t1:tnode);virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ ttryfinallynodeclass = class of ttryfinallynode;
+
+ tonnode = class(tbinarynode)
+ exceptsymtable : tsymtable;
+ excepttype : tobjectdef;
+ constructor create(l,r:tnode);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ function _getcopy : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ tonnodeclass = class of tonnode;
+
+ var
+ cwhilerepeatnode : twhilerepeatnodeclass;
+ cifnode : tifnodeclass;
+ cfornode : tfornodeclass;
+ cexitnode : texitnodeclass;
+ cbreaknode : tbreaknodeclass;
+ ccontinuenode : tcontinuenodeclass;
+ cgotonode : tgotonodeclass;
+ clabelnode : tlabelnodeclass;
+ craisenode : traisenodeclass;
+ ctryexceptnode : ttryexceptnodeclass;
+ ctryfinallynode : ttryfinallynodeclass;
+ connode : tonnodeclass;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,paramgr,defcmp,defutil,htypechk,pass_1,
+ ncal,nadd,ncon,nmem,nld,ncnv,nbas,cgobj,nutils,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif}
+ cgbase,procinfo
+ ;
+
+
+{****************************************************************************
+ TLOOPNODE
+*****************************************************************************}
+
+ constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode);
+
+ begin
+ inherited create(tt,l,r);
+ t1:=_t1;
+ t2:=_t2;
+ fileinfo:=l.fileinfo;
+ end;
+
+ destructor tloopnode.destroy;
+
+ begin
+ t1.free;
+ t2.free;
+ inherited destroy;
+ end;
+
+
+ constructor tloopnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ t1:=ppuloadnode(ppufile);
+ t2:=ppuloadnode(ppufile);
+ end;
+
+
+ procedure tloopnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,t1);
+ ppuwritenode(ppufile,t2);
+ end;
+
+
+ procedure tloopnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(t1) then
+ t1.buildderefimpl;
+ if assigned(t2) then
+ t2.buildderefimpl;
+ end;
+
+
+ procedure tloopnode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(t1) then
+ t1.derefimpl;
+ if assigned(t2) then
+ t2.derefimpl;
+ end;
+
+
+ function tloopnode._getcopy : tnode;
+
+ var
+ p : tloopnode;
+
+ begin
+ p:=tloopnode(inherited _getcopy);
+ if assigned(t1) then
+ p.t1:=t1._getcopy
+ else
+ p.t1:=nil;
+ if assigned(t2) then
+ p.t2:=t2._getcopy
+ else
+ p.t2:=nil;
+ p.loopflags:=loopflags;
+ _getcopy:=p;
+ end;
+
+ procedure tloopnode.insertintolist(l : tnodelist);
+
+ begin
+ end;
+
+
+ procedure tloopnode.printnodetree(var t:text);
+ begin
+ write(t,printnodeindention,'(');
+ printnodeindent;
+ printnodeinfo(t);
+ writeln(t);
+ printnode(t,left);
+ printnode(t,right);
+ printnode(t,t1);
+ printnode(t,t2);
+ printnodeunindent;
+ writeln(t,printnodeindention,')');
+ end;
+
+
+ function tloopnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (loopflags*loopflagsequal=tloopnode(p).loopflags*loopflagsequal) and
+ t1.isequal(tloopnode(p).t1) and
+ t2.isequal(tloopnode(p).t2);
+ end;
+
+{****************************************************************************
+ TWHILEREPEATNODE
+*****************************************************************************}
+
+ constructor Twhilerepeatnode.create(l,r:Tnode;tab,cn:boolean);
+ begin
+ inherited create(whilerepeatn,l,r,nil,nil);
+ if tab then
+ include(loopflags, lnf_testatbegin);
+ if cn then
+ include(loopflags,lnf_checknegate);
+ end;
+
+
+ function twhilerepeatnode.det_resulttype:tnode;
+ var
+ t:Tunarynode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+
+ resulttypepass(left);
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+
+ {A not node can be removed.}
+ if left.nodetype=notn then
+ begin
+ t:=Tunarynode(left);
+ left:=Tunarynode(left).left;
+ t.left:=nil;
+ t.destroy;
+ {Symdif operator, in case you are wondering:}
+ loopflags:=loopflags >< [lnf_checknegate];
+ end;
+ { loop instruction }
+ if assigned(right) then
+ resulttypepass(right);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ if not is_boolean(left.resulttype.def) then
+ begin
+ if left.resulttype.def.deftype=variantdef then
+ inserttypeconv(left,booltype)
+ else
+ CGMessage1(type_e_boolean_expr_expected,left.resulttype.def.typename);
+ end;
+
+ { Give warnings for code that will never be executed for
+ while false do }
+ if (lnf_testatbegin in loopflags) and
+ (left.nodetype=ordconstn) and
+ (tordconstnode(left).value=0) and
+ assigned(right) then
+ CGMessagePos(right.fileinfo,cg_w_unreachable_code);
+ end;
+
+
+ function twhilerepeatnode.pass_1 : tnode;
+ var
+ old_t_times : longint;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ old_t_times:=cg.t_times;
+
+ { calc register weight }
+ if not(cs_littlesize in aktglobalswitches ) then
+ cg.t_times:=cg.t_times*8;
+
+ firstpass(left);
+ if codegenerror then
+ exit;
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+
+ { loop instruction }
+ if assigned(right) then
+ begin
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+ if registersint<right.registersint then
+ registersint:=right.registersint;
+ if registersfpu<right.registersfpu then
+ registersfpu:=right.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if registersmmx<right.registersmmx then
+ registersmmx:=right.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+ cg.t_times:=old_t_times;
+ end;
+
+{$ifdef state_tracking}
+ function Twhilerepeatnode.track_state_pass(exec_known:boolean):boolean;
+
+ var condition:Tnode;
+ code:Tnode;
+ done:boolean;
+ value:boolean;
+ change:boolean;
+ firsttest:boolean;
+ factval:Tnode;
+
+ begin
+ track_state_pass:=false;
+ done:=false;
+ firsttest:=true;
+ {For repeat until statements, first do a pass through the code.}
+ if not(lnf_testatbegin in flags) then
+ begin
+ code:=right.getcopy;
+ if code.track_state_pass(exec_known) then
+ track_state_pass:=true;
+ code.destroy;
+ end;
+ repeat
+ condition:=left.getcopy;
+ code:=right.getcopy;
+ change:=condition.track_state_pass(exec_known);
+ factval:=aktstate.find_fact(left);
+ if factval<>nil then
+ begin
+ condition.destroy;
+ condition:=factval.getcopy;
+ change:=true;
+ end;
+ if change then
+ begin
+ track_state_pass:=true;
+ {Force new resulttype pass.}
+ condition.resulttype.def:=nil;
+ do_resulttypepass(condition);
+ end;
+ if is_constboolnode(condition) then
+ begin
+ {Try to turn a while loop into a repeat loop.}
+ if firsttest then
+ exclude(flags,testatbegin);
+ value:=(Tordconstnode(condition).value<>0) xor checknegate;
+ if value then
+ begin
+ if code.track_state_pass(exec_known) then
+ track_state_pass:=true;
+ end
+ else
+ done:=true;
+ end
+ else
+ begin
+ {Remove any modified variables from the state.}
+ code.track_state_pass(false);
+ done:=true;
+ end;
+ code.destroy;
+ condition.destroy;
+ firsttest:=false;
+ until done;
+ {The loop condition is also known, for example:
+ while i<10 do
+ begin
+ ...
+ end;
+
+ When the loop is done, we do know that i<10 = false.
+ }
+ condition:=left.getcopy;
+ if condition.track_state_pass(exec_known) then
+ begin
+ track_state_pass:=true;
+ {Force new resulttype pass.}
+ condition.resulttype.def:=nil;
+ do_resulttypepass(condition);
+ end;
+ if not is_constboolnode(condition) then
+ aktstate.store_fact(condition,
+ cordconstnode.create(byte(checknegate),booltype,true))
+ else
+ condition.destroy;
+ end;
+{$endif}
+
+{*****************************************************************************
+ TIFNODE
+*****************************************************************************}
+
+ constructor tifnode.create(l,r,_t1 : tnode);
+ begin
+ inherited create(ifn,l,r,_t1,nil);
+ end;
+
+
+ function tifnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+
+ resulttypepass(left);
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+
+ { if path }
+ if assigned(right) then
+ resulttypepass(right);
+ { else path }
+ if assigned(t1) then
+ resulttypepass(t1);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ if not is_boolean(left.resulttype.def) then
+ begin
+ if left.resulttype.def.deftype=variantdef then
+ inserttypeconv(left,booltype)
+ else
+ Message1(type_e_boolean_expr_expected,left.resulttype.def.typename);
+ end;
+
+ { optimize constant expressions }
+ if left.nodetype=ordconstn then
+ begin
+ if tordconstnode(left).value=1 then
+ begin
+ if assigned(right) then
+ result:=right
+ else
+ result:=cnothingnode.create;
+ right:=nil;
+ if assigned(t1) then
+ CGMessagePos(t1.fileinfo,cg_w_unreachable_code);
+ end
+ else
+ begin
+ if assigned(t1) then
+ result:=t1
+ else
+ result:=cnothingnode.create;
+ t1:=nil;
+ if assigned(right) then
+ CGMessagePos(right.fileinfo,cg_w_unreachable_code);
+ end;
+ end;
+ end;
+
+
+ function tifnode.pass_1 : tnode;
+ var
+ old_t_times : longint;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ old_t_times:=cg.t_times;
+ firstpass(left);
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+
+ { determines registers weigths }
+ if not(cs_littlesize in aktglobalswitches) then
+ cg.t_times:=cg.t_times div 2;
+ if cg.t_times=0 then
+ cg.t_times:=1;
+
+ { if path }
+ if assigned(right) then
+ begin
+ firstpass(right);
+
+ if registersint<right.registersint then
+ registersint:=right.registersint;
+ if registersfpu<right.registersfpu then
+ registersfpu:=right.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if registersmmx<right.registersmmx then
+ registersmmx:=right.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+ { else path }
+ if assigned(t1) then
+ begin
+ firstpass(t1);
+
+ if registersint<t1.registersint then
+ registersint:=t1.registersint;
+ if registersfpu<t1.registersfpu then
+ registersfpu:=t1.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if registersmmx<t1.registersmmx then
+ registersmmx:=t1.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+ { leave if we've got an error in one of the paths }
+
+ if codegenerror then
+ exit;
+
+ cg.t_times:=old_t_times;
+ end;
+
+
+{*****************************************************************************
+ TFORNODE
+*****************************************************************************}
+
+ constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
+
+ begin
+ inherited create(forn,l,r,_t1,_t2);
+ if back then
+ include(loopflags,lnf_backward);
+ include(loopflags,lnf_testatbegin);
+ end;
+
+ procedure Tfornode.loop_var_access(not_type:Tnotification_flag;
+ symbol:Tsym);
+
+ begin
+ {If there is a read access, the value of the loop counter is important;
+ at the end of the loop the loop variable should contain the value it
+ had in the last iteration.}
+ if not_type=vn_onwrite then
+ begin
+ writeln('Loopvar does not matter on exit');
+ end
+ else
+ begin
+ exclude(loopflags,lnf_dont_mind_loopvar_on_exit);
+ writeln('Loopvar does matter on exit');
+ end;
+ Tabstractvarsym(symbol).unregister_notification(loopvar_notid);
+ end;
+
+ function tfornode.det_resulttype:tnode;
+ var
+ unrollres : tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+
+ { loop unrolling }
+ if cs_loopunroll in aktglobalswitches then
+ begin
+ unrollres:=unroll_loop(self);
+ if assigned(unrollres) then
+ begin
+ resulttypepass(unrollres);
+ result:=unrollres;
+ exit;
+ end;
+ end;
+
+ { process the loopvar, from and to, varstates are already set }
+ resulttypepass(left);
+ resulttypepass(right);
+ resulttypepass(t1);
+
+ {Can we spare the first comparision?}
+ if (t1.nodetype=ordconstn) and
+ (right.nodetype=ordconstn) and
+ (
+ (
+ (lnf_backward in loopflags) and
+ (Tordconstnode(right).value>=Tordconstnode(t1).value)
+ ) or
+ (
+ not(lnf_backward in loopflags) and
+ (Tordconstnode(right).value<=Tordconstnode(t1).value)
+ )
+ ) then
+ exclude(loopflags,lnf_testatbegin);
+
+ { Make sure that the loop var and the
+ from and to values are compatible types }
+ inserttypeconv(right,left.resulttype);
+ inserttypeconv(t1,left.resulttype);
+
+ if assigned(t2) then
+ resulttypepass(t2);
+ end;
+
+
+ function tfornode.pass_1 : tnode;
+ var
+ old_t_times : longint;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ firstpass(left);
+ if left.registersint>registersint then
+ registersint:=left.registersint;
+ if left.registersfpu>registersfpu then
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if left.registersmmx>registersmmx then
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+
+ firstpass(right);
+ if right.registersint>registersint then
+ registersint:=right.registersint;
+ if right.registersfpu>registersfpu then
+ registersfpu:=right.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if right.registersmmx>registersmmx then
+ registersmmx:=right.registersmmx;
+{$endif SUPPORT_MMX}
+
+ firstpass(t1);
+ if t1.registersint>registersint then
+ registersint:=t1.registersint;
+ if t1.registersfpu>registersfpu then
+ registersfpu:=t1.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if t1.registersmmx>registersmmx then
+ registersmmx:=t1.registersmmx;
+{$endif SUPPORT_MMX}
+
+ if assigned(t2) then
+ begin
+ { Calc register weight }
+ old_t_times:=cg.t_times;
+ if not(cs_littlesize in aktglobalswitches) then
+ cg.t_times:=cg.t_times*8;
+ firstpass(t2);
+ if codegenerror then
+ exit;
+ if t2.registersint>registersint then
+ registersint:=t2.registersint;
+ if t2.registersfpu>registersfpu then
+ registersfpu:=t2.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if t2.registersmmx>registersmmx then
+ registersmmx:=t2.registersmmx;
+{$endif SUPPORT_MMX}
+ cg.t_times:=old_t_times;
+ end;
+
+ { we need at least one register for comparisons PM }
+ if registersint=0 then
+ inc(registersint);
+ end;
+
+
+{*****************************************************************************
+ TEXITNODE
+*****************************************************************************}
+
+ constructor texitnode.create(l:tnode);
+ begin
+ inherited create(exitn,l);
+ end;
+
+
+ constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ end;
+
+
+ procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ end;
+
+
+ function texitnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ if assigned(left) then
+ begin
+ { add assignment to funcretsym }
+ inserttypeconv(left,current_procinfo.procdef.rettype);
+ left:=cassignmentnode.create(
+ cloadnode.create(current_procinfo.procdef.funcretsym,current_procinfo.procdef.funcretsym.owner),
+ left);
+ resulttypepass(left);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ end;
+ resulttype:=voidtype;
+ end;
+
+
+ function texitnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ if assigned(left) then
+ begin
+ firstpass(left);
+ if codegenerror then
+ exit;
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+
+{*****************************************************************************
+ TBREAKNODE
+*****************************************************************************}
+
+ constructor tbreaknode.create;
+
+ begin
+ inherited create(breakn);
+ end;
+
+
+ function tbreaknode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ end;
+
+
+ function tbreaknode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+{*****************************************************************************
+ TCONTINUENODE
+*****************************************************************************}
+
+ constructor tcontinuenode.create;
+ begin
+ inherited create(continuen);
+ end;
+
+
+ function tcontinuenode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ end;
+
+
+ function tcontinuenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+{*****************************************************************************
+ TGOTONODE
+*****************************************************************************}
+
+ constructor tgotonode.create(p : tlabelnode);
+ begin
+ inherited create(goton);
+ exceptionblock:=aktexceptblock;
+ labelnode:=p;
+ labelsym:=nil;
+ end;
+
+
+ constructor tgotonode.create_sym(p : tlabelsym);
+ begin
+ inherited create(goton);
+ exceptionblock:=aktexceptblock;
+ if assigned(p.code) then
+ labelnode:=tlabelnode(p.code)
+ else
+ labelnode:=nil;
+ labelsym:=p;
+ end;
+
+
+ constructor tgotonode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ labelnode:=tlabelnode(ppuloadnoderef(ppufile));
+ exceptionblock:=ppufile.getbyte;
+ end;
+
+
+ procedure tgotonode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenoderef(ppufile,labelnode);
+ ppufile.putbyte(exceptionblock);
+ end;
+
+
+ procedure tgotonode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ //!!! deref(labelnode);
+ end;
+
+
+ procedure tgotonode.derefimpl;
+ begin
+ inherited derefimpl;
+ //!!! deref(labelnode);
+ end;
+
+
+ function tgotonode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ end;
+
+
+ function tgotonode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ if not(assigned(labelnode)) then
+ begin
+ if assigned(labelsym.code) then
+ labelnode:=tlabelnode(labelsym.code)
+ else
+ internalerror(200506183);
+ end;
+
+ { check if we don't mess with exception blocks }
+ if assigned(labelnode) and
+ (exceptionblock<>labelnode.exceptionblock) then
+ CGMessage(cg_e_goto_inout_of_exception_block);
+ end;
+
+
+ function tgotonode._getcopy : tnode;
+ var
+ p : tgotonode;
+ i : aint;
+ begin
+ p:=tgotonode(inherited _getcopy);
+ {
+ p.exceptionblock:=exceptionblock;
+ { When we copying, we do an ugly trick to determine if the label used
+ by the current goto node is already copied: if the referinggotonodes
+ contains the current label, it isn't copied yet, so copy also the
+ label node and set the copiedto field to the newly created node.
+
+ If a label to copy is reached the copiedto field is checked. If it's non nil
+ the copiedto field is returned and the copiedto field is reset to nil.
+ }
+ { assume no copying }
+ newlabelnode:=labelnode;
+ for i:=0 to labelnode.copiedto.referingotonodes.count-1 do
+ begin
+ { copy labelnode? }
+ if labelnode.copiedto.referinggotonodes[i]=self then
+ begin
+ oldlabelnode.copiedto:=newlabelnode;
+ end;
+ end;
+ p.labelnode:=newlabelnode;
+ p.labelnode.referinggotonodes.add(self);
+ }
+ result:=p;
+ end;
+
+
+ function tgotonode.docompare(p: tnode): boolean;
+ begin
+ docompare := false;
+ end;
+
+
+{*****************************************************************************
+ TLABELNODE
+*****************************************************************************}
+
+ constructor tlabelnode.create(l:tnode);
+ begin
+ inherited create(labeln,l);
+ exceptionblock:=aktexceptblock;
+ end;
+
+
+ constructor tlabelnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ exceptionblock:=ppufile.getbyte;
+ end;
+
+
+ procedure tlabelnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(exceptionblock);
+ end;
+
+
+ procedure tlabelnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ end;
+
+
+ procedure tlabelnode.derefimpl;
+ begin
+ inherited derefimpl;
+ end;
+
+
+ function tlabelnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ { left could still be unassigned }
+ if assigned(left) then
+ resulttypepass(left);
+ resulttype:=voidtype;
+ end;
+
+
+ function tlabelnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ if assigned(left) then
+ begin
+ firstpass(left);
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+
+ function tlabelnode._getcopy : tnode;
+ var
+ p : tlabelnode;
+ begin
+ p:=tlabelnode(inherited _getcopy);
+ p.exceptionblock:=exceptionblock;
+
+ result:=p;
+ end;
+
+
+ function tlabelnode.docompare(p: tnode): boolean;
+ begin
+ docompare := false;
+ end;
+
+
+{*****************************************************************************
+ TRAISENODE
+*****************************************************************************}
+
+ constructor traisenode.create(l,taddr,tframe:tnode);
+ begin
+ inherited create(raisen,l,taddr);
+ frametree:=tframe;
+ end;
+
+
+ constructor traisenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ frametree:=ppuloadnode(ppufile);
+ end;
+
+
+ procedure traisenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,frametree);
+ end;
+
+
+ procedure traisenode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(frametree) then
+ frametree.buildderefimpl;
+ end;
+
+
+ procedure traisenode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(frametree) then
+ frametree.derefimpl;
+ end;
+
+
+ function traisenode._getcopy : tnode;
+ var
+ n : traisenode;
+ begin
+ n:=traisenode(inherited _getcopy);
+ if assigned(frametree) then
+ n.frametree:=frametree._getcopy
+ else
+ n.frametree:=nil;
+ _getcopy:=n;
+ end;
+
+
+ procedure traisenode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ function traisenode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ if assigned(left) then
+ begin
+ { first para must be a _class_ }
+ resulttypepass(left);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+ if not(is_class(left.resulttype.def)) then
+ CGMessage1(type_e_class_type_expected,left.resulttype.def.typename);
+ { insert needed typeconvs for addr,frame }
+ if assigned(right) then
+ begin
+ { addr }
+ resulttypepass(right);
+ inserttypeconv(right,voidpointertype);
+ { frame }
+ if assigned(frametree) then
+ begin
+ resulttypepass(frametree);
+ inserttypeconv(frametree,voidpointertype);
+ end;
+ end;
+ end;
+ end;
+
+
+ function traisenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ include(current_procinfo.flags,pi_do_call);
+ expectloc:=LOC_VOID;
+ if assigned(left) then
+ begin
+ { first para must be a _class_ }
+ firstpass(left);
+ { insert needed typeconvs for addr,frame }
+ if assigned(right) then
+ begin
+ { addr }
+ firstpass(right);
+ { frame }
+ if assigned(frametree) then
+ firstpass(frametree);
+ end;
+ left_right_max;
+ end;
+ end;
+
+
+ function traisenode.docompare(p: tnode): boolean;
+ begin
+ docompare := false;
+ end;
+
+
+{*****************************************************************************
+ TTRYEXCEPTNODE
+*****************************************************************************}
+
+ constructor ttryexceptnode.create(l,r,_t1 : tnode);
+ begin
+ inherited create(tryexceptn,l,r,_t1,nil);
+ end;
+
+
+ function ttryexceptnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ { on statements }
+ if assigned(right) then
+ resulttypepass(right);
+ { else block }
+ if assigned(t1) then
+ resulttypepass(t1);
+ resulttype:=voidtype;
+ end;
+
+
+ function ttryexceptnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ include(current_procinfo.flags,pi_do_call);
+ expectloc:=LOC_VOID;
+ firstpass(left);
+ { on statements }
+ if assigned(right) then
+ begin
+ firstpass(right);
+ registersint:=max(registersint,right.registersint);
+ registersfpu:=max(registersfpu,right.registersfpu);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(registersmmx,right.registersmmx);
+{$endif SUPPORT_MMX}
+ end;
+ { else block }
+ if assigned(t1) then
+ begin
+ firstpass(t1);
+ registersint:=max(registersint,t1.registersint);
+ registersfpu:=max(registersfpu,t1.registersfpu);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(registersmmx,t1.registersmmx);
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+
+{*****************************************************************************
+ TTRYFINALLYNODE
+*****************************************************************************}
+
+ constructor ttryfinallynode.create(l,r:tnode);
+ begin
+ inherited create(tryfinallyn,l,r,nil,nil);
+ implicitframe:=false;
+ end;
+
+
+ constructor ttryfinallynode.create_implicit(l,r,_t1:tnode);
+ begin
+ inherited create(tryfinallyn,l,r,_t1,nil);
+ implicitframe:=true;
+ end;
+
+
+ function ttryfinallynode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ include(current_procinfo.flags,pi_do_call);
+ resulttype:=voidtype;
+
+ resulttypepass(left);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+
+ resulttypepass(right);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+
+ { special finally block only executed when there was an exception }
+ if assigned(t1) then
+ begin
+ resulttypepass(t1);
+ set_varstate(t1,vs_used,[vsf_must_be_valid]);
+ end;
+ end;
+
+
+ function ttryfinallynode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ firstpass(left);
+
+ firstpass(right);
+ left_right_max;
+
+ if assigned(t1) then
+ begin
+ firstpass(t1);
+ registersint:=max(registersint,t1.registersint);
+ registersfpu:=max(registersfpu,t1.registersfpu);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(registersmmx,t1.registersmmx);
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+
+{*****************************************************************************
+ TONNODE
+*****************************************************************************}
+
+ constructor tonnode.create(l,r:tnode);
+ begin
+ inherited create(onn,l,r);
+ exceptsymtable:=nil;
+ excepttype:=nil;
+ end;
+
+
+ destructor tonnode.destroy;
+ begin
+ { copied nodes don't need to release the symtable }
+ if assigned(exceptsymtable) then
+ exceptsymtable.free;
+ inherited destroy;
+ end;
+
+
+ constructor tonnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ exceptsymtable:=nil;
+ excepttype:=nil;
+ end;
+
+
+ function tonnode._getcopy : tnode;
+ var
+ n : tonnode;
+ begin
+ n:=tonnode(inherited _getcopy);
+ n.exceptsymtable:=exceptsymtable.getcopy;
+ n.excepttype:=excepttype;
+ result:=n;
+ end;
+
+
+ function tonnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ if not(is_class(excepttype)) then
+ CGMessage1(type_e_class_type_expected,excepttype.typename);
+ if assigned(left) then
+ resulttypepass(left);
+ if assigned(right) then
+ resulttypepass(right);
+ end;
+
+
+ function tonnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ include(current_procinfo.flags,pi_do_call);
+ expectloc:=LOC_VOID;
+ registersint:=0;
+ registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=0;
+{$endif SUPPORT_MMX}
+ if assigned(left) then
+ begin
+ firstpass(left);
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+ if assigned(right) then
+ begin
+ firstpass(right);
+ registersint:=max(registersint,right.registersint);
+ registersfpu:=max(registersfpu,right.registersfpu);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(registersmmx,right.registersmmx);
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+
+ function tonnode.docompare(p: tnode): boolean;
+ begin
+ docompare := false;
+ end;
+
+
+begin
+ cwhilerepeatnode:=twhilerepeatnode;
+ cifnode:=tifnode;
+ cfornode:=tfornode;
+ cexitnode:=texitnode;
+ cgotonode:=tgotonode;
+ clabelnode:=tlabelnode;
+ craisenode:=traisenode;
+ ctryexceptnode:=ttryexceptnode;
+ ctryfinallynode:=ttryfinallynode;
+ connode:=tonnode;
+end.
diff --git a/compiler/ninl.pas b/compiler/ninl.pas
new file mode 100644
index 0000000000..332f728d4d
--- /dev/null
+++ b/compiler/ninl.pas
@@ -0,0 +1,2526 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Type checking and register allocation for inline 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 ninl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,htypechk,cpuinfo,symtype;
+
+ {$i compinnr.inc}
+
+ type
+ tinlinenode = class(tunarynode)
+ inlinenumber : byte;
+ constructor create(number : byte;is_const:boolean;l : tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ { All the following routines currently
+ call compilerprocs, unless they are
+ overriden in which case, the code
+ generator handles them.
+ }
+ function first_pi: tnode ; virtual;
+ function first_arctan_real: tnode; virtual;
+ function first_abs_real: tnode; virtual;
+ function first_sqr_real: tnode; virtual;
+ function first_sqrt_real: tnode; virtual;
+ function first_ln_real: tnode; virtual;
+ function first_cos_real: tnode; virtual;
+ function first_sin_real: tnode; virtual;
+ function first_exp_real: tnode; virtual;
+ function first_frac_real: tnode; virtual;
+ function first_round_real: tnode; virtual;
+ function first_trunc_real: tnode; virtual;
+ function first_int_real: tnode; virtual;
+ private
+ function handle_str: tnode;
+ function handle_reset_rewrite_typed: tnode;
+ function handle_read_write: tnode;
+ function handle_val: tnode;
+ end;
+ tinlinenodeclass = class of tinlinenode;
+
+ var
+ cinlinenode : tinlinenodeclass;
+
+ function geninlinenode(number : byte;is_const:boolean;l : tnode) : tinlinenode;
+
+implementation
+
+ uses
+ verbose,globals,systems,
+ globtype, cutils,
+ symconst,symdef,symsym,symtable,paramgr,defutil,
+ pass_1,
+ ncal,ncon,ncnv,nadd,nld,nbas,nflw,nmem,nmat,nutils,
+ cgbase,procinfo
+ ;
+
+ function geninlinenode(number : byte;is_const:boolean;l : tnode) : tinlinenode;
+
+ begin
+ geninlinenode:=cinlinenode.create(number,is_const,l);
+ end;
+
+{*****************************************************************************
+ TINLINENODE
+*****************************************************************************}
+
+ constructor tinlinenode.create(number : byte;is_const:boolean;l : tnode);
+
+ begin
+ inherited create(inlinen,l);
+ if is_const then
+ include(flags,nf_inlineconst);
+ inlinenumber:=number;
+ end;
+
+
+ constructor tinlinenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ inlinenumber:=ppufile.getbyte;
+ end;
+
+
+ procedure tinlinenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(inlinenumber);
+ end;
+
+
+ function tinlinenode._getcopy : tnode;
+ var
+ n : tinlinenode;
+ begin
+ n:=tinlinenode(inherited _getcopy);
+ n.inlinenumber:=inlinenumber;
+ result:=n;
+ end;
+
+
+ function tinlinenode.handle_str : tnode;
+ var
+ lenpara,
+ fracpara,
+ newparas,
+ dest,
+ source : tcallparanode;
+ procname: string;
+ is_real : boolean;
+
+ begin
+ result := cerrornode.create;
+
+ { make sure we got at least two parameters (if we got only one, }
+ { this parameter may not be encapsulated in a callparan) }
+ if not assigned(left) or
+ (left.nodetype <> callparan) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ exit;
+ end;
+
+ { get destination string }
+ dest := tcallparanode(left);
+
+ { get source para (number) }
+ source := dest;
+ while assigned(source.right) do
+ source := tcallparanode(source.right);
+
+ { destination parameter must be a normal (not a colon) parameter, this
+ check is needed because str(v:len) also has 2 parameters }
+ if (source=dest) or
+ (cpf_is_colon_para in tcallparanode(dest).callparaflags) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ exit;
+ end;
+
+ is_real := source.resulttype.def.deftype = floatdef;
+
+ if ((dest.left.resulttype.def.deftype<>stringdef) and
+ not(is_chararray(dest.left.resulttype.def))) or
+ not(is_real or
+ (source.left.resulttype.def.deftype = orddef)) then
+ begin
+ CGMessagePos(fileinfo,parser_e_illegal_expression);
+ exit;
+ end;
+
+ { get len/frac parameters }
+ lenpara := nil;
+ fracpara := nil;
+ if (cpf_is_colon_para in tcallparanode(dest.right).callparaflags) then
+ begin
+ lenpara := tcallparanode(dest.right);
+
+ { we can let the callnode do the type checking of these parameters too, }
+ { but then the error messages aren't as nice }
+ if not is_integer(lenpara.resulttype.def) then
+ begin
+ CGMessagePos1(lenpara.fileinfo,
+ type_e_integer_expr_expected,lenpara.resulttype.def.typename);
+ exit;
+ end;
+ if (cpf_is_colon_para in tcallparanode(lenpara.right).callparaflags) then
+ begin
+ { parameters are in reverse order! }
+ fracpara := lenpara;
+ lenpara := tcallparanode(lenpara.right);
+ if not is_real then
+ begin
+ CGMessagePos(lenpara.fileinfo,parser_e_illegal_colon_qualifier);
+ exit
+ end;
+ if not is_integer(lenpara.resulttype.def) then
+ begin
+ CGMessagePos1(lenpara.fileinfo,
+ type_e_integer_expr_expected,lenpara.resulttype.def.typename);
+ exit;
+ end;
+ end;
+ end;
+
+ { generate the parameter list for the compilerproc }
+ newparas := dest;
+
+ { if we have a float parameter, insert the realtype, len and fracpara parameters }
+ if is_real then
+ begin
+ { insert realtype parameter }
+ newparas.right := ccallparanode.create(cordconstnode.create(
+ ord(tfloatdef(source.left.resulttype.def).typ),s32inttype,true),
+ newparas.right);
+ { if necessary, insert a fraction parameter }
+ if not assigned(fracpara) then
+ begin
+ tcallparanode(newparas.right).right := ccallparanode.create(
+ cordconstnode.create(-1,s32inttype,false),
+ tcallparanode(newparas.right).right);
+ fracpara := tcallparanode(tcallparanode(newparas.right).right);
+ end;
+ { if necessary, insert a length para }
+ if not assigned(lenpara) then
+ fracpara.right := ccallparanode.create(
+ cordconstnode.create(-32767,s32inttype,false),
+ fracpara.right);
+ end
+ else
+ { for a normal parameter, insert a only length parameter if one is missing }
+ if not assigned(lenpara) then
+ newparas.right := ccallparanode.create(cordconstnode.create(-1,s32inttype,false),
+ newparas.right);
+
+ { remove the parameters from the original node so they won't get disposed, }
+ { since they're reused }
+ left := nil;
+
+ { create procedure name }
+ if is_chararray(dest.resulttype.def) then
+ procname:='fpc_chararray_'
+ else
+ procname := 'fpc_' + tstringdef(dest.resulttype.def).stringtypname+'_';
+ if is_real then
+ procname := procname + 'float'
+ else
+ case torddef(source.resulttype.def).typ of
+{$ifdef cpu64bit}
+ u64bit:
+ procname := procname + 'uint';
+{$else}
+ u32bit:
+ procname := procname + 'uint';
+ u64bit:
+ procname := procname + 'qword';
+ scurrency,
+ s64bit:
+ procname := procname + 'int64';
+{$endif}
+ else
+ procname := procname + 'sint';
+ end;
+
+ { free the errornode we generated in the beginning }
+ result.free;
+ { create the call node, }
+ result := ccallnode.createintern(procname,newparas);
+ end;
+
+
+ function tinlinenode.handle_reset_rewrite_typed: tnode;
+ begin
+ { since this is a "in_xxxx_typedfile" node, we can be sure we have }
+ { a typed file as argument and we don't have to check it again (JM) }
+
+ { add the recsize parameter }
+ { note: for some reason, the parameter of intern procedures with only one }
+ { parameter is gets lifted out of its original tcallparanode (see round }
+ { line 1306 of ncal.pas), so recreate a tcallparanode here (JM) }
+ left := ccallparanode.create(cordconstnode.create(
+ tfiledef(left.resulttype.def).typedfiletype.def.size,s32inttype,true),
+ ccallparanode.create(left,nil));
+ { create the correct call }
+ if inlinenumber=in_reset_typedfile then
+ result := ccallnode.createintern('fpc_reset_typed',left)
+ else
+ result := ccallnode.createintern('fpc_rewrite_typed',left);
+ { make sure left doesn't get disposed, since we use it in the new call }
+ left := nil;
+ end;
+
+
+ function tinlinenode.handle_read_write: tnode;
+
+ const
+ procnames: array[boolean,boolean] of string[11] =
+ (('write_text_','read_text_'),('typed_write','typed_read'));
+
+ var
+ filepara,
+ lenpara,
+ fracpara,
+ nextpara,
+ para : tcallparanode;
+ newstatement : tstatementnode;
+ newblock : tblocknode;
+ p1 : tnode;
+ filetemp,
+ temp : ttempcreatenode;
+ procprefix,
+ name : string[31];
+ textsym : ttypesym;
+ readfunctype : ttype;
+ is_typed,
+ do_read,
+ is_real,
+ error_para,
+ found_error : boolean;
+ begin
+ filepara := nil;
+ is_typed := false;
+ filetemp := nil;
+ do_read := inlinenumber in [in_read_x,in_readln_x];
+ { if we fail, we can quickly exit this way. We must generate something }
+ { instead of the inline node, because firstpass will bomb with an }
+ { internalerror if it encounters a read/write }
+ result := cerrornode.create;
+
+ { reverse the parameters (needed to get the colon parameters in the }
+ { correct order when processing write(ln) }
+ left := reverseparameters(tcallparanode(left));
+
+ if assigned(left) then
+ begin
+ { check if we have a file parameter and if yes, what kind it is }
+ filepara := tcallparanode(left);
+
+ if (filepara.resulttype.def.deftype=filedef) then
+ begin
+ if (tfiledef(filepara.resulttype.def).filetyp=ft_untyped) then
+ begin
+ CGMessagePos(fileinfo,type_e_no_read_write_for_untyped_file);
+ exit;
+ end
+ else
+ begin
+ if (tfiledef(filepara.resulttype.def).filetyp=ft_typed) then
+ begin
+ if (inlinenumber in [in_readln_x,in_writeln_x]) then
+ begin
+ CGMessagePos(fileinfo,type_e_no_readln_writeln_for_typed_file);
+ exit;
+ end;
+ is_typed := true;
+ end
+ end;
+ end
+ else
+ filepara := nil;
+ end;
+
+ { create a blocknode in which the successive write/read statements will be }
+ { put, since they belong together. Also create a dummy statement already to }
+ { make inserting of additional statements easier }
+ newblock:=internalstatements(newstatement);
+
+ { if we don't have a filepara, create one containing the default }
+ if not assigned(filepara) then
+ begin
+ { since the input/output variables are threadvars loading them into
+ a temp once is faster. Create a temp which will hold a pointer to the file }
+ filetemp := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent,true);
+ addstatement(newstatement,filetemp);
+
+ { make sure the resulttype of the temp (and as such of the }
+ { temprefs coming after it) is set (necessary because the }
+ { temprefs will be part of the filepara, of which we need }
+ { the resulttype later on and temprefs can only be }
+ { resulttypepassed if the resulttype of the temp is known) }
+ resulttypepass(tnode(filetemp));
+
+ { assign the address of the file to the temp }
+ if do_read then
+ name := 'input'
+ else
+ name := 'output';
+ addstatement(newstatement,
+ cassignmentnode.create(ctemprefnode.create(filetemp),
+ ccallnode.createintern('fpc_get_'+name,nil)));
+
+ { create a new fileparameter as follows: file_type(temp^) }
+ { (so that we pass the value and not the address of the temp }
+ { to the read/write routine) }
+ if not searchsystype('TEXT',textsym) then
+ internalerror(200108313);
+ filepara := ccallparanode.create(ctypeconvnode.create_internal(
+ cderefnode.create(ctemprefnode.create(filetemp)),textsym.restype),nil);
+ end
+ else
+ { remove filepara from the parameter chain }
+ begin
+ left := filepara.right;
+ filepara.right := nil;
+ { the file para is a var parameter, but it must be valid already }
+ set_varstate(filepara.left,vs_used,[vsf_must_be_valid]);
+ { check if we should make a temp to store the result of a complex }
+ { expression (better heuristics, anyone?) (JM) }
+ if (filepara.left.nodetype <> loadn) then
+ begin
+ { create a temp which will hold a pointer to the file }
+ filetemp := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent,true);
+
+ { add it to the statements }
+ addstatement(newstatement,filetemp);
+
+ { make sure the resulttype of the temp (and as such of the }
+ { temprefs coming after it) is set (necessary because the }
+ { temprefs will be part of the filepara, of which we need }
+ { the resulttype later on and temprefs can only be }
+ { resulttypepassed if the resulttype of the temp is known) }
+ resulttypepass(tnode(filetemp));
+
+ { assign the address of the file to the temp }
+ addstatement(newstatement,
+ cassignmentnode.create(ctemprefnode.create(filetemp),
+ caddrnode.create_internal(filepara.left)));
+ resulttypepass(newstatement.left);
+ { create a new fileparameter as follows: file_type(temp^) }
+ { (so that we pass the value and not the address of the temp }
+ { to the read/write routine) }
+ nextpara := ccallparanode.create(ctypeconvnode.create_internal(
+ cderefnode.create(ctemprefnode.create(filetemp)),filepara.left.resulttype),nil);
+
+ { replace the old file para with the new one }
+ filepara.left := nil;
+ filepara.free;
+ filepara := nextpara;
+ end;
+ end;
+
+ { the resulttype of the filepara must be set since it's }
+ { used below }
+ filepara.get_paratype;
+
+ { now, filepara is nowhere referenced anymore, so we can safely dispose it }
+ { if something goes wrong or at the end of the procedure }
+
+ { choose the correct procedure prefix }
+ procprefix := 'fpc_'+procnames[is_typed,do_read];
+
+ { we're going to reuse the paranodes, so make sure they don't get freed }
+ { twice }
+ para := tcallparanode(left);
+ left := nil;
+
+ { no errors found yet... }
+ found_error := false;
+
+ if is_typed then
+ begin
+ { add the typesize to the filepara }
+ if filepara.resulttype.def.deftype=filedef then
+ filepara.right := ccallparanode.create(cordconstnode.create(
+ tfiledef(filepara.resulttype.def).typedfiletype.def.size,s32inttype,true),nil);
+
+ { check for "no parameters" (you need at least one extra para for typed files) }
+ if not assigned(para) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ found_error := true;
+ end;
+
+ { process all parameters }
+ while assigned(para) do
+ begin
+ { check if valid parameter }
+ if para.left.nodetype=typen then
+ begin
+ CGMessagePos(para.left.fileinfo,type_e_cant_read_write_type);
+ found_error := true;
+ end;
+
+ { support writeln(procvar) }
+ if (para.left.resulttype.def.deftype=procvardef) then
+ begin
+ p1:=ccallnode.create_procvar(nil,para.left);
+ resulttypepass(p1);
+ para.left:=p1;
+ end;
+
+ if filepara.resulttype.def.deftype=filedef then
+ inserttypeconv(para.left,tfiledef(filepara.resulttype.def).typedfiletype);
+
+ if assigned(para.right) and
+ (cpf_is_colon_para in tcallparanode(para.right).callparaflags) then
+ begin
+ CGMessagePos(para.right.fileinfo,parser_e_illegal_colon_qualifier);
+
+ { skip all colon para's }
+ nextpara := tcallparanode(tcallparanode(para.right).right);
+ while assigned(nextpara) and
+ (cpf_is_colon_para in nextpara.callparaflags) do
+ nextpara := tcallparanode(nextpara.right);
+
+ found_error := true;
+ end
+ else
+ { get next parameter }
+ nextpara := tcallparanode(para.right);
+
+ { When we have a call, we have a problem: you can't pass the }
+ { result of a call as a formal const parameter. Solution: }
+ { assign the result to a temp and pass this temp as parameter }
+ { This is not very efficient, but write(typedfile,x) is }
+ { already slow by itself anyway (no buffering) (JM) }
+ { Actually, thge same goes for every non-simple expression }
+ { (such as an addition, ...) -> put everything but load nodes }
+ { into temps (JM) }
+ { of course, this must only be allowed for writes!!! (JM) }
+ if not(do_read) and
+ (para.left.nodetype <> loadn) then
+ begin
+ { create temp for result }
+ temp := ctempcreatenode.create(para.left.resulttype,
+ para.left.resulttype.def.size,tt_persistent,false);
+ addstatement(newstatement,temp);
+ { assign result to temp }
+ addstatement(newstatement,
+ cassignmentnode.create(ctemprefnode.create(temp),
+ para.left));
+ { replace (reused) paranode with temp }
+ para.left := ctemprefnode.create(temp);
+ end;
+ { add fileparameter }
+ para.right := filepara.getcopy;
+
+ { create call statment }
+ { since the parameters are in the correct order, we have to insert }
+ { the statements always at the end of the current block }
+ addstatement(newstatement,ccallnode.createintern(procprefix,para));
+
+ { if we used a temp, free it }
+ if para.left.nodetype = temprefn then
+ addstatement(newstatement,ctempdeletenode.create(temp));
+
+ { process next parameter }
+ para := nextpara;
+ end;
+
+ { free the file parameter }
+ filepara.free;
+ end
+ else
+ { text read/write }
+ begin
+ while assigned(para) do
+ begin
+ { is this parameter faulty? }
+ error_para := false;
+ { is this parameter a real? }
+ is_real:=false;
+ { type used for the read(), this is used to check
+ whether a temp is needed for range checking }
+ readfunctype.reset;
+
+ { can't read/write types }
+ if para.left.nodetype=typen then
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end;
+
+ { support writeln(procvar) }
+ if (para.left.resulttype.def.deftype=procvardef) then
+ begin
+ p1:=ccallnode.create_procvar(nil,para.left);
+ resulttypepass(p1);
+ para.left:=p1;
+ end;
+
+ { Currency will be written using the bestreal }
+ if is_currency(para.left.resulttype.def) then
+ inserttypeconv(para.left,pbestrealtype^);
+
+ case para.left.resulttype.def.deftype of
+ stringdef :
+ begin
+ name := procprefix+tstringdef(para.left.resulttype.def).stringtypname;
+ end;
+ pointerdef :
+ begin
+ if (not is_pchar(para.left.resulttype.def)) or do_read then
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end
+ else
+ name := procprefix+'pchar_as_pointer';
+ end;
+ floatdef :
+ begin
+ is_real:=true;
+ name := procprefix+'float';
+ readfunctype:=pbestrealtype^;
+ end;
+ orddef :
+ begin
+ case torddef(para.left.resulttype.def).typ of
+{$ifdef cpu64bit}
+ s64bit,
+{$endif cpu64bit}
+ s8bit,
+ s16bit,
+ s32bit :
+ begin
+ name := procprefix+'sint';
+ readfunctype:=sinttype;
+ end;
+{$ifdef cpu64bit}
+ u64bit,
+{$endif cpu64bit}
+ u8bit,
+ u16bit,
+ u32bit :
+ begin
+ name := procprefix+'uint';
+ readfunctype:=uinttype;
+ end;
+ uchar :
+ begin
+ name := procprefix+'char';
+ readfunctype:=cchartype;
+ end;
+ uwidechar :
+ begin
+ name := procprefix+'widechar';
+ readfunctype:=cwidechartype;
+ end;
+{$ifndef cpu64bit}
+ s64bit :
+ begin
+ name := procprefix+'int64';
+ readfunctype:=s64inttype;
+ end;
+ u64bit :
+ begin
+ name := procprefix+'qword';
+ readfunctype:=u64inttype;
+ end;
+{$endif cpu64bit}
+ bool8bit,
+ bool16bit,
+ bool32bit :
+ begin
+ if do_read then
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end
+ else
+ begin
+ name := procprefix+'boolean';
+ readfunctype:=booltype;
+ end;
+ end
+ else
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end;
+ end;
+ end;
+ variantdef :
+ name:=procprefix+'variant';
+ arraydef :
+ begin
+ if is_chararray(para.left.resulttype.def) then
+ name := procprefix+'pchar_as_array'
+ else
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end
+ end
+ else
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end
+ end;
+
+ { check for length/fractional colon para's }
+ fracpara := nil;
+ lenpara := nil;
+ if assigned(para.right) and
+ (cpf_is_colon_para in tcallparanode(para.right).callparaflags) then
+ begin
+ lenpara := tcallparanode(para.right);
+ if assigned(lenpara.right) and
+ (cpf_is_colon_para in tcallparanode(lenpara.right).callparaflags) then
+ fracpara:=tcallparanode(lenpara.right);
+ end;
+ { get the next parameter now already, because we're going }
+ { to muck around with the pointers }
+ if assigned(fracpara) then
+ nextpara := tcallparanode(fracpara.right)
+ else if assigned(lenpara) then
+ nextpara := tcallparanode(lenpara.right)
+ else
+ nextpara := tcallparanode(para.right);
+
+ { check if a fracpara is allowed }
+ if assigned(fracpara) and not is_real then
+ begin
+ CGMessagePos(fracpara.fileinfo,parser_e_illegal_colon_qualifier);
+ error_para := true;
+ end
+ else if assigned(lenpara) and do_read then
+ begin
+ { I think this is already filtered out by parsing, but I'm not sure (JM) }
+ CGMessagePos(lenpara.fileinfo,parser_e_illegal_colon_qualifier);
+ error_para := true;
+ end;
+
+ { adjust found_error }
+ found_error := found_error or error_para;
+
+ if not error_para then
+ begin
+ { create dummy frac/len para's if necessary }
+ if not do_read then
+ begin
+ { difference in default value for floats and the rest :( }
+ if not is_real then
+ begin
+ if not assigned(lenpara) then
+ lenpara := ccallparanode.create(
+ cordconstnode.create(0,sinttype,false),nil)
+ else
+ { make sure we don't pass the successive }
+ { parameters too. We also already have a }
+ { reference to the next parameter in }
+ { nextpara }
+ lenpara.right := nil;
+ end
+ else
+ begin
+ if not assigned(lenpara) then
+ lenpara := ccallparanode.create(
+ cordconstnode.create(-32767,sinttype,false),nil);
+ { also create a default fracpara if necessary }
+ if not assigned(fracpara) then
+ fracpara := ccallparanode.create(
+ cordconstnode.create(-1,sinttype,false),nil);
+ { add it to the lenpara }
+ lenpara.right := fracpara;
+ { and add the realtype para (this also removes the link }
+ { to any parameters coming after it) }
+ fracpara.right := ccallparanode.create(
+ cordconstnode.create(ord(tfloatdef(para.left.resulttype.def).typ),
+ sinttype,true),nil);
+ end;
+ end;
+
+ { special handling of reading small numbers, because the helpers }
+ { expect a longint/card/bestreal var parameter. Use a temp. can't }
+ { use functions because then the call to FPC_IOCHECK destroys }
+ { their result before we can store it }
+ if do_read and
+ assigned(readfunctype.def) and
+ (para.left.resulttype.def<>readfunctype.def) then
+ begin
+ { create the parameter list: the temp ... }
+ temp := ctempcreatenode.create(readfunctype,readfunctype.def.size,tt_persistent,false);
+ addstatement(newstatement,temp);
+
+ { ... and the file }
+ p1 := ccallparanode.create(ctemprefnode.create(temp),
+ filepara.getcopy);
+
+ { create the call to the helper }
+ addstatement(newstatement,
+ ccallnode.createintern(name,tcallparanode(p1)));
+
+ { assign the result to the original var (this automatically }
+ { takes care of range checking) }
+ addstatement(newstatement,
+ cassignmentnode.create(para.left,
+ ctemprefnode.create(temp)));
+
+ { release the temp location }
+ addstatement(newstatement,ctempdeletenode.create(temp));
+
+ { statement of para is used }
+ para.left := nil;
+
+ { free the enclosing tcallparanode, but not the }
+ { parameters coming after it }
+ para.right := nil;
+ para.free;
+ end
+ else
+ { read of non s/u-8/16bit, or a write }
+ begin
+ { add the filepara to the current parameter }
+ para.right := filepara.getcopy;
+ { add the lenpara (fracpara and realtype are already linked }
+ { with it if necessary) }
+ tcallparanode(para.right).right := lenpara;
+ { create the call statement }
+ addstatement(newstatement,
+ ccallnode.createintern(name,para));
+ end
+ end
+ else
+ { error_para = true }
+ begin
+ { free the parameter, since it isn't referenced anywhere anymore }
+ para.right := nil;
+ para.free;
+ if assigned(lenpara) then
+ begin
+ lenpara.right := nil;
+ lenpara.free;
+ end;
+ if assigned(fracpara) then
+ begin
+ fracpara.right := nil;
+ fracpara.free;
+ end;
+ end;
+
+ { process next parameter }
+ para := nextpara;
+ end;
+
+ { if no error, add the write(ln)/read(ln) end calls }
+ if not found_error then
+ begin
+ case inlinenumber of
+ in_read_x:
+ name:='fpc_read_end';
+ in_write_x:
+ name:='fpc_write_end';
+ in_readln_x:
+ name:='fpc_readln_end';
+ in_writeln_x:
+ name:='fpc_writeln_end';
+ end;
+ addstatement(newstatement,ccallnode.createintern(name,filepara));
+ end;
+ end;
+
+ { if we found an error, simply delete the generated blocknode }
+ if found_error then
+ newblock.free
+ else
+ begin
+ { deallocate the temp for the file para if we used one }
+ if assigned(filetemp) then
+ addstatement(newstatement,ctempdeletenode.create(filetemp));
+ { otherwise return the newly generated block of instructions, }
+ { but first free the errornode we generated at the beginning }
+ result.free;
+ result := newblock
+ end;
+ end;
+
+
+ function tinlinenode.handle_val: tnode;
+ var
+ procname,
+ suffix : string[31];
+ sourcepara,
+ destpara,
+ codepara,
+ sizepara,
+ newparas : tcallparanode;
+ orgcode : tnode;
+ newstatement : tstatementnode;
+ newblock : tblocknode;
+ tempcode : ttempcreatenode;
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ { check the amount of parameters }
+ if not(assigned(left)) or
+ not(assigned(tcallparanode(left).right)) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ exit;
+ end;
+
+ { reverse parameters for easier processing }
+ left := reverseparameters(tcallparanode(left));
+
+ { get the parameters }
+ tempcode := nil;
+ orgcode := nil;
+ sizepara := nil;
+ sourcepara := tcallparanode(left);
+ destpara := tcallparanode(sourcepara.right);
+ codepara := tcallparanode(destpara.right);
+
+ { check if codepara is valid }
+ if assigned(codepara) and
+ (
+ (codepara.resulttype.def.deftype <> orddef)
+{$ifndef cpu64bit}
+ or is_64bitint(codepara.resulttype.def)
+{$endif cpu64bit}
+ ) then
+ begin
+ CGMessagePos1(codepara.fileinfo,type_e_integer_expr_expected,codepara.resulttype.def.typename);
+ exit;
+ end;
+
+ { check if dest para is valid }
+ if not(destpara.resulttype.def.deftype in [orddef,floatdef]) then
+ begin
+ CGMessagePos(destpara.fileinfo,type_e_integer_or_real_expr_expected);
+ exit;
+ end;
+
+ { we're going to reuse the exisiting para's, so make sure they }
+ { won't be disposed }
+ left := nil;
+
+ { create the blocknode which will hold the generated statements + }
+ { an initial dummy statement }
+
+ newblock:=internalstatements(newstatement);
+
+ { do we need a temp for code? Yes, if no code specified, or if }
+ { code is not a 32bit parameter (we already checked whether the }
+ { the code para, if specified, was an orddef) }
+ if not assigned(codepara) or
+ (codepara.resulttype.def.size<>sinttype.def.size) then
+ begin
+ tempcode := ctempcreatenode.create(sinttype,sinttype.def.size,tt_persistent,false);
+ addstatement(newstatement,tempcode);
+ { set the resulttype of the temp (needed to be able to get }
+ { the resulttype of the tempref used in the new code para) }
+ resulttypepass(tnode(tempcode));
+ { create a temp codepara, but save the original code para to }
+ { assign the result to later on }
+ if assigned(codepara) then
+ begin
+ orgcode := codepara.left;
+ codepara.left := ctemprefnode.create(tempcode);
+ end
+ else
+ codepara := ccallparanode.create(ctemprefnode.create(tempcode),nil);
+ { we need its resulttype later on }
+ codepara.get_paratype;
+ end
+ else if (torddef(codepara.resulttype.def).typ = torddef(sinttype.def).typ) then
+ { because code is a var parameter, it must match types exactly }
+ { however, since it will return values in [0..255], both longints }
+ { and cardinals are fine. Since the formal code para type is }
+ { longint, insert a typecoversion to longint for cardinal para's }
+ begin
+ codepara.left := ctypeconvnode.create_internal(codepara.left,sinttype);
+ { make it explicit, oterwise you may get a nonsense range }
+ { check error if the cardinal already contained a value }
+ { > $7fffffff }
+ codepara.get_paratype;
+ end;
+
+ { create the procedure name }
+ procname := 'fpc_val_';
+
+ case destpara.resulttype.def.deftype of
+ orddef:
+ begin
+ case torddef(destpara.resulttype.def).typ of
+{$ifdef cpu64bit}
+ scurrency,
+ s64bit,
+{$endif cpu64bit}
+ s8bit,
+ s16bit,
+ s32bit:
+ begin
+ suffix := 'sint_';
+ { we also need a destsize para in this case }
+ sizepara := ccallparanode.create(cordconstnode.create
+ (destpara.resulttype.def.size,s32inttype,true),nil);
+ end;
+{$ifdef cpu64bit}
+ u64bit,
+{$endif cpu64bit}
+ u8bit,
+ u16bit,
+ u32bit:
+ suffix := 'uint_';
+{$ifndef cpu64bit}
+ scurrency,
+ s64bit: suffix := 'int64_';
+ u64bit: suffix := 'qword_';
+{$endif cpu64bit}
+ else
+ internalerror(200304225);
+ end;
+ end;
+ floatdef:
+ begin
+ suffix := 'real_';
+ end;
+ end;
+
+ procname := procname + suffix;
+
+ { play a trick to have tcallnode handle invalid source parameters: }
+ { the shortstring-longint val routine by default }
+ if (sourcepara.resulttype.def.deftype = stringdef) then
+ procname := procname + tstringdef(sourcepara.resulttype.def).stringtypname
+ else
+ procname := procname + 'shortstr';
+
+ { set up the correct parameters for the call: the code para... }
+ newparas := codepara;
+ { and the source para }
+ codepara.right := sourcepara;
+ { sizepara either contains nil if none is needed (which is ok, since }
+ { then the next statement severes any possible links with other paras }
+ { that sourcepara may have) or it contains the necessary size para and }
+ { its right field is nil }
+ sourcepara.right := sizepara;
+
+ { create the call and assign the result to dest (val helpers are functions).
+ Use a trick to prevent a type size mismatch warning to be generated by the
+ assignment node. First convert implicitly to the resulttype. This will insert
+ the range check. The Second conversion is done explicitly to hide the implicit conversion
+ for the assignment node and therefor preventing the warning (PFV) }
+ addstatement(newstatement,cassignmentnode.create(
+ destpara.left,ctypeconvnode.create_internal(ctypeconvnode.create(ccallnode.createintern(procname,newparas),destpara.left.resulttype),destpara.left.resulttype)));
+
+ { dispose of the enclosing paranode of the destination }
+ destpara.left := nil;
+ destpara.right := nil;
+ destpara.free;
+
+ { check if we used a temp for code and whether we have to store }
+ { it to the real code parameter }
+ if assigned(orgcode) then
+ addstatement(newstatement,cassignmentnode.create(
+ orgcode,
+ ctemprefnode.create(tempcode)));
+
+ { release the temp if we allocated one }
+ if assigned(tempcode) then
+ addstatement(newstatement,ctempdeletenode.create(tempcode));
+
+ { free the errornode }
+ result.free;
+ { and return it }
+ result := newblock;
+ end;
+
+
+{$ifdef fpc}
+{$maxfpuregisters 0}
+{$endif fpc}
+
+ function getpi : bestreal;
+ begin
+ {$ifdef x86}
+ { x86 has pi in hardware }
+ result:=pi;
+ {$else x86}
+ {$ifdef cpuextended}
+ result:=extended(MathPiExtended);
+ {$else cpuextended}
+ result:=double(MathPi);
+ {$endif cpuextended}
+ {$endif x86}
+ end;
+
+
+ function tinlinenode.det_resulttype:tnode;
+
+ function do_lowhigh(const t:ttype) : tnode;
+ var
+ v : tconstexprint;
+ enum : tenumsym;
+ hp : tnode;
+ begin
+ case t.def.deftype of
+ orddef:
+ begin
+ if inlinenumber=in_low_x then
+ v:=torddef(t.def).low
+ else
+ v:=torddef(t.def).high;
+ { low/high of torddef are longints, so we need special }
+ { handling for cardinal and 64bit types (JM) }
+ { 1.0.x doesn't support int64($ffffffff) correct, it'll expand
+ to -1 instead of staying $ffffffff. Therefor we use $ffff with
+ shl twice (PFV) }
+ case torddef(t.def).typ of
+ s64bit,scurrency :
+ begin
+ if (inlinenumber=in_low_x) then
+ v := int64($80000000) shl 32
+ else
+ v := (int64($7fffffff) shl 32) or int64($ffff) shl 16 or int64($ffff)
+ end;
+ u64bit :
+ begin
+ { we have to use a dirty trick for high(qword), }
+ { because it's bigger than high(tconstexprint) (JM) }
+ v := 0
+ end
+ else
+ begin
+ if not is_signed(t.def) then
+ v := cardinal(v);
+ end;
+ end;
+ hp:=cordconstnode.create(v,t,true);
+ resulttypepass(hp);
+ { fix high(qword) }
+ if (torddef(t.def).typ=u64bit) and
+ (inlinenumber = in_high_x) then
+ tordconstnode(hp).value := -1; { is the same as qword($ffffffffffffffff) }
+ do_lowhigh:=hp;
+ end;
+ enumdef:
+ begin
+ enum:=tenumsym(tenumdef(t.def).firstenum);
+ v:=tenumdef(t.def).maxval;
+ if inlinenumber=in_high_x then
+ while assigned(enum) and (enum.value <> v) do
+ enum:=enum.nextenum;
+ if not assigned(enum) then
+ internalerror(309993)
+ else
+ hp:=genenumnode(enum);
+ do_lowhigh:=hp;
+ end;
+ else
+ internalerror(87);
+ end;
+ end;
+
+ function getconstrealvalue : bestreal;
+ begin
+ case left.nodetype of
+ ordconstn:
+ getconstrealvalue:=tordconstnode(left).value;
+ realconstn:
+ getconstrealvalue:=trealconstnode(left).value_real;
+ else
+ internalerror(309992);
+ end;
+ end;
+
+ procedure setconstrealvalue(r : bestreal);
+ begin
+ result:=crealconstnode.create(r,pbestrealtype^);
+ end;
+
+
+ function handle_ln_const(r : bestreal) : tnode;
+ begin
+ if r<=0.0 then
+ if (cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches) then
+ begin
+ result:=crealconstnode.create(0,pbestrealtype^);
+ CGMessage(type_e_wrong_math_argument)
+ end
+ else
+ begin
+ if r=0.0 then
+ result:=crealconstnode.create(double(MathQNaN),pbestrealtype^)
+ else
+ result:=crealconstnode.create(double(MathNegInf),pbestrealtype^)
+ end
+ else
+ result:=crealconstnode.create(ln(r),pbestrealtype^)
+ end;
+
+
+ function handle_sqrt_const(r : bestreal) : tnode;
+ begin
+ if r<0.0 then
+ if (cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches) then
+ begin
+ result:=crealconstnode.create(0,pbestrealtype^);
+ CGMessage(type_e_wrong_math_argument)
+ end
+ else
+ result:=crealconstnode.create(double(MathQNaN),pbestrealtype^)
+ else
+ result:=crealconstnode.create(sqrt(r),pbestrealtype^)
+ end;
+
+
+ procedure setfloatresulttype;
+ begin
+ if (left.resulttype.def.deftype=floatdef) and
+ (tfloatdef(left.resulttype.def).typ in [s32real,s64real,s80real,s128real]) then
+ resulttype:=left.resulttype
+ else
+ begin
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+
+ var
+ vl,vl2 : TConstExprInt;
+ vr : bestreal;
+ hightree,
+ hp : tnode;
+ srsym : tsym;
+ checkrange : boolean;
+ label
+ myexit;
+ begin
+ result:=nil;
+ { if we handle writeln; left contains no valid address }
+ if assigned(left) then
+ begin
+ if left.nodetype=callparan then
+ tcallparanode(left).get_paratype
+ else
+ resulttypepass(left);
+ end;
+ inc(parsing_para_level);
+
+ { handle intern constant functions in separate case }
+ if nf_inlineconst in flags then
+ begin
+ { no parameters? }
+ if not assigned(left) then
+ internalerror(200501231)
+ else
+ begin
+ vl:=0;
+ vl2:=0; { second parameter Ex: ptr(vl,vl2) }
+ case left.nodetype of
+ realconstn :
+ begin
+ { Real functions are all handled with internproc below }
+ CGMessage1(type_e_integer_expr_expected,left.resulttype.def.typename)
+ end;
+ ordconstn :
+ vl:=tordconstnode(left).value;
+ callparan :
+ begin
+ { both exists, else it was not generated }
+ vl:=tordconstnode(tcallparanode(left).left).value;
+ vl2:=tordconstnode(tcallparanode(tcallparanode(left).right).left).value;
+ end;
+ else
+ CGMessage(parser_e_illegal_expression);
+ end;
+ case inlinenumber of
+ in_const_abs :
+ hp:=genintconstnode(abs(vl));
+ in_const_sqr :
+ hp:=genintconstnode(sqr(vl));
+ in_const_odd :
+ hp:=cordconstnode.create(byte(odd(vl)),booltype,true);
+ in_const_swap_word :
+ hp:=cordconstnode.create((vl and $ff) shl 8+(vl shr 8),left.resulttype,true);
+ in_const_swap_long :
+ hp:=cordconstnode.create((vl and $ffff) shl 16+(vl shr 16),left.resulttype,true);
+ in_const_swap_qword :
+ hp:=cordconstnode.create((vl and $ffff) shl 32+(vl shr 32),left.resulttype,true);
+ in_const_ptr :
+ hp:=cpointerconstnode.create((vl2 shl 4)+vl,voidfarpointertype);
+ else
+ internalerror(88);
+ end;
+ end;
+ if hp=nil then
+ hp:=cerrornode.create;
+ result:=hp;
+ goto myexit;
+ end
+ else
+ begin
+ case inlinenumber of
+ in_lo_long,
+ in_hi_long,
+ in_lo_qword,
+ in_hi_qword,
+ in_lo_word,
+ in_hi_word :
+ begin
+ { give warning for incompatibility with tp and delphi }
+ if (inlinenumber in [in_lo_long,in_hi_long,in_lo_qword,in_hi_qword]) and
+ ((m_tp7 in aktmodeswitches) or
+ (m_delphi in aktmodeswitches)) then
+ CGMessage(type_w_maybe_wrong_hi_lo);
+ { constant folding }
+ if left.nodetype=ordconstn then
+ begin
+ case inlinenumber of
+ in_lo_word :
+ hp:=cordconstnode.create(tordconstnode(left).value and $ff,left.resulttype,true);
+ in_hi_word :
+ hp:=cordconstnode.create(tordconstnode(left).value shr 8,left.resulttype,true);
+ in_lo_long :
+ hp:=cordconstnode.create(tordconstnode(left).value and $ffff,left.resulttype,true);
+ in_hi_long :
+ hp:=cordconstnode.create(tordconstnode(left).value shr 16,left.resulttype,true);
+ in_lo_qword :
+ hp:=cordconstnode.create(tordconstnode(left).value and $ffffffff,left.resulttype,true);
+ in_hi_qword :
+ hp:=cordconstnode.create(tordconstnode(left).value shr 32,left.resulttype,true);
+ end;
+ result:=hp;
+ goto myexit;
+ end;
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if not is_integer(left.resulttype.def) then
+ CGMessage1(type_e_integer_expr_expected,left.resulttype.def.typename);
+ case inlinenumber of
+ in_lo_word,
+ in_hi_word :
+ resulttype:=u8inttype;
+ in_lo_long,
+ in_hi_long :
+ resulttype:=u16inttype;
+ in_lo_qword,
+ in_hi_qword :
+ resulttype:=u32inttype;
+ end;
+ end;
+
+
+ in_sizeof_x:
+ begin
+ set_varstate(left,vs_used,[]);
+ if paramanager.push_high_param(vs_value,left.resulttype.def,current_procinfo.procdef.proccalloption) then
+ begin
+ hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ if assigned(hightree) then
+ begin
+ hp:=caddnode.create(addn,hightree,
+ cordconstnode.create(1,sinttype,false));
+ if (left.resulttype.def.deftype=arraydef) and
+ (tarraydef(left.resulttype.def).elesize<>1) then
+ hp:=caddnode.create(muln,hp,cordconstnode.create(tarraydef(
+ left.resulttype.def).elesize,sinttype,true));
+ result:=hp;
+ end;
+ end
+ else
+ resulttype:=sinttype;
+ end;
+
+ in_typeof_x:
+ begin
+ set_varstate(left,vs_used,[]);
+ resulttype:=voidpointertype;
+ end;
+
+ in_ord_x:
+ begin
+ if (left.nodetype=ordconstn) then
+ begin
+ hp:=cordconstnode.create(
+ tordconstnode(left).value,sinttype,true);
+ result:=hp;
+ goto myexit;
+ end;
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ case left.resulttype.def.deftype of
+ orddef :
+ begin
+ case torddef(left.resulttype.def).typ of
+ bool8bit,
+ uchar:
+ begin
+ { change to byte() }
+ hp:=ctypeconvnode.create_internal(left,u8inttype);
+ left:=nil;
+ result:=hp;
+ end;
+ bool16bit,
+ uwidechar :
+ begin
+ { change to word() }
+ hp:=ctypeconvnode.create_internal(left,u16inttype);
+ left:=nil;
+ result:=hp;
+ end;
+ bool32bit :
+ begin
+ { change to dword() }
+ hp:=ctypeconvnode.create_internal(left,u32inttype);
+ left:=nil;
+ result:=hp;
+ end;
+ uvoid :
+ CGMessage1(type_e_ordinal_expr_expected,left.resulttype.def.typename);
+ else
+ begin
+ { all other orddef need no transformation }
+ hp:=left;
+ left:=nil;
+ result:=hp;
+ end;
+ end;
+ end;
+ enumdef :
+ begin
+ hp:=ctypeconvnode.create_internal(left,s32inttype);
+ left:=nil;
+ result:=hp;
+ end;
+ pointerdef :
+ begin
+ if m_mac in aktmodeswitches then
+ begin
+ hp:=ctypeconvnode.create_internal(left,ptrinttype);
+ left:=nil;
+ result:=hp;
+ end
+ else
+ CGMessage1(type_e_ordinal_expr_expected,left.resulttype.def.typename);
+ end
+ else
+ CGMessage1(type_e_ordinal_expr_expected,left.resulttype.def.typename);
+ end;
+ end;
+
+ in_chr_byte:
+ begin
+ { convert to explicit char() }
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ hp:=ctypeconvnode.create_internal(left,cchartype);
+ left:=nil;
+ result:=hp;
+ end;
+
+ in_length_x:
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+
+ case left.resulttype.def.deftype of
+ variantdef:
+ begin
+ inserttypeconv(left,cansistringtype);
+ end;
+
+ stringdef :
+ begin
+ { we don't need string convertions here }
+ if (left.nodetype=typeconvn) and
+ (ttypeconvnode(left).left.resulttype.def.deftype=stringdef) then
+ begin
+ hp:=ttypeconvnode(left).left;
+ ttypeconvnode(left).left:=nil;
+ left.free;
+ left:=hp;
+ end;
+
+ { evaluates length of constant strings direct }
+ if (left.nodetype=stringconstn) then
+ begin
+ hp:=cordconstnode.create(
+ tstringconstnode(left).len,s32inttype,true);
+ result:=hp;
+ goto myexit;
+ end;
+ end;
+ orddef :
+ begin
+ { length of char is one allways }
+ if is_char(left.resulttype.def) or
+ is_widechar(left.resulttype.def) then
+ begin
+ hp:=cordconstnode.create(1,s32inttype,false);
+ result:=hp;
+ goto myexit;
+ end
+ else
+ CGMessage(type_e_mismatch);
+ end;
+ pointerdef :
+ begin
+ if is_pchar(left.resulttype.def) then
+ begin
+ hp := ccallparanode.create(left,nil);
+ result := ccallnode.createintern('fpc_pchar_length',hp);
+ { make sure the left node doesn't get disposed, since it's }
+ { reused in the new node (JM) }
+ left:=nil;
+ goto myexit;
+ end
+ else if is_pwidechar(left.resulttype.def) then
+ begin
+ hp := ccallparanode.create(left,nil);
+ result := ccallnode.createintern('fpc_pwidechar_length',hp);
+ { make sure the left node doesn't get disposed, since it's }
+ { reused in the new node (JM) }
+ left:=nil;
+ goto myexit;
+ end
+ else
+ CGMessage(type_e_mismatch);
+ end;
+ arraydef :
+ begin
+ if is_open_array(left.resulttype.def) or
+ is_array_of_const(left.resulttype.def) then
+ begin
+ hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ if assigned(hightree) then
+ begin
+ hp:=caddnode.create(addn,hightree,
+ cordconstnode.create(1,s32inttype,false));
+ result:=hp;
+ end;
+ goto myexit;
+ end
+ else
+ if not is_dynamic_array(left.resulttype.def) then
+ begin
+ hp:=cordconstnode.create(tarraydef(left.resulttype.def).highrange-
+ tarraydef(left.resulttype.def).lowrange+1,
+ s32inttype,true);
+ result:=hp;
+ goto myexit;
+ end
+ else
+ begin
+ hp := ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil);
+ result := ccallnode.createintern('fpc_dynarray_length',hp);
+ { make sure the left node doesn't get disposed, since it's }
+ { reused in the new node (JM) }
+ left:=nil;
+ goto myexit;
+ end;
+ end;
+ else
+ CGMessage(type_e_mismatch);
+ end;
+
+ { shortstring return an 8 bit value as the length
+ is the first byte of the string }
+ if is_shortstring(left.resulttype.def) then
+ resulttype:=u8inttype
+ else
+ resulttype:=sinttype;
+ end;
+
+ in_typeinfo_x:
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ resulttype:=voidpointertype;
+ end;
+
+ in_assigned_x:
+ begin
+ { the parser has already made sure the expression is valid }
+
+ { handle constant expressions }
+ if is_constnode(tcallparanode(left).left) or
+ (tcallparanode(left).left.nodetype = pointerconstn) then
+ begin
+ { let an add node figure it out }
+ result := caddnode.create(unequaln,tcallparanode(left).left,cnilnode.create);
+ tcallparanode(left).left := nil;
+ { free left, because otherwise some code at 'myexit' tries }
+ { to run get_paratype for it, which crashes since left.left }
+ { is now nil }
+ left.free;
+ left := nil;
+ goto myexit;
+ end;
+ { otherwise handle separately, because there could be a procvar, which }
+ { is 2*sizeof(pointer), while we must only check the first pointer }
+ set_varstate(tcallparanode(left).left,vs_used,[vsf_must_be_valid]);
+ resulttype:=booltype;
+ end;
+
+ in_ofs_x :
+ internalerror(2000101001);
+
+ in_seg_x :
+ begin
+ set_varstate(left,vs_used,[]);
+ result:=cordconstnode.create(0,s32inttype,false);
+ goto myexit;
+ end;
+
+ in_pred_x,
+ in_succ_x:
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ resulttype:=left.resulttype;
+ if not is_ordinal(resulttype.def) then
+ CGMessage(type_e_ordinal_expr_expected)
+ else
+ begin
+ if (resulttype.def.deftype=enumdef) and
+ (tenumdef(resulttype.def).has_jumps) then
+ CGMessage(type_e_succ_and_pred_enums_with_assign_not_possible);
+ end;
+
+ { only if the result is an enum do we do range checking }
+ if (resulttype.def.deftype=enumdef) then
+ checkrange := true
+ else
+ checkrange := false;
+
+ { do constant folding after check for jumps }
+ if left.nodetype=ordconstn then
+ begin
+ if inlinenumber=in_succ_x then
+ result:=cordconstnode.create(tordconstnode(left).value+1,left.resulttype,checkrange)
+ else
+ result:=cordconstnode.create(tordconstnode(left).value-1,left.resulttype,checkrange);
+ end;
+ end;
+
+ in_initialize_x,
+ in_finalize_x,
+ in_setlength_x:
+ begin
+ { inlined from pinline }
+ internalerror(200204231);
+ end;
+
+ in_inc_x,
+ in_dec_x:
+ begin
+ resulttype:=voidtype;
+ if assigned(left) then
+ begin
+ { first param must be var }
+ valid_for_var(tcallparanode(left).left);
+ set_varstate(tcallparanode(left).left,vs_used,[vsf_must_be_valid]);
+
+ if (left.resulttype.def.deftype in [enumdef,pointerdef]) or
+ is_ordinal(left.resulttype.def) or
+ is_currency(left.resulttype.def) then
+ begin
+ { value of left gets changed -> must be unique }
+ set_unique(tcallparanode(left).left);
+ { two paras ? }
+ if assigned(tcallparanode(left).right) then
+ begin
+ set_varstate(tcallparanode(tcallparanode(left).right).left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv_internal(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resulttype);
+ if assigned(tcallparanode(tcallparanode(left).right).right) then
+ CGMessage(parser_e_illegal_expression);
+ end;
+ end
+ else
+ CGMessage(type_e_ordinal_expr_expected);
+ end
+ else
+ CGMessage(type_e_mismatch);
+ end;
+
+ in_read_x,
+ in_readln_x,
+ in_write_x,
+ in_writeln_x :
+ begin
+ result := handle_read_write;
+ end;
+
+ in_settextbuf_file_x :
+ begin
+ resulttype:=voidtype;
+ { now we know the type of buffer }
+ srsym:=searchsymonlyin(systemunit,'SETTEXTBUF');
+ hp:=ccallparanode.create(cordconstnode.create(
+ tcallparanode(left).left.resulttype.def.size,s32inttype,true),left);
+ result:=ccallnode.create(hp,tprocsym(srsym),systemunit,nil,[]);
+ left:=nil;
+ end;
+
+ { the firstpass of the arg has been done in firstcalln ? }
+ in_reset_typedfile,
+ in_rewrite_typedfile :
+ begin
+ result := handle_reset_rewrite_typed;
+ end;
+
+ in_str_x_string :
+ begin
+ result := handle_str;
+ end;
+
+ in_val_x :
+ begin
+ result := handle_val;
+ end;
+
+ in_include_x_y,
+ in_exclude_x_y:
+ begin
+ resulttype:=voidtype;
+ { the parser already checks whether we have two (and exectly two) }
+ { parameters (JM) }
+ { first param must be var }
+ valid_for_var(tcallparanode(left).left);
+ set_varstate(tcallparanode(left).left,vs_used,[vsf_must_be_valid]);
+ { check type }
+ if (left.resulttype.def.deftype=setdef) then
+ begin
+ { insert a type conversion }
+ { to the type of the set elements }
+ set_varstate(tcallparanode(tcallparanode(left).right).left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(tcallparanode(tcallparanode(left).right).left,
+ tsetdef(left.resulttype.def).elementtype);
+ end
+ else
+ CGMessage(type_e_mismatch);
+ end;
+
+ in_slice_x:
+ begin
+ result:=nil;
+ resulttype:=tcallparanode(tcallparanode(left).left).resulttype;
+ if not(resulttype.def.deftype=arraydef) then
+ CGMessage(type_e_mismatch);
+ end;
+
+ in_low_x,
+ in_high_x:
+ begin
+ case left.resulttype.def.deftype of
+ orddef,
+ enumdef:
+ begin
+ result:=do_lowhigh(left.resulttype);
+ end;
+ setdef:
+ begin
+ result:=do_lowhigh(tsetdef(left.resulttype.def).elementtype);
+ end;
+ arraydef:
+ begin
+ if inlinenumber=in_low_x then
+ begin
+ result:=cordconstnode.create(tarraydef(
+ left.resulttype.def).lowrange,tarraydef(left.resulttype.def).rangetype,true);
+ end
+ else
+ begin
+ if is_open_array(left.resulttype.def) or
+ is_array_of_const(left.resulttype.def) then
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ result:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ end
+ else
+ if is_dynamic_array(left.resulttype.def) then
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ { can't use inserttypeconv because we need }
+ { an explicit type conversion (JM) }
+ hp := ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil);
+ result := ccallnode.createintern('fpc_dynarray_high',hp);
+ { make sure the left node doesn't get disposed, since it's }
+ { reused in the new node (JM) }
+ left:=nil;
+ end
+ else
+ begin
+ result:=cordconstnode.create(tarraydef(
+ left.resulttype.def).highrange,tarraydef(left.resulttype.def).rangetype,true);
+ end;
+ end;
+ end;
+ stringdef:
+ begin
+ if inlinenumber=in_low_x then
+ begin
+ result:=cordconstnode.create(0,u8inttype,false);
+ end
+ else
+ begin
+ if is_open_string(left.resulttype.def) then
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ result:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry))
+ end
+ else
+ result:=cordconstnode.create(tstringdef(left.resulttype.def).len,u8inttype,true);
+ end;
+ end;
+ else
+ CGMessage(type_e_mismatch);
+ end;
+ end;
+
+ in_exp_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ result:=crealconstnode.create(exp(getconstrealvalue),pbestrealtype^);
+ if (trealconstnode(result).value_real=double(MathInf)) and
+ ((cs_check_range in aktlocalswitches) or
+ (cs_check_overflow in aktlocalswitches)) then
+ begin
+ result:=crealconstnode.create(0,pbestrealtype^);
+ CGMessage(parser_e_range_check_error);
+ end;
+ end
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+ in_trunc_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ vr:=getconstrealvalue;
+ if (vr>=9223372036854775807.5) or (vr<=-9223372036854775808.5) then
+ begin
+ CGMessage(parser_e_range_check_error);
+ result:=cordconstnode.create(1,s64inttype,false)
+ end
+ else
+ result:=cordconstnode.create(trunc(vr),s64inttype,true)
+ end
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=s64inttype;
+ end;
+ end;
+
+ in_round_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ vr:=getconstrealvalue;
+ if (vr>=9223372036854775807.5) or (vr<=-9223372036854775808.5) then
+ begin
+ CGMessage(parser_e_range_check_error);
+ result:=cordconstnode.create(1,s64inttype,false)
+ end
+ else
+ result:=cordconstnode.create(round(vr),s64inttype,true)
+ end
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=s64inttype;
+ end;
+ end;
+
+ in_frac_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(frac(getconstrealvalue))
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+ in_int_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(int(getconstrealvalue))
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+ in_pi_real :
+ begin
+ if block_type=bt_const then
+ setconstrealvalue(getpi)
+ else
+ resulttype:=pbestrealtype^;
+ end;
+
+ in_cos_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(cos(getconstrealvalue))
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+ in_sin_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(sin(getconstrealvalue))
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+ in_arctan_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(arctan(getconstrealvalue))
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+ in_abs_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(abs(getconstrealvalue))
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+ in_sqr_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(sqr(getconstrealvalue))
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ setfloatresulttype;
+ end;
+ end;
+
+ in_sqrt_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ vr:=getconstrealvalue;
+ if vr<0.0 then
+ result:=handle_sqrt_const(vr)
+ else
+ setconstrealvalue(sqrt(vr));
+ end
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ setfloatresulttype;
+ end;
+ end;
+
+ in_ln_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ vr:=getconstrealvalue;
+ if vr<=0.0 then
+ result:=handle_ln_const(vr)
+ else
+ setconstrealvalue(ln(vr));
+ end
+ else
+ begin
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(left,pbestrealtype^);
+ resulttype:=pbestrealtype^;
+ end;
+ end;
+
+ {$ifdef SUPPORT_MMX}
+ in_mmx_pcmpeqb..in_mmx_pcmpgtw:
+ begin
+ end;
+ {$endif SUPPORT_MMX}
+ in_prefetch_var:
+ begin
+ resulttype:=voidtype;
+ end;
+ in_assert_x_y :
+ begin
+ resulttype:=voidtype;
+ if assigned(left) then
+ begin
+ set_varstate(tcallparanode(left).left,vs_used,[vsf_must_be_valid]);
+ { check type }
+ if is_boolean(left.resulttype.def) then
+ begin
+ set_varstate(tcallparanode(tcallparanode(left).right).left,vs_used,[vsf_must_be_valid]);
+ { must always be a string }
+ inserttypeconv(tcallparanode(tcallparanode(left).right).left,cshortstringtype);
+ end
+ else
+ CGMessage1(type_e_boolean_expr_expected,left.resulttype.def.typename);
+ end
+ else
+ CGMessage(type_e_mismatch);
+
+ { We've checked the whole statement for correctness, now we
+ can remove it if assertions are off }
+ if not(cs_do_assertion in aktlocalswitches) then
+ begin
+ { we need a valid node, so insert a nothingn }
+ result:=cnothingnode.create;
+ end
+ else
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+ else
+ internalerror(8);
+ end;
+ end;
+
+ myexit:
+ { Run get_paratype again to update maybe inserted typeconvs }
+ if not codegenerror then
+ begin
+ if assigned(left) and
+ (left.nodetype=callparan) then
+ tcallparanode(left).get_paratype;
+ end;
+ dec(parsing_para_level);
+ end;
+
+
+ function tinlinenode.pass_1 : tnode;
+ var
+ hp,hpp : tnode;
+ shiftconst: longint;
+ tempnode: ttempcreatenode;
+ newstatement: tstatementnode;
+ newblock: tblocknode;
+
+ begin
+ result:=nil;
+ { if we handle writeln; left contains no valid address }
+ if assigned(left) then
+ begin
+ if left.nodetype=callparan then
+ tcallparanode(left).firstcallparan
+ else
+ firstpass(left);
+ left_max;
+ end;
+
+ inc(parsing_para_level);
+ { intern const should already be handled }
+ if nf_inlineconst in flags then
+ internalerror(200104044);
+ case inlinenumber of
+ in_lo_qword,
+ in_hi_qword,
+ in_lo_long,
+ in_hi_long,
+ in_lo_word,
+ in_hi_word:
+ begin
+ shiftconst := 0;
+ case inlinenumber of
+ in_hi_qword:
+ shiftconst := 32;
+ in_hi_long:
+ shiftconst := 16;
+ in_hi_word:
+ shiftconst := 8;
+ end;
+ if shiftconst <> 0 then
+ result := ctypeconvnode.create_internal(cshlshrnode.create(shrn,left,
+ cordconstnode.create(shiftconst,u32inttype,false)),resulttype)
+ else
+ result := ctypeconvnode.create_internal(left,resulttype);
+ left := nil;
+ firstpass(result);
+ end;
+
+ in_sizeof_x:
+ begin
+ if registersint<1 then
+ registersint:=1;
+ expectloc:=LOC_REGISTER;
+ end;
+
+ in_typeof_x:
+ begin
+ if registersint<1 then
+ registersint:=1;
+ expectloc:=LOC_REGISTER;
+ end;
+
+ in_length_x:
+ begin
+ if is_shortstring(left.resulttype.def) then
+ expectloc:=left.expectloc
+ else
+ begin
+ { ansi/wide string }
+ if registersint<1 then
+ registersint:=1;
+ expectloc:=LOC_REGISTER;
+ end;
+ end;
+
+ in_typeinfo_x:
+ begin
+ expectloc:=LOC_REGISTER;
+ registersint:=1;
+ end;
+
+ in_assigned_x:
+ begin
+ expectloc := LOC_JUMP;
+ registersint:=1;
+ end;
+
+ in_pred_x,
+ in_succ_x:
+ begin
+ if is_64bit(resulttype.def) then
+ begin
+ if (registersint<2) then
+ registersint:=2
+ end
+ else
+ begin
+ if (registersint<1) then
+ registersint:=1;
+ end;
+ expectloc:=LOC_REGISTER;
+ end;
+
+ in_setlength_x,
+ in_initialize_x,
+ in_finalize_x:
+ begin
+ expectloc:=LOC_VOID;
+ end;
+
+ in_inc_x,
+ in_dec_x:
+ begin
+ expectloc:=LOC_VOID;
+
+ { check type }
+ if
+{$ifndef cpu64bit}
+ is_64bit(left.resulttype.def) or
+{$endif cpu64bit}
+ { range/overflow checking doesn't work properly }
+ { with the inc/dec code that's generated (JM) }
+ (
+ (((left.resulttype.def.deftype = orddef) and
+ not(is_char(left.resulttype.def)) and
+ not(is_boolean(left.resulttype.def))) or
+ (left.resulttype.def.deftype = pointerdef)) and
+ (aktlocalswitches * [cs_check_overflow,cs_check_range] <> [])
+ ) then
+ { convert to simple add (JM) }
+ begin
+ newblock := internalstatements(newstatement);
+ { extra parameter? }
+ if assigned(tcallparanode(left).right) then
+ begin
+ { Yes, use for add node }
+ hpp := tcallparanode(tcallparanode(left).right).left;
+ tcallparanode(tcallparanode(left).right).left := nil;
+ if assigned(tcallparanode(tcallparanode(left).right).right) then
+ CGMessage(parser_e_illegal_expression);
+ end
+ else
+ begin
+ { no, create constant 1 }
+ hpp := cordconstnode.create(1,tcallparanode(left).left.resulttype,false);
+ end;
+ resulttypepass(hpp);
+{$ifndef cpu64bit}
+ if not((hpp.resulttype.def.deftype=orddef) and
+ (torddef(hpp.resulttype.def).typ<>u32bit)) then
+{$endif cpu64bit}
+ inserttypeconv_internal(hpp,sinttype);
+ { No overflow check for pointer operations, because inc(pointer,-1) will always
+ trigger an overflow. For uint32 it works because then the operation is done
+ in 64bit }
+ if (tcallparanode(left).left.resulttype.def.deftype=pointerdef) then
+ exclude(aktlocalswitches,cs_check_overflow);
+ { make sure we don't call functions part of the left node twice (and generally }
+ { optimize the code generation) }
+ if node_complexity(tcallparanode(left).left) > 1 then
+ begin
+ tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent,true);
+ addstatement(newstatement,tempnode);
+ addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
+ caddrnode.create_internal(tcallparanode(left).left.getcopy)));
+ hp := cderefnode.create(ctemprefnode.create(tempnode));
+ inserttypeconv_internal(hp,tcallparanode(left).left.resulttype);
+ end
+ else
+ begin
+ hp := tcallparanode(left).left.getcopy;
+ tempnode := nil;
+ end;
+ { addition/substraction depending on inc/dec }
+ if inlinenumber = in_inc_x then
+ hpp := caddnode.create(addn,hp,hpp)
+ else
+ hpp := caddnode.create(subn,hp,hpp);
+ { assign result of addition }
+ inserttypeconv_internal(hpp,hp.resulttype);
+ addstatement(newstatement,cassignmentnode.create(hp.getcopy,hpp));
+ { deallocate the temp }
+ if assigned(tempnode) then
+ addstatement(newstatement,ctempdeletenode.create(tempnode));
+ { firstpass it }
+ firstpass(newblock);
+ { return new node }
+ result := newblock;
+ end
+ else if (left.resulttype.def.deftype in [enumdef,pointerdef]) or
+ is_ordinal(left.resulttype.def) then
+ begin
+ { two paras ? }
+ if assigned(tcallparanode(left).right) then
+ begin
+ { need we an additional register ? }
+ if not(is_constintnode(tcallparanode(tcallparanode(left).right).left)) and
+ (tcallparanode(tcallparanode(left).right).left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) and
+ (tcallparanode(tcallparanode(left).right).left.registersint<=1) then
+ inc(registersint);
+
+ { do we need an additional register to restore the first parameter? }
+ if tcallparanode(tcallparanode(left).right).left.registersint>=registersint then
+ inc(registersint);
+ end;
+ end;
+ end;
+
+ in_include_x_y,
+ in_exclude_x_y:
+ begin
+ expectloc:=LOC_VOID;
+
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+ in_exp_real:
+ begin
+ result:= first_exp_real;
+ end;
+
+ in_round_real:
+ begin
+ result:= first_round_real;
+ end;
+
+ in_trunc_real:
+ begin
+ result:= first_trunc_real;
+ end;
+
+ in_int_real:
+ begin
+ result:= first_int_real;
+ end;
+
+ in_frac_real:
+ begin
+ result:= first_frac_real;
+ end;
+
+ in_cos_real:
+ begin
+ result:= first_cos_real;
+ end;
+
+ in_sin_real:
+ begin
+ result := first_sin_real;
+ end;
+
+ in_arctan_real:
+ begin
+ result := first_arctan_real;
+ end;
+
+ in_pi_real :
+ begin
+ result := first_pi;
+ end;
+
+ in_abs_real:
+ begin
+ result := first_abs_real;
+ end;
+
+ in_sqr_real:
+ begin
+ result := first_sqr_real;
+ end;
+
+ in_sqrt_real:
+ begin
+ result := first_sqrt_real;
+ end;
+
+ in_ln_real:
+ begin
+ result := first_ln_real;
+ end;
+
+{$ifdef SUPPORT_MMX}
+ in_mmx_pcmpeqb..in_mmx_pcmpgtw:
+ begin
+ end;
+{$endif SUPPORT_MMX}
+
+ in_assert_x_y :
+ begin
+ expectloc:=LOC_VOID;
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+ in_low_x,
+ in_high_x:
+ internalerror(200104047);
+
+ in_slice_x:
+ internalerror(2005101501);
+
+ in_ord_x,
+ in_chr_byte:
+ begin
+ { should not happend as it's converted to typeconv }
+ internalerror(200104045);
+ end;
+
+ in_ofs_x :
+ internalerror(2000101001);
+
+ in_seg_x :
+ internalerror(200104046);
+
+ in_settextbuf_file_x,
+ in_reset_typedfile,
+ in_rewrite_typedfile,
+ in_str_x_string,
+ in_val_x,
+ in_read_x,
+ in_readln_x,
+ in_write_x,
+ in_writeln_x :
+ begin
+ { should be handled by det_resulttype }
+ internalerror(200108234);
+ end;
+
+ in_prefetch_var:
+ begin
+ expectloc:=LOC_VOID;
+ end;
+
+ else
+ internalerror(8);
+ end;
+ dec(parsing_para_level);
+ end;
+{$ifdef fpc}
+{$maxfpuregisters default}
+{$endif fpc}
+
+ function tinlinenode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (inlinenumber = tinlinenode(p).inlinenumber);
+ end;
+
+
+ function tinlinenode.first_pi : tnode;
+ begin
+ result:=crealconstnode.create(getpi,pbestrealtype^);
+ end;
+
+
+ function tinlinenode.first_arctan_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_arctan_real := ccallnode.createintern('fpc_arctan_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_abs_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_abs_real := ccallnode.createintern('fpc_abs_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_sqr_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_sqr_real := ctypeconvnode.create_internal(ccallnode.createintern('fpc_sqr_real',
+ ccallparanode.create(left,nil)),resulttype);
+ left := nil;
+ end;
+
+ function tinlinenode.first_sqrt_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_sqrt_real := ctypeconvnode.create_internal(ccallnode.createintern('fpc_sqrt_real',
+ ccallparanode.create(left,nil)),resulttype);
+ left := nil;
+ end;
+
+ function tinlinenode.first_ln_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_ln_real := ccallnode.createintern('fpc_ln_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_cos_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_cos_real := ccallnode.createintern('fpc_cos_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_sin_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_sin_real := ccallnode.createintern('fpc_sin_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_exp_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_exp_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_int_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_int_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_frac_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_frac_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_round_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_round_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_trunc_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_trunc_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+begin
+ cinlinenode:=tinlinenode;
+end.
diff --git a/compiler/nld.pas b/compiler/nld.pas
new file mode 100644
index 0000000000..739629b580
--- /dev/null
+++ b/compiler/nld.pas
@@ -0,0 +1,1209 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for load/assignment 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 nld;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif}
+ symconst,symbase,symtype,symsym,symdef;
+
+ type
+ tloadnode = class(tunarynode)
+ symtableentry : tsym;
+ symtableentryderef : tderef;
+ symtable : tsymtable;
+ procdef : tprocdef;
+ procdefderef : tderef;
+ constructor create(v : tsym;st : tsymtable);virtual;
+ constructor create_procvar(v : tsym;d:tprocdef;st : tsymtable);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure set_mp(p:tnode);
+ function is_addr_param_load:boolean;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ procedure mark_write;override;
+ function docompare(p: tnode): boolean; override;
+ procedure printnodedata(var t:text);override;
+ end;
+ tloadnodeclass = class of tloadnode;
+
+ { different assignment types }
+ tassigntype = (at_normal,at_plus,at_minus,at_star,at_slash);
+
+ tassignmentnode = class(tbinarynode)
+ assigntype : tassigntype;
+ constructor create(l,r : tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ {$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+ {$endif state_tracking}
+ function docompare(p: tnode): boolean; override;
+ end;
+ tassignmentnodeclass = class of tassignmentnode;
+
+ tarrayconstructorrangenode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ end;
+ tarrayconstructorrangenodeclass = class of tarrayconstructorrangenode;
+
+ tarrayconstructornode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ procedure force_type(tt:ttype);
+ procedure insert_typeconvs;
+ end;
+ tarrayconstructornodeclass = class of tarrayconstructornode;
+
+ ttypenode = class(tnode)
+ allowed : boolean;
+ restype : ttype;
+ constructor create(t : ttype);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ ttypenodeclass = class of ttypenode;
+
+ trttinode = class(tnode)
+ l1,l2 : longint;
+ rttitype : trttitype;
+ rttidef : tstoreddef;
+ rttidefderef : tderef;
+ constructor create(def:tstoreddef;rt:trttitype);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ trttinodeclass = class of trttinode;
+
+ var
+ cloadnode : tloadnodeclass;
+ cassignmentnode : tassignmentnodeclass;
+ carrayconstructorrangenode : tarrayconstructorrangenodeclass;
+ carrayconstructornode : tarrayconstructornodeclass;
+ ctypenode : ttypenodeclass;
+ crttinode : trttinodeclass;
+
+
+
+implementation
+
+ uses
+ cutils,verbose,globtype,globals,systems,
+ symnot,
+ defutil,defcmp,
+ htypechk,pass_1,procinfo,paramgr,
+ ncon,ninl,ncnv,nmem,ncal,nutils,
+ cgobj,cgbase
+ ;
+
+{*****************************************************************************
+ TLOADNODE
+*****************************************************************************}
+
+ constructor tloadnode.create(v : tsym;st : tsymtable);
+ begin
+ inherited create(loadn,nil);
+ if not assigned(v) then
+ internalerror(200108121);
+ symtableentry:=v;
+ symtable:=st;
+ procdef:=nil;
+ end;
+
+
+ constructor tloadnode.create_procvar(v : tsym;d:tprocdef;st : tsymtable);
+ begin
+ inherited create(loadn,nil);
+ if not assigned(v) then
+ internalerror(200108121);
+ symtableentry:=v;
+ symtable:=st;
+ procdef:=d;
+ end;
+
+
+ constructor tloadnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(symtableentryderef);
+ symtable:=nil;
+ ppufile.getderef(procdefderef);
+ end;
+
+
+ procedure tloadnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(symtableentryderef);
+ ppufile.putderef(procdefderef);
+ end;
+
+
+ procedure tloadnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ symtableentryderef.build(symtableentry);
+ procdefderef.build(procdef);
+ end;
+
+
+ procedure tloadnode.derefimpl;
+ begin
+ inherited derefimpl;
+ symtableentry:=tsym(symtableentryderef.resolve);
+ symtable:=symtableentry.owner;
+ procdef:=tprocdef(procdefderef.resolve);
+ end;
+
+
+ procedure tloadnode.set_mp(p:tnode);
+ begin
+ { typen nodes should not be set }
+ if p.nodetype=typen then
+ internalerror(200301042);
+ left:=p;
+ end;
+
+
+ function tloadnode._getcopy : tnode;
+ var
+ n : tloadnode;
+
+ begin
+ n:=tloadnode(inherited _getcopy);
+ n.symtable:=symtable;
+ n.symtableentry:=symtableentry;
+ n.procdef:=procdef;
+ result:=n;
+ end;
+
+
+ function tloadnode.is_addr_param_load:boolean;
+ begin
+ result:=(symtable.symtabletype=parasymtable) and
+ (symtableentry.typ=paravarsym) and
+ not(vo_has_local_copy in tparavarsym(symtableentry).varoptions) and
+ not(nf_load_self_pointer in flags) and
+ paramanager.push_addr_param(tparavarsym(symtableentry).varspez,tparavarsym(symtableentry).vartype.def,tprocdef(symtable.defowner).proccalloption);
+ end;
+
+
+ function tloadnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ case symtableentry.typ of
+ absolutevarsym :
+ resulttype:=tabsolutevarsym(symtableentry).vartype;
+ constsym:
+ begin
+ if tconstsym(symtableentry).consttyp=constresourcestring then
+ begin
+ {$ifdef ansistring_bits}
+ case aktansistring_bits of
+ sb_16:
+ resulttype:=cansistringtype16;
+ sb_32:
+ resulttype:=cansistringtype32;
+ sb_64:
+ resulttype:=cansistringtype64;
+ end;
+ {$else}
+ resulttype:=cansistringtype
+ {$endif}
+ end
+ else
+ internalerror(22799);
+ end;
+ globalvarsym,
+ paravarsym,
+ localvarsym :
+ begin
+ inc(tabstractvarsym(symtableentry).refs);
+ { Nested variable? The we need to load the framepointer of
+ the parent procedure }
+ if assigned(current_procinfo) then
+ begin
+ if (symtable.symtabletype in [localsymtable,parasymtable]) and
+ (symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel) then
+ begin
+ if assigned(left) then
+ internalerror(200309289);
+ left:=cloadparentfpnode.create(tprocdef(symtable.defowner));
+ { we can't inline the referenced parent procedure }
+ exclude(tprocdef(symtable.defowner).procoptions,po_inline);
+ { reference in nested procedures, variable needs to be in memory }
+ make_not_regable(self);
+ end;
+ { static variables referenced in procedures or from finalization,
+ variable needs to be in memory.
+ It is too hard and the benefit is too small to detect whether a
+ variable is only used in the finalization to add support for it (PFV) }
+ if (symtable.symtabletype=staticsymtable) and
+ (
+ (symtable.symtablelevel<>current_procinfo.procdef.localst.symtablelevel) or
+ (current_procinfo.procdef.proctypeoption=potype_unitfinalize)
+ ) then
+ make_not_regable(self);
+ end;
+ { fix self type which is declared as voidpointer in the
+ definition }
+ if vo_is_self in tabstractvarsym(symtableentry).varoptions then
+ begin
+ resulttype.setdef(tprocdef(symtableentry.owner.defowner)._class);
+ if (po_classmethod in tprocdef(symtableentry.owner.defowner).procoptions) or
+ (po_staticmethod in tprocdef(symtableentry.owner.defowner).procoptions) then
+ resulttype.setdef(tclassrefdef.create(resulttype))
+ else if is_object(resulttype.def) and
+ (nf_load_self_pointer in flags) then
+ resulttype.setdef(tpointerdef.create(resulttype));
+ end
+ else if vo_is_vmt in tabstractvarsym(symtableentry).varoptions then
+ begin
+ resulttype.setdef(tprocdef(symtableentry.owner.defowner)._class);
+ resulttype.setdef(tclassrefdef.create(resulttype));
+ end
+ else
+ resulttype:=tabstractvarsym(symtableentry).vartype;
+ end;
+ typedconstsym :
+ resulttype:=ttypedconstsym(symtableentry).typedconsttype;
+ procsym :
+ begin
+ if not assigned(procdef) then
+ begin
+ if Tprocsym(symtableentry).procdef_count>1 then
+ CGMessage(parser_e_no_overloaded_procvars);
+ procdef:=tprocsym(symtableentry).first_procdef;
+ end;
+
+ { the result is a procdef, addrn and proc_to_procvar
+ typeconvn need this as resulttype so they know
+ that the address needs to be returned }
+ resulttype.setdef(procdef);
+
+ { process methodpointer }
+ if assigned(left) then
+ resulttypepass(left);
+ end;
+ labelsym:
+ resulttype:=voidtype;
+ else
+ internalerror(200104141);
+ end;
+ end;
+
+ procedure Tloadnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ function tloadnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_REFERENCE;
+ registersint:=0;
+ registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=0;
+{$endif SUPPORT_MMX}
+ if (cs_create_pic in aktmoduleswitches) and
+ not(symtableentry.typ in [paravarsym,localvarsym]) then
+ include(current_procinfo.flags,pi_needs_got);
+
+ case symtableentry.typ of
+ absolutevarsym :
+ ;
+ constsym:
+ begin
+ if tconstsym(symtableentry).consttyp=constresourcestring then
+ expectloc:=LOC_CREFERENCE;
+ end;
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ if assigned(left) then
+ firstpass(left);
+ if not is_addr_param_load and
+ tabstractvarsym(symtableentry).is_regvar then
+ begin
+ case tabstractvarsym(symtableentry).varregable of
+ vr_intreg :
+ expectloc:=LOC_CREGISTER;
+ vr_fpureg :
+ expectloc:=LOC_CFPUREGISTER;
+ vr_mmreg :
+ expectloc:=LOC_CMMREGISTER;
+ end
+ end
+ else
+ if (tabstractvarsym(symtableentry).varspez=vs_const) then
+ expectloc:=LOC_CREFERENCE;
+ { we need a register for call by reference parameters }
+ if paramanager.push_addr_param(tabstractvarsym(symtableentry).varspez,tabstractvarsym(symtableentry).vartype.def,pocall_default) then
+ registersint:=1;
+ if ([vo_is_thread_var,vo_is_dll_var]*tabstractvarsym(symtableentry).varoptions)<>[] then
+ registersint:=1;
+ if (target_info.system=system_powerpc_darwin) and
+ ([vo_is_dll_var,vo_is_external] * tabstractvarsym(symtableentry).varoptions <> []) then
+ include(current_procinfo.flags,pi_needs_got);
+ { call to get address of threadvar }
+ if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
+ include(current_procinfo.flags,pi_do_call);
+ if nf_write in flags then
+ Tabstractvarsym(symtableentry).trigger_notifications(vn_onwrite)
+ else
+ Tabstractvarsym(symtableentry).trigger_notifications(vn_onread);
+ { count variable references }
+ if cg.t_times>1 then
+ inc(tabstractvarsym(symtableentry).refs,cg.t_times-1);
+ end;
+ typedconstsym :
+ ;
+ procsym :
+ begin
+ { method pointer ? }
+ if assigned(left) then
+ begin
+ expectloc:=LOC_CREFERENCE;
+ firstpass(left);
+ registersint:=max(registersint,left.registersint);
+ registersfpu:=max(registersfpu,left.registersfpu);
+ {$ifdef SUPPORT_MMX}
+ registersmmx:=max(registersmmx,left.registersmmx);
+ {$endif SUPPORT_MMX}
+ end;
+ end;
+ labelsym :
+ ;
+ else
+ internalerror(200104143);
+ end;
+ end;
+
+
+ function tloadnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (symtableentry = tloadnode(p).symtableentry) and
+ (procdef = tloadnode(p).procdef) and
+ (symtable = tloadnode(p).symtable);
+ end;
+
+
+ procedure Tloadnode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ write(t,printnodeindention,'symbol = ',symtableentry.name);
+ if symtableentry.typ=procsym then
+ write(t,printnodeindention,'procdef = ',procdef.mangledname);
+ writeln(t,'');
+ end;
+
+
+{*****************************************************************************
+ TASSIGNMENTNODE
+*****************************************************************************}
+
+ constructor tassignmentnode.create(l,r : tnode);
+
+ begin
+ inherited create(assignn,l,r);
+ l.mark_write;
+ assigntype:=at_normal;
+ end;
+
+
+ constructor tassignmentnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ assigntype:=tassigntype(ppufile.getbyte);
+ end;
+
+
+ procedure tassignmentnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(assigntype));
+ end;
+
+
+ function tassignmentnode._getcopy : tnode;
+
+ var
+ n : tassignmentnode;
+
+ begin
+ n:=tassignmentnode(inherited _getcopy);
+ n.assigntype:=assigntype;
+ result:=n;
+ end;
+
+
+ function tassignmentnode.det_resulttype:tnode;
+ var
+ hp : tnode;
+ useshelper : boolean;
+ original_size : longint;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ original_size := 0;
+
+ { must be made unique }
+ set_unique(left);
+
+ resulttypepass(left);
+
+ if is_ansistring(left.resulttype.def) then
+ begin
+ { fold <ansistring>:=<ansistring>+<char|shortstring|ansistring> }
+ if (right.nodetype=addn) and
+ left.isequal(tbinarynode(right).left) and
+ { don't fold multiple concatenations else we could get trouble
+ with multiple uses of s
+ }
+ (tbinarynode(right).left.nodetype<>addn) and
+ (tbinarynode(right).right.nodetype<>addn) then
+ begin
+ { don't do a resulttypepass(right), since then the addnode }
+ { may insert typeconversions that make this optimization }
+ { opportunity quite difficult to detect (JM) }
+ resulttypepass(tbinarynode(right).left);
+ resulttypepass(tbinarynode(right).right);
+ if (is_char(tbinarynode(right).right.resulttype.def) or
+ is_shortstring(tbinarynode(right).right.resulttype.def) or
+ is_ansistring(tbinarynode(right).right.resulttype.def)) then
+ begin
+ { remove property flag so it'll not trigger an error }
+ exclude(left.flags,nf_isproperty);
+ { generate call to helper }
+ hp:=ccallparanode.create(tbinarynode(right).right,
+ ccallparanode.create(left,nil));
+ if is_char(tbinarynode(right).right.resulttype.def) then
+ result:=ccallnode.createintern('fpc_'+Tstringdef(left.resulttype.def).stringtypname+'_append_char',hp)
+ else if is_shortstring(tbinarynode(right).right.resulttype.def) then
+ result:=ccallnode.createintern('fpc_'+Tstringdef(left.resulttype.def).stringtypname+'_append_shortstring',hp)
+ else
+ result:=ccallnode.createintern('fpc_'+Tstringdef(left.resulttype.def).stringtypname+'_append_ansistring',hp);
+ tbinarynode(right).right:=nil;
+ left:=nil;
+ exit;
+ end;
+ end;
+ end
+ else
+ if is_shortstring(left.resulttype.def) then
+ begin
+ { fold <shortstring>:=<shortstring>+<shortstring>,
+ <shortstring>+<char> is handled by an optimized node }
+ if (right.nodetype=addn) and
+ left.isequal(tbinarynode(right).left) and
+ { don't fold multiple concatenations else we could get trouble
+ with multiple uses of s }
+ (tbinarynode(right).left.nodetype<>addn) and
+ (tbinarynode(right).right.nodetype<>addn) then
+ begin
+ { don't do a resulttypepass(right), since then the addnode }
+ { may insert typeconversions that make this optimization }
+ { opportunity quite difficult to detect (JM) }
+ resulttypepass(tbinarynode(right).left);
+ resulttypepass(tbinarynode(right).right);
+ if is_shortstring(tbinarynode(right).right.resulttype.def) then
+ begin
+ { remove property flag so it'll not trigger an error }
+ exclude(left.flags,nf_isproperty);
+ { generate call to helper }
+ hp:=ccallparanode.create(tbinarynode(right).right,
+ ccallparanode.create(left,nil));
+ if is_shortstring(tbinarynode(right).right.resulttype.def) then
+ result:=ccallnode.createintern('fpc_shortstr_append_shortstr',hp);
+ tbinarynode(right).right:=nil;
+ left:=nil;
+ exit;
+ end;
+ end;
+ end;
+
+ resulttypepass(right);
+ set_varstate(left,vs_assigned,[]);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support, when we don't expect a procvar
+ then we need to call the procvar }
+ if (left.resulttype.def.deftype<>procvardef) then
+ maybe_call_procvar(right,true);
+
+ { assignments to formaldefs and open arrays aren't allowed }
+ if (left.resulttype.def.deftype=formaldef) or
+ is_open_array(left.resulttype.def) then
+ CGMessage(type_e_operator_not_allowed);
+
+ { test if node can be assigned, properties are allowed }
+ valid_for_assignment(left);
+
+ { assigning nil to a dynamic array clears the array }
+ if is_dynamic_array(left.resulttype.def) and
+ (right.nodetype=niln) then
+ begin
+ hp:=ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(left.resulttype.def),initrtti)),
+ ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil));
+ result := ccallnode.createintern('fpc_dynarray_clear',hp);
+ left:=nil;
+ exit;
+ end;
+
+ { shortstring helpers can do the conversion directly,
+ so treat them separatly }
+ if (is_shortstring(left.resulttype.def)) then
+ begin
+ { insert typeconv, except for chars that are handled in
+ secondpass and except for ansi/wide string that can
+ be converted immediatly }
+ if not(is_char(right.resulttype.def) or
+ (right.resulttype.def.deftype=stringdef)) then
+ inserttypeconv(right,left.resulttype);
+ if right.resulttype.def.deftype=stringdef then
+ begin
+ useshelper:=true;
+ { convert constant strings to shortstrings. But
+ skip empty constant strings, that will be handled
+ in secondpass }
+ if (right.nodetype=stringconstn) then
+ begin
+ { verify if range fits within shortstring }
+ { just emit a warning, delphi gives an }
+ { error, only if the type definition of }
+ { of the string is less < 255 characters }
+ if not is_open_string(left.resulttype.def) and
+ (tstringconstnode(right).len > tstringdef(left.resulttype.def).len) then
+ cgmessage(type_w_string_too_long);
+ inserttypeconv(right,left.resulttype);
+ if (tstringconstnode(right).len=0) then
+ useshelper:=false;
+ end;
+ { rest is done in pass 1 (JM) }
+ if useshelper then
+ exit;
+ end
+ end
+ else
+ begin
+ { get the size before the type conversion - check for all nodes }
+ if assigned(right.resulttype.def) and
+ (right.resulttype.def.deftype in [enumdef,orddef,floatdef]) and
+ (right.nodetype in [loadn,vecn,calln]) then
+ original_size := right.resulttype.def.size;
+ inserttypeconv(right,left.resulttype);
+ end;
+
+ { check if the assignment may cause a range check error }
+ { if its not explicit, and only if the values are }
+ { ordinals, enumdef and floatdef }
+ if (right.nodetype = typeconvn) and
+ not (nf_explicit in ttypeconvnode(right).flags) then
+ begin
+ if assigned(left.resulttype.def) and
+ (left.resulttype.def.deftype in [enumdef,orddef,floatdef]) and
+ not is_boolean(left.resulttype.def) then
+ begin
+ if (original_size <> 0) and
+ (left.resulttype.def.size < original_size) then
+ begin
+ if (cs_check_range in aktlocalswitches) then
+ Message(type_w_smaller_possible_range_check)
+ else
+ Message(type_h_smaller_possible_range_check);
+ end;
+ end;
+ end;
+
+ { call helpers for interface }
+ if is_interfacecom(left.resulttype.def) then
+ begin
+ hp:=ccallparanode.create(ctypeconvnode.create_internal
+ (right,voidpointertype),
+ ccallparanode.create(ctypeconvnode.create_internal
+ (left,voidpointertype),nil));
+ result:=ccallnode.createintern('fpc_intf_assign',hp);
+ left:=nil;
+ right:=nil;
+ exit;
+ end;
+ { call helpers for variant, they can contain non ref. counted types like
+ vararrays which must be really copied }
+ if left.resulttype.def.deftype=variantdef then
+ begin
+ hp:=ccallparanode.create(ctypeconvnode.create_internal(
+ caddrnode.create_internal(right),voidpointertype),
+ ccallparanode.create(ctypeconvnode.create_internal(
+ caddrnode.create_internal(left),voidpointertype),
+ nil));
+ result:=ccallnode.createintern('fpc_variant_copy',hp);
+ left:=nil;
+ right:=nil;
+ exit;
+ end;
+
+ { check if local proc/func is assigned to procvar }
+ if right.resulttype.def.deftype=procvardef then
+ test_local_to_procvar(tprocvardef(right.resulttype.def),left.resulttype.def);
+ end;
+
+
+ function tassignmentnode.pass_1 : tnode;
+ var
+ hp: tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ firstpass(left);
+ firstpass(right);
+ { assignment to refcounted variable -> inc/decref }
+ if (not is_class(left.resulttype.def) and
+ left.resulttype.def.needs_inittable) then
+ include(current_procinfo.flags,pi_do_call);
+
+ if codegenerror then
+ exit;
+
+
+ if (is_shortstring(left.resulttype.def)) then
+ begin
+ if right.resulttype.def.deftype=stringdef then
+ begin
+ if (right.nodetype<>stringconstn) or
+ (tstringconstnode(right).len<>0) then
+ begin
+ if (cs_optimize in aktglobalswitches) and
+ (right.nodetype in [calln,blockn]) and
+ (left.nodetype = temprefn) and
+ is_shortstring(right.resulttype.def) and
+ not is_open_string(left.resulttype.def) and
+ (tstringdef(left.resulttype.def).len = 255) then
+ begin
+ { the blocknode case is handled in pass_2 at the temp }
+ { reference level (mainly for callparatemp) (JM) }
+ if (right.nodetype = calln) then
+ begin
+ tcallnode(right).funcretnode := left;
+ result := right;
+ end
+ else
+ exit;
+ end
+ else
+ begin
+ hp:=ccallparanode.create
+ (right,
+ ccallparanode.create(cinlinenode.create
+ (in_high_x,false,left.getcopy),nil));
+ result:=ccallnode.createinternreturn('fpc_'+tstringdef(right.resulttype.def).stringtypname+'_to_shortstr',hp,left);
+ firstpass(result);
+ end;
+ left:=nil;
+ right:=nil;
+ exit;
+ end;
+ end;
+ end;
+
+ if (cs_optimize in aktglobalswitches) and
+ (right.nodetype = calln) and
+ { left must be a temp, since otherwise as soon as you modify the }
+ { result, the current left node is modified and that one may }
+ { still be an argument to the function or even accessed in the }
+ { function }
+ (((left.nodetype = temprefn) and
+ paramanager.ret_in_param(right.resulttype.def,
+ tcallnode(right).procdefinition.proccalloption)) or
+ { there's special support for ansi/widestrings in the callnode }
+ is_ansistring(right.resulttype.def) or
+ is_widestring(right.resulttype.def)) then
+ begin
+ tcallnode(right).funcretnode := left;
+ result := right;
+ left := nil;
+ right := nil;
+ exit;
+ end;
+
+
+ registersint:=left.registersint+right.registersint;
+ registersfpu:=max(left.registersfpu,right.registersfpu);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(left.registersmmx,right.registersmmx);
+{$endif SUPPORT_MMX}
+ end;
+
+
+ function tassignmentnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (assigntype = tassignmentnode(p).assigntype);
+ end;
+
+{$ifdef state_tracking}
+ function Tassignmentnode.track_state_pass(exec_known:boolean):boolean;
+
+ var se:Tstate_entry;
+
+ begin
+ track_state_pass:=false;
+ if exec_known then
+ begin
+ track_state_pass:=right.track_state_pass(exec_known);
+ {Force a new resulttype pass.}
+ right.resulttype.def:=nil;
+ do_resulttypepass(right);
+ resulttypepass(right);
+ aktstate.store_fact(left.getcopy,right.getcopy);
+ end
+ else
+ aktstate.delete_fact(left);
+ end;
+{$endif}
+
+
+{*****************************************************************************
+ TARRAYCONSTRUCTORRANGENODE
+*****************************************************************************}
+
+ constructor tarrayconstructorrangenode.create(l,r : tnode);
+
+ begin
+ inherited create(arrayconstructorrangen,l,r);
+ end;
+
+ function tarrayconstructorrangenode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ resulttypepass(right);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+ resulttype:=left.resulttype;
+ end;
+
+
+ function tarrayconstructorrangenode.pass_1 : tnode;
+ begin
+ firstpass(left);
+ firstpass(right);
+ expectloc:=LOC_CREFERENCE;
+ calcregisters(self,0,0,0);
+ result:=nil;
+ end;
+
+
+{****************************************************************************
+ TARRAYCONSTRUCTORNODE
+*****************************************************************************}
+
+ constructor tarrayconstructornode.create(l,r : tnode);
+ begin
+ inherited create(arrayconstructorn,l,r);
+ end;
+
+
+ function tarrayconstructornode._getcopy : tnode;
+ var
+ n : tarrayconstructornode;
+ begin
+ n:=tarrayconstructornode(inherited _getcopy);
+ result:=n;
+ end;
+
+
+ function tarrayconstructornode.det_resulttype:tnode;
+ var
+ htype : ttype;
+ hp : tarrayconstructornode;
+ len : longint;
+ varia : boolean;
+ begin
+ result:=nil;
+
+ { are we allowing array constructor? Then convert it to a set }
+ if not allow_array_constructor then
+ begin
+ hp:=tarrayconstructornode(getcopy);
+ arrayconstructor_to_set(tnode(hp));
+ result:=hp;
+ exit;
+ end;
+
+ { only pass left tree, right tree contains next construct if any }
+ htype.reset;
+ len:=0;
+ varia:=false;
+ if assigned(left) then
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ resulttypepass(hp.left);
+ set_varstate(hp.left,vs_used,[vsf_must_be_valid]);
+ if (htype.def=nil) then
+ htype:=hp.left.resulttype
+ else
+ begin
+ if ((nf_novariaallowed in flags) or (not varia)) and
+ (not equal_defs(htype.def,hp.left.resulttype.def)) then
+ begin
+ varia:=true;
+ end;
+ end;
+ inc(len);
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ { Set the type of empty or varia arrays to void. Also
+ do this if the type is array of const/open array
+ because those can't be used with setelementtype }
+ if not assigned(htype.def) or
+ varia or
+ is_array_of_const(htype.def) or
+ is_open_array(htype.def) then
+ htype:=voidtype;
+ resulttype.setdef(tarraydef.create(0,len-1,s32inttype));
+ tarraydef(resulttype.def).setelementtype(htype);
+ tarraydef(resulttype.def).IsConstructor:=true;
+ tarraydef(resulttype.def).IsVariant:=varia;
+ end;
+
+
+ procedure tarrayconstructornode.force_type(tt:ttype);
+ var
+ hp : tarrayconstructornode;
+ begin
+ tarraydef(resulttype.def).setelementtype(tt);
+ tarraydef(resulttype.def).IsConstructor:=true;
+ tarraydef(resulttype.def).IsVariant:=false;
+ if assigned(left) then
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ inserttypeconv(hp.left,tt);
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ end;
+
+
+ procedure tarrayconstructornode.insert_typeconvs;
+ var
+ hp : tarrayconstructornode;
+ dovariant : boolean;
+ begin
+ dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
+ { only pass left tree, right tree contains next construct if any }
+ if assigned(left) then
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ resulttypepass(hp.left);
+ { Insert typeconvs for array of const }
+ if dovariant then
+ begin
+ case hp.left.resulttype.def.deftype of
+ enumdef :
+ hp.left:=ctypeconvnode.create_internal(hp.left,s32inttype);
+ arraydef :
+ begin
+ if is_chararray(hp.left.resulttype.def) then
+ hp.left:=ctypeconvnode.create_internal(hp.left,charpointertype)
+ else
+ if is_widechararray(hp.left.resulttype.def) then
+ hp.left:=ctypeconvnode.create_internal(hp.left,widecharpointertype)
+ else
+ CGMessagePos1(hp.left.fileinfo,type_e_wrong_type_in_array_constructor,hp.left.resulttype.def.typename);
+ end;
+ orddef :
+ begin
+ if is_integer(hp.left.resulttype.def) and
+ not(is_64bitint(hp.left.resulttype.def)) then
+ hp.left:=ctypeconvnode.create(hp.left,s32inttype);
+ end;
+ floatdef :
+ if not(is_currency(hp.left.resulttype.def)) then
+ hp.left:=ctypeconvnode.create(hp.left,pbestrealtype^);
+ procvardef :
+ hp.left:=ctypeconvnode.create(hp.left,voidpointertype);
+ stringdef,
+ variantdef,
+ pointerdef,
+ classrefdef:
+ ;
+ objectdef :
+ if is_object(hp.left.resulttype.def) then
+ CGMessagePos1(hp.left.fileinfo,type_e_wrong_type_in_array_constructor,hp.left.resulttype.def.typename);
+ else
+ CGMessagePos1(hp.left.fileinfo,type_e_wrong_type_in_array_constructor,hp.left.resulttype.def.typename);
+ end;
+ end;
+ resulttypepass(hp.left);
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ end;
+
+
+ function tarrayconstructornode.pass_1 : tnode;
+ var
+ hp : tarrayconstructornode;
+ do_variant:boolean;
+ begin
+ do_variant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
+ result:=nil;
+ { Insert required type convs, this must be
+ done in pass 1, because the call must be
+ resulttypepassed already }
+ if assigned(left) then
+ begin
+ insert_typeconvs;
+ { call firstpass for all nodes }
+ hp:=self;
+ while assigned(hp) do
+ begin
+ if hp.left<>nil then
+ begin
+ {This check is pessimistic; a call will happen depending
+ on the location in which the elements will be found in
+ pass 2.}
+ if not do_variant then
+ include(current_procinfo.flags,pi_do_call);
+ firstpass(hp.left);
+ end;
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ expectloc:=LOC_CREFERENCE;
+ calcregisters(self,0,0,0);
+ end;
+
+
+ function tarrayconstructornode.docompare(p: tnode): boolean;
+
+ begin
+ docompare:=inherited docompare(p);
+ end;
+
+
+{*****************************************************************************
+ TTYPENODE
+*****************************************************************************}
+
+ constructor ttypenode.create(t : ttype);
+ begin
+ inherited create(typen);
+ restype:=t;
+ allowed:=false;
+ end;
+
+
+ constructor ttypenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.gettype(restype);
+ allowed:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure ttypenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(restype);
+ ppufile.putbyte(byte(allowed));
+ end;
+
+
+ procedure ttypenode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ restype.buildderef;
+ end;
+
+
+ procedure ttypenode.derefimpl;
+ begin
+ inherited derefimpl;
+ restype.resolve;
+ end;
+
+
+ function ttypenode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=restype;
+ { check if it's valid }
+ if restype.def.deftype = errordef then
+ CGMessage(parser_e_illegal_expression);
+ end;
+
+
+ function ttypenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ { a typenode can't generate code, so we give here
+ an error. Else it'll be an abstract error in pass_2.
+ Only when the allowed flag is set we don't generate
+ an error }
+ if not allowed then
+ Message(parser_e_no_type_not_allowed_here);
+ end;
+
+
+ function ttypenode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p);
+ end;
+
+
+{*****************************************************************************
+ TRTTINODE
+*****************************************************************************}
+
+
+ constructor trttinode.create(def:tstoreddef;rt:trttitype);
+ begin
+ inherited create(rttin);
+ rttidef:=def;
+ rttitype:=rt;
+ end;
+
+
+ constructor trttinode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(rttidefderef);
+ rttitype:=trttitype(ppufile.getbyte);
+ end;
+
+
+ procedure trttinode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(rttidefderef);
+ ppufile.putbyte(byte(rttitype));
+ end;
+
+
+ procedure trttinode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ rttidefderef.build(rttidef);
+ end;
+
+
+ procedure trttinode.derefimpl;
+ begin
+ inherited derefimpl;
+ rttidef:=tstoreddef(rttidefderef.resolve);
+ end;
+
+
+ function trttinode._getcopy : tnode;
+ var
+ n : trttinode;
+ begin
+ n:=trttinode(inherited _getcopy);
+ n.rttidef:=rttidef;
+ n.rttitype:=rttitype;
+ result:=n;
+ end;
+
+
+ function trttinode.det_resulttype:tnode;
+ begin
+ { rtti information will be returned as a void pointer }
+ result:=nil;
+ resulttype:=voidpointertype;
+ end;
+
+
+ function trttinode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+ function trttinode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (rttidef = trttinode(p).rttidef) and
+ (rttitype = trttinode(p).rttitype);
+ end;
+
+
+begin
+ cloadnode:=tloadnode;
+ cassignmentnode:=tassignmentnode;
+ carrayconstructorrangenode:=tarrayconstructorrangenode;
+ carrayconstructornode:=tarrayconstructornode;
+ ctypenode:=ttypenode;
+ crttinode:=trttinode;
+end.
diff --git a/compiler/nmat.pas b/compiler/nmat.pas
new file mode 100644
index 0000000000..dffa161df7
--- /dev/null
+++ b/compiler/nmat.pas
@@ -0,0 +1,950 @@
+{
+ Copyright (c) 2000-2005 by Florian Klaempfl
+
+ Type checking and register allocation for math 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 nmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node;
+
+ type
+ tmoddivnode = class(tbinopnode)
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function simplify : tnode;override;
+ protected
+{$ifndef cpu64bit}
+ { override the following if you want to implement }
+ { parts explicitely in the code generator (JM) }
+ function first_moddiv64bitint: tnode; virtual;
+{$endif cpu64bit}
+ function firstoptimize: tnode; virtual;
+ function first_moddivint: tnode; virtual;
+ end;
+ tmoddivnodeclass = class of tmoddivnode;
+
+ tshlshrnode = class(tbinopnode)
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function simplify : tnode;override;
+{$ifndef cpu64bit}
+ { override the following if you want to implement }
+ { parts explicitely in the code generator (CEC)
+ Should return nil, if everything will be handled
+ in the code generator
+ }
+ function first_shlshr64bitint: tnode; virtual;
+{$endif cpu64bit}
+ end;
+ tshlshrnodeclass = class of tshlshrnode;
+
+ tunaryminusnode = class(tunarynode)
+ constructor create(expr : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function simplify : tnode;override;
+ end;
+ tunaryminusnodeclass = class of tunaryminusnode;
+
+ tnotnode = class(tunarynode)
+ constructor create(expr : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function simplify : tnode;override;
+ {$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+ {$endif}
+ end;
+ tnotnodeclass = class of tnotnode;
+
+ var
+ cmoddivnode : tmoddivnodeclass;
+ cshlshrnode : tshlshrnodeclass;
+ cunaryminusnode : tunaryminusnodeclass;
+ cnotnode : tnotnodeclass;
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,cutils,
+ globtype,
+ symconst,symtype,symdef,defutil,
+ htypechk,pass_1,
+ cgbase,
+ ncon,ncnv,ncal,nadd;
+
+{****************************************************************************
+ TMODDIVNODE
+ ****************************************************************************}
+
+ function tmoddivnode.simplify:tnode;
+ var
+ t : tnode;
+ rd,ld : torddef;
+ rv,lv : tconstexprint;
+ begin
+ result:=nil;
+
+ if is_constintnode(right) and is_constintnode(left) then
+ begin
+ rd:=torddef(right.resulttype.def);
+ ld:=torddef(left.resulttype.def);
+
+ rv:=tordconstnode(right).value;
+ lv:=tordconstnode(left).value;
+
+ case nodetype of
+ modn:
+ if (torddef(ld).typ <> u64bit) or
+ (torddef(rd).typ <> u64bit) then
+ t:=genintconstnode(lv mod rv)
+ else
+ t:=genintconstnode(int64(qword(lv) mod qword(rv)));
+ divn:
+ if (torddef(ld).typ <> u64bit) or
+ (torddef(rd).typ <> u64bit) then
+ t:=genintconstnode(lv div rv)
+ else
+ t:=genintconstnode(int64(qword(lv) div qword(rv)));
+ end;
+ result:=t;
+ exit;
+ end;
+ end;
+
+
+ function tmoddivnode.det_resulttype:tnode;
+ var
+ hp,t : tnode;
+ rd,ld : torddef;
+ rv : tconstexprint;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ resulttypepass(right);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { we need 2 orddefs always }
+ if (left.resulttype.def.deftype<>orddef) then
+ inserttypeconv(right,sinttype);
+ if (right.resulttype.def.deftype<>orddef) then
+ inserttypeconv(right,sinttype);
+ if codegenerror then
+ exit;
+
+ rd:=torddef(right.resulttype.def);
+ ld:=torddef(left.resulttype.def);
+
+ { check for division by zero }
+ if is_constintnode(right) then
+ begin
+ rv:=tordconstnode(right).value;
+ if (rv=0) then
+ begin
+ Message(parser_e_division_by_zero);
+ { recover }
+ rv:=1;
+ end;
+ end;
+
+ result:=simplify;
+ if assigned(result) then
+ exit;
+
+ { allow operator overloading }
+ t:=self;
+ if isbinaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ { if one operand is a cardinal and the other is a positive constant, convert the }
+ { constant to a cardinal as well so we don't have to do a 64bit division (JM) }
+ { Do the same for qwords and positive constants as well, otherwise things like }
+ { "qword mod 10" are evaluated with int64 as result, which is wrong if the }
+ { "qword" was > high(int64) (JM) }
+ if (rd.typ in [u32bit,u64bit]) and
+ is_constintnode(left) and
+ (tordconstnode(left).value >= 0) then
+ begin
+ inserttypeconv(left,right.resulttype);
+ ld:=torddef(left.resulttype.def);
+ end;
+ if (ld.typ in [u32bit,u64bit]) and
+ is_constintnode(right) and
+ (tordconstnode(right).value >= 0) then
+ begin
+ inserttypeconv(right,left.resulttype);
+ rd:=torddef(right.resulttype.def);
+ end;
+
+ { when there is one currency value, everything is done
+ using currency }
+ if (ld.typ=scurrency) or
+ (rd.typ=scurrency) then
+ begin
+ if (ld.typ<>scurrency) then
+ inserttypeconv(left,s64currencytype);
+ if (rd.typ<>scurrency) then
+ inserttypeconv(right,s64currencytype);
+ resulttype:=left.resulttype;
+ end
+ else
+{$ifndef cpu64bit}
+ { when there is one 64bit value, everything is done
+ in 64bit }
+ if (is_64bitint(left.resulttype.def) or
+ is_64bitint(right.resulttype.def)) then
+ begin
+ if is_signed(rd) or is_signed(ld) then
+ begin
+ if (ld.typ<>s64bit) then
+ inserttypeconv(left,s64inttype);
+ if (rd.typ<>s64bit) then
+ inserttypeconv(right,s64inttype);
+ end
+ else
+ begin
+ if (ld.typ<>u64bit) then
+ inserttypeconv(left,u64inttype);
+ if (rd.typ<>u64bit) then
+ inserttypeconv(right,u64inttype);
+ end;
+ resulttype:=left.resulttype;
+ end
+ else
+ { when mixing cardinals and signed numbers, convert everythign to 64bit (JM) }
+ if ((rd.typ = u32bit) and
+ is_signed(ld)) or
+ ((ld.typ = u32bit) and
+ is_signed(rd)) then
+ begin
+ CGMessage(type_w_mixed_signed_unsigned);
+ if (ld.typ<>s64bit) then
+ inserttypeconv(left,s64inttype);
+ if (rd.typ<>s64bit) then
+ inserttypeconv(right,s64inttype);
+ resulttype:=left.resulttype;
+ end
+ else
+{$endif cpu64bit}
+ begin
+ { Make everything always default singed int }
+ if not(rd.typ in [torddef(sinttype.def).typ,torddef(uinttype.def).typ]) then
+ inserttypeconv(right,sinttype);
+ if not(ld.typ in [torddef(sinttype.def).typ,torddef(uinttype.def).typ]) then
+ inserttypeconv(left,sinttype);
+ resulttype:=right.resulttype;
+ end;
+
+ { when the result is currency we need some extra code for
+ division. this should not be done when the divn node is
+ created internally }
+ if (nodetype=divn) and
+ not(nf_is_currency in flags) and
+ is_currency(resulttype.def) then
+ begin
+ hp:=caddnode.create(muln,getcopy,cordconstnode.create(10000,s64currencytype,false));
+ include(hp.flags,nf_is_currency);
+ result:=hp;
+ end;
+ end;
+
+
+ function tmoddivnode.first_moddivint: tnode;
+{$ifdef cpuneedsdiv32helper}
+ var
+ procname: string[31];
+ begin
+ result := nil;
+
+ { otherwise create a call to a helper }
+ if nodetype = divn then
+ procname := 'fpc_div_'
+ else
+ procname := 'fpc_mod_';
+ { only qword needs the unsigned code, the
+ signed code is also used for currency }
+ if is_signed(resulttype.def) then
+ procname := procname + 'longint'
+ else
+ procname := procname + 'dword';
+
+ result := ccallnode.createintern(procname,ccallparanode.create(left,
+ ccallparanode.create(right,nil)));
+ left := nil;
+ right := nil;
+ firstpass(result);
+ end;
+{$else cpuneedsdiv32helper}
+ begin
+ result:=nil;
+ end;
+{$endif cpuneedsdiv32helper}
+
+
+{$ifndef cpu64bit}
+ function tmoddivnode.first_moddiv64bitint: tnode;
+ var
+ procname: string[31];
+ begin
+ result := nil;
+
+ { when currency is used set the result of the
+ parameters to s64bit, so they are not converted }
+ if is_currency(resulttype.def) then
+ begin
+ left.resulttype:=s64inttype;
+ right.resulttype:=s64inttype;
+ end;
+
+ { otherwise create a call to a helper }
+ if nodetype = divn then
+ procname := 'fpc_div_'
+ else
+ procname := 'fpc_mod_';
+ { only qword needs the unsigned code, the
+ signed code is also used for currency }
+ if is_signed(resulttype.def) then
+ procname := procname + 'int64'
+ else
+ procname := procname + 'qword';
+
+ result := ccallnode.createintern(procname,ccallparanode.create(left,
+ ccallparanode.create(right,nil)));
+ left := nil;
+ right := nil;
+ firstpass(result);
+ end;
+{$endif cpu64bit}
+
+
+ function tmoddivnode.firstoptimize: tnode;
+ var
+ power{,shiftval} : longint;
+ newtype: tnodetype;
+ begin
+ result := nil;
+ { divide/mod a number by a constant which is a power of 2? }
+ if (cs_optimize in aktglobalswitches) and
+ (right.nodetype = ordconstn) and
+{ ((nodetype = divn) or
+ not is_signed(resulttype.def)) and}
+ (not is_signed(resulttype.def)) and
+ ispowerof2(tordconstnode(right).value,power) then
+ begin
+ if nodetype = divn then
+ begin
+(*
+ if is_signed(resulttype.def) then
+ begin
+ if is_64bitint(left.resulttype.def) then
+ if not (cs_littlesize in aktglobalswitches) then
+ shiftval := 63
+ else
+ { the shift code is a lot bigger than the call to }
+ { the divide helper }
+ exit
+ else
+ shiftval := 31;
+ { we reuse left twice, so create once a copy of it }
+ { !!! if left is a call is -> call gets executed twice }
+ left := caddnode.create(addn,left,
+ caddnode.create(andn,
+ cshlshrnode.create(sarn,left.getcopy,
+ cordconstnode.create(shiftval,sinttype,false)),
+ cordconstnode.create(tordconstnode(right).value-1,
+ right.resulttype,false)));
+ newtype := sarn;
+ end
+ else
+*)
+ newtype := shrn;
+ tordconstnode(right).value := power;
+ result := cshlshrnode.create(newtype,left,right)
+ end
+ else
+ begin
+ dec(tordconstnode(right).value);
+ result := caddnode.create(andn,left,right);
+ end;
+ { left and right are reused }
+ left := nil;
+ right := nil;
+ firstpass(result);
+ exit;
+ end;
+ end;
+
+
+ function tmoddivnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+ { Try to optimize mod/div }
+ result := firstoptimize;
+ if assigned(result) then
+ exit;
+
+{$ifndef cpu64bit}
+ { 64bit }
+ if (left.resulttype.def.deftype=orddef) and
+ (right.resulttype.def.deftype=orddef) and
+ (is_64bitint(left.resulttype.def) or is_64bitint(right.resulttype.def)) then
+ begin
+ result := first_moddiv64bitint;
+ if assigned(result) then
+ exit;
+ expectloc:=LOC_REGISTER;
+ calcregisters(self,2,0,0);
+ end
+ else
+{$endif cpu64bit}
+ begin
+ result := first_moddivint;
+ if assigned(result) then
+ exit;
+ left_right_max;
+ if left.registersint<=right.registersint then
+ inc(registersint);
+ end;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+
+{****************************************************************************
+ TSHLSHRNODE
+ ****************************************************************************}
+
+ function tshlshrnode.simplify:tnode;
+ var
+ t : tnode;
+ begin
+ result:=nil;
+ { constant folding }
+ if is_constintnode(left) and is_constintnode(right) then
+ begin
+ case nodetype of
+ shrn:
+ t:=genintconstnode(tordconstnode(left).value shr tordconstnode(right).value);
+ shln:
+ t:=genintconstnode(tordconstnode(left).value shl tordconstnode(right).value);
+ end;
+ result:=t;
+ exit;
+ end;
+
+ end;
+
+
+ function tshlshrnode.det_resulttype:tnode;
+ var
+ t : tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ resulttypepass(right);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ result:=simplify;
+ if assigned(result) then
+ exit;
+
+ { allow operator overloading }
+ t:=self;
+ if isbinaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ { calculations for ordinals < 32 bit have to be done in
+ 32 bit for backwards compatibility. That way 'shl 33' is
+ the same as 'shl 1'. It's ugly but compatible with delphi/tp/gcc }
+ if (not is_64bit(left.resulttype.def)) and
+ (torddef(left.resulttype.def).typ<>u32bit) then
+ inserttypeconv(left,s32inttype);
+
+ inserttypeconv(right,sinttype);
+
+ resulttype:=left.resulttype;
+ end;
+
+
+{$ifndef cpu64bit}
+ function tshlshrnode.first_shlshr64bitint: tnode;
+ var
+ procname: string[31];
+ begin
+ result := nil;
+ { otherwise create a call to a helper }
+ if nodetype = shln then
+ procname := 'fpc_shl_int64'
+ else
+ procname := 'fpc_shr_int64';
+ { this order of parameters works at least for the arm,
+ however it should work for any calling conventions (FK) }
+ result := ccallnode.createintern(procname,ccallparanode.create(right,
+ ccallparanode.create(left,nil)));
+ left := nil;
+ right := nil;
+ firstpass(result);
+ end;
+{$endif cpu64bit}
+
+
+ function tshlshrnode.pass_1 : tnode;
+ var
+ regs : longint;
+ begin
+ result:=nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+{$ifndef cpu64bit}
+ { 64 bit ints have their own shift handling }
+ if is_64bit(left.resulttype.def) then
+ begin
+ result := first_shlshr64bitint;
+ if assigned(result) then
+ exit;
+ regs:=2;
+ end
+ else
+{$endif cpu64bit}
+ begin
+ regs:=1
+ end;
+
+ if (right.nodetype<>ordconstn) then
+ inc(regs);
+ expectloc:=LOC_REGISTER;
+ calcregisters(self,regs,0,0);
+ end;
+
+
+{****************************************************************************
+ TUNARYMINUSNODE
+ ****************************************************************************}
+
+ constructor tunaryminusnode.create(expr : tnode);
+ begin
+ inherited create(unaryminusn,expr);
+ end;
+
+
+ function tunaryminusnode.simplify:tnode;
+ begin
+ result:=nil;
+ { constant folding }
+ if is_constintnode(left) then
+ begin
+ result:=genintconstnode(-tordconstnode(left).value);
+ exit;
+ end;
+ if is_constrealnode(left) then
+ begin
+ trealconstnode(left).value_real:=-trealconstnode(left).value_real;
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+
+
+ function tunaryminusnode.det_resulttype : tnode;
+ var
+ t : tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ result:=simplify;
+ if assigned(result) then
+ exit;
+
+ resulttype:=left.resulttype;
+ if (left.resulttype.def.deftype=floatdef) then
+ begin
+ end
+{$ifdef SUPPORT_MMX}
+ else if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(left.resulttype.def) then
+ begin
+ { if saturation is on, left.resulttype.def isn't
+ "mmx able" (FK)
+ if (cs_mmx_saturation in aktlocalswitches^) and
+ (torddef(tarraydef(resulttype.def).definition).typ in
+ [s32bit,u32bit]) then
+ CGMessage(type_e_mismatch);
+ }
+ end
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bit}
+ else if is_64bitint(left.resulttype.def) then
+ begin
+ end
+{$endif cpu64bit}
+ else if (left.resulttype.def.deftype=orddef) then
+ begin
+ inserttypeconv(left,sinttype);
+ resulttype:=left.resulttype;
+ end
+ else
+ begin
+ { allow operator overloading }
+ t:=self;
+ if isunaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ CGMessage(type_e_mismatch);
+ end;
+ end;
+
+ { generic code }
+ { overridden by: }
+ { i386 }
+ function tunaryminusnode.pass_1 : tnode;
+ var
+ procname: string[31];
+ temp: tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ if (cs_fp_emulation in aktmoduleswitches) and (left.resulttype.def.deftype=floatdef) then
+ begin
+ if not(target_info.system in system_wince) then
+ begin
+ case tfloatdef(resulttype.def).typ of
+ s32real:
+ procname:='float32_sub';
+ s64real:
+ procname:='float64_sub';
+ {!!! not yet implemented
+ s128real:
+ }
+ else
+ internalerror(2005082801);
+ end;
+ result:=ccallnode.createintern(procname,ccallparanode.create(crealconstnode.create(0,resulttype),
+ ccallparanode.create(left,nil)));
+ end
+ else
+ begin
+ case tfloatdef(resulttype.def).typ of
+ s32real:
+ procname:='NEGS';
+ s64real:
+ procname:='NEGD';
+ {!!! not yet implemented
+ s128real:
+ }
+ else
+ internalerror(2005082802);
+ end;
+ result:=ccallnode.createintern(procname,ccallparanode.create(left,nil));
+ end;
+
+ left:=nil;
+ end
+ else
+ begin
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+
+ if (left.resulttype.def.deftype=floatdef) then
+ begin
+ if (left.expectloc<>LOC_REGISTER) and
+ (registersfpu<1) then
+ registersfpu:=1;
+ expectloc:=LOC_FPUREGISTER;
+ end
+{$ifdef SUPPORT_MMX}
+ else if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(left.resulttype.def) then
+ begin
+ if (left.expectloc<>LOC_MMXREGISTER) and
+ (registersmmx<1) then
+ registersmmx:=1;
+ end
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bit}
+ else if is_64bit(left.resulttype.def) then
+ begin
+ if (left.expectloc<>LOC_REGISTER) and
+ (registersint<2) then
+ registersint:=2;
+ expectloc:=LOC_REGISTER;
+ end
+{$endif cpu64bit}
+ else if (left.resulttype.def.deftype=orddef) then
+ begin
+ if (left.expectloc<>LOC_REGISTER) and
+ (registersint<1) then
+ registersint:=1;
+ expectloc:=LOC_REGISTER;
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TNOTNODE
+ ****************************************************************************}
+
+ const
+ boolean_reverse:array[ltn..unequaln] of Tnodetype=(
+ gten,gtn,lten,ltn,unequaln,equaln
+ );
+
+ constructor tnotnode.create(expr : tnode);
+ begin
+ inherited create(notn,expr);
+ end;
+
+
+ function tnotnode.simplify:tnode;
+ var
+ v : tconstexprint;
+ t : tnode;
+ tt : ttype;
+ begin
+ result:=nil;
+ { Try optmimizing ourself away }
+ if left.nodetype=notn then
+ begin
+ { Double not. Remove both }
+ result:=Tnotnode(left).left;
+ tnotnode(left).left:=nil;
+ exit;
+ end;
+
+ if (left.nodetype in [ltn,lten,equaln,unequaln,gtn,gten]) then
+ begin
+ { Not of boolean expression. Turn around the operator and remove
+ the not. This is not allowed for sets with the gten/lten,
+ because there is no ltn/gtn support }
+ if (taddnode(left).left.resulttype.def.deftype<>setdef) or
+ (left.nodetype in [equaln,unequaln]) then
+ begin
+ result:=left;
+ left.nodetype:=boolean_reverse[left.nodetype];
+ left:=nil;
+ exit;
+ end;
+ end;
+
+ { constant folding }
+ if (left.nodetype=ordconstn) then
+ begin
+ v:=tordconstnode(left).value;
+ tt:=left.resulttype;
+ case torddef(left.resulttype.def).typ of
+ bool8bit,
+ bool16bit,
+ bool32bit :
+ begin
+ { here we do a boolean(byte(..)) type cast because }
+ { boolean(<int64>) is buggy in 1.00 }
+ v:=byte(not(boolean(byte(v))));
+ end;
+ uchar,
+ uwidechar,
+ u8bit,
+ s8bit,
+ u16bit,
+ s16bit,
+ u32bit,
+ s32bit,
+ s64bit,
+ u64bit :
+ begin
+ v:=int64(not int64(v)); { maybe qword is required }
+ int_to_type(v,tt);
+ end;
+ else
+ CGMessage(type_e_mismatch);
+ end;
+ t:=cordconstnode.create(v,tt,true);
+ result:=t;
+ exit;
+ end;
+ end;
+
+
+ function tnotnode.det_resulttype : tnode;
+ var
+ t : tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ set_varstate(left,vs_used,[]);
+ if codegenerror then
+ exit;
+
+ resulttype:=left.resulttype;
+
+ result:=simplify;
+ if assigned(result) then
+ exit;
+
+ if is_boolean(resulttype.def) then
+ begin
+ end
+ else
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(left.resulttype.def) then
+ begin
+ end
+ else
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bit}
+ if is_64bitint(left.resulttype.def) then
+ begin
+ end
+ else
+{$endif cpu64bit}
+ if is_integer(left.resulttype.def) then
+ begin
+ end
+ else
+ begin
+ { allow operator overloading }
+ t:=self;
+ if isunaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ CGMessage(type_e_mismatch);
+ end;
+ end;
+
+
+ function tnotnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ expectloc:=left.expectloc;
+ registersint:=left.registersint;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ if is_boolean(resulttype.def) then
+ begin
+ if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ begin
+ expectloc:=LOC_REGISTER;
+ if (registersint<1) then
+ registersint:=1;
+ end;
+ { before loading it into flags we need to load it into
+ a register thus 1 register is need PM }
+{$ifdef cpuflags}
+ if left.expectloc<>LOC_JUMP then
+ expectloc:=LOC_FLAGS;
+{$endif def cpuflags}
+ end
+ else
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(left.resulttype.def) then
+ begin
+ if (left.expectloc<>LOC_MMXREGISTER) and
+ (registersmmx<1) then
+ registersmmx:=1;
+ end
+ else
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bit}
+ if is_64bit(left.resulttype.def) then
+ begin
+ if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ begin
+ expectloc:=LOC_REGISTER;
+ if (registersint<2) then
+ registersint:=2;
+ end;
+ end
+ else
+{$endif cpu64bit}
+ if is_integer(left.resulttype.def) then
+ begin
+ if (left.expectloc<>LOC_REGISTER) and
+ (registersint<1) then
+ registersint:=1;
+ expectloc:=LOC_REGISTER;
+ end;
+ end;
+
+{$ifdef state_tracking}
+ function Tnotnode.track_state_pass(exec_known:boolean):boolean;
+ begin
+ track_state_pass:=true;
+ if left.track_state_pass(exec_known) then
+ begin
+ left.resulttype.def:=nil;
+ do_resulttypepass(left);
+ end;
+ end;
+{$endif}
+
+begin
+ cmoddivnode:=tmoddivnode;
+ cshlshrnode:=tshlshrnode;
+ cunaryminusnode:=tunaryminusnode;
+ cnotnode:=tnotnode;
+end.
diff --git a/compiler/nmem.pas b/compiler/nmem.pas
new file mode 100644
index 0000000000..0e47b4e53e
--- /dev/null
+++ b/compiler/nmem.pas
@@ -0,0 +1,965 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for memory related 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 nmem;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,
+ symdef,symsym,symtable,symtype;
+
+ type
+ tloadvmtaddrnode = class(tunarynode)
+ constructor create(l : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ end;
+ tloadvmtaddrnodeclass = class of tloadvmtaddrnode;
+
+ tloadparentfpnode = class(tunarynode)
+ parentpd : tprocdef;
+ parentpdderef : tderef;
+ constructor create(pd:tprocdef);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ function _getcopy : tnode;override;
+ end;
+ tloadparentfpnodeclass = class of tloadparentfpnode;
+
+ taddrnode = class(tunarynode)
+ getprocvardef : tprocvardef;
+ getprocvardefderef : tderef;
+ constructor create(l : tnode);virtual;
+ constructor create_internal(l : tnode); virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure mark_write;override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ end;
+ taddrnodeclass = class of taddrnode;
+
+ tderefnode = class(tunarynode)
+ constructor create(l : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ procedure mark_write;override;
+ end;
+ tderefnodeclass = class of tderefnode;
+
+ tsubscriptnode = class(tunarynode)
+ vs : tfieldvarsym;
+ vsderef : tderef;
+ constructor create(varsym : tsym;l : tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ function det_resulttype:tnode;override;
+ procedure mark_write;override;
+ end;
+ tsubscriptnodeclass = class of tsubscriptnode;
+
+ tvecnode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ function det_resulttype:tnode;override;
+ procedure mark_write;override;
+ end;
+ tvecnodeclass = class of tvecnode;
+
+ twithnode = class(tunarynode)
+ withsymtable : twithsymtable;
+ tablecount : longint;
+ withrefnode : tnode;
+ constructor create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function _getcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ function det_resulttype:tnode;override;
+ end;
+ twithnodeclass = class of twithnode;
+
+ var
+ cloadvmtaddrnode : tloadvmtaddrnodeclass;
+ cloadparentfpnode : tloadparentfpnodeclass;
+ caddrnode : taddrnodeclass;
+ cderefnode : tderefnodeclass;
+ csubscriptnode : tsubscriptnodeclass;
+ cvecnode : tvecnodeclass;
+ cwithnode : twithnodeclass;
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symbase,defutil,defcmp,
+ nbas,nutils,
+ htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase,procinfo
+ ;
+
+{*****************************************************************************
+ TLOADVMTADDRNODE
+*****************************************************************************}
+
+ constructor tloadvmtaddrnode.create(l : tnode);
+ begin
+ inherited create(loadvmtaddrn,l);
+ end;
+
+
+ function tloadvmtaddrnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ if codegenerror then
+ exit;
+
+ case left.resulttype.def.deftype of
+ classrefdef :
+ resulttype:=left.resulttype;
+ objectdef :
+ resulttype.setdef(tclassrefdef.create(left.resulttype));
+ else
+ Message(parser_e_pointer_to_class_expected);
+ end;
+ end;
+
+
+ function tloadvmtaddrnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_REGISTER;
+ if left.nodetype<>typen then
+ begin
+ firstpass(left);
+ registersint:=left.registersint;
+ end;
+ if registersint<1 then
+ registersint:=1;
+ end;
+
+
+{*****************************************************************************
+ TLOADPARENTFPNODE
+*****************************************************************************}
+
+ constructor tloadparentfpnode.create(pd:tprocdef);
+ begin
+ inherited create(loadparentfpn,nil);
+ if not assigned(pd) then
+ internalerror(200309288);
+ if (pd.parast.symtablelevel>current_procinfo.procdef.parast.symtablelevel) then
+ internalerror(200309284);
+ parentpd:=pd;
+ end;
+
+
+ constructor tloadparentfpnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(parentpdderef);
+ end;
+
+
+ procedure tloadparentfpnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(parentpdderef);
+ end;
+
+
+ procedure tloadparentfpnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ parentpdderef.build(parentpd);
+ end;
+
+
+ procedure tloadparentfpnode.derefimpl;
+ begin
+ inherited derefimpl;
+ parentpd:=tprocdef(parentpdderef.resolve);
+ end;
+
+
+ function tloadparentfpnode._getcopy : tnode;
+ var
+ p : tloadparentfpnode;
+ begin
+ p:=tloadparentfpnode(inherited _getcopy);
+ p.parentpd:=parentpd;
+ _getcopy:=p;
+ end;
+
+
+ function tloadparentfpnode.det_resulttype:tnode;
+{$ifdef dummy}
+ var
+ currpi : tprocinfo;
+ hsym : tparavarsym;
+{$endif dummy}
+ begin
+ result:=nil;
+ resulttype:=voidpointertype;
+{$ifdef dummy}
+ { currently parentfps are never loaded in registers (FK) }
+
+ if (current_procinfo.procdef.parast.symtablelevel<>parentpd.parast.symtablelevel) then
+ begin
+ currpi:=current_procinfo;
+ { walk parents }
+ while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
+ begin
+ currpi:=currpi.parent;
+ if not assigned(currpi) then
+ internalerror(2005040602);
+ hsym:=tparavarsym(currpi.procdef.parast.search('parentfp'));
+ if not assigned(hsym) then
+ internalerror(2005040601);
+ hsym.varregable:=vr_none;
+ end;
+ end;
+{$endif dummy}
+ end;
+
+
+ function tloadparentfpnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_REGISTER;
+ registersint:=1;
+ end;
+
+
+{*****************************************************************************
+ TADDRNODE
+*****************************************************************************}
+
+ constructor taddrnode.create(l : tnode);
+
+ begin
+ inherited create(addrn,l);
+ getprocvardef:=nil;
+ end;
+
+
+ constructor taddrnode.create_internal(l : tnode);
+ begin
+ self.create(l);
+ include(flags,nf_internal);
+ end;
+
+
+ constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(getprocvardefderef);
+ end;
+
+
+ procedure taddrnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(getprocvardefderef);
+ end;
+
+ procedure Taddrnode.mark_write;
+
+ begin
+ {@procvar:=nil is legal in Delphi mode.}
+ left.mark_write;
+ end;
+
+ procedure taddrnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ getprocvardefderef.build(getprocvardef);
+ end;
+
+
+ procedure taddrnode.derefimpl;
+ begin
+ inherited derefimpl;
+ getprocvardef:=tprocvardef(getprocvardefderef.resolve);
+ end;
+
+
+ function taddrnode._getcopy : tnode;
+
+ var
+ p : taddrnode;
+
+ begin
+ p:=taddrnode(inherited _getcopy);
+ p.getprocvardef:=getprocvardef;
+ _getcopy:=p;
+ end;
+
+
+ function taddrnode.det_resulttype:tnode;
+ var
+ hp : tnode;
+ hsym : tfieldvarsym;
+ isprocvar : boolean;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ if codegenerror then
+ exit;
+
+ make_not_regable(left);
+
+ { don't allow constants }
+ if is_constnode(left) then
+ begin
+ aktfilepos:=left.fileinfo;
+ CGMessage(type_e_no_addr_of_constant);
+ exit;
+ end;
+
+ { Handle @proc special, also @procvar in tp-mode needs
+ special handling }
+ if (left.resulttype.def.deftype=procdef) or
+ (
+ (left.resulttype.def.deftype=procvardef) and
+ ((m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches))
+ ) then
+ begin
+ isprocvar:=(left.resulttype.def.deftype=procvardef);
+
+ if not isprocvar then
+ begin
+ left:=ctypeconvnode.create_proc_to_procvar(left);
+ resulttypepass(left);
+ end;
+
+ { In tp procvar mode the result is always a voidpointer. Insert
+ a typeconversion to voidpointer. For methodpointers we need
+ to load the proc field }
+ if (m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches) then
+ begin
+ if tabstractprocdef(left.resulttype.def).is_addressonly then
+ begin
+ result:=ctypeconvnode.create_internal(left,voidpointertype);
+ include(result.flags,nf_load_procvar);
+ left:=nil;
+ end
+ else
+ begin
+ { For procvars we need to return the proc field of the
+ methodpointer }
+ if isprocvar then
+ begin
+ { find proc field in methodpointer record }
+ hsym:=tfieldvarsym(trecorddef(methodpointertype.def).symtable.search('proc'));
+ if not assigned(hsym) then
+ internalerror(200412041);
+ { Load tmehodpointer(left).proc }
+ result:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(left,methodpointertype));
+ left:=nil;
+ end
+ else
+ CGMessage(type_e_variable_id_expected);
+ end;
+ end
+ else
+ begin
+ { Return the typeconvn only }
+ result:=left;
+ left:=nil;
+ end;
+ end
+ else
+ begin
+ { what are we getting the address from an absolute sym? }
+ hp:=left;
+ while assigned(hp) and (hp.nodetype in [typeconvn,vecn,derefn,subscriptn]) do
+ hp:=tunarynode(hp).left;
+ if not assigned(hp) then
+ internalerror(200412042);
+{$ifdef i386}
+ if (hp.nodetype=loadn) and
+ ((tloadnode(hp).symtableentry.typ=absolutevarsym) and
+ tabsolutevarsym(tloadnode(hp).symtableentry).absseg) then
+ begin
+ if not(nf_typedaddr in flags) then
+ resulttype:=voidfarpointertype
+ else
+ resulttype.setdef(tpointerdef.createfar(left.resulttype));
+ end
+ else
+{$endif i386}
+ if (nf_internal in flags) or
+ valid_for_addr(left) then
+ begin
+ if not(nf_typedaddr in flags) then
+ resulttype:=voidpointertype
+ else
+ resulttype.setdef(tpointerdef.create(left.resulttype));
+ end
+ else
+ CGMessage(type_e_variable_id_expected);
+ end;
+
+ { this is like the function addr }
+ inc(parsing_para_level);
+ set_varstate(left,vs_used,[]);
+ dec(parsing_para_level);
+ end;
+
+
+ function taddrnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ if registersint<1 then
+ registersint:=1;
+ { is this right for object of methods ?? }
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+{*****************************************************************************
+ TDEREFNODE
+*****************************************************************************}
+
+ constructor tderefnode.create(l : tnode);
+
+ begin
+ inherited create(derefn,l);
+
+ end;
+
+ function tderefnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+
+ if left.resulttype.def.deftype=pointerdef then
+ resulttype:=tpointerdef(left.resulttype.def).pointertype
+ else
+ CGMessage(parser_e_invalid_qualifier);
+ end;
+
+ procedure Tderefnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ function tderefnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ registersint:=max(left.registersint,1);
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+
+ expectloc:=LOC_REFERENCE;
+ end;
+
+
+{*****************************************************************************
+ TSUBSCRIPTNODE
+*****************************************************************************}
+
+ constructor tsubscriptnode.create(varsym : tsym;l : tnode);
+
+ begin
+ inherited create(subscriptn,l);
+ { vs should be changed to tsym! }
+ vs:=tfieldvarsym(varsym);
+ end;
+
+ constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(vsderef);
+ end;
+
+
+ procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(vsderef);
+ end;
+
+
+ procedure tsubscriptnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ vsderef.build(vs);
+ end;
+
+
+ procedure tsubscriptnode.derefimpl;
+ begin
+ inherited derefimpl;
+ vs:=tfieldvarsym(vsderef.resolve);
+ end;
+
+
+ function tsubscriptnode._getcopy : tnode;
+
+ var
+ p : tsubscriptnode;
+
+ begin
+ p:=tsubscriptnode(inherited _getcopy);
+ p.vs:=vs;
+ _getcopy:=p;
+ end;
+
+
+ function tsubscriptnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+ resulttype:=vs.vartype;
+ end;
+
+ procedure Tsubscriptnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ function tsubscriptnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ { classes must be dereferenced implicit }
+ if is_class_or_interface(left.resulttype.def) then
+ begin
+ if registersint=0 then
+ registersint:=1;
+ expectloc:=LOC_REFERENCE;
+ end
+ else
+ begin
+ if (left.expectloc<>LOC_CREFERENCE) and
+ (left.expectloc<>LOC_REFERENCE) then
+ CGMessage(parser_e_illegal_expression);
+ expectloc:=left.expectloc;
+ end;
+ end;
+
+ function tsubscriptnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (vs = tsubscriptnode(p).vs);
+ end;
+
+
+{*****************************************************************************
+ TVECNODE
+*****************************************************************************}
+
+ constructor tvecnode.create(l,r : tnode);
+
+ begin
+ inherited create(vecn,l,r);
+ end;
+
+
+ function tvecnode.det_resulttype:tnode;
+ var
+ htype : ttype;
+ valid : boolean;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ resulttypepass(right);
+
+ { implicitly convert stringconstant to stringdef,
+ see tbs/tb0476.pp for a test }
+ if (left.nodetype=stringconstn) and
+ (tstringconstnode(left).st_type=st_conststring) then
+ begin
+ if tstringconstnode(left).len>255 then
+ inserttypeconv(left,cansistringtype)
+ else
+ inserttypeconv(left,cshortstringtype);
+ end;
+
+ { In p[1] p is always valid, it is not possible to
+ declared a shortstring or normal array that has
+ undefined number of elements. Dynamic array and
+ ansi/widestring needs to be valid }
+ valid:=is_dynamic_array(left.resulttype.def) or
+ is_ansistring(left.resulttype.def) or
+ is_widestring(left.resulttype.def);
+ if valid then
+ set_varstate(left,vs_used,[vsf_must_be_valid])
+ else
+ set_varstate(left,vs_used,[]);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { maybe type conversion for the index value, but
+ do not convert enums,booleans,char }
+ if (right.resulttype.def.deftype<>enumdef) and
+ not(is_char(right.resulttype.def) or is_widechar(right.resulttype.def)) and
+ not(is_boolean(right.resulttype.def)) then
+ begin
+ inserttypeconv(right,sinttype);
+ end;
+
+ case left.resulttype.def.deftype of
+ arraydef :
+ begin
+ { check type of the index value }
+ if (compare_defs(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def,right.nodetype)=te_incompatible) then
+ IncompatibleTypes(right.resulttype.def,tarraydef(left.resulttype.def).rangetype.def);
+ resulttype:=tarraydef(left.resulttype.def).elementtype;
+ end;
+ pointerdef :
+ begin
+ { are we accessing a pointer[], then convert the pointer to
+ an array first, in FPC this is allowed for all pointers in
+ delphi/tp7 it's only allowed for pchars }
+ if (m_fpc in aktmodeswitches) or
+ is_pchar(left.resulttype.def) or
+ is_pwidechar(left.resulttype.def) then
+ begin
+ { convert pointer to array }
+ htype.setdef(tarraydef.create_from_pointer(tpointerdef(left.resulttype.def).pointertype));
+ inserttypeconv(left,htype);
+
+ resulttype:=tarraydef(htype.def).elementtype;
+ end
+ else
+ CGMessage(type_e_array_required);
+ end;
+ stringdef :
+ begin
+ { indexed access to 0 element is only allowed for shortstrings }
+ if (right.nodetype=ordconstn) and
+ (tordconstnode(right).value=0) and
+ not(is_shortstring(left.resulttype.def)) then
+ CGMessage(cg_e_can_access_element_zero);
+ case tstringdef(left.resulttype.def).string_typ of
+ st_widestring :
+ resulttype:=cwidechartype;
+ {$ifdef ansistring_bits}
+ st_ansistring16,st_ansistring32,st_ansistring64 :
+ {$else}
+ st_ansistring :
+ {$endif}
+ resulttype:=cchartype;
+ st_longstring :
+ resulttype:=cchartype;
+ st_shortstring :
+ resulttype:=cchartype;
+ end;
+ end;
+ variantdef :
+ resulttype:=cvarianttype;
+ else
+ CGMessage(type_e_array_required);
+ end;
+ end;
+
+ procedure Tvecnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ function tvecnode.pass_1 : tnode;
+{$ifdef consteval}
+ var
+ tcsym : ttypedconstsym;
+{$endif}
+ begin
+ result:=nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+ if (nf_callunique in flags) and
+ (is_ansistring(left.resulttype.def) or
+ is_widestring(left.resulttype.def)) then
+ begin
+ left := ctypeconvnode.create_internal(ccallnode.createintern('fpc_'+tstringdef(left.resulttype.def).stringtypname+'_unique',
+ ccallparanode.create(
+ ctypeconvnode.create_internal(left,voidpointertype),nil)),
+ left.resulttype);
+ firstpass(left);
+ { double resulttype passes somwhere else may cause this to be }
+ { reset though :/ }
+ exclude(flags,nf_callunique);
+ end;
+
+ { the register calculation is easy if a const index is used }
+ if right.nodetype=ordconstn then
+ begin
+{$ifdef consteval}
+ { constant evaluation }
+ if (left.nodetype=loadn) and
+ (left.symtableentry.typ=typedconstsym) then
+ begin
+ tcsym:=ttypedconstsym(left.symtableentry);
+ if tcsym.defintion^.typ=stringdef then
+ begin
+
+ end;
+ end;
+{$endif}
+ registersint:=left.registersint;
+
+ { for ansi/wide strings, we need at least one register }
+ if is_ansistring(left.resulttype.def) or
+ is_widestring(left.resulttype.def) or
+ { ... as well as for dynamic arrays }
+ is_dynamic_array(left.resulttype.def) then
+ registersint:=max(registersint,1);
+ end
+ else
+ begin
+ { this rules are suboptimal, but they should give }
+ { good results }
+ registersint:=max(left.registersint,right.registersint);
+
+ { for ansi/wide strings, we need at least one register }
+ if is_ansistring(left.resulttype.def) or
+ is_widestring(left.resulttype.def) or
+ { ... as well as for dynamic arrays }
+ is_dynamic_array(left.resulttype.def) then
+ registersint:=max(registersint,1);
+
+ { need we an extra register when doing the restore ? }
+ if (left.registersint<=right.registersint) and
+ { only if the node needs less than 3 registers }
+ { two for the right node and one for the }
+ { left address }
+ (registersint<3) then
+ inc(registersint);
+
+ { need we an extra register for the index ? }
+ if (right.expectloc<>LOC_REGISTER)
+ { only if the right node doesn't need a register }
+ and (right.registersint<1) then
+ inc(registersint);
+
+ { not correct, but what works better ?
+ if left.registersint>0 then
+ registersint:=max(registersint,2)
+ else
+ min. one register
+ registersint:=max(registersint,1);
+ }
+ end;
+ registersfpu:=max(left.registersfpu,right.registersfpu);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(left.registersmmx,right.registersmmx);
+{$endif SUPPORT_MMX}
+ if left.expectloc=LOC_CREFERENCE then
+ expectloc:=LOC_CREFERENCE
+ else
+ expectloc:=LOC_REFERENCE;
+ end;
+
+
+{*****************************************************************************
+ TWITHNODE
+*****************************************************************************}
+
+ constructor twithnode.create(l:tnode;symtable:twithsymtable;count:longint;r:tnode);
+ begin
+ inherited create(withn,l);
+ withrefnode:=r;
+ withsymtable:=symtable;
+ tablecount:=count;
+ fileinfo:=l.fileinfo;
+ end;
+
+
+ destructor twithnode.destroy;
+ var
+ hsymt,
+ symt : tsymtable;
+ i : longint;
+ begin
+ symt:=withsymtable;
+ for i:=1 to tablecount do
+ begin
+ if assigned(symt) then
+ begin
+ hsymt:=symt.next;
+ symt.free;
+ symt:=hsymt;
+ end;
+ end;
+ inherited destroy;
+ end;
+
+
+ constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ internalerror(200208192);
+ end;
+
+
+ procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ internalerror(200208193);
+ end;
+
+
+ function twithnode._getcopy : tnode;
+
+ var
+ p : twithnode;
+
+ begin
+ p:=twithnode(inherited _getcopy);
+ p.withsymtable:=withsymtable;
+ p.tablecount:=tablecount;
+ if assigned(p.withrefnode) then
+ p.withrefnode:=withrefnode._getcopy
+ else
+ p.withrefnode:=nil;
+ result:=p;
+ end;
+
+
+ function twithnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+
+ resulttypepass(withrefnode);
+ set_varstate(withrefnode,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ if (withrefnode.nodetype=vecn) and
+ (nf_memseg in withrefnode.flags) then
+ CGMessage(parser_e_no_with_for_variable_in_other_segments);
+
+ if assigned(left) then
+ resulttypepass(left);
+ end;
+
+
+ function twithnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ if assigned(left) then
+ begin
+ firstpass(left);
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+ if assigned(withrefnode) then
+ begin
+ firstpass(withrefnode);
+ if withrefnode.registersint > registersint then
+ registersint:=withrefnode.registersint;
+ if withrefnode.registersfpu > registersfpu then
+ registersint:=withrefnode.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if withrefnode.registersmmx > registersmmx then
+ registersmmx:=withrefnode.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+ end;
+
+
+ function twithnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (withsymtable = twithnode(p).withsymtable) and
+ (tablecount = twithnode(p).tablecount) and
+ (withrefnode.isequal(twithnode(p).withrefnode));
+ end;
+
+begin
+ cloadvmtaddrnode := tloadvmtaddrnode;
+ caddrnode := taddrnode;
+ cderefnode := tderefnode;
+ csubscriptnode := tsubscriptnode;
+ cvecnode := tvecnode;
+ cwithnode := twithnode;
+end.
diff --git a/compiler/nobj.pas b/compiler/nobj.pas
new file mode 100644
index 0000000000..df059347c0
--- /dev/null
+++ b/compiler/nobj.pas
@@ -0,0 +1,1353 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Routines for the code generation of data structures
+ like VMT, Messages, VTables, Interfaces descs
+
+ 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 nobj;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,
+ symdef,symsym,
+ aasmbase,aasmtai
+ ;
+
+ type
+ pprocdeftree = ^tprocdeftree;
+ tprocdeftree = record
+ data : tprocdef;
+ nl : tasmlabel;
+ l,r : pprocdeftree;
+ end;
+
+ pprocdefcoll = ^tprocdefcoll;
+ tprocdefcoll = record
+ data : tprocdef;
+ hidden : boolean;
+ visible : boolean;
+ next : pprocdefcoll;
+ end;
+
+ pvmtentry = ^tvmtentry;
+ tvmtentry = record
+ speedvalue : cardinal;
+ name : pstring;
+ firstprocdef : pprocdefcoll;
+ next : pvmtentry;
+ end;
+
+ tclassheader=class
+ private
+ _Class : tobjectdef;
+ private
+ { message tables }
+ root : pprocdeftree;
+ procedure disposeprocdeftree(p : pprocdeftree);
+ procedure insertmsgint(p : tnamedindexitem;arg:pointer);
+ procedure insertmsgstr(p : tnamedindexitem;arg:pointer);
+ procedure insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+ procedure insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+ procedure writenames(p : pprocdeftree);
+ procedure writeintentry(p : pprocdeftree);
+ procedure writestrentry(p : pprocdeftree);
+{$ifdef WITHDMT}
+ private
+ { dmt }
+ procedure insertdmtentry(p : tnamedindexitem;arg:pointer);
+ procedure writedmtindexentry(p : pprocdeftree);
+ procedure writedmtaddressentry(p : pprocdeftree);
+{$endif}
+ private
+ { published methods }
+ procedure do_count_published_methods(p : tnamedindexitem;arg:pointer);
+ procedure do_gen_published_methods(p : tnamedindexitem;arg:pointer);
+ private
+ { vmt }
+ firstvmtentry : pvmtentry;
+ nextvirtnumber : integer;
+ has_constructor,
+ has_virtual_method : boolean;
+ procedure newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
+ function newvmtentry(sym:tprocsym):pvmtentry;
+ procedure eachsym(sym : tnamedindexitem;arg:pointer);
+ procedure disposevmttree;
+ procedure writevirtualmethods(List:TAAsmoutput);
+ private
+ { interface tables }
+ function gintfgetvtbllabelname(intfindex: integer): string;
+ procedure gintfcreatevtbl(intfindex: integer; rawdata: TAAsmoutput);
+ procedure gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
+ procedure gintfoptimizevtbls;
+ procedure gintfwritedata;
+ function gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
+ procedure gintfdoonintf(intf: tobjectdef; intfindex: longint);
+ procedure gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
+ public
+ constructor create(c:tobjectdef);
+ destructor destroy;override;
+ { generates the message tables for a class }
+ function genstrmsgtab : tasmlabel;
+ function genintmsgtab : tasmlabel;
+ function genpublishedmethodstable : tasmlabel;
+ { generates a VMT entries }
+ procedure genvmt;
+{$ifdef WITHDMT}
+ { generates a DMT for _class }
+ function gendmt : tasmlabel;
+{$endif WITHDMT}
+ { interfaces }
+ function genintftable: tasmlabel;
+ { write the VMT to al_globals }
+ procedure writevmt;
+ procedure writeinterfaceids;
+ end;
+
+
+implementation
+
+ uses
+ strings,
+ globals,verbose,systems,
+ symtable,symconst,symtype,defcmp,
+ dbgbase
+ ;
+
+
+{*****************************************************************************
+ TClassHeader
+*****************************************************************************}
+
+ constructor tclassheader.create(c:tobjectdef);
+ begin
+ inherited Create;
+ _Class:=c;
+ end;
+
+
+ destructor tclassheader.destroy;
+ begin
+ disposevmttree;
+ end;
+
+
+{**************************************
+ Message Tables
+**************************************}
+
+ procedure tclassheader.disposeprocdeftree(p : pprocdeftree);
+ begin
+ if assigned(p^.l) then
+ disposeprocdeftree(p^.l);
+ if assigned(p^.r) then
+ disposeprocdeftree(p^.r);
+ dispose(p);
+ end;
+
+
+ procedure tclassheader.insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+
+ begin
+ if at=nil then
+ begin
+ at:=p;
+ inc(count);
+ end
+ else
+ begin
+ if p^.data.messageinf.i<at^.data.messageinf.i then
+ insertint(p,at^.l,count)
+ else if p^.data.messageinf.i>at^.data.messageinf.i then
+ insertint(p,at^.r,count)
+ else
+ Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
+ end;
+ end;
+
+ procedure tclassheader.insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+
+ var
+ i : integer;
+
+ begin
+ if at=nil then
+ begin
+ at:=p;
+ inc(count);
+ end
+ else
+ begin
+ i:=strcomp(p^.data.messageinf.str,at^.data.messageinf.str);
+ if i<0 then
+ insertstr(p,at^.l,count)
+ else if i>0 then
+ insertstr(p,at^.r,count)
+ else
+ Message1(parser_e_duplicate_message_label,strpas(p^.data.messageinf.str));
+ end;
+ end;
+
+ procedure tclassheader.insertmsgint(p : tnamedindexitem;arg:pointer);
+
+ var
+ i : cardinal;
+ def: Tprocdef;
+ pt : pprocdeftree;
+
+ begin
+ if tsym(p).typ=procsym then
+ for i:=1 to Tprocsym(p).procdef_count do
+ begin
+ def:=Tprocsym(p).procdef[i];
+ if po_msgint in def.procoptions then
+ begin
+ new(pt);
+ pt^.data:=def;
+ pt^.l:=nil;
+ pt^.r:=nil;
+ insertint(pt,root,plongint(arg)^);
+ end;
+ end;
+ end;
+
+ procedure tclassheader.insertmsgstr(p : tnamedindexitem;arg:pointer);
+
+ var
+ i : cardinal;
+ def: Tprocdef;
+ pt : pprocdeftree;
+
+ begin
+ if tsym(p).typ=procsym then
+ for i:=1 to Tprocsym(p).procdef_count do
+ begin
+ def:=Tprocsym(p).procdef[i];
+ if po_msgstr in def.procoptions then
+ begin
+ new(pt);
+ pt^.data:=def;
+ pt^.l:=nil;
+ pt^.r:=nil;
+ insertstr(pt,root,plongint(arg)^);
+ end;
+ end;
+ end;
+
+ procedure tclassheader.writenames(p : pprocdeftree);
+ var
+ ca : pchar;
+ len : longint;
+ begin
+ objectlibrary.getdatalabel(p^.nl);
+ if assigned(p^.l) then
+ writenames(p^.l);
+ asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+ asmlist[al_globals].concat(Tai_label.Create(p^.nl));
+ len:=strlen(p^.data.messageinf.str);
+ asmlist[al_globals].concat(tai_const.create_8bit(len));
+ getmem(ca,len+1);
+ move(p^.data.messageinf.str^,ca^,len+1);
+ asmlist[al_globals].concat(Tai_string.Create_pchar(ca,len));
+ if assigned(p^.r) then
+ writenames(p^.r);
+ end;
+
+ procedure tclassheader.writestrentry(p : pprocdeftree);
+
+ begin
+ if assigned(p^.l) then
+ writestrentry(p^.l);
+
+ { write name label }
+ asmlist[al_globals].concat(Tai_const.Create_sym(p^.nl));
+ asmlist[al_globals].concat(Tai_const.Createname(p^.data.mangledname,AT_FUNCTION,0));
+
+ if assigned(p^.r) then
+ writestrentry(p^.r);
+ end;
+
+
+ function tclassheader.genstrmsgtab : tasmlabel;
+ var
+ r : tasmlabel;
+ count : longint;
+ begin
+ root:=nil;
+ count:=0;
+ { insert all message handlers into a tree, sorted by name }
+ _class.symtable.foreach(@insertmsgstr,@count);
+
+ { write all names }
+ if assigned(root) then
+ writenames(root);
+
+ { now start writing of the message string table }
+ objectlibrary.getdatalabel(r);
+ asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+ asmlist[al_globals].concat(Tai_label.Create(r));
+ genstrmsgtab:=r;
+ asmlist[al_globals].concat(Tai_const.Create_32bit(count));
+ if assigned(root) then
+ begin
+ writestrentry(root);
+ disposeprocdeftree(root);
+ end;
+ end;
+
+
+ procedure tclassheader.writeintentry(p : pprocdeftree);
+ begin
+ if assigned(p^.l) then
+ writeintentry(p^.l);
+
+ { write name label }
+ asmlist[al_globals].concat(Tai_const.Create_32bit(p^.data.messageinf.i));
+ asmlist[al_globals].concat(Tai_const.Createname(p^.data.mangledname,AT_FUNCTION,0));
+
+ if assigned(p^.r) then
+ writeintentry(p^.r);
+ end;
+
+
+ function tclassheader.genintmsgtab : tasmlabel;
+ var
+ r : tasmlabel;
+ count : longint;
+ begin
+ root:=nil;
+ count:=0;
+ { insert all message handlers into a tree, sorted by name }
+ _class.symtable.foreach(@insertmsgint,@count);
+
+ { now start writing of the message string table }
+ objectlibrary.getdatalabel(r);
+ asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+ asmlist[al_globals].concat(Tai_label.Create(r));
+ genintmsgtab:=r;
+ asmlist[al_globals].concat(Tai_const.Create_32bit(count));
+ if assigned(root) then
+ begin
+ writeintentry(root);
+ disposeprocdeftree(root);
+ end;
+ end;
+
+{$ifdef WITHDMT}
+
+{**************************************
+ DMT
+**************************************}
+
+ procedure tclassheader.insertdmtentry(p : tnamedindexitem;arg:pointer);
+
+ var
+ hp : tprocdef;
+ pt : pprocdeftree;
+
+ begin
+ if tsym(p).typ=procsym then
+ begin
+ hp:=tprocsym(p).definition;
+ while assigned(hp) do
+ begin
+ if (po_msgint in hp.procoptions) then
+ begin
+ new(pt);
+ pt^.p:=hp;
+ pt^.l:=nil;
+ pt^.r:=nil;
+ insertint(pt,root);
+ end;
+ hp:=hp.nextoverloaded;
+ end;
+ end;
+ end;
+
+ procedure tclassheader.writedmtindexentry(p : pprocdeftree);
+
+ begin
+ if assigned(p^.l) then
+ writedmtindexentry(p^.l);
+ al_globals.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
+ if assigned(p^.r) then
+ writedmtindexentry(p^.r);
+ end;
+
+ procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
+
+ begin
+ if assigned(p^.l) then
+ writedmtaddressentry(p^.l);
+ al_globals.concat(Tai_const_symbol.Createname(p^.data.mangledname,AT_FUNCTION,0));
+ if assigned(p^.r) then
+ writedmtaddressentry(p^.r);
+ end;
+
+ function tclassheader.gendmt : tasmlabel;
+
+ var
+ r : tasmlabel;
+
+ begin
+ root:=nil;
+ count:=0;
+ gendmt:=nil;
+ { insert all message handlers into a tree, sorted by number }
+ _class.symtable.foreach(insertdmtentry);
+
+ if count>0 then
+ begin
+ objectlibrary.getdatalabel(r);
+ gendmt:=r;
+ al_globals.concat(cai_align.create(const_align(sizeof(aint))));
+ al_globals.concat(Tai_label.Create(r));
+ { entries for caching }
+ al_globals.concat(Tai_const.Create_ptr(0));
+ al_globals.concat(Tai_const.Create_ptr(0));
+
+ al_globals.concat(Tai_const.Create_32bit(count));
+ if assigned(root) then
+ begin
+ writedmtindexentry(root);
+ writedmtaddressentry(root);
+ disposeprocdeftree(root);
+ end;
+ end;
+ end;
+
+{$endif WITHDMT}
+
+{**************************************
+ Published Methods
+**************************************}
+
+ procedure tclassheader.do_count_published_methods(p : tnamedindexitem;arg:pointer);
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ if (tsym(p).typ=procsym) then
+ begin
+ for i:=1 to tprocsym(p).procdef_count do
+ begin
+ pd:=tprocsym(p).procdef[i];
+ if (pd.procsym=tsym(p)) and
+ (sp_published in pd.symoptions) then
+ inc(plongint(arg)^);
+ end;
+ end;
+ end;
+
+
+ procedure tclassheader.do_gen_published_methods(p : tnamedindexitem;arg:pointer);
+ var
+ i : longint;
+ l : tasmlabel;
+ pd : tprocdef;
+ begin
+ if (tsym(p).typ=procsym) then
+ begin
+ for i:=1 to tprocsym(p).procdef_count do
+ begin
+ pd:=tprocsym(p).procdef[i];
+ if (pd.procsym=tsym(p)) and
+ (sp_published in pd.symoptions) then
+ begin
+ objectlibrary.getdatalabel(l);
+
+ asmlist[al_typedconsts].concat(cai_align.create(const_align(sizeof(aint))));
+ asmlist[al_typedconsts].concat(Tai_label.Create(l));
+ asmlist[al_typedconsts].concat(Tai_const.Create_8bit(length(tsym(p).realname)));
+ asmlist[al_typedconsts].concat(Tai_string.Create(tsym(p).realname));
+
+ asmlist[al_globals].concat(Tai_const.Create_sym(l));
+ if po_abstractmethod in pd.procoptions then
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil))
+ else
+ asmlist[al_globals].concat(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0));
+ end;
+ end;
+ end;
+ end;
+
+
+ function tclassheader.genpublishedmethodstable : tasmlabel;
+
+ var
+ l : tasmlabel;
+ count : longint;
+
+ begin
+ count:=0;
+ _class.symtable.foreach(@do_count_published_methods,@count);
+ if count>0 then
+ begin
+ objectlibrary.getdatalabel(l);
+ asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+ asmlist[al_globals].concat(Tai_label.Create(l));
+ asmlist[al_globals].concat(Tai_const.Create_32bit(count));
+ _class.symtable.foreach(@do_gen_published_methods,nil);
+ genpublishedmethodstable:=l;
+ end
+ else
+ genpublishedmethodstable:=nil;
+ end;
+
+
+{**************************************
+ VMT
+**************************************}
+
+
+ procedure tclassheader.newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
+ var
+ procdefcoll : pprocdefcoll;
+ begin
+ if (_class=pd._class) then
+ begin
+ { new entry is needed, override was not possible }
+ if (po_overridingmethod in pd.procoptions) then
+ MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
+
+ { check that all methods have overload directive }
+ if not(m_fpc in aktmodeswitches) then
+ begin
+ procdefcoll:=vmtentry^.firstprocdef;
+ while assigned(procdefcoll) do
+ begin
+ if (procdefcoll^.data._class=pd._class) and
+ ((po_overload in pd.procoptions)<>(po_overload in procdefcoll^.data.procoptions)) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_no_overload_for_all_procs,pd.procsym.realname);
+ { recover }
+ include(procdefcoll^.data.procoptions,po_overload);
+ include(pd.procoptions,po_overload);
+ end;
+ procdefcoll:=procdefcoll^.next;
+ end;
+ end;
+ end;
+
+ { generate new entry }
+ new(procdefcoll);
+ procdefcoll^.data:=pd;
+ procdefcoll^.hidden:=false;
+ procdefcoll^.visible:=is_visible;
+ procdefcoll^.next:=vmtentry^.firstprocdef;
+ vmtentry^.firstprocdef:=procdefcoll;
+
+ { give virtual method a number }
+ if (po_virtualmethod in pd.procoptions) then
+ begin
+ pd.extnumber:=nextvirtnumber;
+ inc(nextvirtnumber);
+ has_virtual_method:=true;
+ end;
+
+ if (pd.proctypeoption=potype_constructor) then
+ has_constructor:=true;
+ end;
+
+
+ function tclassheader.newvmtentry(sym:tprocsym):pvmtentry;
+ begin
+ { generate new vmtentry }
+ new(result);
+ result^.speedvalue:=sym.speedvalue;
+ result^.name:=stringdup(sym.name);
+ result^.next:=firstvmtentry;
+ result^.firstprocdef:=nil;
+ firstvmtentry:=result;
+ end;
+
+
+ procedure tclassheader.eachsym(sym : tnamedindexitem;arg:pointer);
+ const
+ po_comp = [po_classmethod,po_virtualmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
+ po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
+ label
+ handlenextdef;
+ var
+ pd : tprocdef;
+ i : cardinal;
+ is_visible,
+ hasoverloads,
+ pdoverload : boolean;
+ procdefcoll : pprocdefcoll;
+ vmtentry : pvmtentry;
+ _name : string;
+ _speed : cardinal;
+ begin
+ if (tsym(sym).typ<>procsym) then
+ exit;
+
+ { check the current list of symbols }
+ _name:=sym.name;
+ _speed:=sym.speedvalue;
+ vmtentry:=firstvmtentry;
+ while assigned(vmtentry) do
+ begin
+ { does the symbol already exist in the list? First
+ compare speedvalue before doing the string compare to
+ speed it up a little }
+ if (_speed=vmtentry^.speedvalue) and
+ (_name=vmtentry^.name^) then
+ begin
+ hasoverloads:=(Tprocsym(sym).procdef_count>1);
+ { walk through all defs of the symbol }
+ for i:=1 to Tprocsym(sym).procdef_count do
+ begin
+ pd:=Tprocsym(sym).procdef[i];
+
+ { is this procdef visible from the class that we are
+ generating. This will be used to hide the other procdefs.
+ When the symbol is not visible we don't hide the other
+ procdefs, because they can be reused in the next class.
+ The check to skip the invisible methods that are in the
+ list is futher down in the code }
+ is_visible:=pd.is_visible_for_object(_class);
+
+ if pd.procsym=sym then
+ begin
+ pdoverload:=(po_overload in pd.procoptions);
+
+ { compare with all stored definitions }
+ procdefcoll:=vmtentry^.firstprocdef;
+ while assigned(procdefcoll) do
+ begin
+ { compare only if the definition is not hidden }
+ if not procdefcoll^.hidden then
+ begin
+ { check if one of the two methods has virtual }
+ if (po_virtualmethod in procdefcoll^.data.procoptions) or
+ (po_virtualmethod in pd.procoptions) then
+ begin
+ { if the current definition has no virtual then hide the
+ old virtual if the new definition has the same arguments or
+ when it has no overload directive and no overloads }
+ if not(po_virtualmethod in pd.procoptions) then
+ begin
+ if procdefcoll^.visible and
+ (not(pdoverload or hasoverloads) or
+ (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
+ begin
+ if is_visible then
+ procdefcoll^.hidden:=true;
+ if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
+ MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
+ end;
+ end
+ { if both are virtual we check the header }
+ else if (po_virtualmethod in pd.procoptions) and
+ (po_virtualmethod in procdefcoll^.data.procoptions) then
+ begin
+ { new one has not override }
+ if is_class(_class) and
+ not(po_overridingmethod in pd.procoptions) then
+ begin
+ { we start a new virtual tree, hide the old }
+ if (not(pdoverload or hasoverloads) or
+ (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) and
+ (procdefcoll^.visible) then
+ begin
+ if is_visible then
+ procdefcoll^.hidden:=true;
+ if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
+ MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
+ end;
+ end
+ { same parameters }
+ else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal) then
+ begin
+ { overload is inherited }
+ if (po_overload in procdefcoll^.data.procoptions) then
+ include(pd.procoptions,po_overload);
+
+ { inherite calling convention when it was force and the
+ current definition has none force }
+ if (po_hascallingconvention in procdefcoll^.data.procoptions) and
+ not(po_hascallingconvention in pd.procoptions) then
+ begin
+ pd.proccalloption:=procdefcoll^.data.proccalloption;
+ include(pd.procoptions,po_hascallingconvention);
+ end;
+
+ { the flags have to match except abstract and override }
+ { only if both are virtual !! }
+ if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
+ (procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
+ ((procdefcoll^.data.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
+ tprocsym(procdefcoll^.data.procsym).write_parameter_lists(pd);
+ end;
+
+ { error, if the return types aren't equal }
+ if not(equal_defs(procdefcoll^.data.rettype.def,pd.rettype.def)) and
+ not((procdefcoll^.data.rettype.def.deftype=objectdef) and
+ (pd.rettype.def.deftype=objectdef) and
+ is_class(procdefcoll^.data.rettype.def) and
+ is_class(pd.rettype.def) and
+ (tobjectdef(pd.rettype.def).is_related(
+ tobjectdef(procdefcoll^.data.rettype.def)))) then
+ Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false),
+ procdefcoll^.data.fullprocname(false));
+
+ { check if the method to override is visible, check is only needed
+ for the current parsed class. Parent classes are already validated and
+ need to include all virtual methods including the ones not visible in the
+ current class }
+ if (_class=pd._class) and
+ (po_overridingmethod in pd.procoptions) and
+ (not procdefcoll^.visible) then
+ MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
+
+ { override old virtual method in VMT }
+ pd.extnumber:=procdefcoll^.data.extnumber;
+ procdefcoll^.data:=pd;
+ if is_visible then
+ procdefcoll^.visible:=true;
+
+ goto handlenextdef;
+ end
+ { different parameters }
+ else
+ begin
+ { when we got an override directive then can search futher for
+ the procedure to override.
+ If we are starting a new virtual tree then hide the old tree }
+ if not(po_overridingmethod in pd.procoptions) and
+ not pdoverload then
+ begin
+ if is_visible then
+ procdefcoll^.hidden:=true;
+ if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
+ MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
+ end;
+ end;
+ end
+ else
+ begin
+ { the new definition is virtual and the old static, we hide the old one
+ if the new defintion has not the overload directive }
+ if is_visible and
+ ((not(pdoverload or hasoverloads)) or
+ (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
+ procdefcoll^.hidden:=true;
+ end;
+ end
+ else
+ begin
+ { both are static, we hide the old one if the new defintion
+ has not the overload directive }
+ if is_visible and
+ ((not pdoverload) or
+ (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
+ procdefcoll^.hidden:=true;
+ end;
+ end; { not hidden }
+ procdefcoll:=procdefcoll^.next;
+ end;
+
+ { if it isn't saved in the list we create a new entry }
+ newdefentry(vmtentry,pd,is_visible);
+ end;
+ handlenextdef:
+ end;
+ exit;
+ end;
+ vmtentry:=vmtentry^.next;
+ end;
+
+ { Generate new procsym entry in vmt }
+ vmtentry:=newvmtentry(tprocsym(sym));
+
+ { Add procdefs }
+ for i:=1 to Tprocsym(sym).procdef_count do
+ begin
+ pd:=Tprocsym(sym).procdef[i];
+ newdefentry(vmtentry,pd,pd.is_visible_for_object(_class));
+ end;
+ end;
+
+
+ procedure tclassheader.disposevmttree;
+ var
+ vmtentry : pvmtentry;
+ procdefcoll : pprocdefcoll;
+ begin
+ { disposes the above generated tree }
+ vmtentry:=firstvmtentry;
+ while assigned(vmtentry) do
+ begin
+ firstvmtentry:=vmtentry^.next;
+ stringdispose(vmtentry^.name);
+ procdefcoll:=vmtentry^.firstprocdef;
+ while assigned(procdefcoll) do
+ begin
+ vmtentry^.firstprocdef:=procdefcoll^.next;
+ dispose(procdefcoll);
+ procdefcoll:=vmtentry^.firstprocdef;
+ end;
+ dispose(vmtentry);
+ vmtentry:=firstvmtentry;
+ end;
+ end;
+
+
+ procedure tclassheader.genvmt;
+
+ procedure do_genvmt(p : tobjectdef);
+
+ begin
+ { start with the base class }
+ if assigned(p.childof) then
+ do_genvmt(p.childof);
+
+ { walk through all public syms }
+ p.symtable.foreach(@eachsym,nil);
+ end;
+
+ begin
+ firstvmtentry:=nil;
+ nextvirtnumber:=0;
+
+ has_constructor:=false;
+ has_virtual_method:=false;
+
+ { generates a tree of all used methods }
+ do_genvmt(_class);
+
+ if not(is_interface(_class)) and
+ has_virtual_method and
+ not(has_constructor) then
+ Message1(parser_w_virtual_without_constructor,_class.objrealname^);
+ end;
+
+
+{**************************************
+ Interface tables
+**************************************}
+
+ function tclassheader.gintfgetvtbllabelname(intfindex: integer): string;
+ begin
+ gintfgetvtbllabelname:=make_mangledname('VTBL',_class.owner,_class.objname^+
+ '_$_'+_class.implementedinterfaces.interfaces(intfindex).objname^);
+ end;
+
+
+ procedure tclassheader.gintfcreatevtbl(intfindex: integer; rawdata: TAAsmoutput);
+ var
+ implintf: timplementedinterfaces;
+ curintf: tobjectdef;
+ proccount: integer;
+ tmps: string;
+ i: longint;
+ begin
+ implintf:=_class.implementedinterfaces;
+ curintf:=implintf.interfaces(intfindex);
+
+ section_symbol_start(rawdata,gintfgetvtbllabelname(intfindex),AT_DATA,true,sec_data,const_align(sizeof(aint)));
+ proccount:=implintf.implproccount(intfindex);
+ for i:=1 to proccount do
+ begin
+ tmps:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+curintf.objname^+'_$_'+
+ tostr(i)+'_$_'+
+ implintf.implprocs(intfindex,i).mangledname);
+ { create reference }
+ rawdata.concat(Tai_const.Createname(tmps,AT_FUNCTION,0));
+ end;
+ section_symbol_end(rawdata,gintfgetvtbllabelname(intfindex));
+ end;
+
+
+ procedure tclassheader.gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
+ var
+ implintf: timplementedinterfaces;
+ curintf: tobjectdef;
+ tmplabel: tasmlabel;
+ i: longint;
+ begin
+ implintf:=_class.implementedinterfaces;
+ curintf:=implintf.interfaces(intfindex);
+ { GUID }
+ if curintf.objecttype in [odt_interfacecom] then
+ begin
+ { label for GUID }
+ objectlibrary.getdatalabel(tmplabel);
+ rawdata.concat(cai_align.create(const_align(sizeof(aint))));
+ rawdata.concat(Tai_label.Create(tmplabel));
+ rawdata.concat(Tai_const.Create_32bit(longint(curintf.iidguid^.D1)));
+ rawdata.concat(Tai_const.Create_16bit(curintf.iidguid^.D2));
+ rawdata.concat(Tai_const.Create_16bit(curintf.iidguid^.D3));
+ for i:=Low(curintf.iidguid^.D4) to High(curintf.iidguid^.D4) do
+ rawdata.concat(Tai_const.Create_8bit(curintf.iidguid^.D4[i]));
+ asmlist[al_globals].concat(Tai_const.Create_sym(tmplabel));
+ end
+ else
+ begin
+ { nil for Corba interfaces }
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil));
+ end;
+ { VTable }
+ asmlist[al_globals].concat(Tai_const.Createname(gintfgetvtbllabelname(contintfindex),AT_DATA,0));
+ { IOffset field }
+ asmlist[al_globals].concat(Tai_const.Create_32bit(implintf.ioffsets(contintfindex)));
+ { IIDStr }
+ objectlibrary.getdatalabel(tmplabel);
+ rawdata.concat(cai_align.create(const_align(sizeof(aint))));
+ rawdata.concat(Tai_label.Create(tmplabel));
+ rawdata.concat(Tai_const.Create_8bit(length(curintf.iidstr^)));
+ if curintf.objecttype=odt_interfacecom then
+ rawdata.concat(Tai_string.Create(upper(curintf.iidstr^)))
+ else
+ rawdata.concat(Tai_string.Create(curintf.iidstr^));
+ asmlist[al_globals].concat(Tai_const.Create_sym(tmplabel));
+ end;
+
+
+ procedure tclassheader.gintfoptimizevtbls;
+ type
+ tcompintfentry = record
+ weight: longint;
+ compintf: longint;
+ end;
+ { Max 1000 interface in the class header interfaces it's enough imho }
+ tcompintfs = array[1..1000] of tcompintfentry;
+ pcompintfs = ^tcompintfs;
+ tequals = array[1..1000] of longint;
+ pequals = ^tequals;
+ timpls = array[1..1000] of longint;
+ pimpls = ^timpls;
+ var
+ max: longint;
+ equals: pequals;
+ compats: pcompintfs;
+ impls: pimpls;
+ w,i,j,k: longint;
+ cij: boolean;
+ cji: boolean;
+ begin
+ max:=_class.implementedinterfaces.count;
+ if max>High(tequals) then
+ Internalerror(200006135);
+ getmem(compats,sizeof(tcompintfentry)*max);
+ getmem(equals,sizeof(longint)*max);
+ getmem(impls,sizeof(longint)*max);
+ fillchar(compats^,sizeof(tcompintfentry)*max,0);
+ fillchar(equals^,sizeof(longint)*max,0);
+ fillchar(impls^,sizeof(longint)*max,0);
+ { ismergepossible is a containing relation
+ meaning of ismergepossible(a,b,w) =
+ if implementorfunction map of a is contained implementorfunction map of b
+ imp(a,b) and imp(b,c) => imp(a,c) ; imp(a,b) and imp(b,a) => a == b
+ }
+ { the order is very important for correct allocation }
+ for i:=1 to max do
+ begin
+ for j:=i+1 to max do
+ begin
+ cij:=_class.implementedinterfaces.isimplmergepossible(i,j,w);
+ cji:=_class.implementedinterfaces.isimplmergepossible(j,i,w);
+ if cij and cji then { i equal j }
+ begin
+ { get minimum index of equal }
+ if equals^[j]=0 then
+ equals^[j]:=i;
+ end
+ else if cij then
+ begin
+ { get minimum index of maximum weight }
+ if compats^[i].weight<w then
+ begin
+ compats^[i].weight:=w;
+ compats^[i].compintf:=j;
+ end;
+ end
+ else if cji then
+ begin
+ { get minimum index of maximum weight }
+ if (compats^[j].weight<w) then
+ begin
+ compats^[j].weight:=w;
+ compats^[j].compintf:=i;
+ end;
+ end;
+ end;
+ end;
+ { Reset, no replacements by default }
+ for i:=1 to max do
+ impls^[i]:=i;
+ { Replace vtbls when equal or compat, repeat
+ until there are no replacements possible anymore. This is
+ needed for the cases like:
+ First loop: 2->3, 3->1
+ Second loop: 2->1 (because 3 was replaced with 1)
+ }
+ repeat
+ k:=0;
+ for i:=1 to max do
+ begin
+ if compats^[impls^[i]].compintf<>0 then
+ impls^[i]:=compats^[impls^[i]].compintf
+ else if equals^[impls^[i]]<>0 then
+ impls^[i]:=equals^[impls^[i]]
+ else
+ inc(k);
+ end;
+ until k=max;
+ { Update the implindex }
+ for i:=1 to max do
+ _class.implementedinterfaces.setimplindex(i,impls^[i]);
+ freemem(compats);
+ freemem(equals);
+ freemem(impls);
+ end;
+
+
+ procedure tclassheader.gintfwritedata;
+ var
+ rawdata: taasmoutput;
+ max,i,j : smallint;
+ begin
+ max:=_class.implementedinterfaces.count;
+
+ rawdata:=TAAsmOutput.Create;
+ asmlist[al_globals].concat(Tai_const.Create_16bit(max));
+ { Two pass, one for allocation and vtbl creation }
+ for i:=1 to max do
+ begin
+ if _class.implementedinterfaces.implindex(i)=i then { if implement itself }
+ begin
+ { allocate a pointer in the object memory }
+ with tobjectsymtable(_class.symtable) do
+ begin
+ datasize:=align(datasize,min(sizeof(aint),fieldalignment));
+ _class.implementedinterfaces.setioffsets(i,datasize);
+ inc(datasize,sizeof(aint));
+ end;
+ { write vtbl }
+ gintfcreatevtbl(i,rawdata);
+ end;
+ end;
+ { second pass: for fill interfacetable and remained ioffsets }
+ for i:=1 to max do
+ begin
+ j:=_class.implementedinterfaces.implindex(i);
+ if j<>i then
+ _class.implementedinterfaces.setioffsets(i,_class.implementedinterfaces.ioffsets(j));
+ gintfgenentry(i,j,rawdata);
+ end;
+ asmlist[al_globals].concatlist(rawdata);
+ rawdata.free;
+ end;
+
+
+ function tclassheader.gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
+ const
+ po_comp = [po_classmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
+ po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
+ var
+ sym: tsym;
+ implprocdef : Tprocdef;
+ i: cardinal;
+ begin
+ gintfgetcprocdef:=nil;
+
+ sym:=tsym(search_class_member(_class,name));
+ if assigned(sym) and
+ (sym.typ=procsym) then
+ begin
+ { when the definition has overload directive set, we search for
+ overloaded definitions in the class, this only needs to be done once
+ for class entries as the tree keeps always the same }
+ if (not tprocsym(sym).overloadchecked) and
+ (po_overload in tprocsym(sym).first_procdef.procoptions) and
+ (tprocsym(sym).owner.symtabletype=objectsymtable) then
+ search_class_overloads(tprocsym(sym));
+
+ for i:=1 to tprocsym(sym).procdef_count do
+ begin
+ implprocdef:=tprocsym(sym).procdef[i];
+ if (compare_paras(proc.paras,implprocdef.paras,cp_none,[])>=te_equal) and
+ (proc.proccalloption=implprocdef.proccalloption) and
+ (proc.proctypeoption=implprocdef.proctypeoption) and
+ ((proc.procoptions*po_comp)=((implprocdef.procoptions+[po_virtualmethod])*po_comp)) then
+ begin
+ gintfgetcprocdef:=implprocdef;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tclassheader.gintfdoonintf(intf: tobjectdef; intfindex: longint);
+ var
+ def: tdef;
+ hs,
+ mappedname: string;
+ nextexist: pointer;
+ implprocdef: tprocdef;
+ begin
+ def:=tdef(intf.symtable.defindex.first);
+ while assigned(def) do
+ begin
+ if def.deftype=procdef then
+ begin
+ implprocdef:=nil;
+ nextexist:=nil;
+ repeat
+ hs:=intf.symtable.name^+'.'+tprocdef(def).procsym.name;
+ mappedname:=_class.implementedinterfaces.getmappings(intfindex,hs,nextexist);
+ if mappedname<>'' then
+ implprocdef:=gintfgetcprocdef(tprocdef(def),mappedname);
+ until assigned(implprocdef) or not assigned(nextexist);
+ if not assigned(implprocdef) then
+ implprocdef:=gintfgetcprocdef(tprocdef(def),tprocdef(def).procsym.name);
+ if assigned(implprocdef) then
+ _class.implementedinterfaces.addimplproc(intfindex,implprocdef)
+ else
+ Message1(sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
+ end;
+ def:=tdef(def.indexnext);
+ end;
+ end;
+
+
+ procedure tclassheader.gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
+ begin
+ if assigned(intf.childof) then
+ gintfwalkdowninterface(intf.childof,intfindex);
+ gintfdoonintf(intf,intfindex);
+ end;
+
+
+ function tclassheader.genintftable: tasmlabel;
+ var
+ intfindex: longint;
+ curintf: tobjectdef;
+ intftable: tasmlabel;
+ begin
+ { 1. step collect implementor functions into the implementedinterfaces.implprocs }
+ for intfindex:=1 to _class.implementedinterfaces.count do
+ begin
+ curintf:=_class.implementedinterfaces.interfaces(intfindex);
+ gintfwalkdowninterface(curintf,intfindex);
+ end;
+ { 2. step calc required fieldcount and their offsets in the object memory map
+ and write data }
+ objectlibrary.getdatalabel(intftable);
+ asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+ asmlist[al_globals].concat(Tai_label.Create(intftable));
+ { Optimize interface tables to reuse wrappers }
+ gintfoptimizevtbls;
+ { Write interface tables }
+ gintfwritedata;
+ genintftable:=intftable;
+ end;
+
+
+ { Write interface identifiers to the data section }
+ procedure tclassheader.writeinterfaceids;
+ var
+ i : longint;
+ s : string;
+ begin
+ if assigned(_class.iidguid) then
+ begin
+ s:=make_mangledname('IID',_class.owner,_class.objname^);
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_rodata,s,const_align(sizeof(aint)));
+ asmlist[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
+ asmlist[al_globals].concat(Tai_const.Create_32bit(longint(_class.iidguid^.D1)));
+ asmlist[al_globals].concat(Tai_const.Create_16bit(_class.iidguid^.D2));
+ asmlist[al_globals].concat(Tai_const.Create_16bit(_class.iidguid^.D3));
+ for i:=Low(_class.iidguid^.D4) to High(_class.iidguid^.D4) do
+ asmlist[al_globals].concat(Tai_const.Create_8bit(_class.iidguid^.D4[i]));
+ end;
+ maybe_new_object_file(asmlist[al_globals]);
+ s:=make_mangledname('IIDSTR',_class.owner,_class.objname^);
+ new_section(asmlist[al_globals],sec_rodata,s,0);
+ asmlist[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
+ asmlist[al_globals].concat(Tai_const.Create_8bit(length(_class.iidstr^)));
+ asmlist[al_globals].concat(Tai_string.Create(_class.iidstr^));
+ end;
+
+
+ procedure tclassheader.writevirtualmethods(List:TAAsmoutput);
+ var
+ vmtentry : pvmtentry;
+ procdefcoll : pprocdefcoll;
+ i : longint;
+ begin
+ { walk trough all numbers for virtual methods and search }
+ { the method }
+ for i:=0 to nextvirtnumber-1 do
+ begin
+ { walk trough all symbols }
+ vmtentry:=firstvmtentry;
+ while assigned(vmtentry) do
+ begin
+ { walk trough all methods }
+ procdefcoll:=vmtentry^.firstprocdef;
+ while assigned(procdefcoll) do
+ begin
+ { writes the addresses to the VMT }
+ { but only this which are declared as virtual }
+ if procdefcoll^.data.extnumber=i then
+ begin
+ if (po_virtualmethod in procdefcoll^.data.procoptions) then
+ begin
+ { if a method is abstract, then is also the }
+ { class abstract and it's not allow to }
+ { generates an instance }
+ if (po_abstractmethod in procdefcoll^.data.procoptions) then
+ List.concat(Tai_const.Createname('FPC_ABSTRACTERROR',AT_FUNCTION,0))
+ else
+ List.concat(Tai_const.createname(procdefcoll^.data.mangledname,AT_FUNCTION,0));
+ end;
+ end;
+ procdefcoll:=procdefcoll^.next;
+ end;
+ vmtentry:=vmtentry^.next;
+ end;
+ end;
+ end;
+
+ { generates the vmt for classes as well as for objects }
+ procedure tclassheader.writevmt;
+
+ var
+ methodnametable,intmessagetable,
+ strmessagetable,classnamelabel,
+ fieldtablelabel : tasmlabel;
+{$ifdef WITHDMT}
+ dmtlabel : tasmlabel;
+{$endif WITHDMT}
+ interfacetable : tasmlabel;
+ begin
+{$ifdef WITHDMT}
+ dmtlabel:=gendmt;
+{$endif WITHDMT}
+
+ { write tables for classes, this must be done before the actual
+ class is written, because we need the labels defined }
+ if is_class(_class) then
+ begin
+ objectlibrary.getdatalabel(classnamelabel);
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_rodata,classnamelabel.name,const_align(sizeof(aint)));
+
+ { interface table }
+ if _class.implementedinterfaces.count>0 then
+ interfacetable:=genintftable;
+
+ methodnametable:=genpublishedmethodstable;
+ fieldtablelabel:=_class.generate_field_table;
+ { write class name }
+ asmlist[al_globals].concat(Tai_label.Create(classnamelabel));
+ asmlist[al_globals].concat(Tai_const.Create_8bit(length(_class.objrealname^)));
+ asmlist[al_globals].concat(Tai_string.Create(_class.objrealname^));
+
+ { generate message and dynamic tables }
+ if (oo_has_msgstr in _class.objectoptions) then
+ strmessagetable:=genstrmsgtab;
+ if (oo_has_msgint in _class.objectoptions) then
+ intmessagetable:=genintmsgtab;
+ end;
+
+ { write debug info }
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_rodata,_class.vmt_mangledname,const_align(sizeof(aint)));
+ asmlist[al_globals].concat(Tai_symbol.Createname_global(_class.vmt_mangledname,AT_DATA,0));
+
+ { determine the size with symtable.datasize, because }
+ { size gives back 4 for classes }
+ asmlist[al_globals].concat(Tai_const.Create(ait_const_ptr,tobjectsymtable(_class.symtable).datasize));
+ asmlist[al_globals].concat(Tai_const.Create(ait_const_ptr,-int64(tobjectsymtable(_class.symtable).datasize)));
+{$ifdef WITHDMT}
+ if _class.classtype=ct_object then
+ begin
+ if assigned(dmtlabel) then
+ asmlist[al_globals].concat(Tai_const_symbol.Create(dmtlabel)))
+ else
+ asmlist[al_globals].concat(Tai_const.Create_ptr(0));
+ end;
+{$endif WITHDMT}
+ { write pointer to parent VMT, this isn't implemented in TP }
+ { but this is not used in FPC ? (PM) }
+ { it's not used yet, but the delphi-operators as and is need it (FK) }
+ { it is not written for parents that don't have any vmt !! }
+ if assigned(_class.childof) and
+ (oo_has_vmt in _class.childof.objectoptions) then
+ asmlist[al_globals].concat(Tai_const.Createname(_class.childof.vmt_mangledname,AT_DATA,0))
+ else
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil));
+
+ { write extended info for classes, for the order see rtl/inc/objpash.inc }
+ if is_class(_class) then
+ begin
+ { pointer to class name string }
+ asmlist[al_globals].concat(Tai_const.Create_sym(classnamelabel));
+ { pointer to dynamic table or nil }
+ if (oo_has_msgint in _class.objectoptions) then
+ asmlist[al_globals].concat(Tai_const.Create_sym(intmessagetable))
+ else
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil));
+ { pointer to method table or nil }
+ asmlist[al_globals].concat(Tai_const.Create_sym(methodnametable));
+ { pointer to field table }
+ asmlist[al_globals].concat(Tai_const.Create_sym(fieldtablelabel));
+ { pointer to type info of published section }
+ if (oo_can_have_published in _class.objectoptions) then
+ asmlist[al_globals].concat(Tai_const.Create_sym(_class.get_rtti_label(fullrtti)))
+ else
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil));
+ { inittable for con-/destruction }
+ if _class.members_need_inittable then
+ asmlist[al_globals].concat(Tai_const.Create_sym(_class.get_rtti_label(initrtti)))
+ else
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil));
+ { auto table }
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil));
+ { interface table }
+ if _class.implementedinterfaces.count>0 then
+ asmlist[al_globals].concat(Tai_const.Create_sym(interfacetable))
+ else
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil));
+ { table for string messages }
+ if (oo_has_msgstr in _class.objectoptions) then
+ asmlist[al_globals].concat(Tai_const.Create_sym(strmessagetable))
+ else
+ asmlist[al_globals].concat(Tai_const.Create_sym(nil));
+ end;
+ { write virtual methods }
+ writevirtualmethods(asmlist[al_globals]);
+ asmlist[al_globals].concat(Tai_const.create(ait_const_ptr,0));
+ { write the size of the VMT }
+ asmlist[al_globals].concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
+ end;
+
+
+end.
diff --git a/compiler/node.pas b/compiler/node.pas
new file mode 100644
index 0000000000..330833d5cf
--- /dev/null
+++ b/compiler/node.pas
@@ -0,0 +1,1157 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Basic node handling
+
+ 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 node;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,
+ cpubase,cgbase,cgutils,
+ aasmbase,
+ symtype;
+
+ type
+ tnodetype = (
+ emptynode, {No node (returns nil when loading from ppu)}
+ addn, {Represents the + operator}
+ muln, {Represents the * operator}
+ subn, {Represents the - operator}
+ divn, {Represents the div operator}
+ symdifn, {Represents the >< operator}
+ modn, {Represents the mod operator}
+ assignn, {Represents an assignment}
+ loadn, {Represents the use of a variabele}
+ rangen, {Represents a range (i.e. 0..9)}
+ ltn, {Represents the < operator}
+ lten, {Represents the <= operator}
+ gtn, {Represents the > operator}
+ gten, {Represents the >= operator}
+ equaln, {Represents the = operator}
+ unequaln, {Represents the <> operator}
+ inn, {Represents the in operator}
+ orn, {Represents the or operator}
+ xorn, {Represents the xor operator}
+ shrn, {Represents the shr operator}
+ shln, {Represents the shl operator}
+ slashn, {Represents the / operator}
+ andn, {Represents the and operator}
+ subscriptn, {Field in a record/object}
+ derefn, {Dereferences a pointer}
+ addrn, {Represents the @ operator}
+ ordconstn, {Represents an ordinal value}
+ typeconvn, {Represents type-conversion/typecast}
+ calln, {Represents a call node}
+ callparan, {Represents a parameter}
+ realconstn, {Represents a real value}
+ unaryminusn, {Represents a sign change (i.e. -2)}
+ asmn, {Represents an assembler node }
+ vecn, {Represents array indexing}
+ pointerconstn, {Represents a pointer constant}
+ stringconstn, {Represents a string constant}
+ notn, {Represents the not operator}
+ inlinen, {Internal procedures (i.e. writeln)}
+ niln, {Represents the nil pointer}
+ errorn, {This part of the tree could not be
+ parsed because of a compiler error}
+ typen, {A type name. Used for i.e. typeof(obj)}
+ setelementn, {A set element(s) (i.e. [a,b] and also [a..b])}
+ setconstn, {A set constant (i.e. [1,2])}
+ blockn, {A block of statements}
+ statementn, {One statement in a block of nodes}
+ ifn, {An if statement}
+ breakn, {A break statement}
+ continuen, {A continue statement}
+ whilerepeatn, {A while or repeat statement}
+ forn, {A for loop}
+ exitn, {An exit statement}
+ withn, {A with statement}
+ casen, {A case statement}
+ labeln, {A label}
+ goton, {A goto statement}
+ tryexceptn, {A try except block}
+ raisen, {A raise statement}
+ tryfinallyn, {A try finally statement}
+ onn, {For an on statement in exception code}
+ isn, {Represents the is operator}
+ asn, {Represents the as typecast}
+ caretn, {Represents the ^ operator}
+ starstarn, {Represents the ** operator exponentiation }
+ arrayconstructorn, {Construction node for [...] parsing}
+ arrayconstructorrangen, {Range element to allow sets in array construction tree}
+ tempcreaten, { for temps in the result/firstpass }
+ temprefn, { references to temps }
+ tempdeleten, { for temps in the result/firstpass }
+ addoptn, { added for optimizations where we cannot suppress }
+ nothingn, {NOP, Do nothing}
+ loadvmtaddrn, {Load the address of the VMT of a class/object}
+ guidconstn, {A GUID COM Interface constant }
+ rttin, {Rtti information so they can be accessed in result/firstpass}
+ loadparentfpn { Load the framepointer of the parent for nested procedures }
+ );
+
+ const
+ nodetype2str : array[tnodetype] of string[24] = (
+ '<emptynode>',
+ 'addn',
+ 'muln',
+ 'subn',
+ 'divn',
+ 'symdifn',
+ 'modn',
+ 'assignn',
+ 'loadn',
+ 'rangen',
+ 'ltn',
+ 'lten',
+ 'gtn',
+ 'gten',
+ 'equaln',
+ 'unequaln',
+ 'inn',
+ 'orn',
+ 'xorn',
+ 'shrn',
+ 'shln',
+ 'slashn',
+ 'andn',
+ 'subscriptn',
+ 'derefn',
+ 'addrn',
+ 'ordconstn',
+ 'typeconvn',
+ 'calln',
+ 'callparan',
+ 'realconstn',
+ 'unaryminusn',
+ 'asmn',
+ 'vecn',
+ 'pointerconstn',
+ 'stringconstn',
+ 'notn',
+ 'inlinen',
+ 'niln',
+ 'errorn',
+ 'typen',
+ 'setelementn',
+ 'setconstn',
+ 'blockn',
+ 'statementn',
+ 'ifn',
+ 'breakn',
+ 'continuen',
+ 'whilerepeatn',
+ 'forn',
+ 'exitn',
+ 'withn',
+ 'casen',
+ 'labeln',
+ 'goton',
+ 'tryexceptn',
+ 'raisen',
+ 'tryfinallyn',
+ 'onn',
+ 'isn',
+ 'asn',
+ 'caretn',
+ 'starstarn',
+ 'arrayconstructn',
+ 'arrayconstructrangen',
+ 'tempcreaten',
+ 'temprefn',
+ 'tempdeleten',
+ 'addoptn',
+ 'nothingn',
+ 'loadvmtaddrn',
+ 'guidconstn',
+ 'rttin',
+ 'loadparentfpn');
+
+ type
+ { all boolean field of ttree are now collected in flags }
+ tnodeflag = (
+ nf_swapable, { tbinop operands can be swaped }
+ nf_swaped, { tbinop operands are swaped }
+ nf_error,
+
+ { general }
+ nf_pass1_done,
+ nf_write, { Node is written to }
+ nf_isproperty,
+
+ { taddrnode }
+ nf_typedaddr,
+
+ { tderefnode }
+ nf_no_checkpointer,
+
+ { tvecnode }
+ nf_memindex,
+ nf_memseg,
+ nf_callunique,
+
+ { tloadnode }
+ nf_absolute,
+ nf_is_self,
+ nf_load_self_pointer,
+
+ { taddnode }
+ nf_is_currency,
+ nf_has_pointerdiv,
+
+ { tassignmentnode }
+ nf_concat_string,
+ nf_use_strconcat,
+
+ { tarrayconstructnode }
+ nf_forcevaria,
+ nf_novariaallowed,
+
+ { ttypeconvnode }
+ nf_explicit,
+ nf_internal, { no warnings/hints generated }
+ nf_load_procvar,
+
+ { tinlinenode }
+ nf_inlineconst,
+
+ { tasmnode }
+ nf_get_asm_position,
+
+ { tblocknode }
+ nf_block_with_exit
+ );
+
+ tnodeflags = set of tnodeflag;
+
+ const
+ { contains the flags which must be equal for the equality }
+ { of nodes }
+ flagsequal : tnodeflags = [nf_error];
+
+ type
+ tnodelist = class
+ end;
+
+ { later (for the newcg) tnode will inherit from tlinkedlist_item }
+ tnode = class
+ public
+ { type of this node }
+ nodetype : tnodetype;
+ { type of the current code block, general/const/type }
+ blocktype : tblock_type;
+ { expected location of the result of this node (pass1) }
+ expectloc : tcgloc;
+ { the location of the result of this node (pass2) }
+ location : tlocation;
+ { the parent node of this is node }
+ { this field is set by concattolist }
+ parent : tnode;
+ { there are some properties about the node stored }
+ flags : tnodeflags;
+ ppuidx : longint;
+ { the number of registers needed to evalute the node }
+ registersint,registersfpu,registersmm : longint; { must be longint !!!! }
+{$ifdef SUPPORT_MMX}
+ registersmmx : longint;
+{$endif SUPPORT_MMX}
+ resulttype : ttype;
+ fileinfo : tfileposinfo;
+ localswitches : tlocalswitches;
+{$ifdef extdebug}
+ maxfirstpasscount,
+ firstpasscount : longint;
+{$endif extdebug}
+ constructor create(t:tnodetype);
+ { this constructor is only for creating copies of class }
+ { the fields are copied by getcopy }
+ constructor createforcopy;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);virtual;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ procedure buildderefimpl;virtual;
+ procedure derefimpl;virtual;
+ procedure derefnode;virtual;
+
+ { toggles the flag }
+ procedure toggleflag(f : tnodeflag);
+
+ { the 1.1 code generator may override pass_1 }
+ { and it need not to implement det_* then }
+ { 1.1: pass_1 returns a value<>0 if the node has been transformed }
+ { 2.0: runs det_resulttype and det_temp }
+ function pass_1 : tnode;virtual;abstract;
+ { dermines the resulttype of the node }
+ function det_resulttype : tnode;virtual;abstract;
+
+ { tries to simplify the node, returns a value <>nil if a simplified
+ node has been created }
+ function simplify : tnode;virtual;
+{$ifdef state_tracking}
+ { Does optimizations by keeping track of the variable states
+ in a procedure }
+ function track_state_pass(exec_known:boolean):boolean;virtual;
+{$endif}
+ { For a t1:=t2 tree, mark the part of the tree t1 that gets
+ written to (normally the loadnode) as write access. }
+ procedure mark_write;virtual;
+ { dermines the number of necessary temp. locations to evaluate
+ the node }
+ procedure det_temp;virtual;abstract;
+
+ procedure pass_2;virtual;abstract;
+
+ { comparing of nodes }
+ function isequal(p : tnode) : boolean;
+ { to implement comparisation, override this method }
+ function docompare(p : tnode) : boolean;virtual;
+ { wrapper for getcopy }
+ function getcopy : tnode;
+
+ { does the real copying of a node }
+ function _getcopy : tnode;virtual;
+
+ procedure insertintolist(l : tnodelist);virtual;
+ { writes a node for debugging purpose, shouldn't be called }
+ { direct, because there is no test for nil, use printnode }
+ { to write a complete tree }
+ procedure printnodeinfo(var t:text);virtual;
+ procedure printnodedata(var t:text);virtual;
+ procedure printnodetree(var t:text);virtual;
+ procedure concattolist(l : tlinkedlist);virtual;
+ function ischild(p : tnode) : boolean;virtual;
+ end;
+
+ tnodeclass = class of tnode;
+
+ tnodeclassarray = array[tnodetype] of tnodeclass;
+
+ { this node is the anchestor for all nodes with at least }
+ { one child, you have to use it if you want to use }
+ { true- and falselabel }
+ punarynode = ^tunarynode;
+ tunarynode = class(tnode)
+ left : tnode;
+ constructor create(t:tnodetype;l : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure derefnode;override;
+ procedure concattolist(l : tlinkedlist);override;
+ function ischild(p : tnode) : boolean;override;
+ function docompare(p : tnode) : boolean;override;
+ function _getcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure left_max;
+ procedure printnodedata(var t:text);override;
+ end;
+
+ pbinarynode = ^tbinarynode;
+ tbinarynode = class(tunarynode)
+ right : tnode;
+ constructor create(t:tnodetype;l,r : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure derefnode;override;
+ procedure concattolist(l : tlinkedlist);override;
+ function ischild(p : tnode) : boolean;override;
+ function docompare(p : tnode) : boolean;override;
+ procedure swapleftright;
+ function _getcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure left_right_max;
+ procedure printnodedata(var t:text);override;
+ procedure printnodelist(var t:text);
+ end;
+
+ tbinopnode = class(tbinarynode)
+ constructor create(t:tnodetype;l,r : tnode);virtual;
+ function docompare(p : tnode) : boolean;override;
+ end;
+
+ var
+ { array with all class types for tnodes }
+ nodeclass : tnodeclassarray;
+
+ function nodeppuidxget(i:longint):tnode;
+ function ppuloadnode(ppufile:tcompilerppufile):tnode;
+ procedure ppuwritenode(ppufile:tcompilerppufile;n:tnode);
+ function ppuloadnodetree(ppufile:tcompilerppufile):tnode;
+ procedure ppuwritenodetree(ppufile:tcompilerppufile;n:tnode);
+ procedure ppuwritenoderef(ppufile:tcompilerppufile;n:tnode);
+ function ppuloadnoderef(ppufile:tcompilerppufile) : tnode;
+
+ const
+ printnodespacing = ' ';
+ var
+ { indention used when writing the tree to the screen }
+ printnodeindention : string;
+
+ procedure printnodeindent;
+ procedure printnodeunindent;
+ procedure printnode(var t:text;n:tnode);
+
+ function is_constnode(p : tnode) : boolean;
+ function is_constintnode(p : tnode) : boolean;
+ function is_constcharnode(p : tnode) : boolean;
+ function is_constrealnode(p : tnode) : boolean;
+ function is_constboolnode(p : tnode) : boolean;
+ function is_constenumnode(p : tnode) : boolean;
+ function is_constwidecharnode(p : tnode) : boolean;
+
+
+implementation
+
+ uses
+ cutils,verbose,ppu,
+ symconst,
+ defutil;
+
+ const
+ ppunodemarker = 255;
+
+
+{****************************************************************************
+ Helpers
+ ****************************************************************************}
+
+ var
+ nodeppudata : tdynamicarray;
+ nodeppuidx : longint;
+
+
+ procedure nodeppuidxcreate;
+ begin
+ nodeppudata:=tdynamicarray.create(1024);
+ nodeppuidx:=0;
+ end;
+
+
+ procedure nodeppuidxfree;
+ begin
+ nodeppudata.free;
+ nodeppudata:=nil;
+ end;
+
+
+ procedure nodeppuidxadd(n:tnode);
+ begin
+ if n.ppuidx<0 then
+ internalerror(200311072);
+ nodeppudata.seek(n.ppuidx*sizeof(pointer));
+ nodeppudata.write(n,sizeof(pointer));
+ end;
+
+
+ function nodeppuidxget(i:longint):tnode;
+ begin
+ if i<0 then
+ internalerror(200311072);
+ nodeppudata.seek(i*sizeof(pointer));
+ if nodeppudata.read(result,sizeof(pointer))<>sizeof(pointer) then
+ internalerror(200311073);
+ end;
+
+
+ function ppuloadnode(ppufile:tcompilerppufile):tnode;
+ var
+ b : byte;
+ t : tnodetype;
+ hppuidx : longint;
+ begin
+ { marker }
+ b:=ppufile.getbyte;
+ if b<>ppunodemarker then
+ internalerror(200208151);
+ { load nodetype }
+ t:=tnodetype(ppufile.getbyte);
+ if t>high(tnodetype) then
+ internalerror(200208152);
+ if t<>emptynode then
+ begin
+ if not assigned(nodeclass[t]) then
+ internalerror(200208153);
+ hppuidx:=ppufile.getlongint;
+ //writeln('load: ',nodetype2str[t]);
+ { generate node of the correct class }
+ result:=nodeclass[t].ppuload(t,ppufile);
+ result.ppuidx:=hppuidx;
+ nodeppuidxadd(result);
+ end
+ else
+ result:=nil;
+ end;
+
+
+ procedure ppuwritenode(ppufile:tcompilerppufile;n:tnode);
+ begin
+ { marker, read by ppuloadnode }
+ ppufile.putbyte(ppunodemarker);
+ { type, read by ppuloadnode }
+ if assigned(n) then
+ begin
+ if n.ppuidx=-1 then
+ internalerror(200311071);
+ n.ppuidx:=nodeppuidx;
+ inc(nodeppuidx);
+ ppufile.putbyte(byte(n.nodetype));
+ ppufile.putlongint(n.ppuidx);
+ //writeln('write: ',nodetype2str[n.nodetype]);
+ n.ppuwrite(ppufile);
+ end
+ else
+ ppufile.putbyte(byte(emptynode));
+ end;
+
+
+ procedure ppuwritenoderef(ppufile:tcompilerppufile;n:tnode);
+ begin
+ { writing of node references isn't implemented yet (FK) }
+ internalerror(200506181);
+ end;
+
+
+ function ppuloadnoderef(ppufile:tcompilerppufile) : tnode;
+ begin
+ { reading of node references isn't implemented yet (FK) }
+ internalerror(200506182);
+ end;
+
+
+ function ppuloadnodetree(ppufile:tcompilerppufile):tnode;
+ begin
+ if ppufile.readentry<>ibnodetree then
+ Message(unit_f_ppu_read_error);
+ nodeppuidxcreate;
+ result:=ppuloadnode(ppufile);
+ result.derefnode;
+ nodeppuidxfree;
+ end;
+
+
+ procedure ppuwritenodetree(ppufile:tcompilerppufile;n:tnode);
+ begin
+ nodeppuidx:=0;
+ ppuwritenode(ppufile,n);
+ ppufile.writeentry(ibnodetree);
+ end;
+
+
+ procedure printnodeindent;
+ begin
+ printnodeindention:=printnodeindention+printnodespacing;
+ end;
+
+
+ procedure printnodeunindent;
+ begin
+ delete(printnodeindention,1,length(printnodespacing));
+ end;
+
+
+ procedure printnode(var t:text;n:tnode);
+ begin
+ if assigned(n) then
+ n.printnodetree(t)
+ else
+ writeln(t,printnodeindention,'nil');
+ end;
+
+
+ function is_constnode(p : tnode) : boolean;
+ begin
+ is_constnode:=(p.nodetype in [niln,ordconstn,realconstn,stringconstn,setconstn,guidconstn]);
+ end;
+
+
+ function is_constintnode(p : tnode) : boolean;
+ begin
+ is_constintnode:=(p.nodetype=ordconstn) and is_integer(p.resulttype.def);
+ end;
+
+
+ function is_constcharnode(p : tnode) : boolean;
+ begin
+ is_constcharnode:=(p.nodetype=ordconstn) and is_char(p.resulttype.def);
+ end;
+
+
+ function is_constwidecharnode(p : tnode) : boolean;
+ begin
+ is_constwidecharnode:=(p.nodetype=ordconstn) and is_widechar(p.resulttype.def);
+ end;
+
+
+ function is_constrealnode(p : tnode) : boolean;
+ begin
+ is_constrealnode:=(p.nodetype=realconstn);
+ end;
+
+
+ function is_constboolnode(p : tnode) : boolean;
+ begin
+ is_constboolnode:=(p.nodetype=ordconstn) and is_boolean(p.resulttype.def);
+ end;
+
+
+ function is_constenumnode(p : tnode) : boolean;
+ begin
+ is_constenumnode:=(p.nodetype=ordconstn) and (p.resulttype.def.deftype=enumdef);
+ end;
+
+{****************************************************************************
+ TNODE
+ ****************************************************************************}
+
+ constructor tnode.create(t:tnodetype);
+
+ begin
+ inherited create;
+ nodetype:=t;
+ blocktype:=block_type;
+ { updated by firstpass }
+ expectloc:=LOC_INVALID;
+ { updated by secondpass }
+ location.loc:=LOC_INVALID;
+ { save local info }
+ fileinfo:=aktfilepos;
+ localswitches:=aktlocalswitches;
+ resulttype.reset;
+ registersint:=0;
+ registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=0;
+{$endif SUPPORT_MMX}
+{$ifdef EXTDEBUG}
+ maxfirstpasscount:=0;
+ firstpasscount:=0;
+{$endif EXTDEBUG}
+ flags:=[];
+ ppuidx:=-1;
+ end;
+
+ constructor tnode.createforcopy;
+
+ begin
+ end;
+
+ constructor tnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+
+ begin
+ nodetype:=t;
+ { tnode fields }
+ blocktype:=tblock_type(ppufile.getbyte);
+ ppufile.getposinfo(fileinfo);
+ ppufile.getsmallset(localswitches);
+ ppufile.gettype(resulttype);
+ ppufile.getsmallset(flags);
+ { updated by firstpass }
+ expectloc:=LOC_INVALID;
+ { updated by secondpass }
+ location.loc:=LOC_INVALID;
+ registersint:=0;
+ registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=0;
+{$endif SUPPORT_MMX}
+{$ifdef EXTDEBUG}
+ maxfirstpasscount:=0;
+ firstpasscount:=0;
+{$endif EXTDEBUG}
+ ppuidx:=-1;
+ end;
+
+
+ procedure tnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ ppufile.putbyte(byte(block_type));
+ ppufile.putposinfo(fileinfo);
+ ppufile.putsmallset(localswitches);
+ ppufile.puttype(resulttype);
+ ppufile.putsmallset(flags);
+ end;
+
+
+ procedure tnode.buildderefimpl;
+ begin
+ resulttype.buildderef;
+ end;
+
+
+ procedure tnode.derefimpl;
+ begin
+ resulttype.resolve;
+ end;
+
+
+ procedure tnode.derefnode;
+ begin
+ end;
+
+
+ procedure tnode.toggleflag(f : tnodeflag);
+ begin
+ if f in flags then
+ exclude(flags,f)
+ else
+ include(flags,f);
+ end;
+
+
+ function tnode.simplify : tnode;
+ begin
+ result:=nil;
+ end;
+
+
+ destructor tnode.destroy;
+ begin
+{$ifdef EXTDEBUG}
+ if firstpasscount>maxfirstpasscount then
+ maxfirstpasscount:=firstpasscount;
+{$endif EXTDEBUG}
+ end;
+
+
+ procedure tnode.concattolist(l : tlinkedlist);
+ begin
+ end;
+
+
+ function tnode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=false;
+ end;
+
+
+ procedure tnode.mark_write;
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'mark_write not implemented for '+nodetype2str[nodetype]);
+{$endif EXTDEBUG}
+ end;
+
+
+ procedure tnode.printnodeinfo(var t:text);
+ begin
+ write(t,nodetype2str[nodetype]);
+ if assigned(resulttype.def) then
+ write(t,', resulttype = "',resulttype.def.gettypename,'"')
+ else
+ write(t,', resulttype = <nil>');
+ write(t,', pos = (',fileinfo.line,',',fileinfo.column,')',
+ ', loc = ',tcgloc2str[location.loc],
+ ', expectloc = ',tcgloc2str[expectloc],
+ ', intregs = ',registersint,
+ ', fpuregs = ',registersfpu);
+ end;
+
+
+ procedure tnode.printnodedata(var t:text);
+ begin
+ end;
+
+
+ procedure tnode.printnodetree(var t:text);
+ begin
+ write(t,printnodeindention,'(');
+ printnodeinfo(t);
+ writeln(t);
+ printnodeindent;
+ printnodedata(t);
+ printnodeunindent;
+ writeln(t,printnodeindention,')');
+ end;
+
+
+ function tnode.isequal(p : tnode) : boolean;
+ begin
+ isequal:=
+ (not assigned(self) and not assigned(p)) or
+ (assigned(self) and assigned(p) and
+ { optimized subclasses have the same nodetype as their }
+ { superclass (for compatibility), so also check the classtype (JM) }
+ (p.classtype=classtype) and
+ (p.nodetype=nodetype) and
+ (flags*flagsequal=p.flags*flagsequal) and
+ docompare(p));
+ end;
+
+{$ifdef state_tracking}
+ function Tnode.track_state_pass(exec_known:boolean):boolean;
+ begin
+ track_state_pass:=false;
+ end;
+{$endif state_tracking}
+
+
+ function tnode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=true;
+ end;
+
+
+ function tnode.getcopy : tnode;
+ begin
+ result:=_getcopy;
+ end;
+
+
+ function tnode._getcopy : tnode;
+ var
+ p : tnode;
+ begin
+ { this is quite tricky because we need a node of the current }
+ { node type and not one of tnode! }
+ p:=tnodeclass(classtype).createforcopy;
+ p.nodetype:=nodetype;
+ p.expectloc:=expectloc;
+ p.location:=location;
+ p.parent:=parent;
+ p.flags:=flags;
+ p.registersint:=registersint;
+ p.registersfpu:=registersfpu;
+{$ifdef SUPPORT_MMX}
+ p.registersmmx:=registersmmx;
+ p.registersmm:=registersmm;
+{$endif SUPPORT_MMX}
+ p.resulttype:=resulttype;
+ p.fileinfo:=fileinfo;
+ p.localswitches:=localswitches;
+{$ifdef extdebug}
+ p.firstpasscount:=firstpasscount;
+{$endif extdebug}
+{ p.list:=list; }
+ result:=p;
+ end;
+
+
+ procedure tnode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+{****************************************************************************
+ TUNARYNODE
+ ****************************************************************************}
+
+ constructor tunarynode.create(t:tnodetype;l : tnode);
+ begin
+ inherited create(t);
+ left:=l;
+ end;
+
+
+ constructor tunarynode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ left:=ppuloadnode(ppufile);
+ end;
+
+
+ destructor tunarynode.destroy;
+ begin
+ left.free;
+ inherited destroy;
+ end;
+
+
+ procedure tunarynode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,left);
+ end;
+
+
+ procedure tunarynode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(left) then
+ left.buildderefimpl;
+ end;
+
+
+ procedure tunarynode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(left) then
+ left.derefimpl;
+ end;
+
+
+ procedure tunarynode.derefnode;
+ begin
+ inherited derefnode;
+ if assigned(left) then
+ left.derefnode;
+ end;
+
+
+ function tunarynode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p) and
+ ((left=nil) or left.isequal(tunarynode(p).left))
+ );
+ end;
+
+
+ function tunarynode._getcopy : tnode;
+ var
+ p : tunarynode;
+ begin
+ p:=tunarynode(inherited _getcopy);
+ if assigned(left) then
+ p.left:=left._getcopy
+ else
+ p.left:=nil;
+ result:=p;
+ end;
+
+
+ procedure tunarynode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ procedure tunarynode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ printnode(t,left);
+ end;
+
+
+ procedure tunarynode.left_max;
+ begin
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+
+ procedure tunarynode.concattolist(l : tlinkedlist);
+ begin
+ left.parent:=self;
+ left.concattolist(l);
+ inherited concattolist(l);
+ end;
+
+
+ function tunarynode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=p=left;
+ end;
+
+
+{****************************************************************************
+ TBINARYNODE
+ ****************************************************************************}
+
+ constructor tbinarynode.create(t:tnodetype;l,r : tnode);
+ begin
+ inherited create(t,l);
+ right:=r
+ end;
+
+
+ constructor tbinarynode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ right:=ppuloadnode(ppufile);
+ end;
+
+
+ destructor tbinarynode.destroy;
+ begin
+ right.free;
+ inherited destroy;
+ end;
+
+
+ procedure tbinarynode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,right);
+ end;
+
+
+ procedure tbinarynode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(right) then
+ right.buildderefimpl;
+ end;
+
+
+ procedure tbinarynode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(right) then
+ right.derefimpl;
+ end;
+
+
+ procedure tbinarynode.derefnode;
+ begin
+ inherited derefnode;
+ if assigned(right) then
+ right.derefnode;
+ end;
+
+
+ procedure tbinarynode.concattolist(l : tlinkedlist);
+ begin
+ { we could change that depending on the number of }
+ { required registers }
+ left.parent:=self;
+ left.concattolist(l);
+ left.parent:=self;
+ left.concattolist(l);
+ inherited concattolist(l);
+ end;
+
+
+ function tbinarynode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=(p=right);
+ end;
+
+
+ function tbinarynode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p) and
+ ((right=nil) or right.isequal(tbinarynode(p).right))
+ );
+ end;
+
+
+ function tbinarynode._getcopy : tnode;
+ var
+ p : tbinarynode;
+ begin
+ p:=tbinarynode(inherited _getcopy);
+ if assigned(right) then
+ p.right:=right._getcopy
+ else
+ p.right:=nil;
+ result:=p;
+ end;
+
+
+ procedure tbinarynode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ procedure tbinarynode.swapleftright;
+ var
+ swapp : tnode;
+ begin
+ swapp:=right;
+ right:=left;
+ left:=swapp;
+ if nf_swaped in flags then
+ exclude(flags,nf_swaped)
+ else
+ include(flags,nf_swaped);
+ end;
+
+
+ procedure tbinarynode.left_right_max;
+ begin
+ if assigned(left) then
+ begin
+ if assigned(right) then
+ begin
+ registersint:=max(left.registersint,right.registersint);
+ registersfpu:=max(left.registersfpu,right.registersfpu);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=max(left.registersmmx,right.registersmmx);
+{$endif SUPPORT_MMX}
+ end
+ else
+ begin
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+ end;
+ end;
+
+
+ procedure tbinarynode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ printnode(t,right);
+ end;
+
+
+ procedure tbinarynode.printnodelist(var t:text);
+ var
+ hp : tbinarynode;
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ write(t,printnodeindention,'(');
+ printnodeindent;
+ hp.printnodeinfo(t);
+ writeln(t);
+ printnode(t,hp.left);
+ writeln(t);
+ printnodeunindent;
+ writeln(t,printnodeindention,')');
+ hp:=tbinarynode(hp.right);
+ end;
+ end;
+
+
+{****************************************************************************
+ TBINOPYNODE
+ ****************************************************************************}
+
+ constructor tbinopnode.create(t:tnodetype;l,r : tnode);
+ begin
+ inherited create(t,l,r);
+ end;
+
+
+ function tbinopnode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p)) or
+ { if that's in the flags, is p then always a tbinopnode (?) (JM) }
+ ((nf_swapable in flags) and
+ left.isequal(tbinopnode(p).right) and
+ right.isequal(tbinopnode(p).left));
+ end;
+
+end.
diff --git a/compiler/nopt.pas b/compiler/nopt.pas
new file mode 100644
index 0000000000..d5cbb08f82
--- /dev/null
+++ b/compiler/nopt.pas
@@ -0,0 +1,288 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe
+
+ This unit implements optimized 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 nopt;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses node, nadd;
+
+type
+ tsubnodetype = (
+ addsstringcharoptn, { shorstring + char }
+ addsstringcsstringoptn { shortstring + constant shortstring }
+ );
+
+ taddoptnode = class(taddnode)
+ subnodetype: tsubnodetype;
+ constructor create(ts: tsubnodetype; l,r : tnode); virtual;
+ { pass_1 will be overridden by the separate subclasses }
+ { By default, pass_2 is the same as for addnode }
+ { Only if there's a processor specific implementation, it }
+ { will be overridden. }
+ function _getcopy: tnode; override;
+ function docompare(p: tnode): boolean; override;
+ end;
+
+ taddsstringoptnode = class(taddoptnode)
+ { maximum length of the string until now, allows us to skip a compare }
+ { sometimes (it's initialized/updated by calling updatecurmaxlen) }
+ curmaxlen: byte;
+ { pass_1 must be overridden, otherwise we get an endless loop }
+ function det_resulttype: tnode; override;
+ function pass_1: tnode; override;
+ function _getcopy: tnode; override;
+ function docompare(p: tnode): boolean; override;
+ protected
+ procedure updatecurmaxlen;
+ end;
+
+ { add a char to a shortstring }
+ taddsstringcharoptnode = class(taddsstringoptnode)
+ constructor create(l,r : tnode); virtual;
+ end;
+ taddsstringcharoptnodeclass = class of taddsstringcharoptnode;
+
+ { add a constant string to a short string }
+ taddsstringcsstringoptnode = class(taddsstringoptnode)
+ constructor create(l,r : tnode); virtual;
+ function pass_1: tnode; override;
+ end;
+ taddsstringcsstringoptnodeclass = class of taddsstringcsstringoptnode;
+
+function canbeaddsstringcharoptnode(p: taddnode): boolean;
+function genaddsstringcharoptnode(p: taddnode): tnode;
+function canbeaddsstringcsstringoptnode(p: taddnode): boolean;
+function genaddsstringcsstringoptnode(p: taddnode): tnode;
+
+
+function is_addsstringoptnode(p: tnode): boolean;
+
+var
+ caddsstringcharoptnode: taddsstringcharoptnodeclass;
+ caddsstringcsstringoptnode: taddsstringcsstringoptnodeclass;
+
+implementation
+
+uses cutils, htypechk, defutil, defcmp, globtype, globals, cpubase, ncnv, ncon,ncal,
+ verbose, symconst,symdef, cgbase, procinfo;
+
+
+{*****************************************************************************
+ TADDOPTNODE
+*****************************************************************************}
+
+constructor taddoptnode.create(ts: tsubnodetype; l,r : tnode);
+begin
+ { we need to keep the addn nodetype, otherwise taddnode.pass_2 will be }
+ { confused. Comparison for equal nodetypes therefore has to be }
+ { implemented using the classtype() method (JM) }
+ inherited create(addn,l,r);
+ subnodetype := ts;
+end;
+
+function taddoptnode._getcopy: tnode;
+var
+ hp: taddoptnode;
+begin
+ hp := taddoptnode(inherited _getcopy);
+ hp.subnodetype := subnodetype;
+ _getcopy := hp;
+end;
+
+function taddoptnode.docompare(p: tnode): boolean;
+begin
+ docompare :=
+ inherited docompare(p) and
+ (subnodetype = taddoptnode(p).subnodetype);
+end;
+
+
+{*****************************************************************************
+ TADDSSTRINGOPTNODE
+*****************************************************************************}
+
+function taddsstringoptnode.det_resulttype: tnode;
+begin
+ result := nil;
+ updatecurmaxlen;
+ { left and right are already firstpass'ed by taddnode.pass_1 }
+ if not is_shortstring(left.resulttype.def) then
+ inserttypeconv(left,cshortstringtype);
+ if not is_shortstring(right.resulttype.def) then
+ inserttypeconv(right,cshortstringtype);
+ resulttype := left.resulttype;
+end;
+
+function taddsstringoptnode.pass_1: tnode;
+begin
+ pass_1 := nil;
+ expectloc:= LOC_REFERENCE;
+ calcregisters(self,0,0,0);
+ { here we call STRCONCAT or STRCMP or STRCOPY }
+ include(current_procinfo.flags,pi_do_call);
+end;
+
+function taddsstringoptnode._getcopy: tnode;
+var
+ hp: taddsstringoptnode;
+begin
+ hp := taddsstringoptnode(inherited _getcopy);
+ hp.curmaxlen := curmaxlen;
+ _getcopy := hp;
+end;
+
+function taddsstringoptnode.docompare(p: tnode): boolean;
+begin
+ docompare :=
+ inherited docompare(p) and
+ (curmaxlen = taddsstringcharoptnode(p).curmaxlen);
+end;
+
+
+function is_addsstringoptnode(p: tnode): boolean;
+begin
+ is_addsstringoptnode :=
+ p.inheritsfrom(taddsstringoptnode);
+end;
+
+procedure taddsstringoptnode.updatecurmaxlen;
+begin
+ if is_addsstringoptnode(left) then
+ begin
+ { made it a separate block so no other if's are processed (would be a }
+ { simple waste of time) (JM) }
+ if (taddsstringoptnode(left).curmaxlen < 255) then
+ case subnodetype of
+ addsstringcharoptn:
+ curmaxlen := succ(taddsstringoptnode(left).curmaxlen);
+ addsstringcsstringoptn:
+ curmaxlen := min(taddsstringoptnode(left).curmaxlen +
+ tstringconstnode(right).len,255)
+ else
+ internalerror(291220001);
+ end
+ else curmaxlen := 255;
+ end
+ else if (left.nodetype = stringconstn) then
+ curmaxlen := min(tstringconstnode(left).len,255)
+ else if is_char(left.resulttype.def) then
+ curmaxlen := 1
+ else if (left.nodetype = typeconvn) then
+ begin
+ case ttypeconvnode(left).convtype of
+ tc_char_2_string:
+ curmaxlen := 1;
+{ doesn't work yet, don't know why (JM)
+ tc_chararray_2_string:
+ curmaxlen :=
+ min(ttypeconvnode(left).left.resulttype.def.size,255); }
+ else curmaxlen := 255;
+ end;
+ end
+ else
+ curmaxlen := 255;
+end;
+
+{*****************************************************************************
+ TADDSSTRINGCHAROPTNODE
+*****************************************************************************}
+
+
+constructor taddsstringcharoptnode.create(l,r : tnode);
+begin
+ inherited create(addsstringcharoptn,l,r);
+end;
+
+{*****************************************************************************
+ TADDSSTRINGCSSTRINGOPTNODE
+*****************************************************************************}
+
+
+constructor taddsstringcsstringoptnode.create(l,r : tnode);
+begin
+ inherited create(addsstringcsstringoptn,l,r);
+end;
+
+
+function taddsstringcsstringoptnode.pass_1: tnode;
+begin
+ { create the call to the concat routine both strings as arguments }
+ result := ccallnode.createintern('fpc_shortstr_append_shortstr',
+ ccallparanode.create(left,ccallparanode.create(right,nil)));
+ left:=nil;
+ right:=nil;
+end;
+
+
+{*****************************************************************************
+ HELPERS
+*****************************************************************************}
+
+function canbeaddsstringcharoptnode(p: taddnode): boolean;
+begin
+ canbeaddsstringcharoptnode :=
+ (cs_optimize in aktglobalswitches) and
+
+{ the shortstring will be gotten through conversion if necessary (JM)
+ is_shortstring(p.left.resulttype.def) and }
+ ((p.nodetype = addn) and
+ is_char(p.right.resulttype.def));
+end;
+
+function genaddsstringcharoptnode(p: taddnode): tnode;
+var
+ hp: tnode;
+begin
+ hp := caddsstringcharoptnode.create(p.left.getcopy,p.right.getcopy);
+ hp.flags := p.flags;
+ genaddsstringcharoptnode := hp;
+end;
+
+
+
+function canbeaddsstringcsstringoptnode(p: taddnode): boolean;
+begin
+ canbeaddsstringcsstringoptnode :=
+ (cs_optimize in aktglobalswitches) and
+
+{ the shortstring will be gotten through conversion if necessary (JM)
+ is_shortstring(p.left.resulttype.def) and }
+ ((p.nodetype = addn) and
+ (p.right.nodetype = stringconstn));
+end;
+
+function genaddsstringcsstringoptnode(p: taddnode): tnode;
+var
+ hp: tnode;
+begin
+ hp := caddsstringcsstringoptnode.create(p.left.getcopy,p.right.getcopy);
+ hp.flags := p.flags;
+ genaddsstringcsstringoptnode := hp;
+end;
+
+
+begin
+ caddsstringcharoptnode := taddsstringcharoptnode;
+ caddsstringcsstringoptnode := taddsstringcsstringoptnode;
+end.
diff --git a/compiler/nset.pas b/compiler/nset.pas
new file mode 100644
index 0000000000..94870d0166
--- /dev/null
+++ b/compiler/nset.pas
@@ -0,0 +1,808 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for 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 nset;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ node,globtype,globals,
+ aasmbase,aasmtai,symtype;
+
+ type
+ pcaselabel = ^tcaselabel;
+ tcaselabel = record
+ { range }
+ _low,
+ _high : TConstExprInt;
+ { unique blockid }
+ blockid : longint;
+ { left and right tree node }
+ less,
+ greater : pcaselabel;
+ end;
+
+ pcaseblock = ^tcaseblock;
+ tcaseblock = record
+ { label (only used in pass_2) }
+ blocklabel : tasmlabel;
+ { instructions }
+ statement : tnode;
+ end;
+
+ tsetelementnode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tsetelementnodeclass = class of tsetelementnode;
+
+ tinnode = class(tbinopnode)
+ constructor create(l,r : tnode);virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tinnodeclass = class of tinnode;
+
+ trangenode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ trangenodeclass = class of trangenode;
+
+ tcasenode = class(tunarynode)
+ labels : pcaselabel;
+ blocks : tlist;
+ elseblock : tnode;
+ constructor create(l:tnode);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function _getcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ function det_resulttype:tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ procedure addlabel(blockid:longint;l,h : TConstExprInt);
+ procedure addblock(blockid:longint;instr:tnode);
+ procedure addelseblock(instr:tnode);
+ end;
+ tcasenodeclass = class of tcasenode;
+
+ var
+ csetelementnode : tsetelementnodeclass;
+ cinnode : tinnodeclass;
+ crangenode : trangenodeclass;
+ ccasenode : tcasenodeclass;
+
+ { counts the labels }
+ function case_count_labels(root : pcaselabel) : longint;
+ { searches the highest label }
+{$ifdef int64funcresok}
+ function case_get_max(root : pcaselabel) : tconstexprint;
+{$else int64funcresok}
+ function case_get_max(root : pcaselabel) : longint;
+{$endif int64funcresok}
+ { searches the lowest label }
+{$ifdef int64funcresok}
+ function case_get_min(root : pcaselabel) : tconstexprint;
+{$else int64funcresok}
+ function case_get_min(root : pcaselabel) : longint;
+{$endif int64funcresok}
+
+
+implementation
+
+ uses
+ systems,
+ verbose,
+ symconst,symdef,symsym,symtable,defutil,defcmp,
+ htypechk,pass_1,
+ nbas,ncnv,ncon,nld,cgobj,cgbase;
+
+
+{*****************************************************************************
+ TSETELEMENTNODE
+*****************************************************************************}
+
+ constructor tsetelementnode.create(l,r : tnode);
+
+ begin
+ inherited create(setelementn,l,r);
+ end;
+
+
+ function tsetelementnode.det_resulttype:tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ if assigned(right) then
+ resulttypepass(right);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ resulttype:=left.resulttype;
+ end;
+
+
+ function tsetelementnode.pass_1 : tnode;
+
+ begin
+ result:=nil;
+ firstpass(left);
+ if assigned(right) then
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+ expectloc:=left.expectloc;
+ calcregisters(self,0,0,0);
+ end;
+
+
+{*****************************************************************************
+ TINNODE
+*****************************************************************************}
+
+ constructor tinnode.create(l,r : tnode);
+ begin
+ inherited create(inn,l,r);
+ end;
+
+
+ function tinnode.det_resulttype:tnode;
+
+ var
+ t : tnode;
+ pst : pconstset;
+
+ function createsetconst(psd : tsetdef) : pconstset;
+ var
+ pcs : pconstset;
+ pes : tenumsym;
+ i : longint;
+ begin
+ new(pcs);
+ case psd.elementtype.def.deftype of
+ enumdef :
+ begin
+ pes:=tenumsym(tenumdef(psd.elementtype.def).firstenum);
+ while assigned(pes) do
+ begin
+ include(pcs^,pes.value);
+ pes:=pes.nextenum;
+ end;
+ end;
+ orddef :
+ begin
+ for i:=torddef(psd.elementtype.def).low to torddef(psd.elementtype.def).high do
+ include(pcs^,i);
+ end;
+ end;
+ createsetconst:=pcs;
+ end;
+
+ begin
+ result:=nil;
+ resulttype:=booltype;
+ resulttypepass(right);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { Convert array constructor first to set }
+ if is_array_constructor(right.resulttype.def) then
+ begin
+ arrayconstructor_to_set(right);
+ firstpass(right);
+ if codegenerror then
+ exit;
+ end;
+
+ if right.resulttype.def.deftype<>setdef then
+ CGMessage(sym_e_set_expected);
+
+ if (right.nodetype=typen) then
+ begin
+ { we need to create a setconstn }
+ pst:=createsetconst(tsetdef(ttypenode(right).resulttype.def));
+ t:=csetconstnode.create(pst,ttypenode(right).resulttype);
+ dispose(pst);
+ right.free;
+ right:=t;
+ end;
+
+ resulttypepass(left);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ if not assigned(left.resulttype.def) then
+ internalerror(20021126);
+
+ if (m_fpc in aktmodeswitches) then
+ begin
+ { insert a hint that a range check error might occur on non-byte
+ elements with the in operator.
+ }
+ if (
+ (left.resulttype.def.deftype = orddef) and not
+ (torddef(left.resulttype.def).typ in [s8bit,u8bit,uchar,bool8bit])
+ )
+ or
+ (
+ (left.resulttype.def.deftype = enumdef) and
+ (tenumdef(left.resulttype.def).maxval > 255)
+ )
+ then
+ CGMessage(type_h_in_range_check);
+
+ { type conversion/check }
+ if assigned(tsetdef(right.resulttype.def).elementtype.def) then
+ inserttypeconv(left,tsetdef(right.resulttype.def).elementtype);
+ end
+ else
+ begin
+ { insert explicit type conversion/check }
+ if assigned(tsetdef(right.resulttype.def).elementtype.def) then
+ inserttypeconv_internal(left,tsetdef(right.resulttype.def).elementtype);
+ end;
+
+ { empty set then return false }
+ if not assigned(tsetdef(right.resulttype.def).elementtype.def) or
+ ((right.nodetype = setconstn) and
+ (tnormalset(tsetconstnode(right).value_set^) = [])) then
+ begin
+ t:=cordconstnode.create(0,booltype,false);
+ resulttypepass(t);
+ result:=t;
+ exit;
+ end;
+
+ { constant evaluation }
+ if (left.nodetype=ordconstn) and (right.nodetype=setconstn) then
+ begin
+ t:=cordconstnode.create(byte(tordconstnode(left).value in Tsetconstnode(right).value_set^),
+ booltype,true);
+ resulttypepass(t);
+ result:=t;
+ exit;
+ end;
+ end;
+
+
+ { Warning : This is the first pass for the generic version }
+ { the only difference is mainly the result location which }
+ { is changed, compared to the i386 version. }
+ { ALSO REGISTER ALLOC IS WRONG? }
+ function tinnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_REGISTER;
+
+ firstpass(right);
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ left_right_max;
+
+ if tsetdef(right.resulttype.def).settype<>smallset then
+ begin
+ if registersint < 3 then
+ registersint := 3;
+ end
+ else
+ begin
+ { a smallset needs maybe an misc. register }
+ if (left.nodetype<>ordconstn) and
+ not(right.expectloc in [LOC_CREGISTER,LOC_REGISTER]) and
+ (right.registersint<1) then
+ inc(registersint);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TRANGENODE
+*****************************************************************************}
+
+ constructor trangenode.create(l,r : tnode);
+
+ begin
+ inherited create(rangen,l,r);
+ end;
+
+
+ function trangenode.det_resulttype : tnode;
+ begin
+ result:=nil;
+ resulttypepass(left);
+ resulttypepass(right);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ set_varstate(right,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+ { both types must be compatible }
+ if compare_defs(left.resulttype.def,right.resulttype.def,left.nodetype)=te_incompatible then
+ IncompatibleTypes(left.resulttype.def,right.resulttype.def);
+ { Check if only when its a constant set }
+ if (left.nodetype=ordconstn) and (right.nodetype=ordconstn) then
+ begin
+ { upper limit must be greater or equal than lower limit }
+ if (tordconstnode(left).value>tordconstnode(right).value) and
+ ((tordconstnode(left).value<0) or (tordconstnode(right).value>=0)) then
+ CGMessage(parser_e_upper_lower_than_lower);
+ end;
+ resulttype:=left.resulttype;
+ end;
+
+
+ function trangenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+ left_right_max;
+ expectloc:=left.expectloc;
+ end;
+
+
+{*****************************************************************************
+ Case Helpers
+*****************************************************************************}
+
+ function case_count_labels(root : pcaselabel) : longint;
+ var
+ _l : longint;
+
+ procedure count(p : pcaselabel);
+ begin
+ inc(_l);
+ if assigned(p^.less) then
+ count(p^.less);
+ if assigned(p^.greater) then
+ count(p^.greater);
+ end;
+
+ begin
+ _l:=0;
+ count(root);
+ case_count_labels:=_l;
+ end;
+
+
+{$ifdef int64funcresok}
+ function case_get_max(root : pcaselabel) : tconstexprint;
+{$else int64funcresok}
+ function case_get_max(root : pcaselabel) : longint;
+{$endif int64funcresok}
+ var
+ hp : pcaselabel;
+ begin
+ hp:=root;
+ while assigned(hp^.greater) do
+ hp:=hp^.greater;
+ case_get_max:=hp^._high;
+ end;
+
+
+{$ifdef int64funcresok}
+ function case_get_min(root : pcaselabel) : tconstexprint;
+{$else int64funcresok}
+ function case_get_min(root : pcaselabel) : longint;
+{$endif int64funcresok}
+ var
+ hp : pcaselabel;
+ begin
+ hp:=root;
+ while assigned(hp^.less) do
+ hp:=hp^.less;
+ case_get_min:=hp^._low;
+ end;
+
+ procedure deletecaselabels(p : pcaselabel);
+
+ begin
+ if assigned(p^.greater) then
+ deletecaselabels(p^.greater);
+ if assigned(p^.less) then
+ deletecaselabels(p^.less);
+ dispose(p);
+ end;
+
+ function copycaselabel(p : pcaselabel) : pcaselabel;
+
+ var
+ n : pcaselabel;
+
+ begin
+ new(n);
+ n^:=p^;
+ if assigned(p^.greater) then
+ n^.greater:=copycaselabel(p^.greater);
+ if assigned(p^.less) then
+ n^.less:=copycaselabel(p^.less);
+ copycaselabel:=n;
+ end;
+
+
+ procedure ppuwritecaselabel(ppufile:tcompilerppufile;p : pcaselabel);
+ var
+ b : byte;
+ begin
+ ppufile.putexprint(p^._low);
+ ppufile.putexprint(p^._high);
+ ppufile.putlongint(p^.blockid);
+ b:=0;
+ if assigned(p^.greater) then
+ b:=b or 1;
+ if assigned(p^.less) then
+ b:=b or 2;
+ ppufile.putbyte(b);
+ if assigned(p^.greater) then
+ ppuwritecaselabel(ppufile,p^.greater);
+ if assigned(p^.less) then
+ ppuwritecaselabel(ppufile,p^.less);
+ end;
+
+
+ function ppuloadcaselabel(ppufile:tcompilerppufile):pcaselabel;
+ var
+ b : byte;
+ p : pcaselabel;
+ begin
+ new(p);
+ p^._low:=ppufile.getexprint;
+ p^._high:=ppufile.getexprint;
+ p^.blockid:=ppufile.getlongint;
+ b:=ppufile.getbyte;
+ if (b and 1)=1 then
+ p^.greater:=ppuloadcaselabel(ppufile)
+ else
+ p^.greater:=nil;
+ if (b and 2)=2 then
+ p^.less:=ppuloadcaselabel(ppufile)
+ else
+ p^.less:=nil;
+ ppuloadcaselabel:=p;
+ end;
+
+
+{*****************************************************************************
+ TCASENODE
+*****************************************************************************}
+
+ constructor tcasenode.create(l:tnode);
+ begin
+ inherited create(casen,l);
+ labels:=nil;
+ blocks:=tlist.create;
+ elseblock:=nil;
+ end;
+
+
+ destructor tcasenode.destroy;
+ var
+ i : longint;
+ hp : pcaseblock;
+ begin
+ elseblock.free;
+ deletecaselabels(labels);
+ for i:=0 to blocks.count-1 do
+ begin
+ pcaseblock(blocks[i])^.statement.free;
+ hp:=pcaseblock(blocks[i]);
+ dispose(hp);
+ end;
+ inherited destroy;
+ end;
+
+
+ constructor tcasenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ var
+ cnt,i : longint;
+ begin
+ inherited ppuload(t,ppufile);
+ elseblock:=ppuloadnode(ppufile);
+ cnt:=ppufile.getlongint();
+ blocks:=tlist.create;
+ for i:=0 to cnt-1 do
+ addblock(i,ppuloadnode(ppufile));
+ labels:=ppuloadcaselabel(ppufile);
+ end;
+
+
+ procedure tcasenode.ppuwrite(ppufile:tcompilerppufile);
+ var
+ i : longint;
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,elseblock);
+ ppufile.putlongint(blocks.count);
+ for i:=0 to blocks.count-1 do
+ ppuwritenode(ppufile,pcaseblock(blocks[i])^.statement);
+ ppuwritecaselabel(ppufile,labels);
+ end;
+
+
+ procedure tcasenode.buildderefimpl;
+ var
+ i : integer;
+ begin
+ inherited buildderefimpl;
+ if assigned(elseblock) then
+ elseblock.buildderefimpl;
+ for i:=0 to blocks.count-1 do
+ pcaseblock(blocks[i])^.statement.buildderefimpl;
+ end;
+
+
+ procedure tcasenode.derefimpl;
+ var
+ i : integer;
+ begin
+ inherited derefimpl;
+ if assigned(elseblock) then
+ elseblock.derefimpl;
+ for i:=0 to blocks.count-1 do
+ pcaseblock(blocks[i])^.statement.derefimpl;
+ end;
+
+
+ function tcasenode.det_resulttype : tnode;
+ begin
+ result:=nil;
+ resulttype:=voidtype;
+ end;
+
+
+
+ function tcasenode.pass_1 : tnode;
+ var
+ old_t_times : longint;
+ hp : tnode;
+ i : integer;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ { evalutes the case expression }
+ firstpass(left);
+ set_varstate(left,vs_used,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+
+ { walk through all instructions }
+
+ { estimates the repeat of each instruction }
+ old_t_times:=cg.t_times;
+ if not(cs_littlesize in aktglobalswitches) then
+ begin
+ cg.t_times:=cg.t_times div case_count_labels(labels);
+ if cg.t_times<1 then
+ cg.t_times:=1;
+ end;
+ { first case }
+ for i:=0 to blocks.count-1 do
+ begin
+
+ firstpass(pcaseblock(blocks[i])^.statement);
+
+ { searchs max registers }
+ hp:=pcaseblock(blocks[i])^.statement;
+ if hp.registersint>registersint then
+ registersint:=hp.registersint;
+ if hp.registersfpu>registersfpu then
+ registersfpu:=hp.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if hp.registersmmx>registersmmx then
+ registersmmx:=hp.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+
+ { may be handle else tree }
+ if assigned(elseblock) then
+ begin
+ firstpass(elseblock);
+ if registersint<elseblock.registersint then
+ registersint:=elseblock.registersint;
+ if registersfpu<elseblock.registersfpu then
+ registersfpu:=elseblock.registersfpu;
+{$ifdef SUPPORT_MMX}
+ if registersmmx<elseblock.registersmmx then
+ registersmmx:=elseblock.registersmmx;
+{$endif SUPPORT_MMX}
+ end;
+ cg.t_times:=old_t_times;
+
+ { there is one register required for the case expression }
+ { for 64 bit ints we cheat: the high dword is stored in EDI }
+ { so we don't need an extra register }
+ if registersint<1 then
+ registersint:=1;
+ end;
+
+
+ function tcasenode._getcopy : tnode;
+
+ var
+ n : tcasenode;
+ i : longint;
+ begin
+ n:=tcasenode(inherited _getcopy);
+ if assigned(elseblock) then
+ n.elseblock:=elseblock._getcopy
+ else
+ n.elseblock:=nil;
+ if assigned(labels) then
+ n.labels:=copycaselabel(labels)
+ else
+ n.labels:=nil;
+ if assigned(blocks) then
+ begin
+ n.blocks:=tlist.create;
+ for i:=0 to blocks.count-1 do
+ begin
+ if not assigned(blocks[i]) then
+ internalerror(200411302);
+ n.addblock(i,pcaseblock(blocks[i])^.statement._getcopy);
+ end;
+ end
+ else
+ n.labels:=nil;
+ _getcopy:=n;
+ end;
+
+ procedure tcasenode.insertintolist(l : tnodelist);
+
+ begin
+ end;
+
+ function caselabelsequal(n1,n2: pcaselabel): boolean;
+ begin
+ result :=
+ (not assigned(n1) and not assigned(n2)) or
+ (assigned(n1) and assigned(n2) and
+ (n1^._low = n2^._low) and
+ (n1^._high = n2^._high) and
+ { the rest of the fields don't matter for equality (JM) }
+ caselabelsequal(n1^.less,n2^.less) and
+ caselabelsequal(n1^.greater,n2^.greater))
+ end;
+
+
+ function caseblocksequal(b1,b2:tlist): boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ if b1.count<>b2.count then
+ exit;
+ for i:=0 to b1.count-1 do
+ begin
+ if not pcaseblock(b1[i])^.statement.isequal(pcaseblock(b2[i])^.statement) then
+ exit;
+ end;
+ result:=true;
+ end;
+
+
+ function tcasenode.docompare(p: tnode): boolean;
+ begin
+ result :=
+ inherited docompare(p) and
+ caselabelsequal(labels,tcasenode(p).labels) and
+ caseblocksequal(blocks,tcasenode(p).blocks) and
+ elseblock.isequal(tcasenode(p).elseblock);
+ end;
+
+
+ procedure tcasenode.addblock(blockid:longint;instr:tnode);
+ var
+ hcaseblock : pcaseblock;
+ begin
+ new(hcaseblock);
+ fillchar(hcaseblock^,sizeof(hcaseblock^),0);
+ hcaseblock^.statement:=instr;
+ if blockid>=blocks.count then
+ blocks.count:=blockid+1;
+ blocks[blockid]:=hcaseblock;
+ end;
+
+
+ procedure tcasenode.addelseblock(instr:tnode);
+ begin
+ elseblock:=instr;
+ end;
+
+
+ procedure tcasenode.addlabel(blockid:longint;l,h : TConstExprInt);
+ var
+ hcaselabel : pcaselabel;
+
+ function insertlabel(var p : pcaselabel):pcaselabel;
+ begin
+ if p=nil then
+ begin
+ p:=hcaselabel;
+ result:=p;
+ end
+ else
+ if (p^._low>hcaselabel^._low) and
+ (p^._low>hcaselabel^._high) then
+ begin
+ if (hcaselabel^.blockid = p^.blockid) and
+ (p^._low = hcaselabel^._high + 1) then
+ begin
+ p^._low := hcaselabel^._low;
+ dispose(hcaselabel);
+ result:=p;
+ end
+ else
+ result:=insertlabel(p^.less)
+ end
+ else
+ if (p^._high<hcaselabel^._low) and
+ (p^._high<hcaselabel^._high) then
+ begin
+ if (hcaselabel^.blockid = p^.blockid) and
+ (p^._high+1 = hcaselabel^._low) then
+ begin
+ p^._high := hcaselabel^._high;
+ dispose(hcaselabel);
+ result:=p;
+ end
+ else
+ result:=insertlabel(p^.greater);
+ end
+ else
+ Message(parser_e_double_caselabel);
+ end;
+
+ begin
+ new(hcaselabel);
+ fillchar(hcaselabel^,sizeof(tcaselabel),0);
+ hcaselabel^.blockid:=blockid;
+ hcaselabel^._low:=l;
+ hcaselabel^._high:=h;
+ insertlabel(labels);
+ end;
+
+begin
+ csetelementnode:=tsetelementnode;
+ cinnode:=tinnode;
+ crangenode:=trangenode;
+ ccasenode:=tcasenode;
+end.
diff --git a/compiler/nstate.pas b/compiler/nstate.pas
new file mode 100644
index 0000000000..b7cb53235a
--- /dev/null
+++ b/compiler/nstate.pas
@@ -0,0 +1,123 @@
+{
+ Copyright (c) 1998-2002 by Daniel Mantione
+
+ This unit contains support routines for the state tracker
+
+ 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 nstate;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses cclasses,node;
+
+type Tstate_entry=class(Tlinkedlistitem)
+ what:Tnode;
+ value:Tnode;
+ constructor create(w,v:Tnode);
+ end;
+
+ Tstate_storage=class
+ storage:Tlinkedlist;
+ constructor create;
+ procedure store_fact(w,v:Tnode);
+ function find_fact(what:Tnode):Tnode;
+ procedure delete_fact(what:Tnode);
+ end;
+
+var aktstate:Tstate_storage;
+
+implementation
+
+constructor Tstate_entry.create(w,v:Tnode);
+
+begin
+ inherited create;
+ what:=w;
+ value:=v;
+end;
+
+constructor Tstate_storage.create;
+
+begin
+ storage:=Tlinkedlist.create;
+end;
+
+procedure Tstate_storage.store_fact(w,v:Tnode);
+
+var se:Tstate_entry;
+
+begin
+{ writeln('fact:');
+ writenode(w);
+ writeln('=');
+ writenode(v);}
+ se:=Tstate_entry(storage.first);
+ while assigned(se) do
+ begin
+ if se.what.isequal(w) then
+ begin
+ storage.remove(se);
+ se.destroy;
+ break;
+ end;
+ se:=Tstate_entry(se.next);
+ end;
+ se:=Tstate_entry.create(w,v);
+ storage.concat(se);
+end;
+
+function Tstate_storage.find_fact(what:Tnode):Tnode;
+
+var se:Tstate_entry;
+
+begin
+ find_fact:=nil;
+ se:=storage.first as Tstate_entry;
+ while assigned(se) do
+ begin
+ if se.what.isequal(what) then
+ begin
+ find_fact:=se.value;
+ break;
+ end;
+ se:=se.next as Tstate_entry;
+ end;
+end;
+
+procedure Tstate_storage.delete_fact(what:Tnode);
+
+var se:Tstate_entry;
+
+begin
+ se:=storage.first as Tstate_entry;
+ while assigned(se) do
+ begin
+ if se.what.isequal(what) then
+ begin
+ storage.remove(se);
+ se.destroy;
+ break;
+ end;
+ se:=se.next as Tstate_entry;
+ end;
+end;
+
+end.
diff --git a/compiler/nutils.pas b/compiler/nutils.pas
new file mode 100644
index 0000000000..8af3f79d8a
--- /dev/null
+++ b/compiler/nutils.pas
@@ -0,0 +1,619 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Type checking and register allocation for inline 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 nutils;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globals,
+ symsym,node;
+
+ const
+ NODE_COMPLEXITY_INF = 255;
+
+ type
+ { resulttype of functions that process on all nodes in a (sub)tree }
+ foreachnoderesult = (
+ { false, continue recursion }
+ fen_false,
+ { false, stop recursion }
+ fen_norecurse_false,
+ { true, continue recursion }
+ fen_true,
+ { true, stop recursion }
+ fen_norecurse_true
+ );
+
+ tforeachprocmethod = (pm_preprocess,pm_postprocess);
+
+
+ foreachnodefunction = function(var n: tnode; arg: pointer): foreachnoderesult of object;
+ staticforeachnodefunction = function(var n: tnode; arg: pointer): foreachnoderesult;
+
+ function foreachnode(var n: tnode; f: foreachnodefunction; arg: pointer): boolean;
+ function foreachnodestatic(var n: tnode; f: staticforeachnodefunction; arg: pointer): boolean;
+ function foreachnodestatic(procmethod : tforeachprocmethod;var n: tnode; f: staticforeachnodefunction; arg: pointer): boolean;
+
+ procedure load_procvar_from_calln(var p1:tnode);
+ function maybe_call_procvar(var p1:tnode;tponly:boolean):boolean;
+ function load_high_value_node(vs:tparavarsym):tnode;
+ function load_self_node:tnode;
+ function load_result_node:tnode;
+ function load_self_pointer_node:tnode;
+ function load_vmt_pointer_node:tnode;
+ function is_self_node(p:tnode):boolean;
+
+ function call_fail_node:tnode;
+ function initialize_data_node(p:tnode):tnode;
+ function finalize_data_node(p:tnode):tnode;
+
+ function node_complexity(p: tnode): cardinal;
+ procedure node_tree_set_filepos(var n:tnode;const filepos:tfileposinfo);
+
+ { tries to simplify the given node }
+ procedure dosimplify(var n : tnode);
+
+
+implementation
+
+ uses
+ globtype,verbose,
+ symconst,symbase,symtype,symdef,symtable,
+ defutil,defcmp,
+ nbas,ncon,ncnv,nld,nflw,nset,ncal,nadd,nmem,
+ cgbase,procinfo,
+ pass_1;
+
+ function foreachnode(var n: tnode; f: foreachnodefunction; arg: pointer): boolean;
+ var
+ i: longint;
+ begin
+ result := false;
+ if not assigned(n) then
+ exit;
+ case f(n,arg) of
+ fen_norecurse_false:
+ exit;
+ fen_norecurse_true:
+ begin
+ result := true;
+ exit;
+ end;
+ fen_true:
+ result := true;
+ { result is already false
+ fen_false:
+ result := false; }
+ end;
+ case n.nodetype of
+ calln:
+ begin
+ { not in one statement, won't work because of b- }
+ result := foreachnode(tcallnode(n).methodpointer,f,arg) or result;
+ end;
+ ifn, whilerepeatn, forn:
+ begin
+ { not in one statement, won't work because of b- }
+ result := foreachnode(tloopnode(n).t1,f,arg) or result;
+ result := foreachnode(tloopnode(n).t2,f,arg) or result;
+ end;
+ raisen:
+ result := foreachnode(traisenode(n).frametree,f,arg) or result;
+ casen:
+ begin
+ for i := 0 to tcasenode(n).blocks.count-1 do
+ if assigned(tcasenode(n).blocks[i]) then
+ result := foreachnode(pcaseblock(tcasenode(n).blocks[i])^.statement,f,arg) or result;
+ result := foreachnode(tcasenode(n).elseblock,f,arg) or result;
+ end;
+ end;
+ if n.inheritsfrom(tbinarynode) then
+ begin
+ result := foreachnode(tbinarynode(n).right,f,arg) or result;
+ result := foreachnode(tbinarynode(n).left,f,arg) or result;
+ end
+ else if n.inheritsfrom(tunarynode) then
+ result := foreachnode(tunarynode(n).left,f,arg) or result;
+ end;
+
+
+ function foreachnodestatic(procmethod : tforeachprocmethod;var n: tnode; f: staticforeachnodefunction; arg: pointer): boolean;
+
+ function process_children(res : boolean) : boolean;
+ var
+ i: longint;
+ begin
+ result:=res;
+ case n.nodetype of
+ calln:
+ begin
+ result := foreachnodestatic(procmethod,tcallnode(n).methodpointer,f,arg) or result;
+ end;
+ ifn, whilerepeatn, forn:
+ begin
+ { not in one statement, won't work because of b- }
+ result := foreachnodestatic(procmethod,tloopnode(n).t1,f,arg) or result;
+ result := foreachnodestatic(procmethod,tloopnode(n).t2,f,arg) or result;
+ end;
+ raisen:
+ result := foreachnodestatic(traisenode(n).frametree,f,arg) or result;
+ casen:
+ begin
+ for i := 0 to tcasenode(n).blocks.count-1 do
+ if assigned(tcasenode(n).blocks[i]) then
+ result := foreachnodestatic(procmethod,pcaseblock(tcasenode(n).blocks[i])^.statement,f,arg) or result;
+ result := foreachnodestatic(procmethod,tcasenode(n).elseblock,f,arg) or result;
+ end;
+ end;
+ if n.inheritsfrom(tbinarynode) then
+ begin
+ result := foreachnodestatic(procmethod,tbinarynode(n).right,f,arg) or result;
+ result := foreachnodestatic(procmethod,tbinarynode(n).left,f,arg) or result;
+ end
+ else if n.inheritsfrom(tunarynode) then
+ result := foreachnodestatic(procmethod,tunarynode(n).left,f,arg) or result;
+ end;
+
+ begin
+ result := false;
+ if not assigned(n) then
+ exit;
+ if procmethod=pm_preprocess then
+ result:=process_children(result);
+ case f(n,arg) of
+ fen_norecurse_false:
+ exit;
+ fen_norecurse_true:
+ begin
+ result := true;
+ exit;
+ end;
+ fen_true:
+ result := true;
+ { result is already false
+ fen_false:
+ result := false; }
+ end;
+ if procmethod=pm_postprocess then
+ result:=process_children(result);
+ end;
+
+
+ function foreachnodestatic(var n: tnode; f: staticforeachnodefunction; arg: pointer): boolean;
+ begin
+ result:=foreachnodestatic(pm_postprocess,n,f,arg);
+ end;
+
+
+ procedure load_procvar_from_calln(var p1:tnode);
+ var
+ p2 : tnode;
+ begin
+ if p1.nodetype<>calln then
+ internalerror(200212251);
+ { was it a procvar, then we simply remove the calln and
+ reuse the right }
+ if assigned(tcallnode(p1).right) then
+ begin
+ p2:=tcallnode(p1).right;
+ tcallnode(p1).right:=nil;
+ end
+ else
+ begin
+ p2:=cloadnode.create_procvar(tcallnode(p1).symtableprocentry,
+ tprocdef(tcallnode(p1).procdefinition),tcallnode(p1).symtableproc);
+ { when the methodpointer is typen we've something like:
+ tobject.create. Then only the address is needed of the
+ method without a self pointer }
+ if assigned(tcallnode(p1).methodpointer) and
+ (tcallnode(p1).methodpointer.nodetype<>typen) then
+ tloadnode(p2).set_mp(tcallnode(p1).get_load_methodpointer);
+ end;
+ resulttypepass(p2);
+ p1.free;
+ p1:=p2;
+ end;
+
+
+ function maybe_call_procvar(var p1:tnode;tponly:boolean):boolean;
+ var
+ hp : tnode;
+ begin
+ result:=false;
+ if (p1.resulttype.def.deftype<>procvardef) or
+ (tponly and
+ not(m_tp_procvar in aktmodeswitches)) then
+ exit;
+ { ignore vecn,subscriptn }
+ hp:=p1;
+ repeat
+ case hp.nodetype of
+ vecn,
+ derefn,
+ typeconvn,
+ subscriptn :
+ hp:=tunarynode(hp).left;
+ else
+ break;
+ end;
+ until false;
+ { a tempref is used when it is loaded from a withsymtable }
+ if (hp.nodetype in [calln,loadn,temprefn]) then
+ begin
+ hp:=ccallnode.create_procvar(nil,p1);
+ resulttypepass(hp);
+ p1:=hp;
+ result:=true;
+ end;
+ end;
+
+
+ function load_high_value_node(vs:tparavarsym):tnode;
+ var
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ result:=nil;
+ srsymtable:=vs.owner;
+ srsym:=searchsymonlyin(srsymtable,'high'+vs.name);
+ if assigned(srsym) then
+ begin
+ result:=cloadnode.create(srsym,srsymtable);
+ resulttypepass(result);
+ end
+ else
+ CGMessage(parser_e_illegal_expression);
+ end;
+
+
+ function load_self_node:tnode;
+ var
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ result:=nil;
+ searchsym('self',srsym,srsymtable);
+ if assigned(srsym) then
+ begin
+ result:=cloadnode.create(srsym,srsymtable);
+ include(result.flags,nf_is_self);
+ end
+ else
+ begin
+ result:=cerrornode.create;
+ CGMessage(parser_e_illegal_expression);
+ end;
+ resulttypepass(result);
+ end;
+
+
+ function load_result_node:tnode;
+ var
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ result:=nil;
+ searchsym('result',srsym,srsymtable);
+ if assigned(srsym) then
+ result:=cloadnode.create(srsym,srsymtable)
+ else
+ begin
+ result:=cerrornode.create;
+ CGMessage(parser_e_illegal_expression);
+ end;
+ resulttypepass(result);
+ end;
+
+
+ function load_self_pointer_node:tnode;
+ var
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ result:=nil;
+ searchsym('self',srsym,srsymtable);
+ if assigned(srsym) then
+ begin
+ result:=cloadnode.create(srsym,srsymtable);
+ include(result.flags,nf_load_self_pointer);
+ end
+ else
+ begin
+ result:=cerrornode.create;
+ CGMessage(parser_e_illegal_expression);
+ end;
+ resulttypepass(result);
+ end;
+
+
+ function load_vmt_pointer_node:tnode;
+ var
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ result:=nil;
+ searchsym('vmt',srsym,srsymtable);
+ if assigned(srsym) then
+ result:=cloadnode.create(srsym,srsymtable)
+ else
+ begin
+ result:=cerrornode.create;
+ CGMessage(parser_e_illegal_expression);
+ end;
+ resulttypepass(result);
+ end;
+
+
+ function is_self_node(p:tnode):boolean;
+ begin
+ is_self_node:=(p.nodetype=loadn) and
+ (tloadnode(p).symtableentry.typ=paravarsym) and
+ (vo_is_self in tparavarsym(tloadnode(p).symtableentry).varoptions);
+ end;
+
+
+
+ function call_fail_node:tnode;
+ var
+ para : tcallparanode;
+ newstatement : tstatementnode;
+ srsym : tsym;
+ begin
+ result:=internalstatements(newstatement);
+
+ { call fail helper and exit normal }
+ if is_class(current_procinfo.procdef._class) then
+ begin
+ srsym:=search_class_member(current_procinfo.procdef._class,'FREEINSTANCE');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { if self<>0 and vmt=1 then freeinstance }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(andn,
+ caddnode.create(unequaln,
+ load_self_pointer_node,
+ cnilnode.create),
+ caddnode.create(equaln,
+ ctypeconvnode.create(
+ load_vmt_pointer_node,
+ voidpointertype),
+ cpointerconstnode.create(1,voidpointertype))),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
+ nil));
+ end
+ else
+ internalerror(200305108);
+ end
+ else
+ if is_object(current_procinfo.procdef._class) then
+ begin
+ { parameter 3 : vmt_offset }
+ { parameter 2 : pointer to vmt }
+ { parameter 1 : self pointer }
+ para:=ccallparanode.create(
+ cordconstnode.create(current_procinfo.procdef._class.vmt_offset,s32inttype,false),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,
+ voidpointertype),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ nil)));
+ addstatement(newstatement,
+ ccallnode.createintern('fpc_help_fail',para));
+ end
+ else
+ internalerror(200305132);
+ { self:=nil }
+ addstatement(newstatement,cassignmentnode.create(
+ load_self_pointer_node,
+ cnilnode.create));
+ { exit }
+ addstatement(newstatement,cexitnode.create(nil));
+ end;
+
+
+ function initialize_data_node(p:tnode):tnode;
+ begin
+ if not assigned(p.resulttype.def) then
+ resulttypepass(p);
+ if is_ansistring(p.resulttype.def) or
+ is_widestring(p.resulttype.def) or
+ is_interfacecom(p.resulttype.def) or
+ is_dynamic_array(p.resulttype.def) then
+ begin
+ result:=cassignmentnode.create(
+ ctypeconvnode.create_internal(p,voidpointertype),
+ cnilnode.create
+ );
+ end
+ else
+ begin
+ result:=ccallnode.createintern('fpc_initialize',
+ ccallparanode.create(
+ caddrnode.create_internal(
+ crttinode.create(
+ tstoreddef(p.resulttype.def),initrtti)),
+ ccallparanode.create(
+ caddrnode.create_internal(p),
+ nil)));
+ end;
+ end;
+
+
+ function finalize_data_node(p:tnode):tnode;
+ begin
+ if not assigned(p.resulttype.def) then
+ resulttypepass(p);
+ result:=ccallnode.createintern('fpc_finalize',
+ ccallparanode.create(
+ caddrnode.create_internal(
+ crttinode.create(
+ tstoreddef(p.resulttype.def),initrtti)),
+ ccallparanode.create(
+ caddrnode.create_internal(p),
+ nil)));
+ end;
+
+
+ { this function must return a very high value ("infinity") for }
+ { trees containing a call, the rest can be balanced more or less }
+ { at will, probably best mainly in terms of required memory }
+ { accesses }
+ function node_complexity(p: tnode): cardinal;
+ begin
+ result := 0;
+ while true do
+ begin
+ case p.nodetype of
+ temprefn,
+ loadvmtaddrn,
+ { main reason for the next one: we can't take the address of }
+ { loadparentfpnode, so replacing it by a temp which is the }
+ { address of this node's location and then dereferencing }
+ { doesn't work. If changed, check whether webtbs/tw0935 }
+ { still works with nodeinlining (JM) }
+ loadparentfpn:
+ begin
+ result := 1;
+ exit;
+ end;
+ loadn:
+ begin
+ { threadvars need a helper call }
+ if (tloadnode(p).symtableentry.typ=globalvarsym) and
+ (vo_is_thread_var in tglobalvarsym(tloadnode(p).symtableentry).varoptions) then
+ inc(result,5)
+ else
+ inc(result);
+ if (result >= NODE_COMPLEXITY_INF) then
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ subscriptn,
+ blockn:
+ p := tunarynode(p).left;
+ derefn :
+ begin
+ inc(result);
+ if (result = NODE_COMPLEXITY_INF) then
+ exit;
+ p := tunarynode(p).left;
+ end;
+ typeconvn:
+ begin
+ { may be more complex in some cases }
+ if not(ttypeconvnode(p).convtype in [tc_equal,tc_int_2_int,tc_bool_2_bool,tc_real_2_real,tc_cord_2_pointer]) then
+ inc(result);
+ if (result = NODE_COMPLEXITY_INF) then
+ exit;
+ p := tunarynode(p).left;
+ end;
+ vecn,
+ statementn:
+ begin
+ inc(result,node_complexity(tbinarynode(p).left));
+ if (result >= NODE_COMPLEXITY_INF) then
+ begin
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ p := tbinarynode(p).right;
+ end;
+ { better: make muln/divn/modn more expensive }
+ addn,subn,orn,andn,xorn,muln,divn,modn,symdifn,
+ assignn:
+ begin
+ inc(result,node_complexity(tbinarynode(p).left)+1);
+ if (result >= NODE_COMPLEXITY_INF) then
+ begin
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ p := tbinarynode(p).right;
+ end;
+ tempcreaten,
+ tempdeleten,
+ ordconstn,
+ pointerconstn:
+ exit;
+ else
+ begin
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ function setnodefilepos(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ result:=fen_true;
+ n.fileinfo:=pfileposinfo(arg)^;
+ end;
+
+
+ procedure node_tree_set_filepos(var n:tnode;const filepos:tfileposinfo);
+ begin
+ foreachnodestatic(n,@setnodefilepos,@filepos);
+ end;
+
+{$ifdef FPCMT}
+ threadvar
+{$else FPCMT}
+ var
+{$endif FPCMT}
+ treechanged : boolean;
+
+ function callsimplify(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ hn : tnode;
+ begin
+ result:=fen_false;
+
+ do_resulttypepass(n);
+
+ hn:=n.simplify;
+ if assigned(hn) then
+ begin
+ treechanged:=true;
+ n:=hn;
+ end;
+ end;
+
+
+ { tries to simplify the given node calling the simplify method recursively }
+ procedure dosimplify(var n : tnode);
+ begin
+ repeat
+ treechanged:=false;
+ foreachnodestatic(pm_preprocess,n,@callsimplify,nil);
+ until not(treechanged);
+ end;
+
+end.
diff --git a/compiler/ogbase.pas b/compiler/ogbase.pas
new file mode 100644
index 0000000000..d9d7de488e
--- /dev/null
+++ b/compiler/ogbase.pas
@@ -0,0 +1,572 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Contains the base stuff for binary object file writers
+
+ 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 ogbase;
+
+{$i fpcdefs.inc}
+
+interface
+ uses
+ { common }
+ cclasses,
+ { targets }
+ systems,
+ { outputwriters }
+ owbase,owar,
+ { assembler }
+ aasmbase,aasmtai;
+
+ type
+ tobjectoutput = class
+ protected
+ { writer }
+ FWriter : tobjectwriter;
+ function writedata(data:TAsmObjectData):boolean;virtual;abstract;
+ public
+ constructor create(smart:boolean);
+ destructor destroy;override;
+ function newobjectdata(const n:string):TAsmObjectData;virtual;
+ function startobjectfile(const fn:string):boolean;
+ function writeobjectfile(data:TAsmObjectData):boolean;
+ procedure exportsymbol(p:tasmsymbol);
+ property Writer:TObjectWriter read FWriter;
+ end;
+
+ tobjectinput = class
+ protected
+ { reader }
+ FReader : tobjectreader;
+ protected
+ function readobjectdata(data:TAsmObjectData):boolean;virtual;abstract;
+ public
+ constructor create;
+ destructor destroy;override;
+ function newobjectdata(const n:string):TAsmObjectData;virtual;
+ function readobjectfile(const fn:string;data:TAsmObjectData):boolean;virtual;
+ property Reader:TObjectReader read FReader;
+ end;
+
+ texesection = class(tnamedindexitem)
+ public
+ available : boolean;
+ secsymidx,
+ datasize,
+ datapos,
+ memsize,
+ mempos : longint;
+ flags : cardinal;
+ secdatalist : TLinkedList;
+ constructor create(const n:string);
+ destructor destroy;override;
+ end;
+
+ texeoutput = class
+ private
+ procedure Sections_FixUpSymbol(s:tnamedindexitem;arg:pointer);
+ protected
+ { writer }
+ FWriter : tobjectwriter;
+ procedure MapObjectdata(var datapos:longint;var mempos:longint);
+ function writedata:boolean;virtual;abstract;
+ public
+ { info for each section }
+ sections : tdictionary;
+ { global symbols }
+ externalsyms : tsinglelist;
+ commonsyms : tsinglelist;
+ globalsyms : tdictionary;
+ { list of all data of the object files to link }
+ objdatalist : tlinkedlist;
+ constructor create;
+ destructor destroy;override;
+ function newobjectinput:tobjectinput;virtual;
+ procedure GenerateExecutable(const fn:string);virtual;abstract;
+ function writeexefile(const fn:string):boolean;
+ function CalculateSymbols:boolean;
+ procedure CalculateMemoryMap;virtual;abstract;
+ procedure addobjdata(objdata:TAsmObjectData);
+ procedure FixUpSymbols;
+ procedure FixUpRelocations;
+ procedure addglobalsym(const name:string;ofs:longint);
+ property Writer:TObjectWriter read FWriter;
+ end;
+
+ var
+ exeoutput : texeoutput;
+
+
+implementation
+
+ uses
+ cutils,globtype,globals,verbose,fmodule,ogmap;
+
+
+
+{****************************************************************************
+ tobjectoutput
+****************************************************************************}
+
+ constructor tobjectoutput.create(smart:boolean);
+ begin
+ { init writer }
+ if smart and
+ not(cs_asm_leave in aktglobalswitches) then
+ FWriter:=tarobjectwriter.create(current_module.staticlibfilename^)
+ else
+ FWriter:=tobjectwriter.create;
+ end;
+
+
+ destructor tobjectoutput.destroy;
+ begin
+ FWriter.free;
+ end;
+
+
+ function tobjectoutput.newobjectdata(const n:string):TAsmObjectData;
+ begin
+ result:=TAsmObjectData.create(n);
+ end;
+
+
+ function tobjectoutput.startobjectfile(const fn:string):boolean;
+ begin
+ result:=false;
+ { start the writer already, so the .a generation can initialize
+ the position of the current objectfile }
+ if not FWriter.createfile(fn) then
+ Comment(V_Fatal,'Can''t create object '+fn);
+ result:=true;
+ end;
+
+
+ function tobjectoutput.writeobjectfile(data:TAsmObjectData):boolean;
+ begin
+ if errorcount=0 then
+ result:=writedata(data)
+ else
+ result:=true;
+ { close the writer }
+ FWriter.closefile;
+ end;
+
+
+ procedure tobjectoutput.exportsymbol(p:tasmsymbol);
+ begin
+ { export globals and common symbols, this is needed
+ for .a files }
+ if p.currbind in [AB_GLOBAL,AB_COMMON] then
+ FWriter.writesym(p.name);
+ end;
+
+
+{****************************************************************************
+ texesection
+****************************************************************************}
+
+ constructor texesection.create(const n:string);
+ begin
+ inherited createname(n);
+ mempos:=0;
+ memsize:=0;
+ datapos:=0;
+ datasize:=0;
+ secsymidx:=0;
+ available:=false;
+ flags:=0;
+ secdatalist:=TLinkedList.Create;
+ end;
+
+
+ destructor texesection.destroy;
+ begin
+ end;
+
+
+{****************************************************************************
+ texeoutput
+****************************************************************************}
+
+ constructor texeoutput.create;
+ begin
+ { init writer }
+ FWriter:=tobjectwriter.create;
+ { object files }
+ objdatalist:=tlinkedlist.create;
+ { symbols }
+ globalsyms:=tdictionary.create;
+ globalsyms.usehash;
+ globalsyms.noclear:=true;
+ externalsyms:=tsinglelist.create;
+ commonsyms:=tsinglelist.create;
+ sections:=tdictionary.create;
+ end;
+
+
+ destructor texeoutput.destroy;
+ begin
+ sections.free;
+ globalsyms.free;
+ externalsyms.free;
+ commonsyms.free;
+ objdatalist.free;
+ FWriter.free;
+ end;
+
+
+ function texeoutput.newobjectinput:tobjectinput;
+ begin
+ result:=tobjectinput.create;
+ end;
+
+
+ function texeoutput.writeexefile(const fn:string):boolean;
+ begin
+ result:=false;
+ if FWriter.createfile(fn) then
+ begin
+ { Only write the .o if there are no errors }
+ if errorcount=0 then
+ result:=writedata
+ else
+ result:=true;
+ { close the writer }
+ FWriter.closefile;
+ end
+ else
+ Comment(V_Fatal,'Can''t create executable '+fn);
+ end;
+
+
+ procedure texeoutput.addobjdata(objdata:TAsmObjectData);
+ begin
+ objdatalist.concat(objdata);
+ end;
+
+
+ procedure texeoutput.MapObjectdata(var datapos:longint;var mempos:longint);
+{$ifdef needrewrite}
+ var
+ sec : TSection;
+ s : TAsmSection;
+ alignedpos : longint;
+ objdata : TAsmObjectData;
+ begin
+ { calculate offsets of each objdata }
+ for sec:=low(TSection) to high(TSection) do
+ begin
+ if sections[sec].available then
+ begin
+ { set start position of section }
+ sections[sec].datapos:=datapos;
+ sections[sec].mempos:=mempos;
+ { update objectfiles }
+ objdata:=TAsmObjectData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ s:=objdata.sects[sec];
+ if assigned(s) then
+ begin
+ { align section }
+ mempos:=align(mempos,$10);
+ if assigned(s.data) then
+ begin
+ alignedpos:=align(datapos,$10);
+ s.dataalignbytes:=alignedpos-datapos;
+ datapos:=alignedpos;
+ end;
+ { set position and size of this objectfile }
+ s.mempos:=mempos;
+ s.datapos:=datapos;
+ inc(mempos,s.datasize);
+ if assigned(s.data) then
+ inc(datapos,s.datasize);
+ end;
+ objdata:=TAsmObjectData(objdata.next);
+ end;
+ { calculate size of the section }
+ sections[sec].datasize:=datapos-sections[sec].datapos;
+ sections[sec].memsize:=mempos-sections[sec].mempos;
+ end;
+ end;
+{$endif needrewrite}
+ begin
+ end;
+
+
+ procedure texeoutput.Sections_FixUpSymbol(s:tnamedindexitem;arg:pointer);
+{$ifdef needrewrite}
+ var
+ secdata : TAsmSection;
+ hsym : TAsmSymbol;
+ begin
+ with texesection(s) do
+ begin
+ if assigned(exemap) then
+ exemap.AddMemoryMapExeSection(TExeSection(s));
+ secdata:=TAsmSection(secdatalist.first);
+ while assigned(secdata) do
+ begin
+ if assigned(exemap) then
+ exemap.AddMemoryMapObjectSection(secdata);
+ hsym:=tasmsymbol(secdata.owner.symbols.first);
+ while assigned(hsym) do
+ begin
+ { process only the symbols that are defined in this section
+ and are located in this module }
+ if ((hsym.section=secdata) or
+ ((secdata.sectype=sec_bss) and (hsym.section.sectype=sec_common))) then
+ begin
+ if hsym.currbind=AB_EXTERNAL then
+ internalerror(200206303);
+ inc(hsym.address,secdata.mempos);
+ if assigned(exemap) then
+ exemap.AddMemoryMapSymbol(hsym);
+ end;
+ hsym:=tasmsymbol(hsym.indexnext);
+ end;
+ secdata:=TAsmSection(secdata.indexnext);
+ end;
+ end;
+ end;
+{$endif needrewrite}
+ begin
+ end;
+
+
+ procedure texeoutput.FixUpSymbols;
+ var
+ sym : tasmsymbol;
+ begin
+ {
+ Fixing up symbols is done in the following steps:
+ 1. Update addresses
+ 2. Update common references
+ 3. Update external references
+ }
+ { Step 1, Update addresses }
+ if assigned(exemap) then
+ exemap.AddMemoryMapHeader;
+ sections.foreach(@sections_fixupsymbol,nil);
+ { Step 2, Update commons }
+ sym:=tasmsymbol(commonsyms.first);
+ while assigned(sym) do
+ begin
+ if sym.currbind=AB_COMMON then
+ begin
+ { update this symbol }
+ sym.currbind:=sym.altsymbol.currbind;
+ sym.address:=sym.altsymbol.address;
+ sym.size:=sym.altsymbol.size;
+ sym.section:=sym.altsymbol.section;
+ sym.typ:=sym.altsymbol.typ;
+ sym.owner:=sym.altsymbol.owner;
+ end;
+ sym:=tasmsymbol(sym.listnext);
+ end;
+ { Step 3, Update externals }
+ sym:=tasmsymbol(externalsyms.first);
+ while assigned(sym) do
+ begin
+ if sym.currbind=AB_EXTERNAL then
+ begin
+ { update this symbol }
+ sym.currbind:=sym.altsymbol.currbind;
+ sym.address:=sym.altsymbol.address;
+ sym.size:=sym.altsymbol.size;
+ sym.section:=sym.altsymbol.section;
+ sym.typ:=sym.altsymbol.typ;
+ sym.owner:=sym.altsymbol.owner;
+ end;
+ sym:=tasmsymbol(sym.listnext);
+ end;
+ end;
+
+
+ procedure texeoutput.FixUpRelocations;
+ var
+ objdata : TAsmObjectData;
+ begin
+ objdata:=TAsmObjectData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ objdata.fixuprelocs;
+ objdata:=TAsmObjectData(objdata.next);
+ end;
+ end;
+
+
+ procedure texeoutput.addglobalsym(const name:string;ofs:longint);
+ var
+ sym : tasmsymbol;
+ begin
+ sym:=tasmsymbol(globalsyms.search(name));
+ if not assigned(sym) then
+ begin
+ sym:=tasmsymbol.create(name,AB_GLOBAL,AT_FUNCTION);
+ globalsyms.insert(sym);
+ end;
+ sym.currbind:=AB_GLOBAL;
+ sym.address:=ofs;
+ end;
+
+
+ function TExeOutput.CalculateSymbols:boolean;
+ var
+ commonobjdata,
+ objdata : TAsmObjectData;
+ sym,p : tasmsymbol;
+ begin
+ commonobjdata:=nil;
+ CalculateSymbols:=true;
+ {
+ The symbol calculation is done in 3 steps:
+ 1. register globals
+ register externals
+ register commons
+ 2. try to find commons, if not found then
+ add to the globals (so externals can be resolved)
+ 3. try to find externals
+ }
+ { Step 1, Register symbols }
+ objdata:=TAsmObjectData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ sym:=tasmsymbol(objdata.symbols.first);
+ while assigned(sym) do
+ begin
+ if not assigned(sym.owner) then
+ internalerror(200206302);
+ case sym.currbind of
+ AB_GLOBAL :
+ begin
+ p:=tasmsymbol(globalsyms.search(sym.name));
+ if not assigned(p) then
+ globalsyms.insert(sym)
+ else
+ begin
+ Comment(V_Error,'Multiple defined symbol '+sym.name);
+ result:=false;
+ end;
+ end;
+ AB_EXTERNAL :
+ externalsyms.insert(sym);
+ AB_COMMON :
+ commonsyms.insert(sym);
+ end;
+ sym:=tasmsymbol(sym.indexnext);
+ end;
+ objdata:=TAsmObjectData(objdata.next);
+ end;
+ { Step 2, Match common symbols or add to the globals }
+ sym:=tasmsymbol(commonsyms.first);
+ while assigned(sym) do
+ begin
+ if sym.currbind=AB_COMMON then
+ begin
+ p:=tasmsymbol(globalsyms.search(sym.name));
+ if assigned(p) then
+ begin
+ if p.size<>sym.size then
+ internalerror(200206301);
+ end
+ else
+ begin
+ { allocate new symbol in .bss and store it in the
+ *COMMON* module }
+ if not assigned(commonobjdata) then
+ begin
+ if assigned(exemap) then
+ exemap.AddCommonSymbolsHeader;
+ { create .bss section and add to list }
+ commonobjdata:=TAsmObjectData.create('*COMMON*');
+ commonobjdata.createsection(sec_bss,'',0,[aso_alloconly]);
+ addobjdata(commonobjdata);
+ end;
+ p:=TAsmSymbol.Create(sym.name,AB_GLOBAL,AT_FUNCTION);
+ commonobjdata.writesymbol(p);
+ if assigned(exemap) then
+ exemap.AddCommonSymbol(p);
+ { make this symbol available as a global }
+ globalsyms.insert(p);
+ end;
+ sym.altsymbol:=p;
+ end;
+ sym:=tasmsymbol(sym.listnext);
+ end;
+ { Step 3 }
+ sym:=tasmsymbol(externalsyms.first);
+ while assigned(sym) do
+ begin
+ if sym.currbind=AB_EXTERNAL then
+ begin
+ p:=tasmsymbol(globalsyms.search(sym.name));
+ if assigned(p) then
+ begin
+ sym.altsymbol:=p;
+ end
+ else
+ begin
+ Comment(V_Error,'Undefined symbol: '+sym.name);
+ CalculateSymbols:=false;
+ end;
+ end;
+ sym:=tasmsymbol(sym.listnext);
+ end;
+ end;
+
+
+{****************************************************************************
+ tobjectinput
+****************************************************************************}
+
+ constructor tobjectinput.create;
+ begin
+ { init reader }
+ FReader:=tobjectreader.create;
+ end;
+
+
+ destructor tobjectinput.destroy;
+ begin
+ FReader.free;
+ end;
+
+
+ function tobjectinput.newobjectdata(const n:string):TAsmObjectData;
+ begin
+ result:=TAsmObjectData.create(n);
+ end;
+
+
+ function tobjectinput.readobjectfile(const fn:string;data:TAsmObjectData):boolean;
+ begin
+ result:=false;
+ { start the reader }
+ if FReader.openfile(fn) then
+ begin
+ result:=readobjectdata(data);
+ FReader.closefile;
+ end;
+ end;
+
+
+end.
diff --git a/compiler/ogcoff.pas b/compiler/ogcoff.pas
new file mode 100644
index 0000000000..877905ad57
--- /dev/null
+++ b/compiler/ogcoff.pas
@@ -0,0 +1,1767 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Pierre Muller
+
+ Contains the binary coff reader and writer
+
+ * 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 ogcoff;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,globtype,
+ { target }
+ systems,
+ { assembler }
+ cpuinfo,cpubase,aasmbase,assemble,link,
+ { output }
+ ogbase,ogmap;
+
+ type
+ TCoffObjectSection = class(TAsmSection)
+ private
+ orgmempos,
+ coffrelocs,
+ coffrelocpos : longint;
+ public
+ flags : cardinal;
+ constructor create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);override;
+ procedure addsymsizereloc(ofs:longint;p:tasmsymbol;size:longint;relative:TAsmRelocationType);
+ procedure fixuprelocs;override;
+ end;
+
+ TDjCoffObjectSection = class(TCoffObjectSection)
+ constructor create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);override;
+ end;
+
+ TPECoffObjectSection = class(TCoffObjectSection)
+ constructor create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);override;
+ end;
+
+ tcoffobjectdata = class(TAsmObjectData)
+ private
+ win32 : boolean;
+ procedure section_mempos(p:tnamedindexitem;arg:pointer);
+ public
+ constructor createcoff(const n:string;awin32:boolean;acasmsection:TAsmSectionClass);
+ destructor destroy;override;
+ function sectionname(atype:tasmsectiontype;const aname:string):string;override;
+ procedure writereloc(data,len:aint;p:tasmsymbol;relative:TAsmRelocationType);override;
+ procedure writesymbol(p:tasmsymbol);override;
+ procedure writestab(offset:aint;ps:tasmsymbol;nidx,nother,line:longint;p:pchar);override;
+ procedure beforealloc;override;
+ procedure beforewrite;override;
+ procedure afteralloc;override;
+ end;
+
+ tdjcoffobjectdata = class(TCoffObjectData)
+ constructor create(const n:string);override;
+ end;
+
+ tpecoffobjectdata = class(TCoffObjectData)
+ constructor create(const n:string);override;
+ end;
+
+ tcoffobjectoutput = class(tobjectoutput)
+ private
+ win32 : boolean;
+ initsym : longint;
+ FCoffStrs : tdynamicarray;
+ procedure write_symbol(const name:string;value,section,typ,aux:longint);
+ procedure section_write_symbol(p:tnamedindexitem;arg:pointer);
+ procedure section_write_relocs(p:tnamedindexitem;arg:pointer);
+ procedure write_symbols(data:TAsmObjectData);
+ procedure section_set_secsymidx(p:tnamedindexitem;arg:pointer);
+ procedure section_set_datapos(p:tnamedindexitem;arg:pointer);
+ procedure section_set_reloc_datapos(p:tnamedindexitem;arg:pointer);
+ procedure section_write_header(p:tnamedindexitem;arg:pointer);
+ procedure section_write_data(p:tnamedindexitem;arg:pointer);
+ protected
+ function writedata(data:TAsmObjectData):boolean;override;
+ public
+ constructor createdjgpp(smart:boolean);
+ constructor createwin32(smart:boolean);
+ function newobjectdata(const n:string):TAsmObjectData;override;
+ end;
+
+ tcoffexeoutput = class(texeoutput)
+ private
+ FCoffsyms,
+ FCoffStrs : tdynamicarray;
+ win32 : boolean;
+ nsects,
+ nsyms,
+ sympos : longint;
+ procedure write_symbol(const name:string;value,section,typ,aux:longint);
+ procedure write_symbols;
+ protected
+ function writedata:boolean;override;
+ public
+ constructor createdjgpp;
+ constructor createwin32;
+ function newobjectinput:tobjectinput;override;
+ procedure CalculateMemoryMap;override;
+ procedure GenerateExecutable(const fn:string);override;
+ end;
+
+ ttasmsymbolrec = record
+ sym : tasmsymbol;
+ orgsize : longint;
+ end;
+ ttasmsymbolarray = array[0..high(word)] of ttasmsymbolrec;
+
+ tcoffobjectinput = class(tobjectinput)
+ private
+ Fidx2sec : array[0..255] of TAsmSection;
+ FCoffsyms,
+ FCoffStrs : tdynamicarray;
+ FSymTbl : ^ttasmsymbolarray;
+ win32 : boolean;
+ procedure read_relocs(s:TCoffObjectSection);
+ procedure handle_symbols(data:TAsmObjectData);
+ protected
+ function readobjectdata(data:TAsmObjectData):boolean;override;
+ public
+ constructor createdjgpp;
+ constructor createwin32;
+ function newobjectdata(const n:string):TAsmObjectData;override;
+ end;
+
+ tcoffassembler = class(tinternalassembler)
+ constructor create(smart:boolean);override;
+ end;
+
+ tpecoffassembler = class(tinternalassembler)
+ constructor create(smart:boolean);override;
+ end;
+
+ tcofflinker = class(tinternallinker)
+ constructor create;override;
+ end;
+
+
+implementation
+
+ uses
+ strings,
+ cutils,verbose,
+ globals,fmodule;
+
+ const
+ COFF_FLAG_NORELOCS = $0001;
+ COFF_FLAG_EXE = $0002;
+ COFF_FLAG_NOLINES = $0004;
+ COFF_FLAG_NOLSYMS = $0008;
+ COFF_FLAG_AR16WR = $0080; { 16bit little endian }
+ COFF_FLAG_AR32WR = $0100; { 32bit little endian }
+ COFF_FLAG_AR32W = $0200; { 32bit big endian }
+ COFF_FLAG_DLL = $2000;
+
+ COFF_SYM_GLOBAL = 2;
+ COFF_SYM_LOCAL = 3;
+ COFF_SYM_LABEL = 6;
+ COFF_SYM_FUNCTION = 101;
+ COFF_SYM_FILE = 103;
+ COFF_SYM_SECTION = 104;
+
+ type
+ { Structures which are written directly to the output file }
+ coffheader=packed record
+ mach : word;
+ nsects : word;
+ time : longint;
+ sympos : longint;
+ syms : longint;
+ opthdr : word;
+ flag : word;
+ end;
+ coffoptheader=packed record
+ magic : word;
+ vstamp : word;
+ tsize : longint;
+ dsize : longint;
+ bsize : longint;
+ entry : longint;
+ text_start : longint;
+ data_start : longint;
+ end;
+ coffsechdr=packed record
+ name : array[0..7] of char;
+ vsize : longint;
+ rvaofs : longint;
+ datasize : longint;
+ datapos : longint;
+ relocpos : longint;
+ lineno1 : longint;
+ nrelocs : word;
+ lineno2 : word;
+ flags : cardinal;
+ end;
+ coffsectionrec=packed record
+ len : longint;
+ nrelocs : word;
+ empty : array[0..11] of char;
+ end;
+ coffreloc=packed record
+ address : longint;
+ sym : longint;
+ relative : word;
+ end;
+ coffsymbol=packed record
+ name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
+ strpos : longint;
+ value : longint;
+ section : smallint;
+ empty : smallint;
+ typ : byte;
+ aux : byte;
+ end;
+ coffstab=packed record
+ strpos : longint;
+ ntype : byte;
+ nother : byte;
+ ndesc : word;
+ nvalue : longint;
+ end;
+
+ const
+ symbolresize = 200*sizeof(coffsymbol);
+ strsresize = 8192;
+
+
+const go32v2stub : array[0..2047] of byte=(
+ $4D,$5A,$00,$00,$04,$00,$00,$00,$20,$00,$27,$00,$FF,$FF,$00,
+ $00,$60,$07,$00,$00,$54,$00,$00,$00,$00,$00,$00,$00,$0D,$0A,
+ $73,$74,$75,$62,$2E,$68,$20,$67,$65,$6E,$65,$72,$61,$74,$65,
+ $64,$20,$66,$72,$6F,$6D,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,
+ $20,$62,$79,$20,$64,$6A,$61,$73,$6D,$2C,$20,$6F,$6E,$20,$54,
+ $68,$75,$20,$44,$65,$63,$20,$20,$39,$20,$31,$30,$3A,$35,$39,
+ $3A,$33,$31,$20,$31,$39,$39,$39,$0D,$0A,$54,$68,$65,$20,$53,
+ $54,$55,$42,$2E,$45,$58,$45,$20,$73,$74,$75,$62,$20,$6C,$6F,
+ $61,$64,$65,$72,$20,$69,$73,$20,$43,$6F,$70,$79,$72,$69,$67,
+ $68,$74,$20,$28,$43,$29,$20,$31,$39,$39,$33,$2D,$31,$39,$39,
+ $35,$20,$44,$4A,$20,$44,$65,$6C,$6F,$72,$69,$65,$2E,$20,$0D,
+ $0A,$50,$65,$72,$6D,$69,$73,$73,$69,$6F,$6E,$20,$67,$72,$61,
+ $6E,$74,$65,$64,$20,$74,$6F,$20,$75,$73,$65,$20,$66,$6F,$72,
+ $20,$61,$6E,$79,$20,$70,$75,$72,$70,$6F,$73,$65,$20,$70,$72,
+ $6F,$76,$69,$64,$65,$64,$20,$74,$68,$69,$73,$20,$63,$6F,$70,
+ $79,$72,$69,$67,$68,$74,$20,$0D,$0A,$72,$65,$6D,$61,$69,$6E,
+ $73,$20,$70,$72,$65,$73,$65,$6E,$74,$20,$61,$6E,$64,$20,$75,
+ $6E,$6D,$6F,$64,$69,$66,$69,$65,$64,$2E,$20,$0D,$0A,$54,$68,
+ $69,$73,$20,$6F,$6E,$6C,$79,$20,$61,$70,$70,$6C,$69,$65,$73,
+ $20,$74,$6F,$20,$74,$68,$65,$20,$73,$74,$75,$62,$2C,$20,$61,
+ $6E,$64,$20,$6E,$6F,$74,$20,$6E,$65,$63,$65,$73,$73,$61,$72,
+ $69,$6C,$79,$20,$74,$68,$65,$20,$77,$68,$6F,$6C,$65,$20,$70,
+ $72,$6F,$67,$72,$61,$6D,$2E,$0A,$0D,$0A,$24,$49,$64,$3A,$20,
+ $73,$74,$75,$62,$2E,$61,$73,$6D,$20,$62,$75,$69,$6C,$74,$20,
+ $31,$32,$2F,$30,$39,$2F,$39,$39,$20,$31,$30,$3A,$35,$39,$3A,
+ $33,$31,$20,$62,$79,$20,$64,$6A,$61,$73,$6D,$20,$24,$0A,$0D,
+ $0A,$40,$28,$23,$29,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,$20,
+ $62,$75,$69,$6C,$74,$20,$31,$32,$2F,$30,$39,$2F,$39,$39,$20,
+ $31,$30,$3A,$35,$39,$3A,$33,$31,$20,$62,$79,$20,$64,$6A,$61,
+ $73,$6D,$0A,$0D,$0A,$1A,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$67,$6F,$33,$32,$73,$74,$75,$62,$2C,$20,$76,$20,$32,
+ $2E,$30,$32,$54,$00,$00,$00,$00,$00,$08,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$43,$57,$53,$44,$50,
+ $4D,$49,$2E,$45,$58,$45,$00,$00,$00,$00,$00,$0E,$1F,$8C,$1E,
+ $24,$00,$8C,$06,$60,$07,$FC,$B4,$30,$CD,$21,$3C,$03,$73,$08,
+ $B0,$6D,$BA,$A7,$05,$E9,$D4,$03,$A2,$69,$08,$BE,$20,$00,$8B,
+ $04,$09,$C0,$75,$02,$B4,$FE,$BB,$70,$08,$39,$C3,$73,$02,$89,
+ $C3,$89,$1C,$FE,$C7,$B9,$04,$FF,$D3,$EB,$B4,$4A,$CD,$21,$73,
+ $08,$D3,$E3,$FE,$CF,$89,$1C,$EB,$D8,$26,$8E,$06,$2C,$00,$31,
+ $FF,$30,$C0,$A9,$F2,$AE,$26,$81,$3D,$50,$41,$75,$15,$AF,$26,
+ $81,$3D,$54,$48,$75,$0D,$AF,$26,$80,$3D,$3D,$75,$06,$47,$89,
+ $3E,$8C,$04,$4F,$AE,$75,$DF,$AF,$B4,$3E,$BB,$13,$00,$CD,$21,
+ $B4,$3E,$BB,$12,$00,$CD,$21,$06,$57,$31,$C9,$74,$12,$B0,$6E,
+ $BA,$7E,$05,$E9,$5E,$03,$09,$C9,$75,$F4,$41,$E8,$A1,$03,$72,
+ $EE,$B8,$87,$16,$CD,$2F,$09,$C0,$75,$ED,$80,$E3,$01,$74,$E8,
+ $89,$3E,$00,$06,$8C,$06,$02,$06,$89,$36,$04,$06,$5F,$07,$E8,
+ $D3,$02,$89,$3E,$2A,$00,$89,$36,$62,$07,$80,$3E,$2C,$00,$00,
+ $74,$23,$B9,$08,$00,$BF,$2C,$00,$8A,$05,$47,$08,$C0,$74,$05,
+ $88,$07,$43,$E2,$F4,$66,$C7,$07,$2E,$45,$58,$45,$83,$C3,$04,
+ $C6,$07,$00,$89,$1E,$62,$07,$B8,$00,$3D,$BA,$64,$07,$CD,$21,
+ $0F,$82,$B3,$02,$A3,$06,$06,$89,$C3,$B9,$06,$00,$BA,$B5,$07,
+ $B4,$3F,$CD,$21,$31,$D2,$31,$C9,$A1,$B5,$07,$3D,$4C,$01,$74,
+ $1B,$3D,$4D,$5A,$0F,$85,$98,$02,$8B,$16,$B9,$07,$C1,$E2,$09,
+ $8B,$1E,$B7,$07,$09,$DB,$74,$05,$80,$EE,$02,$01,$DA,$89,$16,
+ $BB,$07,$89,$0E,$BD,$07,$B8,$00,$42,$8B,$1E,$06,$06,$CD,$21,
+ $B9,$A8,$00,$BA,$BF,$07,$B4,$3F,$CD,$21,$3D,$A8,$00,$75,$06,
+ $81,$3E,$BF,$07,$4C,$01,$0F,$85,$61,$02,$66,$A1,$E3,$07,$66,
+ $A3,$10,$06,$66,$8B,$0E,$BB,$07,$66,$A1,$03,$08,$66,$01,$C8,
+ $66,$A3,$08,$06,$66,$A1,$2B,$08,$66,$01,$C8,$66,$A3,$0C,$06,
+ $66,$8B,$1E,$4B,$08,$66,$A1,$4F,$08,$66,$01,$C3,$66,$B8,$01,
+ $00,$01,$00,$66,$39,$C3,$73,$03,$66,$89,$C3,$66,$81,$C3,$FF,
+ $FF,$00,$00,$31,$DB,$66,$89,$1E,$1C,$00,$E8,$F5,$02,$8B,$1E,
+ $04,$06,$09,$DB,$74,$0A,$B4,$48,$CD,$21,$0F,$82,$15,$02,$8E,
+ $C0,$E8,$08,$03,$B8,$01,$00,$FF,$1E,$00,$06,$0F,$82,$0F,$02,
+ $8C,$06,$26,$00,$8C,$0E,$28,$00,$8C,$D8,$A3,$22,$00,$8E,$C0,
+ $31,$C0,$B9,$01,$00,$CD,$31,$72,$07,$A3,$14,$06,$31,$C0,$CD,
+ $31,$0F,$82,$F3,$01,$A3,$16,$06,$66,$8B,$0E,$1C,$00,$B8,$01,
+ $05,$8B,$1E,$1E,$00,$CD,$31,$0F,$82,$E5,$01,$89,$1E,$1A,$06,
+ $89,$0E,$18,$06,$89,$36,$1A,$00,$89,$3E,$18,$00,$B8,$07,$00,
+ $8B,$1E,$14,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,$CD,$31,$B8,
+ $09,$00,$8C,$C9,$83,$E1,$03,$C1,$E1,$05,$51,$81,$C9,$9B,$C0,
+ $CD,$31,$B8,$08,$00,$8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,
+ $B8,$07,$00,$8B,$1E,$16,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,
+ $CD,$31,$B8,$09,$00,$59,$81,$C9,$93,$C0,$CD,$31,$B8,$08,$00,
+ $8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,$B8,$00,$01,$BB,$00,
+ $0F,$CD,$31,$73,$10,$3D,$08,$00,$0F,$85,$73,$01,$B8,$00,$01,
+ $CD,$31,$0F,$82,$6A,$01,$A3,$1C,$06,$89,$16,$1E,$06,$C1,$E3,
+ $04,$89,$1E,$20,$06,$66,$8B,$36,$08,$06,$66,$8B,$3E,$FB,$07,
+ $66,$8B,$0E,$FF,$07,$E8,$49,$00,$66,$8B,$36,$0C,$06,$66,$8B,
+ $3E,$23,$08,$66,$8B,$0E,$27,$08,$E8,$37,$00,$8E,$06,$16,$06,
+ $66,$8B,$3E,$4B,$08,$66,$8B,$0E,$4F,$08,$66,$31,$C0,$66,$C1,
+ $E9,$02,$67,$F3,$66,$AB,$B4,$3E,$8B,$1E,$06,$06,$CD,$21,$B8,
+ $01,$01,$8B,$16,$1E,$06,$CD,$31,$1E,$0F,$A1,$8E,$1E,$16,$06,
+ $66,$64,$FF,$2E,$10,$06,$66,$89,$F0,$66,$25,$FF,$01,$00,$00,
+ $66,$01,$C1,$29,$C6,$66,$29,$C7,$66,$89,$0E,$26,$06,$66,$89,
+ $3E,$22,$06,$E8,$0F,$01,$89,$36,$3E,$06,$66,$C1,$EE,$10,$89,
+ $36,$42,$06,$8B,$1E,$06,$06,$89,$1E,$3A,$06,$C7,$06,$46,$06,
+ $00,$42,$E8,$03,$01,$A1,$1C,$06,$A3,$4E,$06,$C7,$06,$3E,$06,
+ $00,$00,$C6,$06,$47,$06,$3F,$A1,$28,$06,$09,$C0,$75,$09,$A1,
+ $26,$06,$3B,$06,$20,$06,$76,$03,$A1,$20,$06,$A3,$42,$06,$E8,
+ $D9,$00,$66,$31,$C9,$8B,$0E,$46,$06,$66,$8B,$3E,$22,$06,$66,
+ $01,$0E,$22,$06,$66,$29,$0E,$26,$06,$66,$31,$F6,$C1,$E9,$02,
+ $1E,$06,$8E,$06,$16,$06,$8E,$1E,$1E,$06,$67,$F3,$66,$A5,$07,
+ $1F,$66,$03,$0E,$26,$06,$75,$AF,$C3,$3C,$3A,$74,$06,$3C,$2F,
+ $74,$02,$3C,$5C,$C3,$BE,$64,$07,$89,$F3,$26,$8A,$05,$47,$88,
+ $04,$38,$E0,$74,$0E,$08,$C0,$74,$0A,$46,$E8,$DE,$FF,$75,$EC,
+ $89,$F3,$74,$E8,$C3,$B0,$66,$BA,$48,$05,$EB,$0C,$B0,$67,$BA,
+ $55,$05,$EB,$05,$B0,$68,$BA,$5F,$05,$52,$8B,$1E,$62,$07,$C6,
+ $07,$24,$BB,$64,$07,$EB,$28,$E8,$F5,$00,$B0,$69,$BA,$99,$05,
+ $EB,$1A,$B0,$6A,$BA,$B2,$05,$EB,$13,$B0,$6B,$BA,$C4,$05,$EB,
+ $0C,$B0,$6C,$BA,$D6,$05,$EB,$05,$B0,$69,$BA,$99,$05,$52,$BB,
+ $3B,$05,$E8,$15,$00,$5B,$E8,$11,$00,$BB,$67,$04,$E8,$0B,$00,
+ $B4,$4C,$CD,$21,$43,$50,$B4,$02,$CD,$21,$58,$8A,$17,$80,$FA,
+ $24,$75,$F2,$C3,$0D,$0A,$24,$50,$51,$57,$31,$C0,$BF,$2A,$06,
+ $B9,$19,$00,$F3,$AB,$5F,$59,$58,$C3,$B8,$00,$03,$BB,$21,$00,
+ $31,$C9,$66,$BF,$2A,$06,$00,$00,$CD,$31,$C3,$00,$00,$30,$E4,
+ $E8,$4E,$FF,$89,$DE,$8B,$3E,$8C,$04,$EB,$17,$B4,$3B,$E8,$41,
+ $FF,$81,$FE,$64,$07,$74,$12,$8A,$44,$FF,$E8,$2A,$FF,$74,$04,
+ $C6,$04,$5C,$46,$E8,$03,$00,$72,$E4,$C3,$E8,$34,$00,$BB,$44,
+ $00,$8A,$07,$88,$04,$43,$46,$08,$C0,$75,$F6,$06,$57,$1E,$07,
+ $E8,$9B,$FF,$BB,$2A,$06,$8C,$5F,$04,$89,$5F,$02,$BA,$64,$07,
+ $B8,$00,$4B,$CD,$21,$5F,$07,$72,$09,$B4,$4D,$CD,$21,$2D,$00,
+ $03,$F7,$D8,$EB,$28,$80,$3E,$69,$08,$05,$72,$20,$B8,$00,$58,
+ $CD,$21,$A2,$67,$08,$B8,$02,$58,$CD,$21,$A2,$68,$08,$B8,$01,
+ $58,$BB,$80,$00,$CD,$21,$B8,$03,$58,$BB,$01,$00,$CD,$21,$C3,
+ $9C,$80,$3E,$69,$08,$05,$72,$1A,$50,$53,$B8,$03,$58,$8A,$1E,
+ $68,$08,$30,$FF,$CD,$21,$B8,$01,$58,$8A,$1E,$67,$08,$30,$FF,
+ $CD,$21,$5B,$58,$9D,$C3,$4C,$6F,$61,$64,$20,$65,$72,$72,$6F,
+ $72,$3A,$20,$24,$3A,$20,$63,$61,$6E,$27,$74,$20,$6F,$70,$65,
+ $6E,$24,$3A,$20,$6E,$6F,$74,$20,$45,$58,$45,$24,$3A,$20,$6E,
+ $6F,$74,$20,$43,$4F,$46,$46,$20,$28,$43,$68,$65,$63,$6B,$20,
+ $66,$6F,$72,$20,$76,$69,$72,$75,$73,$65,$73,$29,$24,$6E,$6F,
+ $20,$44,$50,$4D,$49,$20,$2D,$20,$47,$65,$74,$20,$63,$73,$64,
+ $70,$6D,$69,$2A,$62,$2E,$7A,$69,$70,$24,$6E,$6F,$20,$44,$4F,
+ $53,$20,$6D,$65,$6D,$6F,$72,$79,$24,$6E,$65,$65,$64,$20,$44,
+ $4F,$53,$20,$33,$24,$63,$61,$6E,$27,$74,$20,$73,$77,$69,$74,
+ $63,$68,$20,$6D,$6F,$64,$65,$24,$6E,$6F,$20,$44,$50,$4D,$49,
+ $20,$73,$65,$6C,$65,$63,$74,$6F,$72,$73,$24,$6E,$6F,$20,$44,
+ $50,$4D,$49,$20,$6D,$65,$6D,$6F,$72,$79,$24,$90,$90,$90,$90,
+ $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,
+ $90,$90,$90,$90,$90,$90,$90,$90);
+
+
+{****************************************************************************
+ TCoffObjectSection
+****************************************************************************}
+
+ constructor tcoffobjectsection.create(const aname:string;atype:tasmsectiontype;aalign:longint;aoptions:TAsmSectionOptions);
+ begin
+ inherited create(aname,atype,aalign,aoptions);
+ Flags:=0;
+ end;
+
+
+ procedure TCoffObjectSection.addsymsizereloc(ofs:longint;p:tasmsymbol;size:longint;relative:TAsmRelocationType);
+ begin
+ relocations.concat(tasmrelocation.createsymbolsize(ofs,p,size,relative));
+ end;
+
+
+ procedure TCoffObjectSection.fixuprelocs;
+ var
+ r : TAsmRelocation;
+ address,
+ relocval : longint;
+ begin
+ r:=TAsmRelocation(relocations.first);
+ if assigned(r) and
+ (not assigned(data)) then
+ internalerror(200205183);
+ while assigned(r) do
+ begin
+ if assigned(r.symbol) then
+ relocval:=r.symbol.address
+ else
+ internalerror(200205183);
+ data.Seek(r.address);
+ data.Read(address,4);
+ case r.typ of
+ RELOC_RELATIVE :
+ begin
+ dec(address,mempos);
+ inc(address,relocval);
+ end;
+ RELOC_RVA,
+ RELOC_ABSOLUTE :
+ begin
+ if r.symbol.section.sectype=sec_common then
+ dec(address,r.orgsize)
+ else
+ begin
+ { fixup address when the symbol was known in defined object }
+ if (r.symbol.section<>nil) and
+ (r.symbol.owner=owner) then
+ dec(address,TCoffObjectSection(r.symbol.section).orgmempos);
+ end;
+ inc(address,relocval);
+ end;
+ end;
+ data.Seek(r.address);
+ data.Write(address,4);
+ { goto next reloc }
+ r:=TAsmRelocation(r.next);
+ end;
+ end;
+
+
+
+{****************************************************************************
+ TDjCoffObjectSection
+****************************************************************************}
+
+ constructor tdjcoffobjectsection.create(const aname:string;atype:tasmsectiontype;aalign:longint;aoptions:TAsmSectionOptions);
+ begin
+ inherited create(aname,atype,aalign,aoptions);
+ case atype of
+ sec_code :
+ begin
+ Flags:=$20;
+ addralign:=16;
+ end;
+ sec_data :
+ begin
+ Flags:=$40;
+ addralign:=16;
+ end;
+ sec_bss :
+ begin
+ Flags:=$80;
+ addralign:=16;
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TPECoffObjectSection
+****************************************************************************}
+
+ constructor tpecoffobjectsection.create(const aname:string;atype:tasmsectiontype;aalign:longint;aoptions:TAsmSectionOptions);
+ begin
+ inherited create(aname,atype,aalign,aoptions);
+ case atype of
+ sec_code :
+ begin
+ Flags:=$60000020;
+ addralign:=16;
+ end;
+ sec_data :
+ begin
+ Flags:=$c0300040;
+ addralign:=16;
+ end;
+ sec_bss :
+ begin
+ Flags:=$c0300080;
+ addralign:=16;
+ end;
+ sec_idata2,
+ sec_idata4,
+ sec_idata5,
+ sec_idata6,
+ sec_idata7 :
+ begin
+ Flags:=$40000000;
+ end;
+ sec_edata :
+ begin
+ Flags:=$c0300040;
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ tcoffobjectdata
+****************************************************************************}
+
+ constructor tcoffobjectdata.createcoff(const n:string;awin32:boolean;acasmsection:TAsmSectionClass);
+ begin
+ inherited create(n);
+ CAsmSection:=ACAsmSection;
+ win32:=awin32;
+ { we need at least the following 3 sections }
+ createsection(sec_code,'',0,[]);
+ createsection(sec_data,'',0,[]);
+ createsection(sec_bss,'',0,[]);
+ if (cs_use_lineinfo in aktglobalswitches) or
+ (cs_debuginfo in aktmoduleswitches) then
+ begin
+ stabssec:=createsection(sec_stab,'',0,[]);
+ stabstrsec:=createsection(sec_stabstr,'',0,[]);
+ end;
+ end;
+
+
+ destructor tcoffobjectdata.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ function TCoffObjectData.sectionname(atype:tasmsectiontype;const aname:string):string;
+ const
+ secnames : array[tasmsectiontype] of string[16] = ('',
+ '.text','.data','.data','.bss','.threadvar',
+ 'common',
+ '.note',
+ '.text',
+ '.stab','.stabstr',
+ '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
+ '.eh_frame',
+ '.debug_frame',
+ '.fpc'
+ );
+ begin
+ { No support for named sections, because section names are limited to 8 chars }
+ result:=secnames[atype];
+ end;
+
+
+ procedure tcoffobjectdata.writesymbol(p:tasmsymbol);
+ begin
+ if currsec=nil then
+ internalerror(200403071);
+ { already written ? }
+ if p.indexnr<>-1 then
+ exit;
+ { calculate symbol index }
+ if (p.currbind<>AB_LOCAL) then
+ begin
+ { insert the symbol in the local index, the indexarray
+ will take care of the numbering }
+ symbols.insert(p);
+ end
+ else
+ p.indexnr:=-2; { local }
+ end;
+
+
+ procedure tcoffobjectdata.writereloc(data,len:aint;p:tasmsymbol;relative:TAsmRelocationType);
+ var
+ curraddr,
+ symaddr : longint;
+ begin
+ if currsec=nil then
+ internalerror(200403072);
+ if assigned(p) then
+ begin
+ { current address }
+ curraddr:=currsec.mempos+currsec.datasize;
+ { external/common symbols don't have a fixed memory position yet }
+ if (p.currbind=AB_COMMON) then
+ begin
+ { For go32v2 we need to use the size as address }
+ if not win32 then
+ symaddr:=p.size
+ else
+ symaddr:=0;
+ end
+ else
+ begin
+ symaddr:=p.address;
+ if assigned(p.section) then
+ inc(symaddr,p.section.mempos);
+ end;
+ { no symbol relocation need inside a section }
+ if (p.section=currsec) and
+ (p.currbind<>AB_COMMON) then
+ begin
+ case relative of
+ RELOC_ABSOLUTE :
+ begin
+ currsec.addsectionreloc(curraddr,currsec,RELOC_ABSOLUTE);
+ inc(data,symaddr);
+ end;
+ RELOC_RELATIVE :
+ begin
+ inc(data,symaddr-len-currsec.datasize);
+ end;
+ RELOC_RVA :
+ begin
+ currsec.addsectionreloc(curraddr,currsec,RELOC_RVA);
+ inc(data,symaddr);
+ end;
+ end;
+ end
+ else
+ begin
+ writesymbol(p);
+ if (p.section<>nil) and
+ (p.currbind<>AB_COMMON) and
+ (relative<>RELOC_RELATIVE) then
+ currsec.addsectionreloc(curraddr,p.section,relative)
+ else
+ currsec.addsymreloc(curraddr,p,relative);
+ if (not win32) or
+ ((relative<>RELOC_RELATIVE) and (p.section<>nil)) then
+ inc(data,symaddr);
+ if relative=RELOC_RELATIVE then
+ begin
+ if win32 then
+ dec(data,len-4)
+ else
+ dec(data,len+currsec.datasize);
+ end;
+ end;
+ end;
+ currsec.write(data,len);
+ end;
+
+
+ procedure tcoffobjectdata.writestab(offset:aint;ps:tasmsymbol;nidx,nother,line:longint;p:pchar);
+ var
+ stab : coffstab;
+ curraddr : longint;
+ begin
+ { Win32 does not need an offset if a symbol relocation is used }
+ if win32 and
+ assigned(ps) and
+ (ps.currbind<>AB_LOCAL) then
+ offset:=0;
+ if assigned(p) and (p[0]<>#0) then
+ begin
+ stab.strpos:=StabStrSec.datasize;
+ StabStrSec.write(p^,strlen(p)+1);
+ end
+ else
+ stab.strpos:=0;
+ stab.ntype:=nidx;
+ stab.ndesc:=line;
+ stab.nother:=nother;
+ stab.nvalue:=offset;
+ StabsSec.write(stab,sizeof(stab));
+ if assigned(ps) then
+ begin
+ writesymbol(ps);
+ { current address }
+ curraddr:=StabsSec.mempos+StabsSec.datasize;
+ if DLLSource and RelocSection then
+ { avoid relocation in the .stab section
+ because it ends up in the .reloc section instead }
+ StabsSec.addsymreloc(curraddr-4,ps,RELOC_RVA)
+ else
+ StabsSec.addsymreloc(curraddr-4,ps,RELOC_ABSOLUTE);
+ end;
+ end;
+
+
+ procedure tcoffobjectdata.section_mempos(p:tnamedindexitem;arg:pointer);
+ begin
+ tcoffobjectsection(p).memsize:=tcoffobjectsection(p).datasize;
+ { memory position is in arg }
+ if not win32 then
+ begin
+ tcoffobjectsection(p).mempos:=plongint(arg)^;
+ inc(plongint(arg)^,align(tcoffobjectsection(p).memsize,tcoffobjectsection(p).addralign));
+ end;
+ end;
+
+
+ procedure tcoffobjectdata.beforealloc;
+ begin
+ { create stabs sections if debugging }
+ if (cs_debuginfo in aktmoduleswitches) then
+ begin
+ StabsSec.Alloc(sizeof(coffstab));
+ StabStrSec.Alloc(length(SplitFileName(current_module.mainsource^))+2);
+ end;
+ end;
+
+
+ procedure tcoffobjectdata.beforewrite;
+ var
+ s : string;
+ begin
+ { create stabs sections if debugging }
+ if (cs_debuginfo in aktmoduleswitches) then
+ begin
+ writestab(0,nil,0,0,0,nil);
+ { write zero pchar and name together (PM) }
+ s:=#0+SplitFileName(current_module.mainsource^)+#0;
+ stabstrsec.write(s[1],length(s));
+ end;
+ end;
+
+
+ procedure tcoffobjectdata.afteralloc;
+ var
+ mempos : longint;
+ begin
+ { if debug then also count header stab }
+ if (cs_debuginfo in aktmoduleswitches) then
+ begin
+ StabsSec.Alloc(sizeof(coffstab));
+ StabStrSec.Alloc(length(SplitFileName(current_module.mainsource^))+2);
+ end;
+ { calc mempos }
+ mempos:=0;
+ sects.foreach(@section_mempos,@mempos);
+ end;
+
+
+{****************************************************************************
+ tdjcoffobjectdata
+****************************************************************************}
+
+ constructor tdjcoffobjectdata.create(const n:string);
+ begin
+ inherited createcoff(n,false,tdjcoffobjectsection);
+ end;
+
+
+{****************************************************************************
+ tpecoffobjectdata
+****************************************************************************}
+
+ constructor tpecoffobjectdata.create(const n:string);
+ begin
+ inherited createcoff(n,true,tpecoffobjectsection);
+ end;
+
+
+{****************************************************************************
+ tcoffobjectoutput
+****************************************************************************}
+
+ constructor tcoffobjectoutput.createdjgpp(smart:boolean);
+ begin
+ inherited create(smart);
+ win32:=false;
+ end;
+
+
+ constructor tcoffobjectoutput.createwin32(smart:boolean);
+ begin
+ inherited create(smart);
+ win32:=true;
+ end;
+
+
+ function tcoffobjectoutput.newobjectdata(const n:string):TAsmObjectData;
+ begin
+ if win32 then
+ result:=tpecoffobjectdata.create(n)
+ else
+ result:=tdjcoffobjectdata.create(n);
+ end;
+
+
+ procedure tcoffobjectoutput.write_symbol(const name:string;value,section,typ,aux:longint);
+ var
+ sym : coffsymbol;
+ begin
+ FillChar(sym,sizeof(sym),0);
+ { symbolname }
+ if length(name)>8 then
+ begin
+ sym.strpos:=FCoffStrs.size+4;
+ FCoffStrs.writestr(name);
+ FCoffStrs.writestr(#0);
+ end
+ else
+ move(name[1],sym.name,length(name));
+ sym.value:=value;
+ sym.section:=section;
+ sym.typ:=typ;
+ sym.aux:=aux;
+ FWriter.write(sym,sizeof(sym));
+ end;
+
+
+ procedure tcoffobjectoutput.section_write_symbol(p:tnamedindexitem;arg:pointer);
+ var
+ secrec : coffsectionrec;
+ begin
+ write_symbol(tasmsection(p).name,tasmsection(p).mempos,tasmsection(p).secsymidx,3,1);
+ fillchar(secrec,sizeof(secrec),0);
+ secrec.len:=tasmsection(p).aligneddatasize;
+ secrec.nrelocs:=tasmsection(p).relocations.count;
+ FWriter.write(secrec,sizeof(secrec));
+ end;
+
+
+ procedure tcoffobjectoutput.section_write_relocs(p:tnamedindexitem;arg:pointer);
+ var
+ rel : coffreloc;
+ r : TAsmRelocation;
+ begin
+ r:=TasmRelocation(tasmsection(p).relocations.first);
+ while assigned(r) do
+ begin
+ rel.address:=r.address;
+ if assigned(r.symbol) then
+ begin
+ if (r.symbol.currbind=AB_LOCAL) then
+ rel.sym:=2*r.symbol.section.secsymidx
+ else
+ begin
+ if r.symbol.indexnr=-1 then
+ internalerror(4321);
+ { indexnr starts with 1, coff starts with 0 }
+ rel.sym:=r.symbol.indexnr+initsym-1;
+ end;
+ end
+ else
+ begin
+ if r.section<>nil then
+ rel.sym:=2*r.section.secsymidx
+ else
+ rel.sym:=0;
+ end;
+ case r.typ of
+ RELOC_RELATIVE :
+ rel.relative:=$14;
+ RELOC_ABSOLUTE :
+ rel.relative:=$6;
+ RELOC_RVA :
+ rel.relative:=$7;
+ end;
+ FWriter.write(rel,sizeof(rel));
+ r:=TAsmRelocation(r.next);
+ end;
+ end;
+
+
+ procedure tcoffobjectoutput.write_symbols(data:TAsmObjectData);
+ var
+ filename : string[18];
+ value : longint;
+ sectionval,
+ globalval : byte;
+ p : tasmsymbol;
+ begin
+ with tcoffobjectdata(data) do
+ begin
+ { The `.file' record, and the file name auxiliary record }
+ write_symbol('.file', 0, -2, $67, 1);
+ fillchar(filename,sizeof(filename),0);
+ filename:=SplitFileName(current_module.mainsource^);
+ FWriter.write(filename[1],sizeof(filename)-1);
+ { The section records, with their auxiliaries, also store the
+ symbol index }
+ Sects.foreach(@section_write_symbol,nil);
+ { The symbols used }
+ p:=Tasmsymbol(symbols.First);
+ while assigned(p) do
+ begin
+ if assigned(p.section) and
+ (p.currbind<>AB_COMMON) then
+ sectionval:=p.section.secsymidx
+ else
+ sectionval:=0;
+ if p.currbind=AB_LOCAL then
+ globalval:=3
+ else
+ globalval:=2;
+ { if local of global then set the section value to the address
+ of the symbol }
+ if p.currbind in [AB_LOCAL,AB_GLOBAL] then
+ value:=p.address+p.section.mempos
+ else
+ value:=p.size;
+ { symbolname }
+ write_symbol(p.name,value,sectionval,globalval,0);
+ p:=tasmsymbol(p.indexnext);
+ end;
+ end;
+ end;
+
+
+ procedure tcoffobjectoutput.section_set_secsymidx(p:tnamedindexitem;arg:pointer);
+ begin
+ inc(plongint(arg)^);
+ tasmsection(p).secsymidx:=plongint(arg)^;
+ end;
+
+
+ procedure tcoffobjectoutput.section_set_datapos(p:tnamedindexitem;arg:pointer);
+ begin
+ tasmsection(p).datapos:=plongint(arg)^;
+ if not(aso_alloconly in tasmsection(p).secoptions) then
+ inc(plongint(arg)^,tasmsection(p).aligneddatasize);
+ end;
+
+
+ procedure tcoffobjectoutput.section_set_reloc_datapos(p:tnamedindexitem;arg:pointer);
+ begin
+ TCoffObjectSection(p).coffrelocpos:=plongint(arg)^;
+ inc(plongint(arg)^,sizeof(coffreloc)*tasmsection(p).relocations.count);
+ end;
+
+
+ procedure tcoffobjectoutput.section_write_header(p:tnamedindexitem;arg:pointer);
+ var
+ sechdr : coffsechdr;
+ s : string;
+ begin
+ fillchar(sechdr,sizeof(sechdr),0);
+ s:=tasmsection(p).name;
+ { section names are limited to 8 chars }
+ if length(s)>8 then
+ internalerror(200403312);
+ move(s[1],sechdr.name,length(s));
+ if not win32 then
+ begin
+ sechdr.rvaofs:=tasmsection(p).mempos;
+ sechdr.vsize:=tasmsection(p).mempos;
+ end
+ else
+ begin
+ if tasmsection(p).sectype=sec_bss then
+ sechdr.vsize:=tasmsection(p).aligneddatasize;
+ end;
+ sechdr.datasize:=tasmsection(p).aligneddatasize;
+ if (tasmsection(p).datasize>0) and
+ not(aso_alloconly in tasmsection(p).secoptions) then
+ sechdr.datapos:=tasmsection(p).datapos;
+ sechdr.nrelocs:=tasmsection(p).relocations.count;
+ sechdr.relocpos:=TCoffObjectSection(p).coffrelocpos;
+ sechdr.flags:=TCoffObjectSection(p).flags;
+ FWriter.write(sechdr,sizeof(sechdr));
+ end;
+
+
+ procedure tcoffobjectoutput.section_write_data(p:tnamedindexitem;arg:pointer);
+ var
+ hp : pdynamicblock;
+ begin
+ if (aso_alloconly in tasmsection(p).secoptions) then
+ exit;
+ if tasmsection(p).data=nil then
+ internalerror(200403073);
+ tasmsection(p).alignsection;
+ hp:=tasmsection(p).data.firstblock;
+ while assigned(hp) do
+ begin
+ FWriter.write(hp^.data,hp^.used);
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ function tcoffobjectoutput.writedata(data:TAsmObjectData):boolean;
+ var
+ orgdatapos,
+ datapos,
+ nsects,
+ sympos,i : longint;
+ hstab : coffstab;
+ gotreloc : boolean;
+ header : coffheader;
+ empty : array[0..15] of byte;
+ hp : pdynamicblock;
+ s : string;
+ begin
+ result:=false;
+ FCoffStrs:=TDynamicArray.Create(strsresize);
+ with tcoffobjectdata(data) do
+ begin
+ { calc amount of sections we have }
+ fillchar(empty,sizeof(empty),0);
+ nsects:=0;
+ Sects.foreach(@section_set_secsymidx,@nsects);
+ initsym:=2+nsects*2; { 2 for the file }
+ { For the stab section we need an HdrSym which can now be
+ calculated more easily }
+ if StabsSec<>nil then
+ begin
+ { header stab }
+ s:=#0+SplitFileName(current_module.mainsource^)+#0;
+ stabstrsec.write(s[1],length(s));
+ hstab.strpos:=1;
+ hstab.ntype:=0;
+ hstab.nother:=0;
+ hstab.ndesc:=(StabsSec.datasize div sizeof(coffstab))-1{+1 according to gas output PM};
+ hstab.nvalue:=StabStrSec.datasize;
+ StabsSec.data.seek(0);
+ StabsSec.data.write(hstab,sizeof(hstab));
+ end;
+ { Calculate the filepositions }
+ datapos:=sizeof(coffheader)+sizeof(coffsechdr)*nsects;
+ { sections first }
+ Sects.foreach(@section_set_datapos,@datapos);
+ { relocs }
+ orgdatapos:=datapos;
+ Sects.foreach(@section_set_reloc_datapos,@datapos);
+ gotreloc:=(orgdatapos<>datapos);
+ { symbols }
+ sympos:=datapos;
+ { COFF header }
+ fillchar(header,sizeof(coffheader),0);
+{$ifdef i386}
+ header.mach:=$14c;
+{$endif i386}
+{$ifdef arm}
+ header.mach:=$1c0;
+{$endif arm}
+ header.nsects:=nsects;
+ header.sympos:=sympos;
+ header.syms:=symbols.count+initsym;
+ header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES;
+ if not gotreloc then
+ header.flag:=header.flag or COFF_FLAG_NORELOCS;
+ FWriter.write(header,sizeof(header));
+ { Section headers }
+ Sects.foreach(@section_write_header,nil);
+ { Sections }
+ Sects.foreach(@section_write_data,nil);
+ { Relocs }
+ Sects.foreach(@section_write_relocs,nil);
+ { Symbols }
+ write_symbols(data);
+ { Strings }
+ i:=FCoffStrs.size+4;
+ FWriter.write(i,4);
+ hp:=FCoffStrs.firstblock;
+ while assigned(hp) do
+ begin
+ FWriter.write(hp^.data,hp^.used);
+ hp:=hp^.next;
+ end;
+ end;
+ FCoffStrs.Free;
+ end;
+
+
+{****************************************************************************
+ tcoffexeoutput
+****************************************************************************}
+
+ constructor tcoffexeoutput.createdjgpp;
+ begin
+ inherited create;
+ win32:=false;
+ end;
+
+
+ constructor tcoffexeoutput.createwin32;
+ begin
+ inherited create;
+ win32:=true;
+ end;
+
+
+ function tcoffexeoutput.newobjectinput:tobjectinput;
+ begin
+ if win32 then
+ result:=tcoffobjectinput.createwin32
+ else
+ result:=tcoffobjectinput.createdjgpp;
+ end;
+
+
+ procedure tcoffexeoutput.write_symbol(const name:string;value,section,typ,aux:longint);
+ var
+ sym : coffsymbol;
+ begin
+ FillChar(sym,sizeof(sym),0);
+ if length(name)>8 then
+ begin
+ sym.strpos:=FCoffStrs.size+4;
+ FCoffStrs.writestr(name);
+ FCoffStrs.writestr(#0);
+ end
+ else
+ move(name[1],sym.name,length(name));
+ sym.value:=value;
+ sym.section:=section;
+ sym.typ:=typ;
+ sym.aux:=aux;
+ FWriter.write(sym,sizeof(sym));
+ end;
+
+
+ procedure tcoffexeoutput.write_symbols;
+ var
+ value,
+ sectionval,
+ globalval : byte;
+ objdata : TAsmObjectData;
+ p : tasmsymbol;
+ begin
+{$ifdef internallinker}
+ objdata:=TAsmObjectData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ with tcoffobjectdata(objdata) do
+ begin
+ { The symbols used }
+ p:=Tasmsymbol(symbols.First);
+ while assigned(p) do
+ begin
+ if p.section=sec_common then
+ sectionval:=sections[sec_bss].secsymidx
+ else
+ sectionval:=sections[p.section.name].secsymidx;
+ if p.currbind=AB_LOCAL then
+ globalval:=3
+ else
+ globalval:=2;
+ { if local of global then set the section value to the address
+ of the symbol }
+ if p.currbind in [AB_LOCAL,AB_GLOBAL] then
+ value:=p.address
+ else
+ value:=p.size;
+ { symbolname }
+ s:=p.name;
+ if length(s)>8 then
+ begin
+ nameidx:=FCoffStrs.size+4;
+ FCoffStrs.writestr(s);
+ FCoffStrs.writestr(#0);
+ end
+ else
+ begin
+ nameidx:=-1;
+ namestr:=s;
+ end;
+ write_symbol(namestr,nameidx,value,sectionval,globalval,0);
+ p:=tasmsymbol(p.indexnext);
+ end;
+ end;
+ objdata:=TAsmObjectData(objdata.next);
+ end;
+{$endif internallinker}
+ end;
+
+
+ procedure tcoffexeoutput.CalculateMemoryMap;
+ var
+ objdata : TAsmObjectData;
+ secsymidx,
+ mempos,
+ datapos : longint;
+ begin
+{$ifdef internallinker}
+ { retrieve amount of sections }
+ nsects:=0;
+ secsymidx:=0;
+ for sec:=low(TSection) to high(TSection) do
+ begin
+ if sections[sec].available then
+ begin
+ inc(nsects);
+ inc(secsymidx);
+ sections[sec].secsymidx:=secsymidx;
+ end;
+ end;
+ { calculate start positions after the headers }
+ datapos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
+ mempos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
+ if not win32 then
+ inc(mempos,sizeof(go32v2stub)+$1000);
+ { add sections }
+ MapObjectdata(datapos,mempos);
+ { end symbol }
+ AddGlobalSym('_etext',sections[sec_code].mempos+sections[sec_code].memsize);
+ AddGlobalSym('_edata',sections[sec_data].mempos+sections[sec_data].memsize);
+ AddGlobalSym('end',mempos);
+ { symbols }
+ nsyms:=0;
+ sympos:=0;
+ if not(cs_link_strip in aktglobalswitches) then
+ begin
+ sympos:=datapos;
+ objdata:=TAsmObjectData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ inc(nsyms,objdata.symbols.count);
+ objdata:=TAsmObjectData(objdata.next);
+ end;
+ end;
+{$endif internallinker}
+ end;
+
+
+ function tcoffexeoutput.writedata:boolean;
+ var
+ i : longint;
+ header : coffheader;
+ optheader : coffoptheader;
+ sechdr : coffsechdr;
+ hp : pdynamicblock;
+ objdata : TAsmObjectData;
+ hsym : tasmsymbol;
+ begin
+ result:=false;
+{$ifdef internallinker}
+ FCoffSyms:=TDynamicArray.Create(symbolresize);
+ FCoffStrs:=TDynamicArray.Create(strsresize);
+ { Stub }
+ if not win32 then
+ FWriter.write(go32v2stub,sizeof(go32v2stub));
+ { COFF header }
+ fillchar(header,sizeof(header),0);
+ header.mach:=$14c;
+ header.nsects:=nsects;
+ header.sympos:=sympos;
+ header.syms:=nsyms;
+ header.opthdr:=sizeof(coffoptheader);
+ header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
+ FWriter.write(header,sizeof(header));
+ { Optional COFF Header }
+ fillchar(optheader,sizeof(optheader),0);
+ optheader.magic:=$10b;
+ optheader.tsize:=sections[sec_code].memsize;
+ optheader.dsize:=sections[sec_data].memsize;
+ optheader.bsize:=sections[sec_bss].memsize;
+ hsym:=tasmsymbol(globalsyms.search('start'));
+ if not assigned(hsym) then
+ begin
+ Comment(V_Error,'Entrypoint "start" not defined');
+ exit;
+ end;
+ optheader.entry:=hsym.address;
+ optheader.text_start:=sections[sec_code].mempos;
+ optheader.data_start:=sections[sec_data].mempos;
+ FWriter.write(optheader,sizeof(optheader));
+ { Section headers }
+ for sec:=low(TSection) to high(TSection) do
+ if sections[sec].available then
+ begin
+ fillchar(sechdr,sizeof(sechdr),0);
+ move(target_asm.secnames[sec][1],sechdr.name,length(target_asm.secnames[sec]));
+ if not win32 then
+ begin
+ sechdr.rvaofs:=sections[sec].mempos;
+ sechdr.vsize:=sections[sec].mempos;
+ end
+ else
+ begin
+ if sec=sec_bss then
+ sechdr.vsize:=sections[sec].memsize;
+ end;
+ if sec=sec_bss then
+ sechdr.datasize:=sections[sec].memsize
+ else
+ begin
+ sechdr.datasize:=sections[sec].datasize;
+ sechdr.datapos:=sections[sec].datapos;
+ end;
+ sechdr.nrelocs:=0;
+ sechdr.relocpos:=0;
+ sechdr.flags:=sections[sec].flags;
+ FWriter.write(sechdr,sizeof(sechdr));
+ end;
+ { Sections }
+ for sec:=low(TSection) to high(TSection) do
+ if sections[sec].available then
+ begin
+ { update objectfiles }
+ objdata:=TAsmObjectData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ if assigned(objdata.sects[sec]) and
+ assigned(objdata.sects[sec].data) then
+ begin
+ FWriter.WriteZeros(objdata.sects[sec].dataalignbytes);
+ hp:=objdata.sects[sec].data.firstblock;
+ while assigned(hp) do
+ begin
+ FWriter.write(hp^.data,hp^.used);
+ hp:=hp^.next;
+ end;
+ end;
+ objdata:=TAsmObjectData(objdata.next);
+ end;
+ end;
+ { Optional symbols }
+ if not(cs_link_strip in aktglobalswitches) then
+ begin
+ { Symbols }
+ write_symbols;
+ { Strings }
+ i:=FCoffStrs.size+4;
+ FWriter.write(i,4);
+ hp:=FCoffStrs.firstblock;
+ while assigned(hp) do
+ begin
+ FWriter.write(hp^.data,hp^.used);
+ hp:=hp^.next;
+ end;
+ end;
+ { Release }
+ FCoffStrs.Free;
+ FCoffSyms.Free;
+ result:=true;
+{$endif internallinker}
+ end;
+
+
+ procedure tcoffexeoutput.GenerateExecutable(const fn:string);
+ begin
+ AddGlobalSym('_etext',0);
+ AddGlobalSym('_edata',0);
+ AddGlobalSym('end',0);
+ if not CalculateSymbols then
+ exit;
+ CalculateMemoryMap;
+ FixupSymbols;
+ FixupRelocations;
+ writeexefile(fn);
+ end;
+
+
+{****************************************************************************
+ tcoffobjectinput
+****************************************************************************}
+
+ constructor tcoffobjectinput.createdjgpp;
+ begin
+ inherited create;
+ win32:=false;
+ end;
+
+
+ constructor tcoffobjectinput.createwin32;
+ begin
+ inherited create;
+ win32:=true;
+ end;
+
+
+ function tcoffobjectinput.newobjectdata(const n:string):TAsmObjectData;
+ begin
+ if win32 then
+ result:=tpecoffobjectdata.create(n)
+ else
+ result:=tdjcoffobjectdata.create(n);
+ end;
+
+
+ procedure tcoffobjectinput.read_relocs(s:TCoffObjectSection);
+ var
+ rel : coffreloc;
+ rel_type : TAsmRelocationType;
+ i : longint;
+ p : tasmsymbol;
+ begin
+ for i:=1 to s.coffrelocs do
+ begin
+ FReader.read(rel,sizeof(rel));
+ case rel.relative of
+ $14 : rel_type:=RELOC_RELATIVE;
+ $06 : rel_type:=RELOC_ABSOLUTE;
+ $07 : rel_type:=RELOC_RVA;
+ else
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+ end;
+
+ p:=FSymTbl^[rel.sym].sym;
+ if assigned(p) then
+ begin
+ s.addsymsizereloc(rel.address-s.mempos,p,FSymTbl^[rel.sym].orgsize,rel_type);
+ end
+ else
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure tcoffobjectinput.handle_symbols(data:TAsmObjectData);
+ var
+ size,
+ address,
+ i,nsyms,
+ symidx : longint;
+ sym : coffsymbol;
+ strname : string;
+ p : tasmsymbol;
+ bind : Tasmsymbind;
+ auxrec : array[0..17] of byte;
+ begin
+{$ifdef internallinker}
+ with tcoffobjectdata(data) do
+ begin
+ nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
+ { Allocate memory for symidx -> tasmsymbol table }
+ GetMem(FSymTbl,nsyms*sizeof(ttasmsymbolrec));
+ FillChar(FSymTbl^,nsyms*sizeof(ttasmsymbolrec),0);
+ { Loop all symbols }
+ FCoffSyms.Seek(0);
+ symidx:=0;
+ while (symidx<nsyms) do
+ begin
+ FCoffSyms.Read(sym,sizeof(sym));
+ if plongint(@sym.name)^<>0 then
+ begin
+ move(sym.name,strname[1],8);
+ strname[9]:=#0;
+ end
+ else
+ begin
+ FCoffStrs.Seek(sym.strpos-4);
+ FCoffStrs.Read(strname[1],255);
+ strname[255]:=#0;
+ end;
+ strname[0]:=chr(strlen(@strname[1]));
+ if strname='' then
+ Internalerror(200205172);
+ bind:=AB_EXTERNAL;
+ sec:=sec_none;
+ size:=0;
+ address:=0;
+ case sym.typ of
+ COFF_SYM_GLOBAL :
+ begin
+ if sym.section=0 then
+ begin
+ if sym.value=0 then
+ bind:=AB_EXTERNAL
+ else
+ begin
+ bind:=AB_COMMON;
+ size:=sym.value;
+ end;
+ end
+ else
+ begin
+ bind:=AB_GLOBAL;
+ sec:=Fidx2sec[sym.section];
+ if assigned(sects[sec]) then
+ begin
+ if sym.value>=sects[sec].mempos then
+ address:=sym.value-sects[sec].mempos
+ else
+ internalerror(432432432);
+ end
+ else
+ internalerror(34243214);
+ end;
+ p:=TAsmSymbol.Create(strname,bind,AT_FUNCTION);
+ p.SetAddress(0,sec,address,size);
+ p.objectdata:=data;
+ symbols.insert(p);
+ end;
+ COFF_SYM_LABEL,
+ COFF_SYM_LOCAL :
+ begin
+ { do not add constants (section=-1) }
+ if sym.section<>-1 then
+ begin
+ bind:=AB_LOCAL;
+ sec:=Fidx2sec[sym.section];
+ if assigned(sects[sec]) then
+ begin
+ if sym.value>=sects[sec].mempos then
+ address:=sym.value-sects[sec].mempos
+ else
+ internalerror(432432432);
+ end
+ else
+ internalerror(34243214);
+ p:=TAsmSymbol.Create(strname,bind,AT_FUNCTION);
+ p.SetAddress(0,sec,address,size);
+ p.objectdata:=data;
+ symbols.insert(p);
+ end;
+ end;
+ COFF_SYM_SECTION,
+ COFF_SYM_FUNCTION,
+ COFF_SYM_FILE :
+ ;
+ else
+ internalerror(4342343);
+ end;
+ FSymTbl^[symidx].sym:=p;
+ FSymTbl^[symidx].orgsize:=size;
+ { read aux records }
+ for i:=1 to sym.aux do
+ begin
+ FCoffSyms.Read(auxrec,sizeof(auxrec));
+ inc(symidx);
+ end;
+ inc(symidx);
+ end;
+ end;
+{$endif internallinker}
+ end;
+
+
+ function tcoffobjectinput.readobjectdata(data:TAsmObjectData):boolean;
+ var
+ strsize,
+ i : longint;
+ header : coffheader;
+ sechdr : coffsechdr;
+ secname : array[0..15] of char;
+ begin
+ result:=false;
+{$ifdef internallinker}
+ FCoffSyms:=TDynamicArray.Create(symbolresize);
+ FCoffStrs:=TDynamicArray.Create(strsresize);
+ with tcoffobjectdata(data) do
+ begin
+ FillChar(Fidx2sec,sizeof(Fidx2sec),0);
+ { Read COFF header }
+ if not reader.read(header,sizeof(coffheader)) then
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+{$ifdef i386}
+ if header.mach<>$14c then
+{$endif i386}
+{$ifdef arm}
+ if header.mach<>$1c0 then
+{$endif arm}
+ begin
+ Comment(V_Error,'Not a coff file');
+ exit;
+ end;
+ if header.nsects>255 then
+ begin
+ Comment(V_Error,'To many sections');
+ exit;
+ end;
+ { Section headers }
+ for i:=1 to header.nsects do
+ begin
+ if not reader.read(sechdr,sizeof(sechdr)) then
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+
+ move(sechdr.name,secname,8);
+ secname[8]:=#0;
+ sec:=str2sec(strpas(secname));
+ if sec<>sec_none then
+ begin
+ Fidx2sec[i]:=sec;
+ createsection(sec);
+ if not win32 then
+ sects[sec].mempos:=sechdr.rvaofs;
+ TCoffObjectSection(sects[sec]).coffrelocs:=sechdr.nrelocs;
+ TCoffObjectSection(sects[sec]).coffrelocpos:=sechdr.relocpos;
+ sects[sec].datapos:=sechdr.datapos;
+ sects[sec].datasize:=sechdr.datasize;
+ sects[sec].memsize:=sechdr.datasize;
+ TCoffObjectSection(sects[sec]).orgmempos:=sects[sec].mempos;
+ sects[sec].flags:=sechdr.flags;
+ end
+ else
+ Comment(V_Warning,'skipping unsupported section '+strpas(sechdr.name));
+ end;
+ { Symbols }
+ Reader.Seek(header.sympos);
+ if not Reader.ReadArray(FCoffSyms,header.syms*sizeof(CoffSymbol)) then
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+ { Strings }
+ if not Reader.Read(strsize,4) then
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+ if strsize<4 then
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+ if not Reader.ReadArray(FCoffStrs,Strsize-4) then
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+ { Insert all symbols }
+ handle_symbols(data);
+ { Sections }
+ for sec:=low(TSection) to high(TSection) do
+ if assigned(sects[sec]) and
+ (sec<>sec_bss) then
+ begin
+ Reader.Seek(sects[sec].datapos);
+ if not Reader.ReadArray(sects[sec].data,sects[sec].datasize) then
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+ end;
+ { Relocs }
+ for sec:=low(TSection) to high(TSection) do
+ if assigned(sects[sec]) and
+ (TCoffObjectSection(sects[sec]).coffrelocs>0) then
+ begin
+ Reader.Seek(TCoffObjectSection(sects[sec]).coffrelocpos);
+ read_relocs(TCoffObjectSection(sects[sec]));
+ end;
+ end;
+ FCoffStrs.Free;
+ FCoffSyms.Free;
+ result:=true;
+{$endif internallinker}
+ end;
+
+
+{****************************************************************************
+ TCoffAssembler
+****************************************************************************}
+
+ constructor TCoffAssembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ objectoutput:=tcoffobjectoutput.createdjgpp(smart);
+ end;
+
+
+{****************************************************************************
+ TPECoffAssembler
+****************************************************************************}
+
+ constructor TPECoffAssembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ objectoutput:=tcoffobjectoutput.createwin32(smart);
+ end;
+
+
+{****************************************************************************
+ TCoffLinker
+****************************************************************************}
+
+ constructor TCoffLinker.Create;
+ begin
+ inherited Create;
+ exeoutput:=tcoffexeoutput.createdjgpp;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_i386_coff_info : tasminfo =
+ (
+ id : as_i386_coff;
+ idtxt : 'COFF';
+ asmbin : '';
+ asmcmd : '';
+ supported_target : system_i386_go32v2;
+ flags : [af_outputbinary];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+ as_i386_pecoff_info : tasminfo =
+ (
+ id : as_i386_pecoff;
+ idtxt : 'PECOFF';
+ asmbin : '';
+ asmcmd : '';
+ supported_target : system_i386_win32;
+ flags : [af_outputbinary];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+ as_i386_pecoffwdosx_info : tasminfo =
+ (
+ id : as_i386_pecoffwdosx;
+ idtxt : 'PEWDOSX';
+ asmbin : '';
+ asmcmd : '';
+ supported_target : system_i386_wdosx;
+ flags : [af_outputbinary];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+ as_i386_pecoffwince_info : tasminfo =
+ (
+ id : as_i386_pecoffwince;
+ idtxt : 'PECOFFWINCE';
+ asmbin : '';
+ asmcmd : '';
+ supported_target : system_i386_wince;
+ flags : [af_outputbinary];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+
+ as_arm_pecoffwince_info : tasminfo =
+ (
+ id : as_arm_pecoffwince;
+ idtxt : 'PECOFFWINCE';
+ asmbin : '';
+ asmcmd : '';
+ supported_target : system_arm_wince;
+ flags : [af_outputbinary];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+initialization
+{$ifdef i386}
+ RegisterAssembler(as_i386_coff_info,TCoffAssembler);
+ RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
+ RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
+ RegisterAssembler(as_i386_pecoffwince_info,TPECoffAssembler);
+{$endif i386}
+{$ifdef arm}
+ RegisterAssembler(as_arm_pecoffwince_info,TPECoffAssembler);
+{$endif arm}
+end.
diff --git a/compiler/ogelf.pas b/compiler/ogelf.pas
new file mode 100644
index 0000000000..175cc3f6bd
--- /dev/null
+++ b/compiler/ogelf.pas
@@ -0,0 +1,886 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Contains the binary elf writer
+
+ * 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 ogelf;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,globtype,
+ { target }
+ systems,
+ { assembler }
+ cpuinfo,cpubase,aasmbase,aasmtai,assemble,
+ { output }
+ ogbase;
+
+ type
+ telf32section = class(TAsmSection)
+ public
+ secshidx : longint; { index for the section in symtab }
+ shstridx,
+ shtype,
+ shflags,
+ shlink,
+ shinfo,
+ entsize : longint;
+ { relocation }
+ relocsect : telf32Section;
+ constructor create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);override;
+ constructor create_ext(const Aname:string;Atype:TAsmSectionType;Ashtype,Ashflags,Ashlink,Ashinfo,Aalign,Aentsize:longint);
+ destructor destroy;override;
+ end;
+
+ telf32objectdata = class(TAsmObjectData)
+ public
+ symtabsect,
+ strtabsect,
+ shstrtabsect,
+ gotpcsect,
+ gotoffsect,
+ goTSect,
+ plTSect,
+ symsect : telf32Section;
+ syms : Tdynamicarray;
+ constructor create(const n:string);
+ destructor destroy;override;
+ function sectionname(atype:tasmsectiontype;const aname:string):string;override;
+ procedure writereloc(data,len:aint;p:tasmsymbol;relative:TAsmRelocationType);override;
+ procedure writesymbol(p:tasmsymbol);override;
+ procedure writestab(offset:aint;ps:tasmsymbol;nidx,nother,line:longint;p:pchar);override;
+ procedure beforealloc;override;
+ procedure beforewrite;override;
+ end;
+
+ telf32objectoutput = class(tobjectoutput)
+ private
+ elf32data : telf32objectdata;
+ initsym : longint;
+ procedure createrelocsection(s:telf32section);
+ procedure createshstrtab;
+ procedure createsymtab;
+ procedure writesectionheader(s:telf32section);
+ procedure writesectiondata(s:telf32section);
+ procedure section_write_symbol(p:tnamedindexitem;arg:pointer);
+ procedure section_write_sh_string(p:tnamedindexitem;arg:pointer);
+ procedure section_number_symbol(p:tnamedindexitem;arg:pointer);
+ procedure section_count_sects(p:tnamedindexitem;arg:pointer);
+ procedure section_create_relocsec(p:tnamedindexitem;arg:pointer);
+ procedure section_set_datapos(p:tnamedindexitem;arg:pointer);
+ procedure section_relocsec_set_datapos(p:tnamedindexitem;arg:pointer);
+ procedure section_write_data(p:tnamedindexitem;arg:pointer);
+ procedure section_write_sechdr(p:tnamedindexitem;arg:pointer);
+ procedure section_write_relocsec(p:tnamedindexitem;arg:pointer);
+ protected
+ function writedata(data:TAsmObjectData):boolean;override;
+ public
+ function newobjectdata(const n:string):TAsmObjectData;override;
+ end;
+
+ telf32assembler = class(tinternalassembler)
+ constructor create(smart:boolean);override;
+ end;
+
+
+implementation
+
+ uses
+ strings,
+ verbose,
+ cutils,globals,fmodule;
+
+ const
+ symbolresize = 200*18;
+
+ const
+ R_386_32 = 1; { ordinary absolute relocation }
+ R_386_PC32 = 2; { PC-relative relocation }
+ R_386_GOT32 = 3; { an offset into GOT }
+ R_386_PLT32 = 4; { a PC-relative offset into PLT }
+ R_386_GOTOFF = 9; { an offset from GOT base }
+ R_386_GOTPC = 10; { a PC-relative offset _to_ GOT }
+
+ SHN_UNDEF = 0;
+ SHN_ABS = $fff1;
+ SHN_COMMON = $fff2;
+
+ SHT_NULL = 0;
+ SHT_PROGBITS = 1;
+ SHT_SYMTAB = 2;
+ SHT_STRTAB = 3;
+ SHT_RELA = 4;
+ SHT_HASH = 5;
+ SHT_DYNAMIC = 6;
+ SHT_NOTE = 7;
+ SHT_NOBITS = 8;
+ SHT_REL = 9;
+ SHT_SHLIB = 10;
+ SHT_DYNSYM = 11;
+
+ SHF_WRITE = 1;
+ SHF_ALLOC = 2;
+ SHF_EXECINSTR = 4;
+
+ STB_LOCAL = 0;
+ STB_GLOBAL = 1;
+ STB_WEAK = 2;
+
+ STT_NOTYPE = 0;
+ STT_OBJECT = 1;
+ STT_FUNC = 2;
+ STT_SECTION = 3;
+ STT_FILE = 4;
+
+ type
+ { Structures which are written directly to the output file }
+ telf32header=packed record
+ magic0123 : longint;
+ file_class : byte;
+ data_encoding : byte;
+ file_version : byte;
+ padding : array[$07..$0f] of byte;
+ e_type : word;
+ e_machine : word;
+ e_version : longint;
+ e_entry : longint; { entrypoint }
+ e_phoff : longint; { program header offset }
+ e_shoff : longint; { sections header offset }
+ e_flags : longint;
+ e_ehsize : word; { elf header size in bytes }
+ e_phentsize : word; { size of an entry in the program header array }
+ e_phnum : word; { 0..e_phnum-1 of entrys }
+ e_shentsize : word; { size of an entry in sections header array }
+ e_shnum : word; { 0..e_shnum-1 of entrys }
+ e_shstrndx : word; { index of string section header }
+ end;
+ telf32sechdr=packed record
+ sh_name : longint;
+ sh_type : longint;
+ sh_flags : longint;
+ sh_addr : longint;
+ sh_offset : longint;
+ sh_size : longint;
+ sh_link : longint;
+ sh_info : longint;
+ sh_addralign : longint;
+ sh_entsize : longint;
+ end;
+ telf32reloc=packed record
+ address : longint;
+ info : longint; { bit 0-7: type, 8-31: symbol }
+ end;
+ telf32symbol=packed record
+ st_name : longint;
+ st_value : longint;
+ st_size : longint;
+ st_info : byte; { bit 0-3: type, 4-7: bind }
+ st_other : byte;
+ st_shndx : word;
+ end;
+ telf32stab=packed record
+ strpos : longint;
+ ntype : byte;
+ nother : byte;
+ ndesc : word;
+ nvalue : longint;
+ end;
+
+
+{****************************************************************************
+ TSection
+****************************************************************************}
+
+ constructor telf32section.create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);
+ var
+ Ashflags,Ashtype,Aentsize : longint;
+ begin
+ Ashflags:=0;
+ Ashtype:=0;
+ Aentsize:=0;
+ case Atype of
+ sec_code :
+ begin
+ Ashflags:=SHF_ALLOC or SHF_EXECINSTR;
+ AshType:=SHT_PROGBITS;
+ AAlign:=max(sizeof(aint),AAlign);
+ end;
+ sec_data :
+ begin
+ Ashflags:=SHF_ALLOC or SHF_WRITE;
+ AshType:=SHT_PROGBITS;
+ AAlign:=max(sizeof(aint),AAlign);
+ end;
+ sec_rodata :
+ begin
+{$warning TODO Remove rodata hack}
+ Ashflags:=SHF_ALLOC or SHF_WRITE;
+ AshType:=SHT_PROGBITS;
+ AAlign:=max(sizeof(aint),AAlign);
+ end;
+ sec_bss,sec_threadvar :
+ begin
+ Ashflags:=SHF_ALLOC or SHF_WRITE;
+ AshType:=SHT_NOBITS;
+ AAlign:=max(sizeof(aint),AAlign);
+ end;
+ sec_stab :
+ begin
+ AshType:=SHT_PROGBITS;
+ AAlign:=max(sizeof(aint),AAlign);
+ Aentsize:=sizeof(telf32stab);
+ end;
+ sec_stabstr :
+ begin
+ AshType:=SHT_STRTAB;
+ AAlign:=1;
+ end;
+ sec_fpc :
+ begin
+ AshFlags:=SHF_ALLOC;
+ AshType:=SHT_PROGBITS ;
+ AAlign:=4;// max(sizeof(aint),AAlign);
+ end;
+ else
+ internalerror(200509122);
+ end;
+ create_ext(Aname,Atype,Ashtype,Ashflags,0,0,Aalign,Aentsize);
+ end;
+
+
+ constructor telf32section.create_ext(const Aname:string;Atype:TAsmSectionType;Ashtype,Ashflags,Ashlink,Ashinfo,Aalign,Aentsize:longint);
+ var
+ aoptions : TAsmSectionOptions;
+ begin
+ aoptions:=[];
+ if (AshType=SHT_NOBITS) then
+ include(aoptions,aso_alloconly);
+ inherited create(Aname,Atype,Aalign,aoptions);
+ secshidx:=0;
+ shstridx:=0;
+ shtype:=AshType;
+ shflags:=AshFlags;
+ shlink:=Ashlink;
+ shinfo:=Ashinfo;
+ entsize:=Aentsize;
+ relocsect:=nil;
+ end;
+
+
+ destructor telf32section.destroy;
+ begin
+ if assigned(relocsect) then
+ relocsect.free;
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ telf32objectdata
+****************************************************************************}
+
+ constructor telf32objectdata.create(const n:string);
+ begin
+ inherited create(n);
+ CAsmSection:=TElf32Section;
+ { reset }
+ Syms:=TDynamicArray.Create(symbolresize);
+ { default sections }
+ symtabsect:=telf32section.create_ext('.symtab',sec_custom,2,0,0,0,4,16);
+ strtabsect:=telf32section.create_ext('.strtab',sec_custom,3,0,0,0,1,0);
+ shstrtabsect:=telf32section.create_ext('.shstrtab',sec_custom,3,0,0,0,1,0);
+ { insert the empty and filename as first in strtab }
+ strtabsect.writestr(#0);
+ strtabsect.writestr(SplitFileName(current_module.mainsource^)+#0);
+ { we need at least the following sections }
+ createsection(sec_code,'',0,[]);
+ createsection(sec_data,'',0,[]);
+ createsection(sec_bss,'',0,[]);
+{$ifdef segment_threadvars}
+ createsection(sec_threadvar,'',0,[]);
+{$endif}
+ { create stabs sections if debugging }
+ if (cs_debuginfo in aktmoduleswitches) then
+ begin
+ stabssec:=createsection(sec_stab,'',0,[]);
+ stabstrsec:=createsection(sec_stabstr,'',0,[]);
+ end;
+ end;
+
+
+ destructor telf32objectdata.destroy;
+ begin
+ Syms.Free;
+ symtabsect.free;
+ strtabsect.free;
+ shstrtabsect.free;
+ inherited destroy;
+ end;
+
+
+ function telf32objectdata.sectionname(atype:tasmsectiontype;const aname:string):string;
+ const
+ secnames : array[tasmsectiontype] of string[12] = ('',
+{$ifdef userodata}
+ '.text','.data','.rodata','.bss','.threadvar',
+{$else userodata}
+ '.text','.data','.data','.bss','.threadvar',
+{$endif userodata}
+ 'common',
+ '.note',
+ '.text', { darwin stubs }
+ '.stab','.stabstr',
+ '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
+ '.eh_frame',
+ '.debug_frame',
+ 'fpc'
+ );
+ begin
+ if (use_smartlink_section and
+ (aname<>'')) or (atype=sec_fpc) then
+ result:=secnames[atype]+'.'+aname
+ else
+ result:=secnames[atype];
+ end;
+
+
+ procedure telf32objectdata.writesymbol(p:tasmsymbol);
+ begin
+ if currsec=nil then
+ internalerror(200403291);
+ { already written ? }
+ if p.indexnr<>-1 then
+ exit;
+ { calculate symbol index }
+ if (p.currbind<>AB_LOCAL) then
+ begin
+ { insert the symbol in the local index, the indexarray
+ will take care of the numbering }
+ symbols.insert(p);
+ end
+ else
+ p.indexnr:=-2; { local }
+ end;
+
+
+ procedure telf32objectdata.writereloc(data,len:aint;p:tasmsymbol;relative:TAsmRelocationType);
+ var
+ symaddr : longint;
+ begin
+ if currsec=nil then
+ internalerror(200403292);
+{$ifdef userodata}
+ if currsec.sectype in [sec_rodata,sec_bss,sec_threadvar] then
+ internalerror(200408252);
+{$endif userodata}
+ if assigned(p) then
+ begin
+ { real address of the symbol }
+ symaddr:=p.address;
+ { Local symbols can be resolved already or need a section reloc }
+ if (p.currbind=AB_LOCAL) then
+ begin
+ { For a relative relocation in the same section the
+ value can be calculated }
+ if (p.section=currsec) and
+ (relative=RELOC_RELATIVE) then
+ inc(data,symaddr-len-currsec.datasize)
+ else
+ begin
+ currsec.addsectionreloc(currsec.datasize,p.section,relative);
+ inc(data,symaddr);
+ end;
+ end
+ else
+ begin
+ writesymbol(p);
+ currsec.addsymreloc(currsec.datasize,p,relative);
+ if relative=RELOC_RELATIVE then
+ dec(data,len);
+ end;
+ end;
+ currsec.write(data,len);
+ end;
+
+
+ procedure telf32objectdata.writestab(offset:aint;ps:tasmsymbol;nidx,nother,line:longint;p:pchar);
+ var
+ stab : telf32stab;
+ begin
+ fillchar(stab,sizeof(telf32stab),0);
+ if assigned(p) and (p[0]<>#0) then
+ begin
+ stab.strpos:=stabstrsec.datasize;
+ stabstrsec.write(p^,strlen(p)+1);
+ end;
+ stab.ntype:=nidx;
+ stab.ndesc:=line;
+ stab.nother:=nother;
+ stab.nvalue:=offset;
+ stabssec.write(stab,sizeof(stab));
+ if assigned(ps) then
+ begin
+ writesymbol(ps);
+ stabssec.addsymreloc(stabssec.datasize-4,ps,RELOC_ABSOLUTE);
+ end;
+ end;
+
+
+ procedure telf32objectdata.beforealloc;
+ begin
+ { create stabs sections if debugging }
+ if (cs_debuginfo in aktmoduleswitches) then
+ begin
+ StabsSec.Alloc(sizeof(telf32stab));
+ StabStrSec.Alloc(length(SplitFileName(current_module.mainsource^))+2);
+ end;
+ end;
+
+
+ procedure telf32objectdata.beforewrite;
+ var
+ s : string;
+ begin
+ { create stabs sections if debugging }
+ if (cs_debuginfo in aktmoduleswitches) then
+ begin
+ writestab(0,nil,0,0,0,nil);
+ { write zero pchar and name together (PM) }
+ s:=#0+SplitFileName(current_module.mainsource^)+#0;
+ stabstrsec.write(s[1],length(s));
+ end;
+ end;
+
+
+{****************************************************************************
+ telf32objectoutput
+****************************************************************************}
+
+ function telf32objectoutput.newobjectdata(const n:string):TAsmObjectData;
+ begin
+ result:=telf32objectdata.create(n);
+ end;
+
+
+ procedure telf32objectoutput.createrelocsection(s:telf32section);
+ var
+ rel : telf32reloc;
+ r : tasmrelocation;
+ relsym,reltyp : longint;
+ begin
+ with elf32data do
+ begin
+{$ifdef userodata}
+ { rodata can't have relocations }
+ if s.sectype=sec_rodata then
+ begin
+ if assigned(s.relocations.first) then
+ internalerror(200408251);
+ exit;
+ end;
+{$endif userodata}
+ { create the reloc section }
+ s.relocsect:=telf32section.create_ext('.rel'+s.name,sec_custom,9,0,symtabsect.secshidx,s.secshidx,4,8);
+ { add the relocations }
+ r:=TasmRelocation(s.relocations.first);
+ while assigned(r) do
+ begin
+ rel.address:=r.address;
+ if assigned(r.symbol) then
+ begin
+ if (r.symbol.currbind=AB_LOCAL) then
+ relsym:=r.symbol.section.secsymidx
+ else
+ begin
+ if r.symbol.indexnr=-1 then
+ internalerror(4321);
+ { indexnr starts with 1, ELF starts with 0 }
+ relsym:=r.symbol.indexnr+initsym-1;
+ end;
+ end
+ else
+ if r.section<>nil then
+ relsym:=r.section.secsymidx
+ else
+ relsym:=SHN_UNDEF;
+ case r.typ of
+ RELOC_RELATIVE :
+ reltyp:=R_386_PC32;
+ RELOC_ABSOLUTE :
+ reltyp:=R_386_32;
+ end;
+ rel.info:=(relsym shl 8) or reltyp;
+ { write reloc }
+ s.relocsect.write(rel,sizeof(rel));
+ r:=TAsmRelocation(r.next);
+ end;
+ end;
+ end;
+
+
+ procedure telf32objectoutput.section_write_symbol(p:tnamedindexitem;arg:pointer);
+ var
+ elfsym : telf32symbol;
+ begin
+ fillchar(elfsym,sizeof(elfsym),0);
+ elfsym.st_name:=telf32section(p).shstridx;
+ elfsym.st_info:=STT_SECTION;
+ elfsym.st_shndx:=telf32section(p).secshidx;
+ elf32data.symtabsect.write(elfsym,sizeof(elfsym));
+ { increase locals count }
+ inc(plongint(arg)^);
+ end;
+
+
+ procedure telf32objectoutput.createsymtab;
+ var
+ elfsym : telf32symbol;
+ locals : longint;
+ sym : tasmsymbol;
+ begin
+ with elf32data do
+ begin
+ locals:=2;
+ { empty entry }
+ fillchar(elfsym,sizeof(elfsym),0);
+ symtabsect.write(elfsym,sizeof(elfsym));
+ { filename entry }
+ elfsym.st_name:=1;
+ elfsym.st_info:=STT_FILE;
+ elfsym.st_shndx:=SHN_ABS;
+ symtabsect.write(elfsym,sizeof(elfsym));
+ { section }
+ sects.foreach(@section_write_symbol,@locals);
+ { symbols }
+ sym:=Tasmsymbol(symbols.First);
+ while assigned(sym) do
+ begin
+ fillchar(elfsym,sizeof(elfsym),0);
+ { symbolname, write the #0 separate to overcome 255+1 char not possible }
+ elfsym.st_name:=strtabsect.datasize;
+ strtabsect.writestr(sym.name);
+ strtabsect.writestr(#0);
+ case sym.currbind of
+ AB_LOCAL,
+ AB_GLOBAL :
+ elfsym.st_value:=sym.address;
+ AB_COMMON :
+ elfsym.st_value:=$10;
+ end;
+ elfsym.st_size:=sym.size;
+ case sym.currbind of
+ AB_LOCAL :
+ begin
+ elfsym.st_info:=STB_LOCAL shl 4;
+ inc(locals);
+ end;
+ AB_COMMON,
+ AB_EXTERNAL,
+ AB_GLOBAL :
+ elfsym.st_info:=STB_GLOBAL shl 4;
+ end;
+ if (sym.currbind<>AB_EXTERNAL) and
+ not(assigned(sym.section) and
+ (sym.section.sectype=sec_bss)) then
+ begin
+ case sym.typ of
+ AT_FUNCTION :
+ elfsym.st_info:=elfsym.st_info or STT_FUNC;
+ AT_DATA :
+ elfsym.st_info:=elfsym.st_info or STT_OBJECT;
+ end;
+ end;
+ if sym.currbind=AB_COMMON then
+ elfsym.st_shndx:=SHN_COMMON
+ else
+ if assigned(sym.section) then
+ elfsym.st_shndx:=telf32section(sym.section).secshidx
+ else
+ elfsym.st_shndx:=SHN_UNDEF;
+ symtabsect.write(elfsym,sizeof(elfsym));
+ sym:=tasmsymbol(sym.indexnext);
+ end;
+ { update the .symtab section header }
+ symtabsect.shlink:=strtabsect.secshidx;
+ symtabsect.shinfo:=locals;
+ end;
+ end;
+
+
+ procedure telf32objectoutput.section_write_sh_string(p:tnamedindexitem;arg:pointer);
+ begin
+ telf32section(p).shstridx:=elf32data.shstrtabsect.writestr(tasmsection(p).name+#0);
+ if assigned(telf32section(p).relocsect) then
+ telf32section(p).relocsect.shstridx:=elf32data.shstrtabsect.writestr(telf32section(p).relocsect.name+#0);
+ end;
+
+
+ procedure telf32objectoutput.createshstrtab;
+ begin
+ with elf32data do
+ begin
+ with shstrtabsect do
+ begin
+ writestr(#0);
+ symtabsect.shstridx:=writestr('.symtab'#0);
+ strtabsect.shstridx:=writestr('.strtab'#0);
+ shstrtabsect.shstridx:=writestr('.shstrtab'#0);
+ sects.foreach(@section_write_sh_string,nil);
+ end;
+ end;
+ end;
+
+
+ procedure telf32objectoutput.writesectionheader(s:telf32section);
+ var
+ sechdr : telf32sechdr;
+ begin
+ fillchar(sechdr,sizeof(sechdr),0);
+ sechdr.sh_name:=s.shstridx;
+ sechdr.sh_type:=s.shtype;
+ sechdr.sh_flags:=s.shflags;
+ sechdr.sh_offset:=s.datapos;
+ sechdr.sh_size:=s.datasize;
+ sechdr.sh_link:=s.shlink;
+ sechdr.sh_info:=s.shinfo;
+ sechdr.sh_addralign:=s.addralign;
+ sechdr.sh_entsize:=s.entsize;
+ writer.write(sechdr,sizeof(sechdr));
+ end;
+
+
+
+ procedure telf32objectoutput.writesectiondata(s:telf32section);
+ var
+ hp : pdynamicblock;
+ begin
+ FWriter.writezeros(s.dataalignbytes);
+ s.alignsection;
+ hp:=s.data.firstblock;
+ while assigned(hp) do
+ begin
+ FWriter.write(hp^.data,hp^.used);
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure telf32objectoutput.section_number_symbol(p:tnamedindexitem;arg:pointer);
+ begin
+ tasmsection(p).secsymidx:=plongint(arg)^;
+ inc(plongint(arg)^);
+ end;
+
+
+ procedure telf32objectoutput.section_count_sects(p:tnamedindexitem;arg:pointer);
+ begin
+ telf32section(p).secshidx:=plongint(arg)^;
+ inc(plongint(arg)^);
+ if telf32section(p).relocations.count>0 then
+ inc(plongint(arg)^);
+ end;
+
+
+ procedure telf32objectoutput.section_create_relocsec(p:tnamedindexitem;arg:pointer);
+ begin
+ if (telf32section(p).relocations.count>0) then
+ createrelocsection(telf32section(p));
+ end;
+
+
+ procedure telf32objectoutput.section_set_datapos(p:tnamedindexitem;arg:pointer);
+ begin
+ if (aso_alloconly in tasmsection(p).secoptions) then
+ tasmsection(p).datapos:=paint(arg)^
+ else
+ tasmsection(p).setdatapos(paint(arg)^);
+ end;
+
+
+ procedure telf32objectoutput.section_relocsec_set_datapos(p:tnamedindexitem;arg:pointer);
+ begin
+ if assigned(telf32section(p).relocsect) then
+ telf32section(p).relocsect.setdatapos(paint(arg)^);
+ end;
+
+
+ procedure telf32objectoutput.section_write_data(p:tnamedindexitem;arg:pointer);
+ begin
+ if (aso_alloconly in tasmsection(p).secoptions) then
+ exit;
+ if tasmsection(p).data=nil then
+ internalerror(200403073);
+ writesectiondata(telf32section(p));
+ end;
+
+
+ procedure telf32objectoutput.section_write_sechdr(p:tnamedindexitem;arg:pointer);
+ begin
+ writesectionheader(telf32section(p));
+ if assigned(telf32section(p).relocsect) then
+ writesectionheader(telf32section(p).relocsect);
+ end;
+
+
+ procedure telf32objectoutput.section_write_relocsec(p:tnamedindexitem;arg:pointer);
+ begin
+ if assigned(telf32section(p).relocsect) then
+ writesectiondata(telf32section(p).relocsect);
+ end;
+
+
+
+ function telf32objectoutput.writedata(data:TAsmObjectData):boolean;
+ var
+ header : telf32header;
+ datapos : aint;
+ shoffset,
+ nsects : longint;
+ hstab : telf32stab;
+ empty : array[0..63] of byte;
+ begin
+ result:=false;
+ elf32data:=telf32objectdata(data);
+ with elf32data do
+ begin
+ { calc amount of sections we have }
+ initsym:=2;
+ nsects:=1;
+ fillchar(empty,sizeof(empty),0);
+ { each section requires a symbol for relocation }
+ sects.foreach(@section_number_symbol,@initsym);
+ { also create the index in the section header table }
+ sects.foreach(@section_count_sects,@nsects);
+ { add default sections follows }
+ shstrtabsect.secshidx:=nsects;
+ inc(nsects);
+ symtabsect.secshidx:=nsects;
+ inc(nsects);
+ strtabsect.secshidx:=nsects;
+ inc(nsects);
+ { For the stab section we need an HdrSym which can now be
+ calculated more easily }
+ if assigned(stabssec) then
+ begin
+ hstab.strpos:=1;
+ hstab.ntype:=0;
+ hstab.nother:=0;
+ hstab.ndesc:=(stabssec.datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
+ hstab.nvalue:=stabstrsec.datasize;
+ stabssec.Data.seek(0);
+ stabssec.Data.write(hstab,sizeof(hstab));
+ end;
+ { Create the relocation sections }
+ sects.foreach(@section_create_relocsec,nil);
+ { create .symtab and .strtab }
+ createsymtab;
+ { create .shstrtab }
+ createshstrtab;
+ { Calculate the filepositions }
+ datapos:=$40; { elfheader + alignment }
+ { sections first }
+ sects.foreach(@section_set_datapos,@datapos);
+ { shstrtab }
+ shstrtabsect.setdatapos(datapos);
+ { section headers }
+ shoffset:=datapos;
+ inc(datapos,nsects*sizeof(telf32sechdr));
+ { symtab }
+ symtabsect.setdatapos(datapos);
+ { strtab }
+ strtabsect.setdatapos(datapos);
+ { .rel sections }
+ sects.foreach(@section_relocsec_set_datapos,@datapos);
+ { Write ELF Header }
+ fillchar(header,sizeof(header),0);
+ header.magic0123:=$464c457f; { = #127'ELF' }
+ header.file_class:=1;
+ header.data_encoding:=1;
+ header.file_version:=1;
+ header.e_type:=1;
+ header.e_machine:=3;
+ header.e_version:=1;
+ header.e_shoff:=shoffset;
+ header.e_shstrndx:=shstrtabsect.secshidx;
+ header.e_shnum:=nsects;
+ header.e_ehsize:=sizeof(telf32header);
+ header.e_shentsize:=sizeof(telf32sechdr);
+ writer.write(header,sizeof(header));
+ writer.write(empty,$40-sizeof(header)); { align }
+ { Sections }
+ sects.foreach(@section_write_data,nil);
+ { .shstrtab }
+ writesectiondata(shstrtabsect);
+ { section headers, start with an empty header for sh_undef }
+ writer.write(empty,sizeof(telf32sechdr));
+ sects.foreach(@section_write_sechdr,nil);
+ writesectionheader(shstrtabsect);
+ writesectionheader(symtabsect);
+ writesectionheader(strtabsect);
+ { .symtab }
+ writesectiondata(symtabsect);
+ { .strtab }
+ writesectiondata(strtabsect);
+ { .rel sections }
+ sects.foreach(@section_write_relocsec,nil);
+ end;
+ result:=true;
+ end;
+
+
+{****************************************************************************
+ TELFAssembler
+****************************************************************************}
+
+ constructor TELF32Assembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ objectoutput:=telf32objectoutput.create(smart);
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_i386_elf32_info : tasminfo =
+ (
+ id : as_i386_elf32;
+ idtxt : 'ELF';
+ asmbin : '';
+ asmcmd : '';
+ supported_target : system_any; //target_i386_linux;
+ flags : [af_outputbinary,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+
+initialization
+ RegisterAssembler(as_i386_elf32_info,TElf32Assembler);
+end.
diff --git a/compiler/oglx.pas b/compiler/oglx.pas
new file mode 100644
index 0000000000..5168aa602e
--- /dev/null
+++ b/compiler/oglx.pas
@@ -0,0 +1,394 @@
+{
+ Copyright (c) 2002 by Daniel Mantione, Peter Vreman
+
+ Contains the binary reader and writer for the linear executable
+ format used by OS/2
+
+ * 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 oglx;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ { common }
+ cclasses,
+ { target }
+ systems,
+ { assembler }
+ cpubase,aasmbase,assemble,link,
+ { output }
+ ogbase,ogmap,ogcoff;
+
+{ An LX executable is called a module; it can be either an executable
+ or a DLL.
+
+ A module consists of objects. In other executable formats, these
+ are usually called sections.
+
+ Objects consist of pages.
+
+ The objects are numbered, numbers do not have any special meaning. The
+ pages of the object are loaded into memory with the access rights specified
+ the object table entry. (DM)}
+
+
+{ For the operating system the object numbers have no special meaning.
+ However, for Free Pascal generated executables, I define: (DM)}
+
+const code_object = 0;
+ data_object = 1;
+ bss_object = 2;
+ stack_object = 3;
+ heap_object = 4;
+
+type Tlxheader = packed record
+ magic:word; {'LX'}
+ byteorder:byte; {0 = little 1 = big endian.}
+ wordorder:byte; {0 = little 1 = big endian.}
+ format_level:cardinal; {Nothing else than LX level
+ 0 has ever been defined.}
+ cpu_type:word; {1 = 286, 2 = 386, 3 = 486,
+ 4 = pentium.}
+ os_type:word; {1 = OS/2, 2 = Windows,
+ 3 = Siemens MS-Dos 4.0,
+ 4 = Windows 386.}
+ module_version:cardinal; {Version of executable,
+ defined by user.}
+ module_flags:cardinal; {Flags.}
+ module_page_count:cardinal; {Amount of pages in module.}
+ eip_object,eip:cardinal; {Initial EIP, object nr and
+ offset within object.}
+ esp_object,esp:cardinal; {Initial ESP, object nr and
+ offset within object.}
+ page_size,page_shift:cardinal; {Page size, in bytes and
+ 1 << pageshift.}
+ fixup_sect_size:cardinal;
+ fixup_sect_checksum:cardinal;
+ loader_sect_size:cardinal;
+ loader_sect_chksum:cardinal;
+ object_table_offset:cardinal; {Location of object table.}
+ object_count:cardinal; {Amount of objects in module.}
+ object_pagetable_ofs:cardinal; {Location of object page
+ table.}
+ object_iterpages_ofs:cardinal;
+ resource_table_ofs:cardinal; {Location of resource table.}
+ resource_count:cardinal; {Amount of resources in
+ resource table.}
+ resid_name_tbl_ofs:cardinal;
+ entry_table_offset:cardinal;
+ module_dir_offset:cardinal;
+ module_dir_count:cardinal;
+ fixup_pagetab_ofs:cardinal;
+ fixup_recrab_ofs:cardinal;
+ import_modtab_ofs:cardinal;
+ import_modtab_count:cardinal;
+ data_pages_offset:cardinal;
+ preload_page_count:cardinal;
+ nonresid_table_ofs:cardinal;
+ nonresid_table_len:cardinal;
+ nonresid_tbl_chksum:cardinal;
+ auto_ds_object_no:cardinal; {Not used by OS/2.}
+ debug_info_offset:cardinal;
+ inst_preload_count:cardinal;
+ inst_demand_count:cardinal;
+ heapsize:cardinal; {Only used for 16-bit programs.}
+ end;
+
+ Tlxobject_flags = (ofreadable,ofwriteable,ofexecutable,ofresource,
+ ofdiscardable,ofshared,ofpreload,ofinvalid,
+ ofzerofilled);
+ Tlxobject_flag_set = set of Tlxobject_flags;
+
+ Tlxobject_table_entry = packed record
+ virtual_size:cardinal;
+ reloc_base_addr:cardinal;
+ object_flags:Tlxobject_flag_set;
+ page_table_index:cardinal;
+ page_count:cardinal;
+ reserved:cardinal;
+ end;
+
+ Tlxexeoutput = class(texeoutput)
+ private
+{ FCoffsyms,
+ FCoffStrs : tdynamicarray;
+ win32 : boolean;}
+ nsects,
+ nsyms,
+ sympos : longint;
+ procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
+ procedure write_symbols;
+ protected
+ function writedata:boolean;override;
+ public
+ constructor createos2;
+ function newobjectinput:tobjectinput;override;
+ procedure CalculateMemoryMap;override;
+ procedure GenerateExecutable(const fn:string);override;
+ end;
+
+ Tlxlinker = class(tinternallinker)
+ constructor create;override;
+ end;
+
+
+implementation
+
+uses
+ strings,
+ cutils,verbose,
+ globtype,globals,fmodule;
+
+
+{****************************************************************************
+ tcoffexeoutput
+****************************************************************************}
+
+ constructor Tlxexeoutput.createos2;
+ begin
+ inherited create;
+ end;
+
+
+ function Tlxexeoutput.newobjectinput:tobjectinput;
+ begin
+ result:=tcoffobjectinput.createdjgpp;
+ end;
+
+
+ procedure Tlxexeoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
+{ var
+ sym : coffsymbol;}
+ begin
+{ FillChar(sym,sizeof(sym),0);
+ if strpos=-1 then
+ move(name[1],sym.name,length(name))
+ else
+ sym.strpos:=strpos;
+ sym.value:=value;
+ sym.section:=section;
+ sym.typ:=typ;
+ sym.aux:=aux;
+ FWriter.write(sym,sizeof(sym));}
+ end;
+
+
+ procedure Tlxexeoutput.write_symbols;
+{ var
+ filename : string[18];
+ sec : TSection;
+ namestr : string[8];
+ nameidx,
+ value,
+ sectionval,
+ i : longint;
+ globalval : byte;
+ secrec : coffsectionrec;
+ objdata : TAsmObjectData;
+ p : tasmsymbol;
+ s : string;}
+ begin
+(* objdata:=TAsmObjectData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ with tcoffobjectdata(objdata) do
+ begin
+ { The symbols used }
+ p:=Tasmsymbol(symbols.First);
+ while assigned(p) do
+ begin
+ if p.section=sec_common then
+ sectionval:=sections[sec_bss].secsymidx
+ else
+ sectionval:=sections[p.section].secsymidx;
+ if p.currbind=AB_LOCAL then
+ globalval:=3
+ else
+ globalval:=2;
+ { if local of global then set the section value to the address
+ of the symbol }
+ if p.currbind in [AB_LOCAL,AB_GLOBAL] then
+ value:=p.address
+ else
+ value:=p.size;
+ { symbolname }
+ s:=p.name;
+ if length(s)>8 then
+ begin
+ nameidx:=FCoffStrs.size+4;
+ FCoffStrs.writestr(s);
+ FCoffStrs.writestr(#0);
+ end
+ else
+ begin
+ nameidx:=-1;
+ namestr:=s;
+ end;
+ write_symbol(namestr,nameidx,value,sectionval,globalval,0);
+ p:=tasmsymbol(p.indexnext);
+ end;
+ end;
+ objdata:=TAsmObjectData(objdata.next);
+ end;*)
+ end;
+
+
+ procedure Tlxexeoutput.CalculateMemoryMap;
+{ var
+ objdata : TAsmObjectData;
+ secsymidx,
+ mempos,
+ datapos : longint;
+ sec : TSection;
+ sym : tasmsymbol;
+ s : TAsmSection;}
+ begin
+(* { retrieve amount of sections }
+ nsects:=0;
+ secsymidx:=0;
+ for sec:=low(TSection) to high(TSection) do
+ begin
+ if sections[sec].available then
+ begin
+ inc(nsects);
+ inc(secsymidx);
+ sections[sec].secsymidx:=secsymidx;
+ end;
+ end;
+ { calculate start positions after the headers }
+ datapos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
+ mempos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
+ if not win32 then
+ inc(mempos,sizeof(go32v2stub)+$1000);
+ { add sections }
+ MapObjectdata(datapos,mempos);
+ { end symbol }
+ AddGlobalSym('_etext',sections[sec_code].mempos+sections[sec_code].memsize);
+ AddGlobalSym('_edata',sections[sec_data].mempos+sections[sec_data].memsize);
+ AddGlobalSym('end',mempos);
+ { symbols }
+ nsyms:=0;
+ sympos:=0;
+ if not(cs_link_strip in aktglobalswitches) then
+ begin
+ sympos:=datapos;
+ objdata:=TAsmObjectData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ inc(nsyms,objdata.symbols.count);
+ objdata:=TAsmObjectData(objdata.next);
+ end;
+ end;*)
+ end;
+
+function gen_section_header(sec:Tsection;obj:cardinal):Tlxobject_table_entry;
+ virtual_size:cardinal;
+ reloc_base_addr:cardinal;
+ object_flags:Tlxobject_flag_set;
+ page_table_index:cardinal;
+ page_count:cardinal;
+ reserved:cardinal;
+
+begin
+ gen_section_header.virtual_size:=sections[sec.memsize];
+
+end;
+
+function Tlxexeoutput.writedata:boolean;
+
+var header:Tlxheader;
+ hsym:Tasmsymbol;
+ code_object_header,data_object_header,bss_object_header,stack_object_header,
+ heap_object_header:Tlxobject_table_entry;
+
+
+begin
+ result:=false;
+ fillchar(header,sizeof(header),0);
+ header.magic:=$584c; {'LX'}
+ header.cpu_type:=2; {Intel 386}
+ header.os_type:=1; {OS/2}
+ {Set the initial EIP.}
+ header.eip_object:=code_object;
+ hsym:=tasmsymbol(globalsyms.search('start'));
+ if not assigned(hsym) then
+ begin
+ comment(V_Error,'Entrypoint "start" not defined');
+ exit;
+ end;
+ header.eip:=hsym.address-sections[sec_code].mempos;
+ {Set the initial ESP.}
+ header.esp_object:=stack_object;
+ header.esp:=stacksize;
+ Fwriter.write(header,sizeof(header));
+ for sec:=low(Tsection) to high(Tsection) do
+ if sections[sec].available then
+ if not(sec in [sec_code,sec_data,sec_bss,sec_stab,sec_stabstr]) then
+ begin
+ result:=false;
+ exit;
+ end;
+ code_object_header:=gen_section_header(sec_code,code_object);
+ data_object_header:=gen_section_header(sec_data,data_object);
+ bss_object_header:=gen_section_header(sec_bss,bss_object);
+ result:=true;
+end;
+
+
+ procedure Tlxexeoutput.GenerateExecutable(const fn:string);
+ begin
+{ AddGlobalSym('_etext',0);
+ AddGlobalSym('_edata',0);
+ AddGlobalSym('end',0);
+ if not CalculateSymbols then
+ exit;
+ CalculateMemoryMap;
+ FixupSymbols;
+ FixupRelocations;
+ writeexefile(fn);}
+ end;
+
+{****************************************************************************
+ TCoffLinker
+****************************************************************************}
+
+ constructor Tlxlinker.Create;
+ begin
+ inherited Create;
+ exeoutput:=Tlxexeoutput.createos2;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+
+begin
+{ RegisterAssembler(as_i386_coff_info,TCoffAssembler);
+ RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
+ RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
+
+ RegisterLinker(ld_i386_coff,Tlxlinker);}
+end.
diff --git a/compiler/ogmap.pas b/compiler/ogmap.pas
new file mode 100644
index 0000000000..bf73c5e7f5
--- /dev/null
+++ b/compiler/ogmap.pas
@@ -0,0 +1,137 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Contains the class for generating a map file
+
+ 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 ogmap;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,systems,
+ { object writer }
+ aasmbase,ogbase
+ ;
+
+ type
+ texemap = class
+ private
+ t : text;
+ public
+ constructor Create(const s:string);
+ destructor Destroy;override;
+ procedure Add(const s:string);
+ procedure AddCommonSymbolsHeader;
+ procedure AddCommonSymbol(p:tasmsymbol);
+ procedure AddMemoryMapHeader;
+ procedure AddMemoryMapExeSection(p:texesection);
+ procedure AddMemoryMapObjectSection(p:TAsmSection);
+ procedure AddMemoryMapSymbol(p:tasmsymbol);
+ end;
+
+ var
+ exemap : texemap;
+
+
+implementation
+
+ uses
+ cutils,globals,verbose;
+
+
+{****************************************************************************
+ TExeMap
+****************************************************************************}
+
+ constructor TExeMap.Create(const s:string);
+ begin
+ Assign(t,FixFileName(s));
+ Rewrite(t);
+ end;
+
+
+ destructor TExeMap.Destroy;
+ begin
+ Close(t);
+ end;
+
+
+ procedure TExeMap.Add(const s:string);
+ begin
+ writeln(t,s);
+ end;
+
+
+ procedure TExeMap.AddCommonSymbolsHeader;
+ begin
+ writeln(t,'');
+ writeln(t,'Allocating common symbols');
+ writeln(t,'Common symbol size file');
+ writeln(t,'');
+ end;
+
+
+ procedure TExeMap.AddCommonSymbol(p:tasmsymbol);
+ var
+ s : string;
+ begin
+ { Common symbol size file }
+ s:=p.name;
+ if length(s)>20 then
+ begin
+ writeln(t,p.name);
+ s:='';
+ end;
+ writeln(t,PadSpace(s,20)+'0x'+PadSpace(hexstr(p.size,1),16)+p.owner.name);
+ end;
+
+
+ procedure TExeMap.AddMemoryMapHeader;
+ begin
+ writeln(t,'');
+ writeln(t,'Memory map');
+ writeln(t,'');
+ end;
+
+
+ procedure TExeMap.AddMemoryMapExeSection(p:texesection);
+ begin
+ { .text 0x000018a8 0xd958 }
+ writeln(t,PadSpace(p.name,18)+PadSpace('0x'+HexStr(p.mempos,8),15)+'0x'+HexStr(p.memsize,1));
+ end;
+
+
+ procedure TExeMap.AddMemoryMapObjectSection(p:TAsmSection);
+ begin
+ { .text 0x000018a8 0xd958 object.o }
+ writeln(t,' '+PadSpace(p.name,17)+PadSpace('0x'+HexStr(p.mempos,8),16)+
+ '0x'+HexStr(p.memsize,1)+' '+p.owner.name);
+ end;
+
+
+ procedure TExeMap.AddMemoryMapSymbol(p:tasmsymbol);
+ begin
+ { 0x00001e30 setup_screens }
+ writeln(t,Space(18)+PadSpace('0x'+HexStr(p.address,8),26)+p.name);
+ end;
+
+end.
diff --git a/compiler/optcse.pas b/compiler/optcse.pas
new file mode 100644
index 0000000000..9eaecd8290
--- /dev/null
+++ b/compiler/optcse.pas
@@ -0,0 +1,79 @@
+{
+ Common subexpression elimination on base blocks
+
+ Copyright (c) 2005 by Florian Klaempfl
+
+ 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 optcse;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ procedure docse(rootnode : tnode);
+
+ implementation
+
+ procedure docse(rootnode : tnode);
+ begin
+ { create a linear list of nodes }
+
+ { create hash values }
+
+ { sort by hash values, taking care of nf_csebarrier and keeping the
+ original order of the nodes }
+
+ { compare nodes with equal hash values }
+
+ { search barrier }
+ for i:=0 to nodelist.length-1 do
+ begin
+ { and then search backward so we get always the largest equal trees }
+ j:=i+1;
+ { collect equal nodes }
+ while (j<=nodelist.length-1) and
+ nodelist[i].docompare(nodelist[j]) do
+ inc(j);
+ dec(j);
+ if j>i then
+ begin
+ { cse found }
+
+ { create temp. location }
+
+ { replace first node by
+ - temp. creation
+ - expression calculation
+ - assignment of expression to temp. }
+ tempnode:=ctempcreatenode.create(nodelist[i].resulttype,nodelist[i].resulttype.def.size,tt_persistent,
+ nodelist[i].resulttype.def.is_intregable or nodelist[i].resulttype.def.is_fpuregable);
+ addstatement(createstatement,tempnode);
+ addstatement(createstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
+ caddrnode.create_internal(para.left)));
+ para.left := ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),para.left.resulttype);
+ addstatement(deletestatement,ctempdeletenode.create(tempnode));
+
+ { replace next nodes by loading the temp. reference }
+
+ { replace last node by loading the temp. reference and
+ delete the temp. }
+ end;
+ end;
+ end;
+
+end.
diff --git a/compiler/options.pas b/compiler/options.pas
new file mode 100644
index 0000000000..ade924bce2
--- /dev/null
+++ b/compiler/options.pas
@@ -0,0 +1,2138 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Reads command line options and config files
+
+ 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 options;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,globals,verbose,systems,cpuinfo;
+
+type
+ TOption=class
+ FirstPass,
+ ParaLogo,
+ NoPressEnter,
+ LogoWritten : boolean;
+ FileLevel : longint;
+ QuickInfo : string;
+ ParaIncludePath,
+ ParaUnitPath,
+ ParaObjectPath,
+ ParaLibraryPath : TSearchPathList;
+ ParaAlignment : TAlignmentInfo;
+ Constructor Create;
+ Destructor Destroy;override;
+ procedure WriteLogo;
+ procedure WriteInfo;
+ procedure WriteHelpPages;
+ procedure WriteQuickInfo;
+ procedure IllegalPara(const opt:string);
+ function Unsetbool(var Opts:string; Pos: Longint):boolean;
+ procedure interpret_proc_specific_options(const opt:string);virtual;
+ procedure interpret_option(const opt :string;ispara:boolean);
+ procedure Interpret_envvar(const envname : string);
+ procedure Interpret_file(const filename : string);
+ procedure Read_Parameters;
+ procedure parsecmd(cmd:string);
+ procedure TargetDefines(def:boolean);
+ end;
+
+ TOptionClass=class of toption;
+
+var
+ coption : TOptionClass;
+
+procedure read_arguments(cmd:string);
+
+
+implementation
+
+uses
+ widestr,
+{$IFDEF USE_SYSUTILS}
+ SysUtils,
+{$ELSE USE_SYSUTILS}
+ dos,
+{$ENDIF USE_SYSUTILS}
+ version,
+ cutils,cmsgs,
+ comphook,
+ symtable,scanner
+{$ifdef BrowserLog}
+ ,browlog
+{$endif BrowserLog}
+ ;
+
+const
+ page_size = 24;
+
+var
+ option : toption;
+ read_configfile, { read config file, set when a cfgfile is found }
+ disable_configfile : boolean;
+ fpcdir,
+ ppccfg,
+ ppcaltcfg,
+ param_file : string; { file to compile specified on the commandline }
+
+{****************************************************************************
+ Defines
+****************************************************************************}
+
+procedure set_default_link_type;
+begin
+ { win32 and wdosx need smartlinking by default to prevent including too much
+ dll dependencies }
+ if (target_info.system in [system_i386_win32,system_i386_wdosx]) then
+ begin
+ def_system_macro('FPC_LINK_SMART');
+ undef_system_macro('FPC_LINK_STATIC');
+ undef_system_macro('FPC_LINK_DYNAMIC');
+ initglobalswitches:=initglobalswitches+[cs_link_smart];
+ initglobalswitches:=initglobalswitches-[cs_link_shared,cs_link_static];
+ end
+ else
+ begin
+ undef_system_macro('FPC_LINK_SMART');
+ def_system_macro('FPC_LINK_STATIC');
+ undef_system_macro('FPC_LINK_DYNAMIC');
+ initglobalswitches:=initglobalswitches+[cs_link_static];
+ initglobalswitches:=initglobalswitches-[cs_link_shared,cs_link_smart];
+ end;
+end;
+
+
+
+{****************************************************************************
+ Toption
+****************************************************************************}
+
+procedure StopOptions(err:longint);
+begin
+ if assigned(Option) then
+ begin
+ Option.free;
+ Option:=nil;
+ end;
+ raise ECompilerAbortSilent.Create;
+end;
+
+
+procedure Toption.WriteLogo;
+var
+ p : pchar;
+begin
+ if not LogoWritten then
+ begin
+ p:=MessagePchar(option_logo);
+ while assigned(p) do
+ Comment(V_Normal,GetMsgLine(p));
+ LogoWritten:= true;
+ end;
+end;
+
+
+procedure Toption.WriteInfo;
+var
+ p : pchar;
+ hs,hs1,s : TCmdStr;
+ target : tsystem;
+ cpu : tprocessors;
+ fpu : tfputype;
+begin
+ p:=MessagePchar(option_info);
+ while assigned(p) do
+ begin
+ s:=GetMsgLine(p);
+ { list OS Targets }
+ if pos('$OSTARGETS',s)>0 then
+ begin
+ for target:=low(tsystem) to high(tsystem) do
+ if assigned(targetinfos[target]) then
+ begin
+ hs:=s;
+ hs1:=targetinfos[target]^.name;
+ if tf_under_development in targetinfos[target]^.flags then
+ hs1:=hs1+' (under development)';
+ Replace(hs,'$OSTARGETS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end
+ else if pos('$INSTRUCTIONSETS',s)>0 then
+ begin
+ for cpu:=low(tprocessors) to high(tprocessors) do
+ begin
+ hs:=s;
+ hs1:=processorsstr[cpu];
+ if hs1<>'' then
+ begin
+ Replace(hs,'$INSTRUCTIONSETS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end;
+ end
+ else if pos('$FPUINSTRUCTIONSETS',s)>0 then
+ begin
+ for fpu:=low(tfputype) to high(tfputype) do
+ begin
+ hs:=s;
+ hs1:=fputypestr[fpu];
+ if hs1<>'' then
+ begin
+ Replace(hs,'$FPUINSTRUCTIONSETS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end;
+ end
+ else
+ Comment(V_Normal,s);
+ end;
+ StopOptions(0);
+end;
+
+
+procedure Toption.WriteHelpPages;
+
+ function PadEnd(s:string;i:longint):string;
+ begin
+ while (length(s)<i) do
+ s:=s+' ';
+ PadEnd:=s;
+ end;
+
+var
+ lastident,
+ j,outline,
+ ident,
+ lines : longint;
+ show : boolean;
+ opt : string[32];
+ input,
+ s : string;
+ p : pchar;
+begin
+ WriteLogo;
+ Lines:=4;
+ Message1(option_usage,FixFileName(system.paramstr(0)));
+ lastident:=0;
+ p:=MessagePChar(option_help_pages);
+ while assigned(p) do
+ begin
+ { get a line and reset }
+ s:=GetMsgLine(p);
+ ident:=0;
+ show:=false;
+ { parse options }
+ case s[1] of
+{$ifdef UNITALIASES}
+ 'a',
+{$endif}
+{$ifdef EXTDEBUG}
+ 'e',
+{$endif EXTDEBUG}
+{$ifdef i386}
+ '3',
+{$endif}
+{$ifdef x86_64}
+ '4',
+{$endif}
+{$ifdef m68k}
+ '6',
+{$endif}
+{$ifdef arm}
+ 'A',
+{$endif}
+{$ifdef powerpc}
+ 'P',
+{$endif}
+{$ifdef sparc}
+ 'S',
+{$endif}
+{$ifdef vis}
+ 'V',
+{$endif}
+ '*' : show:=true;
+ end;
+ if show then
+ begin
+ case s[2] of
+ 'g',
+{$ifdef Unix}
+ 'L',
+{$endif}
+{$ifdef os2}
+ 'O',
+{$endif}
+ '*' : show:=true;
+ else
+ show:=false;
+ end;
+ end;
+ { now we may show the message or not }
+ if show then
+ begin
+ case s[3] of
+ '0' : begin
+ ident:=0;
+ outline:=0;
+ end;
+ '1' : begin
+ ident:=2;
+ outline:=7;
+ end;
+ '2' : begin
+ ident:=6;
+ outline:=11;
+ end;
+ '3' : begin
+ ident:=9;
+ outline:=11;
+ end;
+ end;
+ j:=pos('_',s);
+ opt:=Copy(s,4,j-4);
+ if opt='*' then
+ opt:=''
+ else
+ if opt=' ' then
+ opt:=PadEnd(opt,outline)
+ else
+ opt:=PadEnd('-'+opt,outline);
+ if (ident=0) and (lastident<>0) then
+ begin
+ Comment(V_Normal,'');
+ inc(Lines);
+ end;
+ { page full ? }
+ if (lines >= page_size - 1) then
+ begin
+ if not NoPressEnter then
+ begin
+ Message(option_help_press_enter);
+ readln(input);
+ if upper(input)='Q' then
+ StopOptions(0);
+ end;
+ lines:=0;
+ end;
+ Comment(V_Normal,PadEnd('',ident)+opt+Copy(s,j+1,255));
+ LastIdent:=Ident;
+ inc(Lines);
+ end;
+ end;
+ StopOptions(0);
+end;
+
+
+procedure Toption.IllegalPara(const opt:string);
+begin
+ Message1(option_illegal_para,opt);
+ Message(option_help_pages_para);
+ StopOptions(1);
+end;
+
+
+function Toption.Unsetbool(var Opts:string; Pos: Longint):boolean;
+{ checks if the character after pos in Opts is a + or a - and returns resp.
+ false or true. If it is another character (or none), it also returns false }
+begin
+ UnsetBool := false;
+ if Length(Opts)>Pos then
+ begin
+ inc(Pos);
+ UnsetBool := Opts[Pos] = '-';
+ if Opts[Pos] in ['-','+']then
+ delete(Opts,Pos,1);
+ end;
+end;
+
+
+procedure TOption.interpret_proc_specific_options(const opt:string);
+begin
+end;
+
+
+procedure TOption.interpret_option(const opt:string;ispara:boolean);
+var
+ code : integer;
+ c : char;
+ more : string;
+ major,minor : longint;
+ error : integer;
+ j,l : longint;
+ d : DirStr;
+ e : ExtStr;
+ s : string;
+begin
+ if opt='' then
+ exit;
+
+ { only parse define,undef,target,verbosity,link etc options the firsttime }
+ if firstpass and
+ not(
+ (opt[1]='-') and
+ (
+ ((length(opt)>1) and (opt[2] in ['i','d','v','T','u','n','X','l'])) or
+ ((length(opt)>3) and (opt[2]='F') and (opt[3]='e'))
+ )
+ ) then
+ exit;
+
+ Message1(option_handling_option,opt);
+ case opt[1] of
+ '-' :
+ begin
+ more:=Copy(opt,3,255);
+ if firstpass then
+ Message1(option_interpreting_firstpass_option,opt)
+ else
+ Message1(option_interpreting_option,opt);
+ case opt[2] of
+ '?' :
+ WriteHelpPages;
+
+ 'a' :
+ begin
+ include(initglobalswitches,cs_asm_leave);
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ 'l' :
+ include(initglobalswitches,cs_asm_source);
+ 'r' :
+ include(initglobalswitches,cs_asm_regalloc);
+ 't' :
+ include(initglobalswitches,cs_asm_tempalloc);
+ 'n' :
+ include(initglobalswitches,cs_asm_nodes);
+ 'p' :
+ begin
+ exclude(initglobalswitches,cs_asm_leave);
+ if UnsetBool(More, 0) then
+ exclude(initglobalswitches,cs_asm_pipe)
+ else
+ include(initglobalswitches,cs_asm_pipe);
+ end;
+ '-' :
+ initglobalswitches:=initglobalswitches -
+ [cs_asm_leave, cs_asm_source,cs_asm_regalloc, cs_asm_tempalloc,
+ cs_asm_nodes, cs_asm_pipe];
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'A' :
+ begin
+ paratargetasm:=find_asm_by_string(More);
+ if paratargetasm=as_none then
+ IllegalPara(opt);
+ end;
+
+ 'b' :
+ begin
+{$ifdef supportbrowser}
+ if UnsetBool(More,0) then
+ begin
+ exclude(initmoduleswitches,cs_browser);
+ exclude(initmoduleswitches,cs_local_browser);
+{$ifdef BrowserLog}
+ exclude(initglobalswitches,cs_browser_log);
+{$endif}
+ end
+ else
+ begin
+ include(initmoduleswitches,cs_browser);
+{$ifdef BrowserLog}
+ include(initglobalswitches,cs_browser_log);
+{$endif}
+ end;
+ if More<>'' then
+ if (More='l') or (More='l+') then
+ include(initmoduleswitches,cs_local_browser)
+ else
+ if More='l-' then
+ exclude(initmoduleswitches,cs_local_browser)
+ else
+{$ifdef BrowserLog}
+ browserlog.elements_to_list.insert(more);
+{$else}
+ IllegalPara(opt);
+{$endif}
+{$endif supportbrowser}
+ end;
+
+ 'B' :
+ do_build:=not UnSetBool(more,0);
+
+ 'C' :
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ 'a' :
+ Message2(option_obsolete_switch_use_new,'-Ca','-Or');
+ 'c' :
+ begin
+ if not SetAktProcCall(upper(copy(more,j+1,length(more)-j)),true) then
+ IllegalPara(opt);
+ break;
+ end;
+{$ifdef cpufpemu}
+ 'e' :
+ begin
+ If UnsetBool(More, j) then
+ exclude(initmoduleswitches,cs_fp_emulation)
+ Else
+ include(initmoduleswitches,cs_fp_emulation);
+ end;
+{$endif cpufpemu}
+ 'f' :
+ begin
+ s:=upper(copy(more,j+1,length(more)-j));
+ if not(SetFpuType(s,true)) then
+ IllegalPara(opt);
+ break;
+ end;
+ 'g' :
+ include(initmoduleswitches,cs_create_pic);
+ 'h' :
+ begin
+ val(copy(more,j+1,length(more)-j),heapsize,code);
+ if (code<>0) or (heapsize<1024) then
+ IllegalPara(opt);
+ break;
+ end;
+ 'i' :
+ If UnsetBool(More, j) then
+ exclude(initlocalswitches,cs_check_io)
+ else
+ include(initlocalswitches,cs_check_io);
+ 'n' :
+ If UnsetBool(More, j) then
+ exclude(initglobalswitches,cs_link_extern)
+ Else
+ include(initglobalswitches,cs_link_extern);
+ 'o' :
+ If UnsetBool(More, j) then
+ exclude(initlocalswitches,cs_check_overflow)
+ Else
+ include(initlocalswitches,cs_check_overflow);
+ 'p' :
+ begin
+ s:=upper(copy(more,j+1,length(more)-j));
+ if not(SetProcessor(s,true)) then
+ IllegalPara(opt);
+ break;
+ end;
+ 'r' :
+ If UnsetBool(More, j) then
+ exclude(initlocalswitches,cs_check_range)
+ Else
+ include(initlocalswitches,cs_check_range);
+ 'R' :
+ If UnsetBool(More, j) then
+ begin
+ exclude(initlocalswitches,cs_check_range);
+ exclude(initlocalswitches,cs_check_object);
+ end
+ Else
+ begin
+ include(initlocalswitches,cs_check_range);
+ include(initlocalswitches,cs_check_object);
+ end;
+ 's' :
+ begin
+ val(copy(more,j+1,length(more)-j),stacksize,code);
+ if (code<>0) or (stacksize>=67107840) or (stacksize<1024) then
+ IllegalPara(opt);
+ break;
+ end;
+ 't' :
+ If UnsetBool(More, j) then
+ exclude(initlocalswitches,cs_check_stack)
+ Else
+ include(initlocalswitches,cs_check_stack);
+ 'D' :
+ If UnsetBool(More, j) then
+ exclude(initmoduleswitches,cs_create_dynamic)
+ Else
+ include(initmoduleswitches,cs_create_dynamic);
+ 'X' :
+ If UnsetBool(More, j) then
+ exclude(initmoduleswitches,cs_create_smart)
+ Else
+ include(initmoduleswitches,cs_create_smart);
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'd' :
+ if more <> '' then
+ begin
+ l:=Pos(':=',more);
+ if l>0 then
+ set_system_compvar(Copy(more,1,l-1),Copy(more,l+2,255))
+ else
+ def_system_macro(more);
+ end;
+ 'D' :
+ begin
+ include(initglobalswitches,cs_link_deffile);
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ 'd' :
+ begin
+ description:=Copy(more,j+1,255);
+ break;
+ end;
+ 'v' :
+ begin
+ dllversion:=Copy(more,j+1,255);
+ l:=pos('.',dllversion);
+ dllminor:=0;
+ error:=0;
+ if l>0 then
+ begin
+ val(copy(dllversion,l+1,255),minor,error);
+ if (error=0) and
+ (minor>=0) and (minor<=$ffff) then
+ dllminor:=minor
+ else
+ if error=0 then
+ error:=1;
+ end;
+ if l=0 then
+ l:=256;
+ dllmajor:=1;
+ if error=0 then
+ val(copy(dllversion,1,l-1),major,error);
+ if (error=0) and (major>=0) and (major<=$ffff) then
+ dllmajor:=major
+ else
+ if error=0 then
+ error:=1;
+ if error<>0 then
+ Message1(scan_w_wrong_version_ignored,dllversion);
+ break;
+ end;
+ 'w' :
+ usewindowapi:=true;
+ '-' :
+ begin
+ exclude(initglobalswitches,cs_link_deffile);
+ usewindowapi:=false;
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'e' :
+ exepath:=FixPath(More,true);
+
+ 'E' :
+ begin
+ if UnsetBool(More, 0) then
+ exclude(initglobalswitches,cs_link_extern)
+ else
+ include(initglobalswitches,cs_link_extern);
+ end;
+
+ 'F' :
+ begin
+ c:=more[1];
+ Delete(more,1,1);
+ DefaultReplacements(More);
+ case c of
+ 'a' :
+ autoloadunits:=more;
+ 'c' :
+ begin
+ if (upper(more)='UTF8') or (upper(more)='UTF-8') then
+ initsourcecodepage:='utf8'
+ else if not(cpavailable(more)) then
+ Message1(option_code_page_not_available,more)
+ else
+ initsourcecodepage:=more;
+ end;
+ 'D' :
+ utilsdirectory:=FixPath(More,true);
+ 'e' :
+ SetRedirectFile(More);
+ 'E' :
+ OutputExeDir:=FixPath(More,true);
+ 'i' :
+ begin
+ if ispara then
+ ParaIncludePath.AddPath(More,false)
+ else
+ includesearchpath.AddPath(More,true);
+ end;
+ 'g' :
+ Message2(option_obsolete_switch_use_new,'-Fg','-Fl');
+ 'l' :
+ begin
+ if ispara then
+ ParaLibraryPath.AddPath(More,false)
+ else
+ LibrarySearchPath.AddPath(More,true);
+ end;
+ 'L' :
+ begin
+ if More<>'' then
+ ParaDynamicLinker:=More
+ else
+ IllegalPara(opt);
+ end;
+ 'o' :
+ begin
+ if ispara then
+ ParaObjectPath.AddPath(More,false)
+ else
+ ObjectSearchPath.AddPath(More,true);
+ end;
+ 'r' :
+ Msgfilename:=More;
+ 'u' :
+ begin
+ if ispara then
+ ParaUnitPath.AddPath(More,false)
+ else
+ unitsearchpath.AddPath(More,true);
+ end;
+ 'U' :
+ OutputUnitDir:=FixPath(More,true);
+ else
+ IllegalPara(opt);
+ end;
+ end;
+ 'g' : begin
+ if UnsetBool(More, 0) then
+ begin
+ exclude(initmoduleswitches,cs_debuginfo);
+ exclude(initglobalswitches,cs_use_heaptrc);
+ exclude(initglobalswitches,cs_use_lineinfo);
+ exclude(initlocalswitches,cs_checkpointer);
+ end
+ else
+ begin
+ include(initmoduleswitches,cs_debuginfo);
+ end;
+ if not RelocSectionSetExplicitly then
+ RelocSection:=false;
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ 'c' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(initlocalswitches,cs_checkpointer)
+ else
+ include(initlocalswitches,cs_checkpointer);
+ end;
+ 'd' :
+ begin
+ paratargetdbg:=dbg_dwarf;
+ end;
+ 'h' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(initglobalswitches,cs_use_heaptrc)
+ else
+ include(initglobalswitches,cs_use_heaptrc);
+ end;
+ 'l' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(initglobalswitches,cs_use_lineinfo)
+ else
+ include(initglobalswitches,cs_use_lineinfo);
+ end;
+ 's' :
+ begin
+ paratargetdbg:=dbg_stabs;
+ end;
+ 'v' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(initglobalswitches,cs_gdb_valgrind)
+ else
+ include(initglobalswitches,cs_gdb_valgrind);
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'h' :
+ begin
+ NoPressEnter:=true;
+ WriteHelpPages;
+ end;
+
+ 'i' :
+ begin
+ if More='' then
+ WriteInfo
+ else
+ QuickInfo:=QuickInfo+More;
+ end;
+
+ 'I' :
+ begin
+ if ispara then
+ ParaIncludePath.AddPath(More,false)
+ else
+ includesearchpath.AddPath(More,false);
+ end;
+
+ 'k' :
+ begin
+ if more<>'' then
+ ParaLinkOptions:=ParaLinkOptions+' '+More
+ else
+ IllegalPara(opt);
+ end;
+
+ 'l' :
+ if not UnSetBool(more,0) then
+ ParaLogo:=true;
+
+ 'm' :
+ parapreprocess:=not UnSetBool(more,0);
+
+ 'M' :
+ begin
+ more:=Upper(more);
+ if not SetCompileMode(more, true) then
+ IllegalPara(opt);
+ end;
+
+ 'n' :
+ begin
+ if More='' then
+ disable_configfile:=true
+ else
+ IllegalPara(opt);
+ end;
+
+ 'N' :
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ 'u' :
+ initglobalswitches:=initglobalswitches+[cs_loopunroll];
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'o' :
+ begin
+ if More<>'' then
+{$IFDEF USE_SYSUTILS}
+ begin
+ d := SplitPath(More);
+ OutputFile := SplitFileName(More);
+ end
+{$ELSE USE_SYSUTILS}
+ Fsplit(More,d,OutputFile,e)
+{$ENDIF USE_SYSUTILS}
+ else
+ IllegalPara(opt);
+ end;
+
+ 'p' :
+ begin
+ if UnsetBool(More, 0) then
+ begin
+ initmoduleswitches:=initmoduleswitches-[cs_profile];
+ undef_system_macro('FPC_PROFILE');
+ end
+ else
+ if Length(More)=0 then
+ IllegalPara(opt)
+ else
+ case more[1] of
+ 'g' : if UnsetBool(more, 1) then
+ begin
+ exclude(initmoduleswitches,cs_profile);
+ undef_system_macro('FPC_PROFILE');
+ end
+ else
+ begin
+ include(initmoduleswitches,cs_profile);
+ def_system_macro('FPC_PROFILE');
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ end;
+
+ 'P' : ; { Ignore used by fpc.pp }
+
+ 's' :
+ begin
+ if UnsetBool(More, 0) then
+ begin
+ initglobalswitches:=initglobalswitches-[cs_asm_extern,cs_link_extern];
+ if more<>'' then
+ IllegalPara(opt);
+ end
+ else
+ begin
+ initglobalswitches:=initglobalswitches+[cs_asm_extern,cs_link_extern];
+ if more='h' then
+ initglobalswitches:=initglobalswitches-[cs_link_on_target]
+ else if more='t' then
+ initglobalswitches:=initglobalswitches+[cs_link_on_target]
+ else if more='r' then
+ initglobalswitches:=initglobalswitches+[cs_asm_leave,cs_no_regalloc]
+ else if more<>'' then
+ IllegalPara(opt);
+ end;
+ end;
+
+ 'S' :
+ begin
+ if more[1]='I' then
+ begin
+ if upper(more)='ICOM' then
+ initinterfacetype:=it_interfacecom
+ else if upper(more)='ICORBA' then
+ initinterfacetype:=it_interfacecorba
+ else
+ IllegalPara(opt);
+ end
+ else
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ '2' : //an alternative to -Mobjfpc
+ SetCompileMode('OBJFPC',true);
+ 'a' :
+ include(initlocalswitches,cs_do_assertion);
+ 'c' :
+ include(initmoduleswitches,cs_support_c_operators);
+ 'd' : //an alternative to -Mdelphi
+ SetCompileMode('DELPHI',true);
+ 'e' :
+ begin
+ SetErrorFlags(copy(more,j+1,length(more)));
+ break;
+ end;
+ 'g' :
+ include(initmoduleswitches,cs_support_goto);
+ 'h' :
+ include(initlocalswitches,cs_ansistrings);
+ 'i' :
+ include(initmoduleswitches,cs_support_inline);
+ 'k' :
+ include(initglobalswitches,cs_load_fpcylix_unit);
+ 'm' :
+ include(initmoduleswitches,cs_support_macro);
+ 'o' : //an alternative to -Mtp
+ SetCompileMode('TP',true);
+ 'p' : //an alternative to -Mgpc
+ SetCompileMode('GPC',true);
+ 's' :
+ include(initglobalswitches,cs_constructor_name);
+ 't' :
+ include(initmoduleswitches,cs_static_keyword);
+ '-' :
+ begin
+ exclude(initglobalswitches,cs_constructor_name);
+ initlocalswitches:=InitLocalswitches - [cs_do_assertion, cs_ansistrings];
+ initmoduleswitches:=initmoduleswitches - [cs_support_c_operators, cs_support_goto,
+ cs_support_inline, cs_support_macro,
+ cs_static_keyword];
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+ end;
+
+ 'T' :
+ begin
+ more:=Upper(More);
+ if paratarget=system_none then
+ begin
+ { remove old target define }
+ TargetDefines(false);
+ { load new target }
+ paratarget:=find_system_by_string(More);
+ if paratarget<>system_none then
+ set_target(paratarget)
+ else
+ IllegalPara(opt);
+ { set new define }
+ TargetDefines(true);
+ end
+ else
+ if More<>upper(target_info.shortname) then
+ Message1(option_target_is_already_set,target_info.shortname);
+ end;
+
+ 'u' :
+ if more <> '' then
+ undef_system_macro(more);
+ 'U' :
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+{$ifdef UNITALIASES}
+ 'a' :
+ begin
+ AddUnitAlias(Copy(More,j+1,255));
+ break;
+ end;
+{$endif UNITALIASES}
+ 'n' :
+ exclude(initglobalswitches,cs_check_unit_name);
+ 'p' :
+ begin
+ Message2(option_obsolete_switch_use_new,'-Up','-Fu');
+ break;
+ end;
+ 'r' :
+ do_release:=true;
+ 's' :
+ include(initmoduleswitches,cs_compilesystem);
+ '-' :
+ begin
+ exclude(initmoduleswitches,cs_compilesystem);
+ exclude(initglobalswitches,cs_check_unit_name);
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'v' :
+ begin
+ if not setverbosity(More) then
+ IllegalPara(opt);
+ end;
+
+ 'V' : ; { Ignore used by fpc }
+
+ 'W' :
+ begin
+ j:=1;
+ while j<=length(More) do
+ begin
+ case More[j] of
+ 'A':
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_native
+ else
+ apptype:=app_cui;
+ end;
+ 'B':
+ begin
+ { -WB200000 means set trefered base address
+ to $200000, but does not change relocsection boolean
+ this way we can create both relocatble and
+ non relocatable DLL at a specific base address PM }
+ if (length(More)>j) then
+ begin
+ if DLLImageBase=nil then
+ DLLImageBase:=StringDup(Copy(More,j+1,255));
+ end
+ else
+ begin
+ RelocSection:=true;
+ RelocSectionSetExplicitly:=true;
+ end;
+ break;
+ end;
+ 'C':
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_gui
+ else
+ apptype:=app_cui;
+ end;
+ 'D':
+ begin
+ UseDeffileForExports:=not UnsetBool(More, j);
+ UseDeffileForExportsSetExplicitly:=true;
+ end;
+ 'F':
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_cui
+ else
+ apptype:=app_fs;
+ end;
+ 'G':
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_cui
+ else
+ apptype:=app_gui;
+ end;
+ 'T':
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_cui
+ else
+ apptype:=app_tool;
+ end;
+ 'N':
+ begin
+ RelocSection:=UnsetBool(More,j);
+ RelocSectionSetExplicitly:=true;
+ end;
+ 'R':
+ begin
+ { support -WR+ / -WR- as synonyms to -WR / -WN }
+ RelocSection:=not UnsetBool(More,j);
+ RelocSectionSetExplicitly:=true;
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'X' :
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case More[j] of
+ 'i' :
+ include(initglobalswitches,cs_link_internal);
+ 'm' :
+ include(initglobalswitches,cs_link_map);
+ 'f' :
+ include(initglobalswitches,cs_link_pthread);
+ 's' :
+ include(initglobalswitches,cs_link_strip);
+ 'c' : Cshared:=TRUE;
+ 't' :
+ include(initglobalswitches,cs_link_staticflag);
+ 'D' :
+ begin
+ def_system_macro('FPC_LINK_DYNAMIC');
+ undef_system_macro('FPC_LINK_SMART');
+ undef_system_macro('FPC_LINK_STATIC');
+ exclude(initglobalswitches,cs_link_static);
+ exclude(initglobalswitches,cs_link_smart);
+ include(initglobalswitches,cs_link_shared);
+ LinkTypeSetExplicitly:=true;
+ end;
+ 'd' : Dontlinkstdlibpath:=TRUE;
+ 'P' : Begin
+ utilsprefix:=Copy(more,2,length(More)-1);
+ DefaultReplacements(utilsprefix);
+ More:='';
+ End;
+ 'r' : Begin
+ rlinkpath:=Copy(more,2,length(More)-1);
+ DefaultReplacements(rlinkpath);
+ More:='';
+ end;
+ 'S' :
+ begin
+ def_system_macro('FPC_LINK_STATIC');
+ undef_system_macro('FPC_LINK_SMART');
+ undef_system_macro('FPC_LINK_DYNAMIC');
+ include(initglobalswitches,cs_link_static);
+ exclude(initglobalswitches,cs_link_smart);
+ exclude(initglobalswitches,cs_link_shared);
+ LinkTypeSetExplicitly:=true;
+ end;
+ 'X' :
+ begin
+ def_system_macro('FPC_LINK_SMART');
+ undef_system_macro('FPC_LINK_STATIC');
+ undef_system_macro('FPC_LINK_DYNAMIC');
+ exclude(initglobalswitches,cs_link_static);
+ include(initglobalswitches,cs_link_smart);
+ exclude(initglobalswitches,cs_link_shared);
+ LinkTypeSetExplicitly:=true;
+ end;
+ 'M' :
+ begin
+ mainaliasname:=Copy(more,2,length(More)-1);
+ More:='';
+ end;
+ '-' :
+ begin
+ exclude(initglobalswitches,cs_link_staticflag);
+ exclude(initglobalswitches,cs_link_strip);
+ exclude(initglobalswitches,cs_link_map);
+ set_default_link_type;
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ { give processor specific options a chance }
+ else
+ interpret_proc_specific_options(opt);
+ end;
+ end;
+
+ '@' :
+ begin
+ Message(option_no_nested_response_file);
+ StopOptions(1);
+ end;
+
+ else
+ begin
+ if (length(param_file)<>0) then
+ Message(option_only_one_source_support);
+ param_file:=opt;
+ Message1(option_found_file,opt);
+ end;
+ end;
+end;
+
+
+procedure Toption.Interpret_file(const filename : string);
+
+ procedure RemoveSep(var fn:string);
+ var
+ i : longint;
+ begin
+ i:=0;
+ while (i<length(fn)) and (fn[i+1] in [',',' ',#9]) do
+ inc(i);
+ Delete(fn,1,i);
+ i:=length(fn);
+ while (i>0) and (fn[i] in [',',' ',#9]) do
+ dec(i);
+ fn:=copy(fn,1,i);
+ end;
+
+ function GetName(var fn:string):string;
+ var
+ i : longint;
+ begin
+ i:=0;
+ while (i<length(fn)) and (fn[i+1] in ['a'..'z','A'..'Z','0'..'9','_','-']) do
+ inc(i);
+ GetName:=Copy(fn,1,i);
+ Delete(fn,1,i);
+ end;
+
+const
+ maxlevel=16;
+var
+ f : text;
+ s, tmp,
+ opts : string;
+ skip : array[0..maxlevel-1] of boolean;
+ level : longint;
+ option_read : boolean;
+begin
+{ avoid infinite loop }
+ Inc(FileLevel);
+ Option_read:=false;
+ If FileLevel>MaxLevel then
+ Message(option_too_many_cfg_files);
+{ open file }
+ Message1(option_using_file,filename);
+{$ifdef USE_SYSUTILS}
+ assign(f,ExpandFileName(filename));
+{$else USE_SYSUTILS}
+ assign(f,FExpand(filename));
+{$endif USE_SYsUTILS}
+ {$I-}
+ reset(f);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ Message1(option_unable_open_file,filename);
+ exit;
+ end;
+ Message1(option_start_reading_configfile,filename);
+ fillchar(skip,sizeof(skip),0);
+ level:=0;
+ while not eof(f) do
+ begin
+ readln(f,opts);
+ RemoveSep(opts);
+ if (opts<>'') and (opts[1]<>';') then
+ begin
+ if opts[1]='#' then
+ begin
+ Message1(option_interpreting_file_option,opts);
+ Delete(opts,1,1);
+ s:=upper(GetName(opts));
+ if (s='SECTION') then
+ begin
+ RemoveSep(opts);
+ s:=upper(GetName(opts));
+ if level=0 then
+ skip[level]:=not (assigned(search_macro(s)) or (s='COMMON'));
+ end
+ else
+ if (s='IFDEF') then
+ begin
+ RemoveSep(opts);
+ if Level>=maxlevel then
+ begin
+ Message(option_too_many_ifdef);
+ stopOptions(1);
+ end;
+ inc(Level);
+ skip[level]:=(skip[level-1] or not assigned(search_macro(upper(GetName(opts)))));
+ end
+ else
+ if (s='IFNDEF') then
+ begin
+ RemoveSep(opts);
+ if Level>=maxlevel then
+ begin
+ Message(option_too_many_ifdef);
+ stopOptions(1);
+ end;
+ inc(Level);
+ skip[level]:=(skip[level-1] or assigned(search_macro(upper(GetName(opts)))));
+ end
+ else
+ if (s='ELSE') then
+ skip[level]:=skip[level-1] or (not skip[level])
+ else
+ if (s='ENDIF') then
+ begin
+ skip[level]:=false;
+ if Level=0 then
+ begin
+ Message(option_too_many_endif);
+ stopOptions(1);
+ end;
+ dec(level);
+ end
+ else
+ if (not skip[level]) then
+ begin
+ if (s='DEFINE') then
+ begin
+ RemoveSep(opts);
+ tmp:= GetName(opts);
+ if tmp <> '' then
+ def_system_macro(tmp);
+ end
+ else
+ if (s='UNDEF') then
+ begin
+ RemoveSep(opts);
+ tmp:= GetName(opts);
+ if tmp <> '' then
+ undef_system_macro(tmp);
+ end
+ else
+ if (s='WRITE') then
+ begin
+ Delete(opts,1,1);
+ WriteLn(opts);
+ end
+ else
+ if (s='INCLUDE') then
+ begin
+ Delete(opts,1,1);
+ Interpret_file(opts);
+ end;
+ end;
+ end
+ else
+ begin
+ if (opts[1]='-') or (opts[1]='@') then
+ begin
+ if (not skip[level]) then
+ interpret_option(opts,false);
+ Option_read:=true;
+ end
+ else
+ Message1(option_illegal_para,opts);
+ end;
+ end;
+ end;
+ if Level>0 then
+ Message(option_too_less_endif);
+ if Not Option_read then
+ Message1(option_no_option_found,filename)
+ else
+ Message1(option_end_reading_configfile,filename);
+ Close(f);
+ Dec(FileLevel);
+end;
+
+
+procedure Toption.Interpret_envvar(const envname : string);
+var
+ argstart,
+ env,
+ pc : pchar;
+ arglen : longint;
+ quote : set of char;
+ hs : string;
+begin
+ Message1(option_using_env,envname);
+ env:=GetEnvPChar(envname);
+ pc:=env;
+ if assigned(pc) then
+ begin
+ repeat
+ { skip leading spaces }
+ while pc^ in [' ',#9,#13] do
+ inc(pc);
+ case pc^ of
+ #0 :
+ break;
+ '"' :
+ begin
+ quote:=['"'];
+ inc(pc);
+ end;
+ '''' :
+ begin
+ quote:=[''''];
+ inc(pc);
+ end;
+ else
+ quote:=[' ',#9,#13];
+ end;
+ { scan until the end of the argument }
+ argstart:=pc;
+ while (pc^<>#0) and not(pc^ in quote) do
+ inc(pc);
+ { create argument }
+ arglen:=pc-argstart;
+ hs[0]:=chr(arglen);
+ move(argstart^,hs[1],arglen);
+ interpret_option(hs,true);
+ { skip quote }
+ if pc^ in quote then
+ inc(pc);
+ until false;
+ end
+ else
+ Message1(option_no_option_found,'(env) '+envname);
+ FreeEnvPChar(env);
+end;
+
+
+procedure toption.read_parameters;
+var
+ opts : string;
+ paramindex : longint;
+begin
+ paramindex:=0;
+ while paramindex<paramcount do
+ begin
+ inc(paramindex);
+ opts:=system.paramstr(paramindex);
+ case opts[1] of
+ '@' :
+ if not firstpass then
+ begin
+ Delete(opts,1,1);
+ Message1(option_reading_further_from,opts);
+ interpret_file(opts);
+ end;
+ '!' :
+ if not firstpass then
+ begin
+ Delete(opts,1,1);
+ Message1(option_reading_further_from,'(env) '+opts);
+ interpret_envvar(opts);
+ end;
+ else
+ interpret_option(opts,true);
+ end;
+ end;
+end;
+
+
+procedure toption.parsecmd(cmd:string);
+var
+ i,ps : longint;
+ opts : string;
+begin
+ while (cmd<>'') do
+ begin
+ while cmd[1]=' ' do
+ delete(cmd,1,1);
+ i:=pos(' ',cmd);
+ if i=0 then
+ i:=256;
+ opts:=Copy(cmd,1,i-1);
+ Delete(cmd,1,i);
+ case opts[1] of
+ '@' :
+ if not firstpass then
+ begin
+ Delete(opts,1,1);
+ Message1(option_reading_further_from,opts);
+ interpret_file(opts);
+ end;
+ '!' :
+ if not firstpass then
+ begin
+ Delete(opts,1,1);
+ Message1(option_reading_further_from,'(env) '+opts);
+ interpret_envvar(opts);
+ end;
+ '"' :
+ begin
+ Delete(opts,1,1);
+ ps:=pos('"',cmd);
+ if (i<>256) and (ps>0) then
+ begin
+ opts:=opts + ' '+ copy(cmd,1,ps-1);
+ cmd:=copy(cmd,ps+1,255);
+ end;
+ interpret_option(opts,true);
+ end;
+ else
+ interpret_option(opts,true);
+ end;
+ end;
+end;
+
+
+procedure toption.writequickinfo;
+var
+ s : string;
+ i : longint;
+
+ procedure addinfo(const hs:string);
+ begin
+ if s<>'' then
+ s:=s+' '+hs
+ else
+ s:=hs;
+ end;
+
+begin
+ s:='';
+ i:=0;
+ while (i<length(quickinfo)) do
+ begin
+ inc(i);
+ case quickinfo[i] of
+ 'S' :
+ begin
+ inc(i);
+ case quickinfo[i] of
+ 'O' :
+ addinfo(lower(source_info.shortname));
+ 'P' :
+ addinfo(source_cpu_string);
+ else
+ IllegalPara('-i'+QuickInfo);
+ end;
+ end;
+ 'T' :
+ begin
+ inc(i);
+ case quickinfo[i] of
+ 'O' :
+ addinfo(lower(target_info.shortname));
+ 'P' :
+ AddInfo(target_cpu_string);
+ else
+ IllegalPara('-i'+QuickInfo);
+ end;
+ end;
+ 'V' :
+ AddInfo(version_string);
+ 'D' :
+ AddInfo(date_string);
+ '_' :
+ ;
+ else
+ IllegalPara('-i'+QuickInfo);
+ end;
+ end;
+ if s<>'' then
+ begin
+ writeln(s);
+ stopoptions(0);
+ end;
+end;
+
+
+procedure TOption.TargetDefines(def:boolean);
+var
+ s : string;
+ i : integer;
+begin
+ if def then
+ def_system_macro(target_info.shortname)
+ else
+ undef_system_macro(target_info.shortname);
+ s:=target_info.extradefines;
+ while (s<>'') do
+ begin
+ i:=pos(';',s);
+ if i=0 then
+ i:=length(s)+1;
+ if def then
+ def_system_macro(Copy(s,1,i-1))
+ else
+ undef_system_macro(Copy(s,1,i-1));
+ delete(s,1,i);
+ end;
+end;
+
+
+constructor TOption.create;
+begin
+ LogoWritten:=false;
+ NoPressEnter:=false;
+ FirstPass:=false;
+ FileLevel:=0;
+ Quickinfo:='';
+ ParaIncludePath:=TSearchPathList.Create;
+ ParaObjectPath:=TSearchPathList.Create;
+ ParaUnitPath:=TSearchPathList.Create;
+ ParaLibraryPath:=TSearchPathList.Create;
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+end;
+
+
+destructor TOption.destroy;
+begin
+ ParaIncludePath.Free;
+ ParaObjectPath.Free;
+ ParaUnitPath.Free;
+ ParaLibraryPath.Free;
+end;
+
+
+{****************************************************************************
+ Callable Routines
+****************************************************************************}
+
+function check_configfile(const fn:string;var foundfn:string):boolean;
+
+ function CfgFileExists(const fn:string):boolean;
+ begin
+ Comment(V_Tried,'Configfile search: '+fn);
+ CfgFileExists:=FileExists(fn);
+ end;
+
+var
+ configpath : pathstr;
+begin
+ foundfn:=fn;
+ check_configfile:=true;
+ { retrieve configpath }
+{$IFDEF USE_SYSUTILS}
+ configpath:=FixPath(GetEnvironmentVariable('PPC_CONFIG_PATH'),false);
+{$ELSE USE_SYSUTILS}
+ configpath:=FixPath(dos.getenv('PPC_CONFIG_PATH'),false);
+{$ENDIF USE_SYSUTILS}
+{$ifdef Unix}
+ if configpath='' then
+ configpath:=CleanPath(FixPath(exepath+'../etc/',false));
+{$endif}
+ {
+ Order to read configuration file :
+ try reading fpc.cfg in :
+ 1 - current dir
+ 2 - configpath
+ 3 - compiler path
+ }
+ if not FileExists(fn) then
+ begin
+{$ifdef Unix}
+{$IFDEF USE_SYSUTILS}
+ if (GetEnvironmentVariable('HOME')<>'') and CfgFileExists(FixPath(GetEnvironmentVariable('HOME'),false)+'.'+fn) then
+ foundfn:=FixPath(GetEnvironmentVariable('HOME'),false)+'.'+fn
+{$ELSE USE_SYSUTILS}
+ if (dos.getenv('HOME')<>'') and CfgFileExists(FixPath(dos.getenv('HOME'),false)+'.'+fn) then
+ foundfn:=FixPath(dos.getenv('HOME'),false)+'.'+fn
+{$ENDIF USE_SYSUTILS}
+ else
+{$endif}
+ if CfgFileExists(configpath+fn) then
+ foundfn:=configpath+fn
+ else
+{$ifndef Unix}
+ if CfgFileExists(exepath+fn) then
+ foundfn:=exepath+fn
+ else
+{$else}
+ if CfgFileExists('/etc/'+fn) then
+ foundfn:='/etc/'+fn
+ else
+{$endif}
+ check_configfile:=false;
+ end;
+end;
+
+
+procedure read_arguments(cmd:string);
+begin
+ option:=coption.create;
+ disable_configfile:=false;
+
+{ get default messagefile }
+{$IFDEF USE_SYSUTILS}
+ msgfilename:=GetEnvironmentVariable('PPC_ERROR_FILE');
+{$ELSE USE_SYSUTILS}
+ msgfilename:=dos.getenv('PPC_ERROR_FILE');
+{$ENDIF USE_SYSUTILS}
+
+{ default configfile can be specified on the commandline,
+ remove it first }
+ if (cmd<>'') and (cmd[1]='[') then
+ begin
+ ppccfg:=Copy(cmd,2,pos(']',cmd)-2);
+ Delete(cmd,1,pos(']',cmd));
+ end
+ else
+ begin
+ ppccfg:='fpc.cfg';
+ ppcaltcfg:='ppc386.cfg';
+ end;
+
+{ first pass reading of parameters, only -i -v -T etc.}
+ option.firstpass:=true;
+ if cmd<>'' then
+ option.parsecmd(cmd)
+ else
+ begin
+ option.read_parameters;
+ { Write only quickinfo }
+ if option.quickinfo<>'' then
+ option.writequickinfo;
+ end;
+ option.firstpass:=false;
+
+{ target is set here, for wince the default app type is gui }
+ if target_info.system in system_wince then
+ apptype:=app_gui;
+
+{ default defines }
+ def_system_macro(target_info.shortname);
+ def_system_macro('FPC');
+ def_system_macro('VER'+version_nr);
+ def_system_macro('VER'+version_nr+'_'+release_nr);
+ def_system_macro('VER'+version_nr+'_'+release_nr+'_'+patch_nr);
+
+{ Temporary defines, until things settle down }
+ { "main" symbol is generated in the main program, and left out of the system unit }
+ def_system_macro('FPC_DARWIN_PASCALMAIN');
+ def_system_macro('COMPPROCINLINEFIXED');
+
+ if pocall_default = pocall_register then
+ def_system_macro('REGCALL');
+
+{ using a case is pretty useless here (FK) }
+{ some stuff for TP compatibility }
+{$ifdef i386}
+ def_system_macro('CPU86');
+ def_system_macro('CPU87');
+{$endif}
+{$ifdef m68k}
+ def_system_macro('CPU68');
+{$endif}
+
+{ new processor stuff }
+{$ifdef i386}
+ def_system_macro('CPUI386');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_HAS_TYPE_EXTENDED');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+ def_system_macro('FPC_HAS_RESOURCES');
+{$endif}
+{$ifdef m68k}
+ def_system_macro('CPU68K');
+ def_system_macro('CPUM68K');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+{$endif}
+{$ifdef ALPHA}
+ def_system_macro('CPUALPHA');
+ def_system_macro('CPU64');
+{$endif}
+{$ifdef powerpc}
+ def_system_macro('CPUPOWERPC');
+ def_system_macro('CPUPOWERPC32');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+ def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+{$endif}
+{$ifdef POWERPC64}
+ def_system_macro('CPUPOWERPC');
+ def_system_macro('CPUPOWERPC64');
+ def_system_macro('CPU64');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+ def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+ def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
+{$endif}
+{$ifdef iA64}
+ def_system_macro('CPUIA64');
+ def_system_macro('CPU64');
+{$endif}
+{$ifdef x86_64}
+ def_system_macro('CPUX86_64');
+ def_system_macro('CPUAMD64');
+ def_system_macro('CPU64');
+ { not supported for now, afaik (FK)
+ def_system_macro('FPC_HAS_TYPE_FLOAT128'); }
+
+ { win64 doesn't support the legacy fpu }
+ if target_info.system<>system_x86_64_win64 then
+ def_system_macro('FPC_HAS_TYPE_EXTENDED')
+ else
+ begin
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+ undef_system_macro('FPC_HAS_TYPE_EXTENDED');
+ end;
+
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+{$endif}
+{$ifdef sparc}
+ def_system_macro('CPUSPARC');
+ def_system_macro('CPUSPARC32');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+ def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+ def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
+{$endif}
+{$ifdef vis}
+ def_system_macro('CPUVIS');
+ def_system_macro('CPU32');
+{$endif}
+{$ifdef arm}
+ def_system_macro('CPUARM');
+ def_system_macro('FPUFPA');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+ def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+ def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
+{$endif arm}
+
+ if source_info.system<>target_info.system then
+ def_system_macro('FPC_CROSSCOMPILING');
+
+ if source_info.cpu<>target_info.cpu then
+ def_system_macro('FPC_CPUCROSSCOMPILING');
+
+ { read configuration file }
+ if (not disable_configfile) and
+ (ppccfg<>'') then
+ begin
+ read_configfile:=check_configfile(ppccfg,ppccfg);
+ { Maybe alternative configfile ? }
+ if (not read_configfile) and
+ (ppcaltcfg<>'') then
+ read_configfile:=check_configfile(ppcaltcfg,ppccfg);
+ end
+ else
+ read_configfile := false;
+
+{ Read commandline and configfile }
+ param_file:='';
+
+ { read configfile }
+ if read_configfile then
+ option.interpret_file(ppccfg);
+
+ { read parameters again to override config file }
+ if cmd<>'' then
+ option.parsecmd(cmd)
+ else
+ begin
+ { Write help pages if no parameters are passed }
+ if (paramcount=0) then
+ Option.WriteHelpPages;
+ option.read_parameters;
+ { Write only quickinfo }
+ if option.quickinfo<>'' then
+ option.writequickinfo;
+ end;
+
+ { Stop if errors in options }
+ if ErrorCount>0 then
+ StopOptions(1);
+
+ { Write logo }
+ if option.ParaLogo then
+ option.writelogo;
+
+ { Non-core target defines }
+ Option.TargetDefines(true);
+
+ { endian define }
+ case target_info.endian of
+ endian_little :
+ begin
+ def_system_macro('ENDIAN_LITTLE');
+ def_system_macro('FPC_LITTLE_ENDIAN');
+ end;
+ endian_big :
+ begin
+ def_system_macro('ENDIAN_BIG');
+ def_system_macro('FPC_BIG_ENDIAN');
+ end;
+ end;
+
+ { abi define }
+ case target_info.abi of
+ abi_powerpc_sysv :
+ def_system_macro('FPC_ABI_SYSV');
+ abi_powerpc_aix :
+ def_system_macro('FPC_ABI_AIX');
+ end;
+
+{$ifdef m68k}
+ if initoptprocessor=MC68020 then
+ def_system_macro('CPUM68020');
+{$endif m68k}
+
+{ Check file to compile }
+ if param_file='' then
+ begin
+ Message(option_no_source_found);
+ StopOptions(1);
+ end;
+{$ifndef Unix}
+ param_file:=FixFileName(param_file);
+{$endif}
+{$IFDEF USE_SYSUTILS}
+ inputdir := SplitPath(param_file);
+ inputfile := SplitName(param_file);
+ inputextension := SplitExtension(param_file);
+{$ELSE USE_SYSUTILS}
+ fsplit(param_file,inputdir,inputfile,inputextension);
+{$ENDIF USE_SYSUTILS}
+ if inputextension='' then
+ begin
+ if FileExists(inputdir+inputfile+sourceext) then
+ inputextension:=sourceext
+ else if FileExists(inputdir+inputfile+pasext) then
+ inputextension:=pasext
+ else if ((m_mac in aktmodeswitches) or target_info.p_ext_support)
+ and FileExists(inputdir+inputfile+pext) then
+ inputextension:=pext;
+ end;
+
+ { Check output dir }
+ if (OutputExeDir<>'') and
+ not PathExists(OutputExeDir) then
+ begin
+ Message1(general_e_path_does_not_exist,OutputExeDir);
+ StopOptions(1);
+ end;
+
+ { Add paths specified with parameters to the searchpaths }
+ UnitSearchPath.AddList(option.ParaUnitPath,true);
+ ObjectSearchPath.AddList(option.ParaObjectPath,true);
+ IncludeSearchPath.AddList(option.ParaIncludePath,true);
+ LibrarySearchPath.AddList(option.ParaLibraryPath,true);
+
+ { add unit environment and exepath to the unit search path }
+ if inputdir<>'' then
+ Unitsearchpath.AddPath(inputdir,true);
+ if not disable_configfile then
+ begin
+{$IFDEF USE_SYSUTILS}
+ UnitSearchPath.AddPath(GetEnvironmentVariable(target_info.unit_env),false);
+{$ELSE USE_SYSUTILS}
+ UnitSearchPath.AddPath(dos.getenv(target_info.unit_env),false);
+{$ENDIF USE_SYSUTILS}
+ end;
+
+{$ifdef Unix}
+{$IFDEF USE_SYSUTILS}
+ fpcdir:=FixPath(GetEnvironmentVariable('FPCDIR'),false);
+{$ELSE USE_SYSUTILS}
+ fpcdir:=FixPath(getenv('FPCDIR'),false);
+{$ENDIF USE_SYSUTILS}
+ if fpcdir='' then
+ begin
+ if PathExists('/usr/local/lib/fpc/'+version_string) then
+ fpcdir:='/usr/local/lib/fpc/'+version_string+'/'
+ else
+ fpcdir:='/usr/lib/fpc/'+version_string+'/';
+ end;
+{$else}
+{$IFDEF USE_SYSUTILS}
+ fpcdir:=FixPath(GetEnvironmentVariable('FPCDIR'),false);
+{$ELSE USE_SYSUTILS}
+ fpcdir:=FixPath(getenv('FPCDIR'),false);
+{$ENDIF USE_SYSUTILS}
+ if fpcdir='' then
+ begin
+ fpcdir:=ExePath+'../';
+ if not(PathExists(fpcdir+'/units')) and
+ not(PathExists(fpcdir+'/rtl')) then
+ fpcdir:=fpcdir+'../';
+ end;
+{$endif}
+ { first try development RTL, else use the default installation path }
+ if not disable_configfile then
+ begin
+ if PathExists(FpcDir+'rtl') then
+ if tf_use_8_3 in Source_Info.Flags then
+ UnitSearchPath.AddPath(FpcDir+'rtl/'+target_os_string,false)
+ else
+ UnitSearchPath.AddPath(FpcDir+'rtl/'+target_full_string,false)
+ else
+ if tf_use_8_3 in Source_Info.Flags then
+ UnitSearchPath.AddPath(FpcDir+'units/'+target_os_string+'/rtl',false)
+ else
+ UnitSearchPath.AddPath(FpcDir+'units/'+target_full_string+'/rtl',false);
+ end;
+ { Add exepath if the exe is not in the current dir, because that is always searched already.
+ Do not add it when linking on the target because then we can maybe already find
+ .o files that are not for the target }
+ if (ExePath<>GetCurrentDir) and
+ not(cs_link_on_target in initglobalswitches) then
+ UnitSearchPath.AddPath(ExePath,false);
+ { Add unit dir to the object and library path }
+ objectsearchpath.AddList(unitsearchpath,false);
+ librarysearchpath.AddList(unitsearchpath,false);
+
+ { maybe override debug info format }
+ if (paratargetdbg<>dbg_none) then
+ set_target_dbg(paratargetdbg);
+
+ { maybe override assembler }
+ if (paratargetasm<>as_none) then
+ set_target_asm(paratargetasm);
+
+ { switch assembler if it's binary and we got -a on the cmdline }
+ if (cs_asm_leave in initglobalswitches) and
+ (af_outputbinary in target_asm.flags) then
+ begin
+ Message(option_switch_bin_to_src_assembler);
+ set_target_asm(target_info.assemextern);
+ end;
+
+ if (target_asm.supported_target <> system_any) and
+ (target_asm.supported_target <> target_info.system) then
+ begin
+ Message2(option_incompatible_asm,target_asm.idtxt,target_info.name);
+ set_target_asm(target_info.assemextern);
+ Message1(option_asm_forced,target_asm.idtxt);
+ end;
+
+ { turn off stripping if compiling with debuginfo or profile }
+ if (cs_debuginfo in initmoduleswitches) or
+ (cs_profile in initmoduleswitches) then
+ exclude(initglobalswitches,cs_link_strip);
+
+ { force fpu emulation on arm/wince }
+ if target_info.system=system_arm_wince then
+ include(initmoduleswitches,cs_fp_emulation);
+
+{$ifdef x86_64}
+ {$warning HACK: turn off smartlinking}
+ exclude(initmoduleswitches,cs_create_smart);
+{$endif}
+
+ if not LinkTypeSetExplicitly then
+ set_default_link_type;
+
+ { Default alignment settings,
+ 1. load the defaults for the target
+ 2. override with generic optimizer setting (little size)
+ 3. override with the user specified -Oa }
+ UpdateAlignment(initalignment,target_info.alignment);
+ if (cs_littlesize in aktglobalswitches) then
+ begin
+ initalignment.procalign:=1;
+ initalignment.jumpalign:=1;
+ initalignment.loopalign:=1;
+ end;
+
+ UpdateAlignment(initalignment,option.paraalignment);
+
+ set_system_macro('FPC_VERSION',version_nr);
+ set_system_macro('FPC_RELEASE',release_nr);
+ set_system_macro('FPC_PATCH',patch_nr);
+
+ option.free;
+ Option:=nil;
+end;
+
+
+initialization
+ coption:=toption;
+finalization
+ if assigned(option) then
+ option.free;
+end.
diff --git a/compiler/optunrol.pas b/compiler/optunrol.pas
new file mode 100644
index 0000000000..0b69d121c2
--- /dev/null
+++ b/compiler/optunrol.pas
@@ -0,0 +1,170 @@
+{
+ Loop unrolling
+
+ Copyright (c) 2005 by Florian Klaempfl
+
+ 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 optunrol;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ node;
+
+ function unroll_loop(node : tnode) : tnode;
+
+ implementation
+
+ uses
+ globtype,globals,
+ cpuinfo,
+ nutils,
+ nbas,nflw,ncon,ninl,ncal;
+
+ var
+ nodecount : aint;
+
+ function donodecount(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ inc(nodecount);
+ result:=fen_false;
+ end;
+
+
+ { rough estimation how large the tree "node" is }
+ function countnodes(node : tnode) : aint;
+ begin
+ nodecount:=0;
+ foreachnodestatic(node,@donodecount,nil);
+ result:=nodecount;
+ end;
+
+
+ function number_unrolls(node : tnode) : integer;
+ begin
+{$ifdef i386}
+ { multiply by 2 for CPUs with a long pipeline }
+ if aktoptprocessor in [ClassPentium4] then
+ number_unrolls:=60 div countnodes(node)
+ else
+{$endif i386}
+ number_unrolls:=30 div countnodes(node);
+
+ if number_unrolls=0 then
+ number_unrolls:=1;
+ end;
+
+
+ function unroll_loop(node : tnode) : tnode;
+ var
+ unrolls,i : integer;
+ counts : qword;
+ unrollstatement : tstatementnode;
+ unrollblock : tblocknode;
+ entrylabel : tlabelnode;
+ begin
+ result:=nil;
+ if (cs_littlesize in aktglobalswitches) then
+ exit;
+ if not(node.nodetype in [forn]) then
+ exit;
+ unrolls:=number_unrolls(tfornode(node).t2);
+ if unrolls>1 then
+ begin
+ { number of executions known? }
+ if (tfornode(node).right.nodetype=ordconstn) and (tfornode(node).t1.nodetype=ordconstn) then
+ begin
+ if lnf_backward in tfornode(node).loopflags then
+ counts:=tordconstnode(tfornode(node).right).value-tordconstnode(tfornode(node).t1).value+1
+ else
+ counts:=tordconstnode(tfornode(node).t1).value-tordconstnode(tfornode(node).right).value+1;
+
+ { don't unroll more than we need }
+ if unrolls>counts then
+ unrolls:=counts;
+
+ { create block statement }
+ unrollblock:=internalstatements(unrollstatement);
+
+ { let's unroll (and rock of course) }
+ for i:=1 to unrolls do
+ begin
+ { create and insert copy of the statement block }
+ addstatement(unrollstatement,tfornode(tfornode(node).t2).getcopy);
+
+ { set and insert entry label? }
+ if (counts mod unrolls<>0) and
+ ((counts mod unrolls)=unrolls-i) then
+ begin
+ tfornode(node).entrylabel:=clabelnode.create(cnothingnode.create);
+ addstatement(unrollstatement,tfornode(node).entrylabel);
+ end;
+
+ { for itself increases at the last iteration }
+ if i<unrolls then
+ begin
+ { insert incrementation of counter var }
+ addstatement(unrollstatement,
+ geninlinenode(in_inc_x,false,ccallparanode.create(tfornode(node).left.getcopy,nil)));
+ end;
+ end;
+ { can we get rid of the for statement? }
+ if unrolls=counts then
+ result:=unrollblock;
+ end
+ else
+ begin
+ { unrolling is a little bit more tricky if we don't know the
+ loop count at compile time, but the solution is to use a jump table
+ which is indexed by "loop count mod unrolls" at run time and which
+ jumps then at the appropriate place inside the loop. Because
+ a module division is expensive, we can use only unroll counts dividable
+ by 2 }
+ case unrolls of
+ 1..2:
+ ;
+ 3:
+ unrolls:=2;
+ 4..7:
+ unrolls:=4;
+ { unrolls>4 already make no sense imo, but who knows (FK) }
+ 8..15:
+ unrolls:=8;
+ 16..31:
+ unrolls:=16;
+ 32..63:
+ unrolls:=32;
+ 64..$7fff:
+ unrolls:=64;
+ else
+ exit;
+ end;
+ { we don't handle this yet }
+ exit;
+ end;
+ if not(assigned(result)) then
+ begin
+ tfornode(node).t2.free;
+ tfornode(node).t2:=unrollblock;
+ end;
+ end;
+ end;
+
+end.
diff --git a/compiler/owar.pas b/compiler/owar.pas
new file mode 100644
index 0000000000..4980c0a793
--- /dev/null
+++ b/compiler/owar.pas
@@ -0,0 +1,282 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Contains the stuff for writing .a files directly
+
+ 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 owar;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,
+ owbase;
+
+type
+ tarhdr=packed record
+ name : array[0..15] of char;
+ date : array[0..11] of char;
+ uid : array[0..5] of char;
+ gid : array[0..5] of char;
+ mode : array[0..7] of char;
+ size : array[0..9] of char;
+ fmag : array[0..1] of char;
+ end;
+
+ tarobjectwriter=class(tobjectwriter)
+ constructor create(const Aarfn:string);
+ destructor destroy;override;
+ function createfile(const fn:string):boolean;override;
+ procedure closefile;override;
+ procedure writesym(const sym:string);override;
+ procedure write(const b;len:longint);override;
+ private
+ arfn : string;
+ arhdr : tarhdr;
+ symreloc,
+ symstr,
+ lfnstr,
+ ardata : TDynamicArray;
+ objpos : longint;
+ objfn : string;
+ timestamp : string[12];
+ procedure createarhdr(fn:string;size:longint;const gid,uid,mode:string);
+ procedure writear;
+ end;
+
+
+implementation
+
+uses
+ cstreams,
+ systems,
+ globals,
+ verbose,
+ dos;
+
+const
+ symrelocbufsize = 4096;
+ symstrbufsize = 8192;
+ lfnstrbufsize = 4096;
+ arbufsize = 65536;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+const
+ C1970=2440588;
+ D0=1461;
+ D1=146097;
+ D2=1721119;
+Function Gregorian2Julian(DT:DateTime):LongInt;
+Var
+ Century,XYear,Month : LongInt;
+Begin
+ Month:=DT.Month;
+ If Month<=2 Then
+ Begin
+ Dec(DT.Year);
+ Inc(Month,12);
+ End;
+ Dec(Month,3);
+ Century:=(longint(DT.Year Div 100)*D1) shr 2;
+ XYear:=(longint(DT.Year Mod 100)*D0) shr 2;
+ Gregorian2Julian:=((((Month*153)+2) div 5)+DT.Day)+D2+XYear+Century;
+End;
+
+function DT2Unix(DT:DateTime):LongInt;
+Begin
+ DT2Unix:=(Gregorian2Julian(DT)-C1970)*86400+(LongInt(DT.Hour)*3600)+(DT.Min*60)+DT.Sec;
+end;
+
+
+{*****************************************************************************
+ TArObjectWriter
+*****************************************************************************}
+
+constructor tarobjectwriter.create(const Aarfn:string);
+var
+ time : datetime;
+ dummy : word;
+begin
+ arfn:=Aarfn;
+ ardata:=TDynamicArray.Create(arbufsize);
+ symreloc:=TDynamicArray.Create(symrelocbufsize);
+ symstr:=TDynamicArray.Create(symstrbufsize);
+ lfnstr:=TDynamicArray.Create(lfnstrbufsize);
+{ create timestamp }
+ getdate(time.year,time.month,time.day,dummy);
+ gettime(time.hour,time.min,time.sec,dummy);
+ Str(DT2Unix(time),timestamp);
+end;
+
+
+destructor tarobjectwriter.destroy;
+begin
+ if Errorcount=0 then
+ writear;
+ arData.Free;
+ symreloc.Free;
+ symstr.Free;
+ lfnstr.Free;
+end;
+
+
+procedure tarobjectwriter.createarhdr(fn:string;size:longint;const gid,uid,mode:string);
+var
+ tmp : string[9];
+ hfn : string;
+begin
+ fillchar(arhdr,sizeof(tarhdr),' ');
+{ create ar header }
+ { win32 will change names starting with .\ to ./ when using lfn, corrupting
+ the sort order required for the idata sections. To prevent this strip
+ always the path from the filename. (PFV) }
+ hfn:=SplitFileName(fn);
+ if hfn='' then
+ hfn:=fn;
+ fn:=hfn+'/';
+ if length(fn)>16 then
+ begin
+ arhdr.name[0]:='/';
+ str(lfnstr.size,tmp);
+ move(tmp[1],arhdr.name[1],length(tmp));
+ fn:=fn+#10;
+ lfnstr.write(fn[1],length(fn));
+ end
+ else
+ move(fn[1],arhdr.name,length(fn));
+ { don't write a date if also no gid/uid/mode is specified }
+ if gid<>'' then
+ move(timestamp[1],arhdr.date,sizeof(timestamp));
+ str(size,tmp);
+ move(tmp[1],arhdr.size,length(tmp));
+ move(gid[1],arhdr.gid,length(gid));
+ move(uid[1],arhdr.uid,length(uid));
+ move(mode[1],arhdr.mode,length(mode));
+ arhdr.fmag:='`'#10;
+end;
+
+
+function tarobjectwriter.createfile(const fn:string):boolean;
+begin
+ objfn:=fn;
+ objpos:=ardata.size;
+ ardata.seek(objpos + sizeof(tarhdr));
+ createfile:=true;
+end;
+
+
+procedure tarobjectwriter.closefile;
+begin
+ ardata.align(2);
+{ fix the size in the header }
+ createarhdr(objfn,ardata.size-objpos-sizeof(tarhdr),'42','42','644');
+{ write the header }
+ ardata.seek(objpos);
+ ardata.write(arhdr,sizeof(tarhdr));
+end;
+
+
+procedure tarobjectwriter.writesym(const sym:string);
+var
+ c : char;
+begin
+ c:=#0;
+ symreloc.write(objpos,4);
+ symstr.write(sym[1],length(sym));
+ symstr.write(c,1);
+end;
+
+
+procedure tarobjectwriter.write(const b;len:longint);
+begin
+ ardata.write(b,len);
+end;
+
+
+procedure tarobjectwriter.writear;
+
+ function lsb2msb(l:longint):longint;
+ type
+ bytearr=array[0..3] of byte;
+ var
+ l1 : longint;
+ begin
+ bytearr(l1)[0]:=bytearr(l)[3];
+ bytearr(l1)[1]:=bytearr(l)[2];
+ bytearr(l1)[2]:=bytearr(l)[1];
+ bytearr(l1)[3]:=bytearr(l)[0];
+ lsb2msb:=l1;
+ end;
+
+const
+ armagic:array[1..8] of char='!<arch>'#10;
+var
+ arf : TCFileStream;
+ fixup,l,
+ relocs,i : longint;
+begin
+ arf:=TCFileStream.Create(arfn,fmCreate);
+ if CStreamError<>0 then
+ begin
+ Message1(exec_e_cant_create_archivefile,arfn);
+ exit;
+ end;
+ arf.Write(armagic,sizeof(armagic));
+ { align first, because we need the size for the fixups of the symbol reloc }
+ if lfnstr.size>0 then
+ lfnstr.align(2);
+ if symreloc.size>0 then
+ begin
+ symstr.align(2);
+ fixup:=12+sizeof(tarhdr)+symreloc.size+symstr.size;
+ if lfnstr.size>0 then
+ inc(fixup,lfnstr.size+sizeof(tarhdr));
+ relocs:=symreloc.size div 4;
+ { fixup relocs }
+ for i:=0to relocs-1 do
+ begin
+ symreloc.seek(i*4);
+ symreloc.read(l,4);
+ symreloc.seek(i*4);
+ l:=lsb2msb(l+fixup);
+ symreloc.write(l,4);
+ end;
+ createarhdr('',4+symreloc.size+symstr.size,'0','0','0');
+ arf.Write(arhdr,sizeof(tarhdr));
+ relocs:=lsb2msb(relocs);
+ arf.Write(relocs,4);
+ symreloc.WriteStream(arf);
+ symstr.WriteStream(arf);
+ end;
+ if lfnstr.size>0 then
+ begin
+ createarhdr('/',lfnstr.size,'','','');
+ arf.Write(arhdr,sizeof(tarhdr));
+ lfnstr.WriteStream(arf);
+ end;
+ ardata.WriteStream(arf);
+ Arf.Free;
+end;
+
+
+end.
diff --git a/compiler/owbase.pas b/compiler/owbase.pas
new file mode 100644
index 0000000000..c913dabcc7
--- /dev/null
+++ b/compiler/owbase.pas
@@ -0,0 +1,320 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Contains the base stuff for writing for object files to disk
+
+ 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 owbase;
+
+{$i fpcdefs.inc}
+
+interface
+uses
+ cstreams,
+ cclasses;
+
+type
+ tobjectwriter=class
+ private
+ f : TCFileStream;
+ opened : boolean;
+ buf : pchar;
+ bufidx : longint;
+ size : longint;
+ procedure writebuf;
+ public
+ constructor create;
+ destructor destroy;override;
+ function createfile(const fn:string):boolean;virtual;
+ procedure closefile;virtual;
+ procedure writesym(const sym:string);virtual;
+ procedure write(const b;len:longint);virtual;
+ procedure WriteZeros(l:longint);
+ end;
+
+ tobjectreader=class
+ private
+ f : TCFileStream;
+ opened : boolean;
+ buf : pchar;
+ bufidx,
+ bufmax : longint;
+ function readbuf:boolean;
+ public
+ constructor create;
+ destructor destroy;override;
+ function openfile(const fn:string):boolean;virtual;
+ procedure closefile;virtual;
+ procedure seek(len:longint);
+ function read(var b;len:longint):boolean;virtual;
+ function readarray(a:TDynamicArray;len:longint):boolean;
+ end;
+
+implementation
+
+uses
+ verbose, globals;
+
+const
+ bufsize = 32768;
+
+
+{****************************************************************************
+ TObjectWriter
+****************************************************************************}
+
+constructor tobjectwriter.create;
+begin
+ getmem(buf,bufsize);
+ bufidx:=0;
+ opened:=false;
+ size:=0;
+end;
+
+
+destructor tobjectwriter.destroy;
+begin
+ if opened then
+ closefile;
+ freemem(buf,bufsize);
+end;
+
+
+function tobjectwriter.createfile(const fn:string):boolean;
+begin
+ createfile:=false;
+ f:=TCFileStream.Create(fn,fmCreate);
+ if CStreamError<>0 then
+ begin
+ Message1(exec_e_cant_create_objectfile,fn);
+ exit;
+ end;
+ bufidx:=0;
+ size:=0;
+ opened:=true;
+ createfile:=true;
+end;
+
+
+procedure tobjectwriter.closefile;
+var
+ fn : string;
+begin
+ if bufidx>0 then
+ writebuf;
+ fn:=f.filename;
+ f.free;
+{ Remove if size is 0 }
+ if size=0 then
+ RemoveFile(fn);
+ opened:=false;
+ size:=0;
+end;
+
+
+procedure tobjectwriter.writebuf;
+begin
+ f.write(buf^,bufidx);
+ bufidx:=0;
+end;
+
+
+procedure tobjectwriter.writesym(const sym:string);
+begin
+end;
+
+
+procedure tobjectwriter.write(const b;len:longint);
+var
+ p : pchar;
+ left,
+ idx : longint;
+begin
+ inc(size,len);
+ p:=pchar(@b);
+ idx:=0;
+ while len>0 do
+ begin
+ left:=bufsize-bufidx;
+ if len>left then
+ begin
+ move(p[idx],buf[bufidx],left);
+ dec(len,left);
+ inc(idx,left);
+ inc(bufidx,left);
+ writebuf;
+ end
+ else
+ begin
+ move(p[idx],buf[bufidx],len);
+ inc(bufidx,len);
+ exit;
+ end;
+ end;
+end;
+
+
+procedure tobjectwriter.WriteZeros(l:longint);
+var
+ empty : array[0..255] of byte;
+begin
+ if l>sizeof(empty) then
+ internalerror(200404081);
+ if l>0 then
+ begin
+ fillchar(empty,l,0);
+ Write(empty,l);
+ end;
+end;
+
+
+{****************************************************************************
+ TObjectReader
+****************************************************************************}
+
+constructor tobjectreader.create;
+begin
+ getmem(buf,bufsize);
+ bufidx:=0;
+ bufmax:=0;
+ opened:=false;
+end;
+
+
+destructor tobjectreader.destroy;
+begin
+ if opened then
+ closefile;
+ freemem(buf,bufsize);
+end;
+
+
+function tobjectreader.openfile(const fn:string):boolean;
+begin
+ openfile:=false;
+ f:=TCFileStream.Create(fn,fmOpenRead);
+ if CStreamError<>0 then
+ begin
+ Message1(exec_e_cant_create_objectfile,fn);
+ exit;
+ end;
+ bufidx:=0;
+ bufmax:=0;
+ opened:=true;
+ openfile:=true;
+end;
+
+
+procedure tobjectreader.closefile;
+begin
+ f.free;
+ opened:=false;
+ bufidx:=0;
+ bufmax:=0;
+end;
+
+
+function tobjectreader.readbuf:boolean;
+begin
+ bufmax:=f.read(buf^,bufsize);
+ bufidx:=0;
+ readbuf:=(bufmax>0);
+end;
+
+
+procedure tobjectreader.seek(len:longint);
+begin
+ f.seek(len,soFromBeginning);
+ bufidx:=0;
+ bufmax:=0;
+end;
+
+
+function tobjectreader.read(var b;len:longint):boolean;
+var
+ p : pchar;
+ left,
+ idx : longint;
+begin
+ read:=false;
+ if bufmax=0 then
+ if not readbuf then
+ exit;
+ p:=pchar(@b);
+ idx:=0;
+ while len>0 do
+ begin
+ left:=bufmax-bufidx;
+ if len>left then
+ begin
+ move(buf[bufidx],p[idx],left);
+ dec(len,left);
+ inc(idx,left);
+ inc(bufidx,left);
+ if not readbuf then
+ exit;
+ end
+ else
+ begin
+ move(buf[bufidx],p[idx],len);
+ inc(bufidx,len);
+ inc(idx,len);
+ break;
+ end;
+ end;
+ read:=(idx=len);
+end;
+
+
+function tobjectreader.readarray(a:TDynamicArray;len:longint):boolean;
+var
+ orglen,
+ left,
+ idx : longint;
+begin
+ readarray:=false;
+ if bufmax=0 then
+ if not readbuf then
+ exit;
+ orglen:=len;
+ idx:=0;
+ while len>0 do
+ begin
+ left:=bufmax-bufidx;
+ if len>left then
+ begin
+ a.Write(buf[bufidx],left);
+ dec(len,left);
+ inc(idx,left);
+ inc(bufidx,left);
+ if not readbuf then
+ exit;
+ end
+ else
+ begin
+ a.Write(buf[bufidx],len);
+ inc(bufidx,len);
+ inc(idx,len);
+ break;
+ end;
+ end;
+ readarray:=(idx=orglen);
+end;
+
+
+end.
diff --git a/compiler/parabase.pas b/compiler/parabase.pas
new file mode 100644
index 0000000000..5f3499d4bd
--- /dev/null
+++ b/compiler/parabase.pas
@@ -0,0 +1,250 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generic calling convention handling
+
+ 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 parabase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,globtype,
+ cpubase,cgbase,cgutils;
+
+ type
+ TCGParaReference = record
+ index : tregister;
+ offset : aint;
+ end;
+
+ PCGParaLocation = ^TCGParaLocation;
+ TCGParaLocation = record
+ Next : PCGParaLocation;
+ Size : TCGSize; { size of this location }
+ Loc : TCGLoc;
+ case TCGLoc of
+ LOC_REFERENCE : (reference : TCGParaReference);
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_REGISTER,
+ LOC_CREGISTER : (register : tregister);
+ end;
+
+ TCGPara = object
+ Location : PCGParalocation;
+ Alignment : ShortInt;
+ Size : TCGSize; { Size of the parameter included in all locations }
+ IntSize: aint; { size of the total location in bytes }
+{$ifdef powerpc}
+ composite: boolean; { under the AIX abi, how certain parameters are passed depends on whether they are composite or not }
+{$endif powerpc}
+ constructor init;
+ destructor done;
+ procedure reset;
+ function getcopy:tcgpara;
+ procedure check_simple_location;
+ function add_location:pcgparalocation;
+ procedure get_location(var newloc:tlocation);
+ end;
+
+ tvarargsinfo = (
+ va_uses_float_reg
+ );
+
+ tparalist = class(tlist)
+ procedure SortParas;
+ end;
+
+ tvarargsparalist = class(tparalist)
+ varargsinfo : set of tvarargsinfo;
+{$ifdef x86_64}
+ { x86_64 requires %al to contain the no. SSE regs passed }
+ mmregsused : longint;
+{$endif x86_64}
+ end;
+
+
+
+implementation
+
+ uses
+ systems,verbose,
+ symsym;
+
+
+{****************************************************************************
+ TCGPara
+****************************************************************************}
+
+ constructor tcgpara.init;
+ begin
+ alignment:=0;
+ size:=OS_NO;
+ intsize:=0;
+ location:=nil;
+{$ifdef powerpc}
+ composite:=false;
+{$endif powerpc}
+ end;
+
+
+ destructor tcgpara.done;
+ begin
+ reset;
+ end;
+
+
+ procedure tcgpara.reset;
+ var
+ hlocation : pcgparalocation;
+ begin
+ while assigned(location) do
+ begin
+ hlocation:=location^.next;
+ dispose(location);
+ location:=hlocation;
+ end;
+ alignment:=0;
+ size:=OS_NO;
+ intsize:=0;
+{$ifdef powerpc}
+ composite:=false;
+{$endif powerpc}
+ end;
+
+
+ function tcgpara.getcopy:tcgpara;
+ var
+ hlocation : pcgparalocation;
+ begin
+ result.init;
+ while assigned(location) do
+ begin
+ hlocation:=result.add_location;
+ hlocation^:=location^;
+ hlocation^.next:=nil;
+ location:=location^.next;
+ end;
+ result.alignment:=alignment;
+ result.size:=size;
+ result.intsize:=intsize;
+{$ifdef powerpc}
+ result.composite:=composite;
+{$endif powerpc}
+ end;
+
+
+ function tcgpara.add_location:pcgparalocation;
+ var
+ prevlocation,
+ hlocation : pcgparalocation;
+ begin
+ prevlocation:=nil;
+ hlocation:=location;
+ while assigned(hlocation) do
+ begin
+ prevlocation:=hlocation;
+ hlocation:=hlocation^.next;
+ end;
+ new(hlocation);
+ Fillchar(hlocation^,sizeof(tcgparalocation),0);
+ if assigned(prevlocation) then
+ prevlocation^.next:=hlocation
+ else
+ location:=hlocation;
+ result:=hlocation;
+ end;
+
+
+ procedure tcgpara.check_simple_location;
+ begin
+ if not assigned(location) then
+ internalerror(200408161);
+ if assigned(location^.next) then
+ internalerror(200408162);
+ end;
+
+
+ procedure tcgpara.get_location(var newloc:tlocation);
+ begin
+ if not assigned(location) then
+ internalerror(200408205);
+ fillchar(newloc,sizeof(newloc),0);
+ newloc.loc:=location^.loc;
+ newloc.size:=size;
+ case location^.loc of
+ LOC_REGISTER :
+ begin
+{$ifndef cpu64bit}
+ if size in [OS_64,OS_S64] then
+ begin
+ if not assigned(location^.next) then
+ internalerror(200408206);
+ if (location^.next^.loc<>LOC_REGISTER) then
+ internalerror(200408207);
+ if (target_info.endian = ENDIAN_BIG) then
+ begin
+ newloc.register64.reghi:=location^.register;
+ newloc.register64.reglo:=location^.next^.register;
+ end
+ else
+ begin
+ newloc.register64.reglo:=location^.register;
+ newloc.register64.reghi:=location^.next^.register;
+ end;
+ end
+ else
+{$endif}
+ newloc.register:=location^.register;
+ end;
+ LOC_FPUREGISTER,
+ LOC_MMREGISTER :
+ newloc.register:=location^.register;
+ LOC_REFERENCE :
+ begin
+ newloc.reference.base:=location^.reference.index;
+ newloc.reference.offset:=location^.reference.offset;
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TParaList
+****************************************************************************}
+
+ function ParaNrCompare(Item1, Item2: Pointer): Integer;
+ var
+ I1 : tparavarsym absolute Item1;
+ I2 : tparavarsym absolute Item2;
+ begin
+ Result:=longint(I1.paranr)-longint(I2.paranr);
+ end;
+
+
+ procedure TParaList.SortParas;
+ begin
+ Sort(@ParaNrCompare);
+ end;
+
+
+end.
diff --git a/compiler/paramgr.pas b/compiler/paramgr.pas
new file mode 100644
index 0000000000..1d0a0159e6
--- /dev/null
+++ b/compiler/paramgr.pas
@@ -0,0 +1,385 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generic calling convention handling
+
+ 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.
+ ****************************************************************************
+}
+{# Parameter passing manager. Used to manage how
+ parameters are passed to routines.
+}
+unit paramgr;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,globtype,
+ cpubase,cgbase,
+ parabase,
+ aasmtai,
+ symconst,symtype,symsym,symdef;
+
+ type
+ {# This class defines some methods to take care of routine
+ parameters. It should be overriden for each new processor
+ }
+ tparamanager = class
+ { true if the location in paraloc can be reused as localloc }
+ function param_use_paraloc(const cgpara:tcgpara):boolean;virtual;
+ {# Returns true if the return value is actually a parameter
+ pointer.
+ }
+ function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;virtual;
+
+ function push_high_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;virtual;
+
+ { Returns true if a parameter is too large to copy and only
+ the address is pushed
+ }
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;virtual;abstract;
+ { return the size of a push }
+ function push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint;
+ {# Returns a structure giving the information on
+ the storage of the parameter (which must be
+ an integer parameter). This is only used when calling
+ internal routines directly, where all parameters must
+ be 4-byte values.
+
+ In case the location is a register, this register is allocated.
+ Call freeintparaloc() after the call to free the locations again.
+ Default implementation: don't do anything at all (in case you don't
+ use register parameter passing)
+
+ @param(list Current assembler list)
+ @param(nr Parameter number of routine, starting from 1)
+ }
+ function get_para_align(calloption : tproccalloption):byte;virtual;
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;virtual;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;virtual;
+ function get_volatile_registers_flags(calloption : tproccalloption):tcpuregisterset;virtual;
+ function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;virtual;
+
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);virtual;abstract;
+
+ {# allocate a parameter location created with create_paraloc_info
+
+ @param(list Current assembler list)
+ @param(loc Parameter location)
+ }
+ procedure allocparaloc(list: taasmoutput; const cgpara: TCGPara); virtual;
+
+ {# free a parameter location allocated with alloccgpara
+
+ @param(list Current assembler list)
+ @param(loc Parameter location)
+ }
+ procedure freeparaloc(list: taasmoutput; const cgpara: TCGPara); virtual;
+
+ { This is used to populate the location information on all parameters
+ for the routine as seen in either the caller or the callee. It returns
+ the size allocated on the stack
+ }
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;virtual;abstract;
+
+ { This is used to populate the location information on all parameters
+ for the routine when it is being inlined. It returns
+ the size allocated on the stack
+ }
+ function create_inline_paraloc_info(p : tabstractprocdef):longint;virtual;
+
+ { This is used to populate the location information on all parameters
+ for the routine that are passed as varargs. It returns
+ the size allocated on the stack (including the normal parameters)
+ }
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;virtual;abstract;
+
+ procedure createtempparaloc(list: taasmoutput;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);virtual;
+ procedure duplicateparaloc(list: taasmoutput;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
+
+ function parseparaloc(parasym : tparavarsym;const s : string) : boolean;virtual;abstract;
+ end;
+
+
+ var
+ paramanager : tparamanager;
+
+
+implementation
+
+ uses
+ systems,
+ cgobj,tgobj,cgutils,
+ defutil,verbose;
+
+ { true if the location in paraloc can be reused as localloc }
+ function tparamanager.param_use_paraloc(const cgpara:tcgpara):boolean;
+ begin
+ result:=false;
+ end;
+
+
+ { true if uses a parameter as return value }
+ function tparamanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ ret_in_param:=((def.deftype=arraydef) and not(is_dynamic_array(def))) or
+ (def.deftype=recorddef) or
+ ((def.deftype=stringdef) and (tstringdef(def).string_typ in [st_shortstring,st_longstring])) or
+ ((def.deftype=procvardef) and (po_methodpointer in tprocvardef(def).procoptions)) or
+ ((def.deftype=objectdef) and is_object(def)) or
+ (def.deftype=variantdef) or
+ ((def.deftype=setdef) and (tsetdef(def).settype<>smallset));
+ end;
+
+
+ function tparamanager.push_high_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ push_high_param:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and
+ (
+ is_open_array(def) or
+ is_open_string(def) or
+ is_array_of_const(def)
+ );
+ end;
+
+
+ { return the size of a push }
+ function tparamanager.push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint;
+ begin
+ push_size:=-1;
+ case varspez of
+ vs_out,
+ vs_var :
+ push_size:=sizeof(aint);
+ vs_value,
+ vs_const :
+ begin
+ if push_addr_param(varspez,def,calloption) then
+ push_size:=sizeof(aint)
+ else
+ begin
+ { special array are normally pushed by addr, only for
+ cdecl array of const it comes here and the pushsize
+ is unknown }
+ if is_array_of_const(def) then
+ push_size:=0
+ else
+ push_size:=def.size;
+ end;
+ end;
+ end;
+ end;
+
+
+ function tparamanager.get_para_align(calloption : tproccalloption):byte;
+ begin
+ result:=std_param_align;
+ end;
+
+
+ function tparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+
+ function tparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+
+ function tparamanager.get_volatile_registers_flags(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+
+ function tparamanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+
+ procedure tparamanager.allocparaloc(list: taasmoutput; const cgpara: TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ paraloc:=cgpara.location;
+ while assigned(paraloc) do
+ begin
+ case paraloc^.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ if getsupreg(paraloc^.register)<first_int_imreg then
+ cg.getcpuregister(list,paraloc^.register);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ if getsupreg(paraloc^.register)<first_fpu_imreg then
+ cg.getcpuregister(list,paraloc^.register);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER :
+ begin
+ if getsupreg(paraloc^.register)<first_mm_imreg then
+ cg.getcpuregister(list,paraloc^.register);
+ end;
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ procedure tparamanager.freeparaloc(list: taasmoutput; const cgpara: TCGPara);
+ var
+ paraloc : Pcgparalocation;
+{$ifdef cputargethasfixedstack}
+ href : treference;
+{$endif cputargethasfixedstack}
+ begin
+ paraloc:=cgpara.location;
+ while assigned(paraloc) do
+ begin
+ case paraloc^.loc of
+ LOC_VOID:
+ ;
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ if getsupreg(paraloc^.register)<first_int_imreg then
+ cg.ungetcpuregister(list,paraloc^.register);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ if getsupreg(paraloc^.register)<first_fpu_imreg then
+ cg.ungetcpuregister(list,paraloc^.register);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER :
+ begin
+ if getsupreg(paraloc^.register)<first_mm_imreg then
+ cg.ungetcpuregister(list,paraloc^.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+{$ifdef cputargethasfixedstack}
+ { don't use reference_reset_base, because that will depend on cgobj }
+ fillchar(href,sizeof(href),0);
+ href.base:=paraloc^.reference.index;
+ href.offset:=paraloc^.reference.offset;
+ tg.ungettemp(list,href);
+{$endif cputargethasfixedstack}
+ end;
+ else
+ internalerror(2004110212);
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ procedure tparamanager.createtempparaloc(list: taasmoutput;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
+ var
+ href : treference;
+ len : aint;
+ paraloc,
+ newparaloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=parasym.paraloc[callerside].size;
+ cgpara.intsize:=parasym.paraloc[callerside].intsize;
+ cgpara.alignment:=parasym.paraloc[callerside].alignment;
+{$ifdef powerpc}
+ cgpara.composite:=parasym.paraloc[callerside].composite;
+{$endif powerpc}
+ paraloc:=parasym.paraloc[callerside].location;
+ while assigned(paraloc) do
+ begin
+ if paraloc^.size=OS_NO then
+ len:=push_size(parasym.varspez,parasym.vartype.def,calloption)
+ else
+ len:=tcgsize2size[paraloc^.size];
+ newparaloc:=cgpara.add_location;
+ newparaloc^.size:=paraloc^.size;
+{$warning maybe release this optimization for all targets?}
+{$ifdef sparc}
+ { Does it fit a register? }
+ if len<=sizeof(aint) then
+ newparaloc^.loc:=LOC_REGISTER
+ else
+{$endif sparc}
+ newparaloc^.loc:=paraloc^.loc;
+ case newparaloc^.loc of
+ LOC_REGISTER :
+ newparaloc^.register:=cg.getintregister(list,paraloc^.size);
+ LOC_FPUREGISTER :
+ newparaloc^.register:=cg.getfpuregister(list,paraloc^.size);
+ LOC_MMREGISTER :
+ newparaloc^.register:=cg.getmmregister(list,paraloc^.size);
+ LOC_REFERENCE :
+ begin
+ tg.gettemp(list,len,tt_persistent,href);
+ newparaloc^.reference.index:=href.base;
+ newparaloc^.reference.offset:=href.offset;
+ end;
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ procedure tparamanager.duplicateparaloc(list: taasmoutput;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
+ var
+ paraloc,
+ newparaloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=parasym.paraloc[callerside].size;
+ cgpara.intsize:=parasym.paraloc[callerside].intsize;
+ cgpara.alignment:=parasym.paraloc[callerside].alignment;
+{$ifdef powerpc}
+ cgpara.composite:=parasym.paraloc[callerside].composite;
+{$endif powerpc}
+ paraloc:=parasym.paraloc[callerside].location;
+ while assigned(paraloc) do
+ begin
+ newparaloc:=cgpara.add_location;
+ move(paraloc^,newparaloc^,sizeof(newparaloc^));
+ newparaloc^.next:=nil;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ function tparamanager.create_inline_paraloc_info(p : tabstractprocdef):longint;
+ begin
+ { We need to return the size allocated }
+ create_paraloc_info(p,callerside);
+ result:=create_paraloc_info(p,calleeside);
+ end;
+
+
+initialization
+ ;
+finalization
+ paramanager.free;
+end.
diff --git a/compiler/parser.pas b/compiler/parser.pas
new file mode 100644
index 0000000000..8d5a6d06fb
--- /dev/null
+++ b/compiler/parser.pas
@@ -0,0 +1,613 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit does the parsing process
+
+ 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 parser;
+
+{$i fpcdefs.inc}
+
+interface
+
+{$ifdef PREPROCWRITE}
+ procedure preprocess(const filename:string);
+{$endif PREPROCWRITE}
+ procedure compile(const filename:string);
+ procedure initparser;
+ procedure doneparser;
+
+implementation
+
+ uses
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+ sysutils,
+{$ENDIF MACOS_USE_FAKE_SYSUTILS}
+ cutils,cclasses,
+ globtype,version,tokens,systems,globals,verbose,
+ symbase,symtable,symsym,
+ finput,fmodule,fppu,
+ aasmbase,aasmtai,
+ cgbase,
+ script,gendef,
+{$ifdef BrowserCol}
+ browcol,
+{$endif BrowserCol}
+{$ifdef BrowserLog}
+ browlog,
+{$endif BrowserLog}
+ comphook,
+ scanner,scandir,
+ pbase,ptype,psystem,pmodules,psub,
+ cresstr,cpuinfo,procinfo;
+
+
+ procedure initparser;
+ begin
+ { ^M means a string or a char, because we don't parse a }
+ { type declaration }
+ ignore_equal:=false;
+
+ { we didn't parse a object or class declaration }
+ { and no function header }
+ testcurobject:=0;
+
+ { Current compiled module/proc }
+ objectlibrary:=nil;
+ current_module:=nil;
+ compiled_module:=nil;
+ current_procinfo:=nil;
+ SetCompileModule(nil);
+
+ loaded_units:=TLinkedList.Create;
+
+ usedunits:=TLinkedList.Create;
+
+ { global switches }
+ aktglobalswitches:=initglobalswitches;
+
+ aktsourcecodepage:=initsourcecodepage;
+
+ { initialize scanner }
+ InitScanner;
+ InitScannerDirectives;
+
+ { scanner }
+ c:=#0;
+ pattern:='';
+ orgpattern:='';
+ current_scanner:=nil;
+
+ { register all nodes and tais }
+ registernodes;
+ registertais;
+
+ { memory sizes }
+ if stacksize=0 then
+ stacksize:=target_info.stacksize;
+
+ { open assembler response }
+ if cs_link_on_target in aktglobalswitches then
+ GenerateAsmRes(outputexedir+inputfile+'_ppas')
+ else
+ GenerateAsmRes(outputexedir+'ppas');
+
+ { open deffile }
+ DefFile:=TDefFile.Create(outputexedir+inputfile+target_info.defext);
+
+ { list of generated .o files, so the linker can remove them }
+ SmartLinkOFiles:=TStringList.Create;
+
+ { codegen }
+ if paraprintnodetree<>0 then
+ printnode_reset;
+
+ { target specific stuff }
+ case target_info.system of
+ system_powerpc_morphos:
+ include(supported_calling_conventions,pocall_syscall);
+ system_m68k_amiga:
+ include(supported_calling_conventions,pocall_syscall);
+ end;
+ end;
+
+
+ procedure doneparser;
+ begin
+ { Reset current compiling info, so destroy routines can't
+ reference the data that might already be destroyed }
+ objectlibrary:=nil;
+ current_module:=nil;
+ compiled_module:=nil;
+ current_procinfo:=nil;
+ SetCompileModule(nil);
+
+ { unload units }
+ loaded_units.free;
+ usedunits.free;
+
+ { if there was an error in the scanner, the scanner is
+ still assinged }
+ if assigned(current_scanner) then
+ begin
+ current_scanner.free;
+ current_scanner:=nil;
+ end;
+
+ { close scanner }
+ DoneScanner;
+
+ { close ppas,deffile }
+ asmres.free;
+ deffile.free;
+
+ { free list of .o files }
+ SmartLinkOFiles.Free;
+ end;
+
+
+
+
+{$ifdef PREPROCWRITE}
+ procedure preprocess(const filename:string);
+ var
+ i : longint;
+ begin
+ new(preprocfile,init('pre'));
+ { initialize a module }
+ current_module:=new(pmodule,init(filename,false));
+
+ macrosymtablestack:= initialmacrosymtable;
+ current_module.localmacrosymtable:= tmacrosymtable.create(false);
+ current_module.localmacrosymtable.next:= initialmacrosymtable;
+ macrosymtablestack:= current_module.localmacrosymtable;
+ ConsolidateMode;
+
+ main_module:=current_module;
+ { startup scanner, and save in current_module }
+ current_scanner:=new(pscannerfile,Init(filename));
+ current_module.scanner:=current_scanner;
+ { loop until EOF is found }
+ repeat
+ current_scanner^.readtoken;
+ preprocfile^.AddSpace;
+ case token of
+ _ID :
+ begin
+ preprocfile^.Add(orgpattern);
+ end;
+ _REALNUMBER,
+ _INTCONST :
+ preprocfile^.Add(pattern);
+ _CSTRING :
+ begin
+ i:=0;
+ while (i<length(pattern)) do
+ begin
+ inc(i);
+ if pattern[i]='''' then
+ begin
+ insert('''',pattern,i);
+ inc(i);
+ end;
+ end;
+ preprocfile^.Add(''''+pattern+'''');
+ end;
+ _CCHAR :
+ begin
+ case pattern[1] of
+ #39 :
+ pattern:='''''''';
+ #0..#31,
+ #128..#255 :
+ begin
+ str(ord(pattern[1]),pattern);
+ pattern:='#'+pattern;
+ end;
+ else
+ pattern:=''''+pattern[1]+'''';
+ end;
+ preprocfile^.Add(pattern);
+ end;
+ _EOF :
+ break;
+ else
+ preprocfile^.Add(tokeninfo^[token].str)
+ end;
+ until false;
+ { free scanner }
+ dispose(current_scanner,done);
+ current_scanner:=nil;
+ { close }
+ dispose(preprocfile,done);
+ end;
+{$endif PREPROCWRITE}
+
+
+{*****************************************************************************
+ Create information for a new module
+*****************************************************************************}
+
+ procedure init_module;
+ var
+ i : Tasmlist;
+ begin
+ exprasmlist:=taasmoutput.create;
+ for i:=low(Tasmlist) to high(Tasmlist) do
+ asmlist[i]:=Taasmoutput.create;
+
+ { PIC data }
+{$ifdef powerpc}
+ if target_info.system=system_powerpc_darwin then
+ asmlist[al_picdata].concat(tai_directive.create(asd_non_lazy_symbol_pointer,''));
+{$endif powerpc}
+
+ { Resource strings }
+ cresstr.resourcestrings:=Tresourcestrings.Create;
+
+ { use the librarydata from current_module }
+ objectlibrary:=current_module.librarydata;
+ end;
+
+
+ procedure done_module;
+ var
+{$ifdef MEMDEBUG}
+ d : tmemdebug;
+{$endif}
+ i:Tasmlist;
+ begin
+{$ifdef MEMDEBUG}
+ d:=tmemdebug.create(current_module.modulename^+' - asmlists');
+{$endif}
+ for i:=low(Tasmlist) to high(Tasmlist) do
+ if asmlist[i]<>nil then
+ asmlist[i].free;
+{$ifdef MEMDEBUG}
+ d.free;
+{$endif}
+ { resource strings }
+ cresstr.resourcestrings.free;
+ objectlibrary:=nil;
+ end;
+
+
+{*****************************************************************************
+ Compile a source file
+*****************************************************************************}
+
+ procedure compile(const filename:string);
+ type
+ polddata=^tolddata;
+ tolddata=record
+ { scanner }
+ oldidtoken,
+ oldtoken : ttoken;
+ oldtokenpos : tfileposinfo;
+ oldc : char;
+ oldpattern,
+ oldorgpattern : string;
+ old_block_type : tblock_type;
+ { symtable }
+ oldrefsymtable,
+ olddefaultsymtablestack,
+ oldsymtablestack : tsymtable;
+ olddefaultmacrosymtablestack,
+ oldmacrosymtablestack : tsymtable;
+ oldaktprocsym : tprocsym;
+ { cg }
+ oldparse_only : boolean;
+ { asmlists }
+ oldexprasmlist:Taasmoutput;
+ oldasmlist:array[Tasmlist] of Taasmoutput;
+ oldobjectlibrary : tasmlibrarydata;
+ { al_resourcestrings }
+ Oldresourcestrings : tresourcestrings;
+ { akt.. things }
+ oldaktlocalswitches : tlocalswitches;
+ oldaktmoduleswitches : tmoduleswitches;
+ oldaktfilepos : tfileposinfo;
+ oldaktpackrecords,
+ oldaktpackenum : shortint;
+ oldaktmaxfpuregisters : longint;
+ oldaktalignment : talignmentinfo;
+ oldaktspecificoptprocessor,
+ oldaktoptprocessor : tprocessors;
+ oldaktfputype : tfputype;
+ oldaktasmmode : tasmmode;
+ oldaktinterfacetype: tinterfacetypes;
+ oldaktmodeswitches : tmodeswitches;
+ old_compiled_module : tmodule;
+ oldcurrent_procinfo : tprocinfo;
+ oldaktdefproccall : tproccalloption;
+ oldsourcecodepage : tcodepagestring;
+ end;
+
+ var
+ olddata : polddata;
+ begin
+ inc(compile_level);
+ parser_current_file:=filename;
+ { Uses heap memory instead of placing everything on the
+ stack. This is needed because compile() can be called
+ recursively }
+ new(olddata);
+ with olddata^ do
+ begin
+ old_compiled_module:=compiled_module;
+ { save symtable state }
+ oldsymtablestack:=symtablestack;
+ oldmacrosymtablestack:=macrosymtablestack;
+ olddefaultsymtablestack:=defaultsymtablestack;
+ olddefaultmacrosymtablestack:=defaultmacrosymtablestack;
+ oldrefsymtable:=refsymtable;
+ oldcurrent_procinfo:=current_procinfo;
+ oldaktdefproccall:=aktdefproccall;
+ { save scanner state }
+ oldc:=c;
+ oldpattern:=pattern;
+ oldorgpattern:=orgpattern;
+ oldtoken:=token;
+ oldidtoken:=idtoken;
+ old_block_type:=block_type;
+ oldtokenpos:=akttokenpos;
+ oldsourcecodepage:=aktsourcecodepage;
+ { save cg }
+ oldparse_only:=parse_only;
+ { save assembler lists }
+ oldasmlist:=asmlist;
+ oldexprasmlist:=exprasmlist;
+ oldobjectlibrary:=objectlibrary;
+ Oldresourcestrings:=resourcestrings;
+ { save akt... state }
+ { handle the postponed case first }
+ if localswitcheschanged then
+ begin
+ aktlocalswitches:=nextaktlocalswitches;
+ localswitcheschanged:=false;
+ end;
+ oldaktlocalswitches:=aktlocalswitches;
+ oldaktmoduleswitches:=aktmoduleswitches;
+ oldaktalignment:=aktalignment;
+ oldaktpackenum:=aktpackenum;
+ oldaktpackrecords:=aktpackrecords;
+ oldaktfputype:=aktfputype;
+ oldaktmaxfpuregisters:=aktmaxfpuregisters;
+ oldaktoptprocessor:=aktoptprocessor;
+ oldaktspecificoptprocessor:=aktspecificoptprocessor;
+ oldaktasmmode:=aktasmmode;
+ oldaktinterfacetype:=aktinterfacetype;
+ oldaktfilepos:=aktfilepos;
+ oldaktmodeswitches:=aktmodeswitches;
+ end;
+ { show info }
+ Message1(parser_i_compiling,filename);
+
+ { reset symtable }
+ symtablestack:=nil;
+ macrosymtablestack:=nil;
+ defaultsymtablestack:=nil;
+ defaultmacrosymtablestack:=nil;
+ systemunit:=nil;
+ refsymtable:=nil;
+ aktdefproccall:=initdefproccall;
+ registerdef:=true;
+ aktexceptblock:=0;
+ exceptblockcounter:=0;
+ aktmaxfpuregisters:=-1;
+ { reset the unit or create a new program }
+ { a unit compiled at command line must be inside the loaded_unit list }
+ if (compile_level=1) then
+ begin
+ if assigned(current_module) then
+ internalerror(200501158);
+ current_module:=tppumodule.create(nil,filename,'',false);
+ addloadedunit(current_module);
+ main_module:=current_module;
+ current_module.state:=ms_compile;
+ end;
+ if not(assigned(current_module) and
+ (current_module.state in [ms_compile,ms_second_compile])) then
+ internalerror(200212281);
+
+ { Set the module to use for verbose }
+ compiled_module:=current_module;
+ SetCompileModule(current_module);
+ Fillchar(aktfilepos,0,sizeof(aktfilepos));
+
+ { Load current state from the init values }
+ aktlocalswitches:=initlocalswitches;
+ aktmoduleswitches:=initmoduleswitches;
+ aktmodeswitches:=initmodeswitches;
+ {$IFDEF Testvarsets}
+ aktsetalloc:=initsetalloc;
+ {$ENDIF}
+ aktalignment:=initalignment;
+ aktfputype:=initfputype;
+ aktpackenum:=initpackenum;
+ aktpackrecords:=0;
+ aktoptprocessor:=initoptprocessor;
+ aktspecificoptprocessor:=initspecificoptprocessor;
+ aktasmmode:=initasmmode;
+ aktinterfacetype:=initinterfacetype;
+
+ { startup scanner and load the first file }
+ current_scanner:=tscannerfile.Create(filename);
+ current_scanner.firstfile;
+ current_module.scanner:=current_scanner;
+
+ { init macros before anything in the file is parsed.}
+ macrosymtablestack:= initialmacrosymtable;
+ current_module.localmacrosymtable:= tmacrosymtable.create(false);
+ current_module.localmacrosymtable.next:= initialmacrosymtable;
+ macrosymtablestack:= current_module.localmacrosymtable;
+
+ { read the first token }
+ current_scanner.readtoken;
+
+ { init code generator for a new module }
+ init_module;
+
+ { If the compile level > 1 we get a nice "unit expected" error
+ message if we are trying to use a program as unit.}
+ try
+ try
+ if (token=_UNIT) or (compile_level>1) then
+ begin
+ current_module.is_unit:=true;
+ proc_unit;
+ end
+ else
+ proc_program(token=_LIBRARY);
+ except
+ on ECompilerAbort do
+ raise;
+ on Exception do
+ begin
+ { Increase errorcounter to prevent some
+ checks during cleanup }
+ inc(status.errorcount);
+ raise;
+ end;
+ end;
+ finally
+ { restore old state }
+ done_module;
+
+ if assigned(current_module) then
+ begin
+ { module is now compiled }
+ tppumodule(current_module).state:=ms_compiled;
+
+ { free ppu }
+ if assigned(tppumodule(current_module).ppufile) then
+ begin
+ tppumodule(current_module).ppufile.free;
+ tppumodule(current_module).ppufile:=nil;
+ end;
+
+ { free scanner }
+ if assigned(current_module.scanner) then
+ begin
+ if current_scanner=tscannerfile(current_module.scanner) then
+ current_scanner:=nil;
+ tscannerfile(current_module.scanner).free;
+ current_module.scanner:=nil;
+ end;
+ end;
+
+ if (compile_level>1) then
+ begin
+ with olddata^ do
+ begin
+ { restore scanner }
+ c:=oldc;
+ pattern:=oldpattern;
+ orgpattern:=oldorgpattern;
+ token:=oldtoken;
+ idtoken:=oldidtoken;
+ akttokenpos:=oldtokenpos;
+ block_type:=old_block_type;
+ { restore cg }
+ parse_only:=oldparse_only;
+ { restore asmlists }
+ exprasmlist:=oldexprasmlist;
+ asmlist:=oldasmlist;
+ { object data }
+ resourcestrings:=oldresourcestrings;
+ objectlibrary:=oldobjectlibrary;
+ { restore previous scanner }
+ if assigned(old_compiled_module) then
+ current_scanner:=tscannerfile(old_compiled_module.scanner)
+ else
+ current_scanner:=nil;
+ if assigned(current_scanner) then
+ parser_current_file:=current_scanner.inputfile.name^;
+ { restore symtable state }
+ refsymtable:=oldrefsymtable;
+ symtablestack:=oldsymtablestack;
+ macrosymtablestack:=oldmacrosymtablestack;
+ defaultsymtablestack:=olddefaultsymtablestack;
+ defaultmacrosymtablestack:=olddefaultmacrosymtablestack;
+ aktdefproccall:=oldaktdefproccall;
+ current_procinfo:=oldcurrent_procinfo;
+ aktsourcecodepage:=oldsourcecodepage;
+ aktlocalswitches:=oldaktlocalswitches;
+ aktmoduleswitches:=oldaktmoduleswitches;
+ aktalignment:=oldaktalignment;
+ aktpackenum:=oldaktpackenum;
+ aktpackrecords:=oldaktpackrecords;
+ aktmaxfpuregisters:=oldaktmaxfpuregisters;
+ aktoptprocessor:=oldaktoptprocessor;
+ aktspecificoptprocessor:=oldaktspecificoptprocessor;
+ aktfputype:=oldaktfputype;
+ aktasmmode:=oldaktasmmode;
+ aktinterfacetype:=oldaktinterfacetype;
+ aktfilepos:=oldaktfilepos;
+ aktmodeswitches:=oldaktmodeswitches;
+ aktexceptblock:=0;
+ exceptblockcounter:=0;
+ end;
+ end
+ else
+ begin
+ { Shut down things when the last file is compiled succesfull }
+ if (compile_level=1) and
+ (status.errorcount=0) then
+ begin
+ parser_current_file:='';
+ { Close script }
+ if (not AsmRes.Empty) then
+ begin
+ Message1(exec_i_closing_script,AsmRes.Fn);
+ AsmRes.WriteToDisk;
+ end;
+
+ { do not create browsers on errors !! }
+ if status.errorcount=0 then
+ begin
+{$ifdef BrowserLog}
+ { Write Browser Log }
+ if (cs_browser_log in aktglobalswitches) and
+ (cs_browser in aktmoduleswitches) then
+ begin
+ if browserlog.elements_to_list.empty then
+ begin
+ Message1(parser_i_writing_browser_log,browserlog.Fname);
+ WriteBrowserLog;
+ end
+ else
+ browserlog.list_elements;
+ end;
+{$endif BrowserLog}
+ { Write Browser Collections, also used by the TextMode IDE to
+ retrieve a list of sourcefiles }
+ do_extractsymbolinfo{$ifdef FPC}(){$endif};
+ end;
+ end;
+ end;
+
+ dec(compile_level);
+ compiled_module:=olddata^.old_compiled_module;
+ SetCompileModule(compiled_module);
+
+ dispose(olddata);
+ end;
+ end;
+
+end.
diff --git a/compiler/pass_1.pas b/compiler/pass_1.pas
new file mode 100644
index 0000000000..e3920e272e
--- /dev/null
+++ b/compiler/pass_1.pas
@@ -0,0 +1,220 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit handles the typecheck and node conversion pass
+
+ 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 pass_1;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node;
+
+ procedure resulttypepass(var p : tnode);
+ function do_resulttypepass(var p : tnode) : boolean;
+
+ procedure firstpass(var p : tnode);
+ function do_firstpass(var p : tnode) : boolean;
+{$ifdef state_tracking}
+ procedure do_track_state_pass(p:Tnode);
+{$endif}
+
+
+implementation
+
+ uses
+ globtype,systems,cclasses,
+ cutils,globals,
+ procinfo,
+ cgbase,symdef
+{$ifdef extdebug}
+ ,verbose,htypechk
+{$endif extdebug}
+{$ifdef state_tracking}
+ ,nstate
+{$endif}
+ ;
+
+{*****************************************************************************
+ Global procedures
+*****************************************************************************}
+
+ procedure resulttypepass(var p : tnode);
+ var
+ oldcodegenerror : boolean;
+ oldlocalswitches : tlocalswitches;
+ oldpos : tfileposinfo;
+ hp : tnode;
+ begin
+ if (p.resulttype.def=nil) then
+ begin
+ oldcodegenerror:=codegenerror;
+ oldpos:=aktfilepos;
+ oldlocalswitches:=aktlocalswitches;
+ codegenerror:=false;
+ aktfilepos:=p.fileinfo;
+ aktlocalswitches:=p.localswitches;
+ hp:=p.det_resulttype;
+ { should the node be replaced? }
+ if assigned(hp) then
+ begin
+ p.free;
+ { run resulttypepass }
+ resulttypepass(hp);
+ { switch to new node }
+ p:=hp;
+ end;
+ aktlocalswitches:=oldlocalswitches;
+ aktfilepos:=oldpos;
+ if codegenerror then
+ begin
+ include(p.flags,nf_error);
+ { default to errortype if no type is set yet }
+ if p.resulttype.def=nil then
+ p.resulttype:=generrortype;
+ end;
+ codegenerror:=codegenerror or oldcodegenerror;
+ end
+ else
+ begin
+ { update the codegenerror boolean with the previous result of this node }
+ if (nf_error in p.flags) then
+ codegenerror:=true;
+ end;
+ end;
+
+
+ function do_resulttypepass(var p : tnode) : boolean;
+ begin
+ codegenerror:=false;
+ resulttypepass(p);
+ do_resulttypepass:=codegenerror;
+ end;
+
+
+ procedure firstpass(var p : tnode);
+ var
+ oldcodegenerror : boolean;
+ oldlocalswitches : tlocalswitches;
+ oldpos : tfileposinfo;
+ hp : tnode;
+ begin
+ if (nf_pass1_done in p.flags) then
+ exit;
+ if not(nf_error in p.flags) then
+ begin
+ oldcodegenerror:=codegenerror;
+ oldpos:=aktfilepos;
+ oldlocalswitches:=aktlocalswitches;
+ codegenerror:=false;
+ aktfilepos:=p.fileinfo;
+ aktlocalswitches:=p.localswitches;
+ { checks make always a call }
+ if ([cs_check_range,cs_check_overflow,cs_check_stack] * aktlocalswitches <> []) then
+ include(current_procinfo.flags,pi_do_call);
+ { determine the resulttype if not done }
+ if (p.resulttype.def=nil) then
+ begin
+ aktfilepos:=p.fileinfo;
+ aktlocalswitches:=p.localswitches;
+ hp:=p.det_resulttype;
+ { should the node be replaced? }
+ if assigned(hp) then
+ begin
+ p.free;
+ { run resulttypepass }
+ resulttypepass(hp);
+ { switch to new node }
+ p:=hp;
+ end;
+ if codegenerror then
+ begin
+ include(p.flags,nf_error);
+ { default to errortype if no type is set yet }
+ if p.resulttype.def=nil then
+ p.resulttype:=generrortype;
+ end;
+ aktlocalswitches:=oldlocalswitches;
+ aktfilepos:=oldpos;
+ codegenerror:=codegenerror or oldcodegenerror;
+ end;
+ if not(nf_error in p.flags) then
+ begin
+ { first pass }
+ aktfilepos:=p.fileinfo;
+ aktlocalswitches:=p.localswitches;
+ hp:=p.pass_1;
+ { should the node be replaced? }
+ if assigned(hp) then
+ begin
+ p.free;
+ { run firstpass }
+ firstpass(hp);
+ { switch to new node }
+ p:=hp;
+ end;
+ if codegenerror then
+ include(p.flags,nf_error)
+ else
+ begin
+{$ifdef EXTDEBUG}
+ if (p.expectloc=LOC_INVALID) then
+ Comment(V_Warning,'Expectloc is not set in firstpass: '+nodetype2str[p.nodetype]);
+{$endif EXTDEBUG}
+ end;
+ end;
+ include(p.flags,nf_pass1_done);
+ codegenerror:=codegenerror or oldcodegenerror;
+ aktlocalswitches:=oldlocalswitches;
+ aktfilepos:=oldpos;
+ end
+ else
+ codegenerror:=true;
+ end;
+
+
+ function do_firstpass(var p : tnode) : boolean;
+ begin
+ codegenerror:=false;
+ firstpass(p);
+{$ifdef state_tracking}
+ writeln('TRACKSTART');
+ writeln('before');
+ writenode(p);
+ do_track_state_pass(p);
+ writeln('after');
+ writenode(p);
+ writeln('TRACKDONE');
+{$endif}
+ do_firstpass:=codegenerror;
+ end;
+
+{$ifdef state_tracking}
+ procedure do_track_state_pass(p:Tnode);
+
+ begin
+ aktstate:=Tstate_storage.create;
+ p.track_state_pass(true);
+ aktstate.destroy;
+ end;
+{$endif}
+
+end.
diff --git a/compiler/pass_2.pas b/compiler/pass_2.pas
new file mode 100644
index 0000000000..9905c27e65
--- /dev/null
+++ b/compiler/pass_2.pas
@@ -0,0 +1,210 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit handles the codegeneration pass
+
+ 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 pass_2;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ node;
+
+ type
+ tenumflowcontrol = (fc_exit,fc_break,fc_continue);
+ tflowcontrol = set of tenumflowcontrol;
+
+ var
+ flowcontrol : tflowcontrol;
+
+{ produces the actual code }
+function do_secondpass(var p : tnode) : boolean;
+procedure secondpass(var p : tnode);
+
+
+implementation
+
+ uses
+{$ifdef EXTDEBUG}
+ cutils,
+{$endif}
+ globtype,systems,verbose,
+ globals,
+ paramgr,
+ aasmtai,
+ cgbase,
+ nflw,cgobj;
+
+{*****************************************************************************
+ SecondPass
+*****************************************************************************}
+
+{$ifdef EXTDEBUG}
+ procedure logsecond(ht:tnodetype; entry: boolean);
+ const
+ secondnames: array[tnodetype] of string[13] =
+ ('<emptynode>',
+ 'add-addn', {addn}
+ 'add-muln', {muln}
+ 'add-subn', {subn}
+ 'moddiv-divn', {divn}
+ 'add-symdifn', {symdifn}
+ 'moddiv-modn', {modn}
+ 'assignment', {assignn}
+ 'load', {loadn}
+ 'nothing-range', {range}
+ 'add-ltn', {ltn}
+ 'add-lten', {lten}
+ 'add-gtn', {gtn}
+ 'add-gten', {gten}
+ 'add-equaln', {equaln}
+ 'add-unequaln', {unequaln}
+ 'in', {inn}
+ 'add-orn', {orn}
+ 'add-xorn', {xorn}
+ 'shlshr-shrn', {shrn}
+ 'shlshr-shln', {shln}
+ 'add-slashn', {slashn}
+ 'add-andn', {andn}
+ 'subscriptn', {subscriptn}
+ 'deref', {derefn}
+ 'addr', {addrn}
+ 'ordconst', {ordconstn}
+ 'typeconv', {typeconvn}
+ 'calln', {calln}
+ 'noth-callpar',{callparan}
+ 'realconst', {realconstn}
+ 'unaryminus', {unaryminusn}
+ 'asm', {asmn}
+ 'vecn', {vecn}
+ 'pointerconst',{pointerconstn}
+ 'stringconst', {stringconstn}
+ 'not', {notn}
+ 'inline', {inlinen}
+ 'niln', {niln}
+ 'error', {errorn}
+ 'nothing-typen', {typen}
+ 'setelement', {setelementn}
+ 'setconst', {setconstn}
+ 'blockn', {blockn}
+ 'statement', {statementn}
+ 'ifn', {ifn}
+ 'breakn', {breakn}
+ 'continuen', {continuen}
+ 'while_repeat', {whilerepeatn}
+ 'for', {forn}
+ 'exitn', {exitn}
+ 'with', {withn}
+ 'case', {casen}
+ 'label', {labeln}
+ 'goto', {goton}
+ 'tryexcept', {tryexceptn}
+ 'raise', {raisen}
+ 'tryfinally', {tryfinallyn}
+ 'on', {onn}
+ 'is', {isn}
+ 'as', {asn}
+ 'error-caret', {caretn}
+ 'add-starstar', {starstarn}
+ 'arrayconstruc', {arrayconstructn}
+ 'noth-arrcnstr', {arrayconstructrangen}
+ 'tempcreaten',
+ 'temprefn',
+ 'tempdeleten',
+ 'addoptn',
+ 'nothing-nothg', {nothingn}
+ 'loadvmt', {loadvmtn}
+ 'guidconstn',
+ 'rttin',
+ 'loadparentfpn'
+ );
+ var
+ p: pchar;
+ begin
+ if entry then
+ p := strpnew('second '+secondnames[ht]+' (entry)')
+ else
+ p := strpnew('second '+secondnames[ht]+' (exit)');
+ exprasmlist.concat(tai_comment.create(p));
+ end;
+{$endif EXTDEBUG}
+
+ procedure secondpass(var p : tnode);
+ var
+ oldcodegenerror : boolean;
+ oldlocalswitches : tlocalswitches;
+ oldpos : tfileposinfo;
+ begin
+ if not assigned(p) then
+ internalerror(200208221);
+ if not(nf_error in p.flags) then
+ begin
+ oldcodegenerror:=codegenerror;
+ oldlocalswitches:=aktlocalswitches;
+ oldpos:=aktfilepos;
+ if not inlining_procedure then
+ aktfilepos:=p.fileinfo;
+ aktlocalswitches:=p.localswitches;
+ codegenerror:=false;
+{$ifdef EXTDEBUG}
+ if (p.expectloc=LOC_INVALID) then
+ Comment(V_Warning,'ExpectLoc is not set before secondpass: '+nodetype2str[p.nodetype]);
+ if (p.location.loc<>LOC_INVALID) then
+ Comment(V_Warning,'Location.Loc is already set before secondpass: '+nodetype2str[p.nodetype]);
+ if (cs_asm_nodes in aktglobalswitches) then
+ logsecond(p.nodetype,true);
+{$endif EXTDEBUG}
+ p.pass_2;
+{$ifdef EXTDEBUG}
+ if (cs_asm_nodes in aktglobalswitches) then
+ logsecond(p.nodetype,false);
+ if (not codegenerror) then
+ begin
+ if (p.location.loc=LOC_INVALID) then
+ Comment(V_Warning,'Location not set in secondpass: '+nodetype2str[p.nodetype]);
+ end;
+{$endif EXTDEBUG}
+ if codegenerror then
+ include(p.flags,nf_error);
+ codegenerror:=codegenerror or oldcodegenerror;
+ aktlocalswitches:=oldlocalswitches;
+ aktfilepos:=oldpos;
+ end
+ else
+ codegenerror:=true;
+ end;
+
+
+ function do_secondpass(var p : tnode) : boolean;
+ begin
+ { exprasmlist must be empty }
+ if not exprasmlist.empty then
+ internalerror(200405201);
+
+ { clear errors before starting }
+ codegenerror:=false;
+ if not(nf_error in p.flags) then
+ secondpass(p);
+ do_secondpass:=codegenerror;
+ end;
+
+
+end.
diff --git a/compiler/pbase.pas b/compiler/pbase.pas
new file mode 100644
index 0000000000..d407e5dafc
--- /dev/null
+++ b/compiler/pbase.pas
@@ -0,0 +1,272 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains some helper routines for the parser
+
+ 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 pbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ tokens,globals,
+ symconst,symbase,symtype,symdef,symsym,symtable
+ ;
+
+ const
+ { tokens that end a block or statement. And don't require
+ a ; on the statement before }
+ endtokens = [_SEMICOLON,_END,_ELSE,_UNTIL,_EXCEPT,_FINALLY];
+
+ { true, if we are after an assignement }
+ afterassignment : boolean = false;
+
+ { true, if we are parsing arguments }
+ in_args : boolean = false;
+
+ { true, if we got an @ to get the address }
+ got_addrn : boolean = false;
+
+ { special for handling procedure vars }
+ getprocvardef : tprocvardef = nil;
+
+ var
+ { for operators }
+ optoken : ttoken;
+
+ { symtable were unit references are stored }
+ refsymtable : tsymtable;
+
+ { true, if only routine headers should be parsed }
+ parse_only : boolean;
+
+ { true, if we should ignore an equal in const x : 1..2=2 }
+ ignore_equal : boolean;
+
+
+ procedure identifier_not_found(const s:string);
+
+{ function tokenstring(i : ttoken):string;}
+
+ { consumes token i, if the current token is unequal i }
+ { a syntax error is written }
+ procedure consume(i : ttoken);
+
+ {Tries to consume the token i, and returns true if it was consumed:
+ if token=i.}
+ function try_to_consume(i:Ttoken):boolean;
+
+ { consumes all tokens til atoken (for error recovering }
+ procedure consume_all_until(atoken : ttoken);
+
+ { consumes tokens while they are semicolons }
+ procedure consume_emptystats;
+
+ { reads a list of identifiers into a string list }
+ { consume a symbol, if not found give an error and
+ and return an errorsym }
+ function consume_sym(var srsym:tsym;var srsymtable:tsymtable):boolean;
+
+ function try_consume_hintdirective(var symopt:tsymoptions):boolean;
+
+ procedure check_hints(const srsym: tsym);
+
+ { just for an accurate position of the end of a procedure (PM) }
+ var
+ last_endtoken_filepos: tfileposinfo;
+
+
+implementation
+
+ uses
+ globtype,scanner,systems,verbose;
+
+{****************************************************************************
+ Token Parsing
+****************************************************************************}
+
+ procedure identifier_not_found(const s:string);
+ begin
+ Message1(sym_e_id_not_found,s);
+ { show a fatal that you need -S2 or -Sd, but only
+ if we just parsed the a token that has m_class }
+ if not(m_class in aktmodeswitches) and
+ (Upper(s)=pattern) and
+ (tokeninfo^[idtoken].keyword=m_class) then
+ Message(parser_f_need_objfpc_or_delphi_mode);
+ end;
+
+
+{ Unused:
+ function tokenstring(i : ttoken):string;
+ begin
+ tokenstring:=tokeninfo^[i].str;
+ end;
+}
+
+ { consumes token i, write error if token is different }
+ procedure consume(i : ttoken);
+ begin
+ if (token<>i) and (idtoken<>i) then
+ if token=_id then
+ Message2(scan_f_syn_expected,tokeninfo^[i].str,'identifier '+pattern)
+ else
+ Message2(scan_f_syn_expected,tokeninfo^[i].str,tokeninfo^[token].str)
+ else
+ begin
+ if token=_END then
+ last_endtoken_filepos:=akttokenpos;
+ current_scanner.readtoken;
+ end;
+ end;
+
+
+ function try_to_consume(i:Ttoken):boolean;
+ begin
+ try_to_consume:=false;
+ if (token=i) or (idtoken=i) then
+ begin
+ try_to_consume:=true;
+ if token=_END then
+ last_endtoken_filepos:=akttokenpos;
+ current_scanner.readtoken;
+ end;
+ end;
+
+
+ procedure consume_all_until(atoken : ttoken);
+ begin
+ while (token<>atoken) and (idtoken<>atoken) do
+ begin
+ Consume(token);
+ if token=_EOF then
+ begin
+ Consume(atoken);
+ Message(scan_f_end_of_file);
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure consume_emptystats;
+ begin
+ repeat
+ until not try_to_consume(_SEMICOLON);
+ end;
+
+
+ { check if a symbol contains the hint directive, and if so gives out a hint
+ if required.
+ }
+ procedure check_hints(const srsym: tsym);
+ begin
+ if not assigned(srsym) then
+ exit;
+ if sp_hint_deprecated in srsym.symoptions then
+ Message1(sym_w_deprecated_symbol,srsym.realname);
+ if sp_hint_platform in srsym.symoptions then
+ Message1(sym_w_non_portable_symbol,srsym.realname);
+ if sp_hint_unimplemented in srsym.symoptions then
+ Message1(sym_w_non_implemented_symbol,srsym.realname);
+ end;
+
+
+
+ function consume_sym(var srsym:tsym;var srsymtable:tsymtable):boolean;
+ begin
+ { first check for identifier }
+ if token<>_ID then
+ begin
+ consume(_ID);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ consume_sym:=false;
+ exit;
+ end;
+ searchsym(pattern,srsym,srsymtable);
+ check_hints(srsym);
+ if assigned(srsym) then
+ begin
+ if (srsym.typ=unitsym) then
+ begin
+ if not(srsym.owner.symtabletype in [staticsymtable,globalsymtable]) then
+ internalerror(200501154);
+ { only allow unit.symbol access if the name was
+ found in the current module }
+ if srsym.owner.iscurrentunit then
+ begin
+ consume(_ID);
+ consume(_POINT);
+ srsymtable:=tunitsym(srsym).unitsymtable;
+ srsym:=searchsymonlyin(srsymtable,pattern);
+ end
+ else
+ srsym:=nil;
+ end;
+ end;
+ { if nothing found give error and return errorsym }
+ if srsym=nil then
+ begin
+ identifier_not_found(orgpattern);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ end;
+ consume(_ID);
+ consume_sym:=assigned(srsym);
+ end;
+
+
+ function try_consume_hintdirective(var symopt:tsymoptions):boolean;
+ begin
+ try_consume_hintdirective:=false;
+ if not(m_hintdirective in aktmodeswitches) then
+ exit;
+ repeat
+ case idtoken of
+ _LIBRARY :
+ begin
+ include(symopt,sp_hint_library);
+ try_consume_hintdirective:=true;
+ end;
+ _DEPRECATED :
+ begin
+ include(symopt,sp_hint_deprecated);
+ try_consume_hintdirective:=true;
+ end;
+ _PLATFORM :
+ begin
+ include(symopt,sp_hint_platform);
+ try_consume_hintdirective:=true;
+ end;
+ _UNIMPLEMENTED :
+ begin
+ include(symopt,sp_hint_unimplemented);
+ try_consume_hintdirective:=true;
+ end;
+ else
+ break;
+ end;
+ consume(Token);
+ until false;
+ end;
+
+end.
diff --git a/compiler/pdecl.pas b/compiler/pdecl.pas
new file mode 100644
index 0000000000..476d25d257
--- /dev/null
+++ b/compiler/pdecl.pas
@@ -0,0 +1,659 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does declaration (but not type) parsing for Free Pascal
+
+ 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 pdecl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { global }
+ globals,
+ { symtable }
+ symsym,
+ { pass_1 }
+ node;
+
+ function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
+
+ procedure const_dec;
+ procedure label_dec;
+ procedure type_dec;
+ procedure var_dec;
+ procedure threadvar_dec;
+ procedure property_dec;
+ procedure resourcestring_dec;
+
+implementation
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,tokens,verbose,widestr,
+ systems,
+ { aasm }
+ aasmbase,aasmtai,fmodule,
+ { symtable }
+ symconst,symbase,symtype,symdef,symtable,paramgr,defutil,
+ { pass 1 }
+ nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nobj,
+ { codegen }
+ ncgutil,
+ { parser }
+ scanner,
+ pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,
+ { cpu-information }
+ cpuinfo
+ ;
+
+
+ function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
+ var
+ hp : tconstsym;
+ p : tnode;
+ ps : pconstset;
+ pd : pbestreal;
+ pg : pguid;
+ sp : pchar;
+ pw : pcompilerwidestring;
+ storetokenpos : tfileposinfo;
+ begin
+ readconstant:=nil;
+ if orgname='' then
+ internalerror(9584582);
+ hp:=nil;
+ p:=comp_expr(true);
+ storetokenpos:=akttokenpos;
+ akttokenpos:=filepos;
+ case p.nodetype of
+ ordconstn:
+ begin
+ if p.resulttype.def.deftype=pointerdef then
+ hp:=tconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value,p.resulttype)
+ else
+ hp:=tconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resulttype);
+ end;
+ stringconstn:
+ begin
+ if is_widestring(p.resulttype.def) then
+ begin
+ initwidestring(pw);
+ copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
+ hp:=tconstsym.create_wstring(orgname,constwstring,pw);
+ end
+ else
+ begin
+ getmem(sp,tstringconstnode(p).len+1);
+ move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
+ hp:=tconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len);
+ end;
+ end;
+ realconstn :
+ begin
+ new(pd);
+ pd^:=trealconstnode(p).value_real;
+ hp:=tconstsym.create_ptr(orgname,constreal,pd,p.resulttype);
+ end;
+ setconstn :
+ begin
+ new(ps);
+ ps^:=tsetconstnode(p).value_set^;
+ hp:=tconstsym.create_ptr(orgname,constset,ps,p.resulttype);
+ end;
+ pointerconstn :
+ begin
+ hp:=tconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resulttype);
+ end;
+ niln :
+ begin
+ hp:=tconstsym.create_ord(orgname,constnil,0,p.resulttype);
+ end;
+ typen :
+ begin
+ if is_interface(p.resulttype.def) then
+ begin
+ if assigned(tobjectdef(p.resulttype.def).iidguid) then
+ begin
+ new(pg);
+ pg^:=tobjectdef(p.resulttype.def).iidguid^;
+ hp:=tconstsym.create_ptr(orgname,constguid,pg,p.resulttype);
+ end
+ else
+ Message1(parser_e_interface_has_no_guid,tobjectdef(p.resulttype.def).objrealname^);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ akttokenpos:=storetokenpos;
+ p.free;
+ readconstant:=hp;
+ end;
+
+
+ procedure const_dec;
+ var
+ orgname : stringid;
+ tt : ttype;
+ sym : tsym;
+ dummysymoptions : tsymoptions;
+ storetokenpos,filepos : tfileposinfo;
+ old_block_type : tblock_type;
+ skipequal : boolean;
+ begin
+ consume(_CONST);
+ old_block_type:=block_type;
+ block_type:=bt_const;
+ repeat
+ orgname:=orgpattern;
+ filepos:=akttokenpos;
+ consume(_ID);
+ case token of
+
+ _EQUAL:
+ begin
+ consume(_EQUAL);
+ sym:=readconstant(orgname,filepos);
+ { Support hint directives }
+ dummysymoptions:=[];
+ try_consume_hintdirective(dummysymoptions);
+ if assigned(sym) then
+ begin
+ sym.symoptions:=sym.symoptions+dummysymoptions;
+ symtablestack.insert(sym);
+ end;
+ consume(_SEMICOLON);
+ end;
+
+ _COLON:
+ begin
+ { set the blocktype first so a consume also supports a
+ caret, to support const s : ^string = nil }
+ block_type:=bt_type;
+ consume(_COLON);
+ ignore_equal:=true;
+ read_type(tt,'',false);
+ ignore_equal:=false;
+ block_type:=bt_const;
+ skipequal:=false;
+ { create symbol }
+ storetokenpos:=akttokenpos;
+ akttokenpos:=filepos;
+ sym:=ttypedconstsym.createtype(orgname,tt,(cs_typed_const_writable in aktlocalswitches));
+ akttokenpos:=storetokenpos;
+ symtablestack.insert(sym);
+ { procvar can have proc directives, but not type references }
+ if (tt.def.deftype=procvardef) and
+ (tt.sym=nil) then
+ begin
+ { support p : procedure;stdcall=nil; }
+ if try_to_consume(_SEMICOLON) then
+ begin
+ if check_proc_directive(true) then
+ parse_var_proc_directives(sym)
+ else
+ begin
+ Message(parser_e_proc_directive_expected);
+ skipequal:=true;
+ end;
+ end
+ else
+ { support p : procedure stdcall=nil; }
+ begin
+ if check_proc_directive(true) then
+ parse_var_proc_directives(sym);
+ end;
+ { add default calling convention }
+ handle_calling_convention(tabstractprocdef(tt.def));
+ end;
+ if not skipequal then
+ begin
+ { get init value }
+ consume(_EQUAL);
+ readtypedconst(tt,ttypedconstsym(sym),(cs_typed_const_writable in aktlocalswitches));
+ try_consume_hintdirective(sym.symoptions);
+ consume(_SEMICOLON);
+ end;
+ end;
+
+ else
+ { generate an error }
+ consume(_EQUAL);
+ end;
+ until token<>_ID;
+ block_type:=old_block_type;
+ end;
+
+
+ procedure label_dec;
+ var
+ hl : tasmlabel;
+ begin
+ consume(_LABEL);
+ if not(cs_support_goto in aktmoduleswitches) then
+ Message(sym_e_goto_and_label_not_supported);
+ repeat
+ if not(token in [_ID,_INTCONST]) then
+ consume(_ID)
+ else
+ begin
+ if token=_ID then
+ symtablestack.insert(tlabelsym.create(orgpattern))
+ else
+ symtablestack.insert(tlabelsym.create(pattern));
+ consume(token);
+ end;
+ if token<>_SEMICOLON then consume(_COMMA);
+ until not(token in [_ID,_INTCONST]);
+ consume(_SEMICOLON);
+ end;
+
+
+ { search in symtablestack used, but not defined type }
+ procedure resolve_type_forward(p : tnamedindexitem;arg:pointer);
+ var
+ hpd,pd : tdef;
+ stpos : tfileposinfo;
+ again : boolean;
+ srsym : tsym;
+ srsymtable : tsymtable;
+
+ begin
+ { Check only typesyms or record/object fields }
+ case tsym(p).typ of
+ typesym :
+ pd:=ttypesym(p).restype.def;
+ fieldvarsym :
+ pd:=tfieldvarsym(p).vartype.def
+ else
+ exit;
+ end;
+ repeat
+ again:=false;
+ case pd.deftype of
+ arraydef :
+ begin
+ { elementtype could also be defined using a forwarddef }
+ pd:=tarraydef(pd).elementtype.def;
+ again:=true;
+ end;
+ pointerdef,
+ classrefdef :
+ begin
+ { classrefdef inherits from pointerdef }
+ hpd:=tpointerdef(pd).pointertype.def;
+ { still a forward def ? }
+ if hpd.deftype=forwarddef then
+ begin
+ { try to resolve the forward }
+ { get the correct position for it }
+ stpos:=akttokenpos;
+ akttokenpos:=tforwarddef(hpd).forwardpos;
+ resolving_forward:=true;
+ make_ref:=false;
+ if not assigned(tforwarddef(hpd).tosymname) then
+ internalerror(20021120);
+ searchsym(tforwarddef(hpd).tosymname^,srsym,srsymtable);
+ make_ref:=true;
+ resolving_forward:=false;
+ akttokenpos:=stpos;
+ { we don't need the forwarddef anymore, dispose it }
+ hpd.free;
+ tpointerdef(pd).pointertype.def:=nil; { if error occurs }
+ { was a type sym found ? }
+ if assigned(srsym) and
+ (srsym.typ=typesym) then
+ begin
+ tpointerdef(pd).pointertype.setsym(srsym);
+ { avoid wrong unused warnings web bug 801 PM }
+ inc(ttypesym(srsym).refs);
+ { we need a class type for classrefdef }
+ if (pd.deftype=classrefdef) and
+ not(is_class(ttypesym(srsym).restype.def)) then
+ Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename);
+ end
+ else
+ begin
+ MessagePos1(tsym(p).fileinfo,sym_e_forward_type_not_resolved,tsym(p).realname);
+ { try to recover }
+ tpointerdef(pd).pointertype:=generrortype;
+ end;
+ end;
+ end;
+ recorddef :
+ trecorddef(pd).symtable.foreach_static(@resolve_type_forward,nil);
+ objectdef :
+ begin
+ if not(m_fpc in aktmodeswitches) and
+ (oo_is_forward in tobjectdef(pd).objectoptions) then
+ begin
+ { only give an error as the implementation may follow in an
+ other type block which is allowed by FPC modes }
+ MessagePos1(tsym(p).fileinfo,sym_e_forward_type_not_resolved,tsym(p).realname);
+ end
+ else
+ begin
+ { Check all fields of the object declaration, but don't
+ check objectdefs in objects/records, because these
+ can't exist (anonymous objects aren't allowed) }
+ if not(tsym(p).owner.symtabletype in [objectsymtable,recordsymtable]) then
+ tobjectdef(pd).symtable.foreach_static(@resolve_type_forward,nil);
+ end;
+ end;
+ end;
+ until not again;
+ end;
+
+
+ { reads a type declaration to the symbol table }
+ procedure type_dec;
+ var
+ typename,orgtypename : stringid;
+ newtype : ttypesym;
+ sym : tsym;
+ srsymtable : tsymtable;
+ tt : ttype;
+ oldfilepos,
+ defpos,storetokenpos : tfileposinfo;
+ old_block_type : tblock_type;
+ ch : tclassheader;
+ unique,istyperenaming : boolean;
+
+ begin
+ old_block_type:=block_type;
+ block_type:=bt_type;
+ consume(_TYPE);
+ typecanbeforward:=true;
+ repeat
+ typename:=pattern;
+ orgtypename:=orgpattern;
+ defpos:=akttokenpos;
+ istyperenaming:=false;
+ consume(_ID);
+ consume(_EQUAL);
+ { support 'ttype=type word' syntax }
+ unique:=try_to_consume(_TYPE);
+
+ { MacPas object model is more like Delphi's than like TP's, but }
+ { uses the object keyword instead of class }
+ if (m_mac in aktmodeswitches) and
+ (token = _OBJECT) then
+ token := _CLASS;
+
+ { is the type already defined? }
+ searchsym(typename,sym,srsymtable);
+ newtype:=nil;
+ { found a symbol with this name? }
+ if assigned(sym) then
+ begin
+ if (sym.typ=typesym) then
+ begin
+ if ((token=_CLASS) or
+ (token=_INTERFACE)) and
+ (assigned(ttypesym(sym).restype.def)) and
+ is_class_or_interface(ttypesym(sym).restype.def) and
+ (oo_is_forward in tobjectdef(ttypesym(sym).restype.def).objectoptions) then
+ begin
+ { we can ignore the result }
+ { the definition is modified }
+ object_dec(orgtypename,tobjectdef(ttypesym(sym).restype.def));
+ newtype:=ttypesym(sym);
+ tt:=newtype.restype;
+ end
+ else
+ message1(parser_h_type_redef,orgtypename);
+ end;
+ end;
+ { no old type reused ? Then insert this new type }
+ if not assigned(newtype) then
+ begin
+ { insert the new type first with an errordef, so that
+ referencing the type before it's really set it
+ will give an error (PFV) }
+ tt:=generrortype;
+ storetokenpos:=akttokenpos;
+ newtype:=ttypesym.create(orgtypename,tt);
+ symtablestack.insert(newtype);
+ akttokenpos:=defpos;
+ akttokenpos:=storetokenpos;
+ { read the type definition }
+ read_type(tt,orgtypename,false);
+ { update the definition of the type }
+ newtype.restype:=tt;
+ if assigned(tt.sym) then
+ istyperenaming:=true
+ else
+ tt.sym:=newtype;
+ if unique and assigned(tt.def) then
+ begin
+ tt.setdef(tstoreddef(tt.def).getcopy);
+ include(tt.def.defoptions,df_unique);
+ newtype.restype:=tt;
+ end;
+ if assigned(tt.def) and not assigned(tt.def.typesym) then
+ tt.def.typesym:=newtype;
+ { KAZ: handle TGUID declaration in system unit }
+ if (cs_compilesystem in aktmoduleswitches) and not assigned(rec_tguid) and
+ (typename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
+ assigned(tt.def) and (tt.def.deftype=recorddef) and (tt.def.size=16) then
+ rec_tguid:=trecorddef(tt.def);
+ end;
+ if assigned(tt.def) then
+ begin
+ case tt.def.deftype of
+ pointerdef :
+ begin
+ consume(_SEMICOLON);
+ if try_to_consume(_FAR) then
+ begin
+ tpointerdef(tt.def).is_far:=true;
+ consume(_SEMICOLON);
+ end;
+ end;
+ procvardef :
+ begin
+ { in case of type renaming, don't parse proc directives }
+ if istyperenaming then
+ consume(_SEMICOLON)
+ else
+ begin
+ if not check_proc_directive(true) then
+ consume(_SEMICOLON);
+ parse_var_proc_directives(tsym(newtype));
+ handle_calling_convention(tprocvardef(tt.def));
+ end;
+ end;
+ objectdef,
+ recorddef :
+ begin
+ try_consume_hintdirective(newtype.symoptions);
+ consume(_SEMICOLON);
+ end;
+ else
+ consume(_SEMICOLON);
+ end;
+ end;
+
+ { Write tables if we are the typesym that defines
+ this type. This will not be done for simple type renamings }
+ if (tt.def.typesym=newtype) then
+ begin
+ { file position }
+ oldfilepos:=aktfilepos;
+ aktfilepos:=newtype.fileinfo;
+
+ { generate persistent init/final tables when it's declared in the interface so it can
+ be reused in other used }
+ if current_module.in_interface and
+ ((is_class(tt.def) and
+ tobjectdef(tt.def).members_need_inittable) or
+ tt.def.needs_inittable) then
+ generate_inittable(newtype);
+
+ { for objects we should write the vmt and interfaces.
+ This need to be done after the rtti has been written, because
+ it can contain a reference to that data (PFV)
+ This is not for forward classes }
+ if (tt.def.deftype=objectdef) and
+ (tt.def.owner.symtabletype in [staticsymtable,globalsymtable]) then
+ with Tobjectdef(tt.def) do
+ begin
+ if not(oo_is_forward in objectoptions) then
+ begin
+ ch:=tclassheader.create(tobjectdef(tt.def));
+ { generate and check virtual methods, must be done
+ before RTTI is written }
+ ch.genvmt;
+ { Generate RTTI for class }
+ generate_rtti(newtype);
+ if is_interface(tobjectdef(tt.def)) then
+ ch.writeinterfaceids;
+ if (oo_has_vmt in objectoptions) then
+ ch.writevmt;
+ ch.free;
+ end;
+ end
+ else
+ begin
+ { Always generate RTTI info for all types. This is to have typeinfo() return
+ the same pointer }
+ generate_rtti(newtype);
+ end;
+
+ aktfilepos:=oldfilepos;
+ end;
+ until token<>_ID;
+ typecanbeforward:=false;
+ symtablestack.foreach_static(@resolve_type_forward,nil);
+ block_type:=old_block_type;
+ end;
+
+
+ procedure var_dec;
+ { parses variable declarations and inserts them in }
+ { the top symbol table of symtablestack }
+ begin
+ consume(_VAR);
+ read_var_decs([]);
+ end;
+
+
+ procedure property_dec;
+ var
+ old_block_type : tblock_type;
+ begin
+ consume(_PROPERTY);
+ if not(symtablestack.symtabletype in [staticsymtable,globalsymtable]) then
+ message(parser_e_resourcestring_only_sg);
+ old_block_type:=block_type;
+ block_type:=bt_const;
+ repeat
+ read_property_dec(nil);
+ consume(_SEMICOLON);
+ until token<>_ID;
+ block_type:=old_block_type;
+ end;
+
+
+ procedure threadvar_dec;
+ { parses thread variable declarations and inserts them in }
+ { the top symbol table of symtablestack }
+ begin
+ consume(_THREADVAR);
+ if not(symtablestack.symtabletype in [staticsymtable,globalsymtable]) then
+ message(parser_e_threadvars_only_sg);
+ read_var_decs([vd_threadvar]);
+ end;
+
+
+ procedure resourcestring_dec;
+ var
+ orgname : stringid;
+ p : tnode;
+ dummysymoptions : tsymoptions;
+ storetokenpos,filepos : tfileposinfo;
+ old_block_type : tblock_type;
+ sp : pchar;
+ sym : tsym;
+ begin
+ consume(_RESOURCESTRING);
+ if not(symtablestack.symtabletype in [staticsymtable,globalsymtable]) then
+ message(parser_e_resourcestring_only_sg);
+ old_block_type:=block_type;
+ block_type:=bt_const;
+ repeat
+ orgname:=orgpattern;
+ filepos:=akttokenpos;
+ consume(_ID);
+ case token of
+ _EQUAL:
+ begin
+ consume(_EQUAL);
+ p:=comp_expr(true);
+ storetokenpos:=akttokenpos;
+ akttokenpos:=filepos;
+ sym:=nil;
+ case p.nodetype of
+ ordconstn:
+ begin
+ if is_constcharnode(p) then
+ begin
+ getmem(sp,2);
+ sp[0]:=chr(tordconstnode(p).value);
+ sp[1]:=#0;
+ sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ stringconstn:
+ with Tstringconstnode(p) do
+ begin
+ getmem(sp,len+1);
+ move(value_str^,sp^,len+1);
+ sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
+ end;
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ akttokenpos:=storetokenpos;
+ { Support hint directives }
+ dummysymoptions:=[];
+ try_consume_hintdirective(dummysymoptions);
+ if assigned(sym) then
+ begin
+ sym.symoptions:=sym.symoptions+dummysymoptions;
+ symtablestack.insert(sym);
+ end;
+ consume(_SEMICOLON);
+ p.free;
+ end;
+ else consume(_EQUAL);
+ end;
+ until token<>_ID;
+ block_type:=old_block_type;
+ end;
+
+end.
diff --git a/compiler/pdecobj.pas b/compiler/pdecobj.pas
new file mode 100644
index 0000000000..474ed8726a
--- /dev/null
+++ b/compiler/pdecobj.pas
@@ -0,0 +1,788 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does object types for Free Pascal
+
+ 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 pdecobj;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,symtype,symdef;
+
+ { parses a object declaration }
+ function object_dec(const n : stringid;fd : tobjectdef) : tdef;
+
+implementation
+
+ uses
+ cutils,cclasses,
+ globals,verbose,systems,tokens,
+ symconst,symbase,symsym,
+ node,nld,nmem,ncon,ncnv,ncal,
+ scanner,
+ pbase,pexpr,pdecsub,pdecvar,ptype
+ ;
+
+ const
+ { Please leave this here, this module should NOT use
+ these variables.
+ Declaring it as string here results in an error when compiling (PFV) }
+ current_procinfo = 'error';
+
+
+ function object_dec(const n : stringid;fd : tobjectdef) : tdef;
+ { this function parses an object or class declaration }
+ var
+ there_is_a_destructor : boolean;
+ classtype : tobjectdeftype;
+ childof : tobjectdef;
+ aktclass : tobjectdef;
+
+ function constructor_head:tprocdef;
+ var
+ pd : tprocdef;
+ begin
+ consume(_CONSTRUCTOR);
+ { must be at same level as in implementation }
+ parse_proc_head(aktclass,potype_constructor,pd);
+ if not assigned(pd) then
+ begin
+ consume(_SEMICOLON);
+ exit;
+ end;
+ if (cs_constructor_name in aktglobalswitches) and
+ (pd.procsym.name<>'INIT') then
+ Message(parser_e_constructorname_must_be_init);
+ consume(_SEMICOLON);
+ include(aktclass.objectoptions,oo_has_constructor);
+ { Set return type, class constructors return the
+ created instance, object constructors return boolean }
+ if is_class(pd._class) then
+ pd.rettype.setdef(pd._class)
+ else
+ pd.rettype:=booltype;
+ constructor_head:=pd;
+ end;
+
+
+ procedure property_dec;
+ var
+ p : tpropertysym;
+ begin
+ { check for a class }
+ if not((is_class_or_interface(aktclass)) or
+ (not(m_tp7 in aktmodeswitches) and (is_object(aktclass)))) then
+ Message(parser_e_syntax_error);
+ consume(_PROPERTY);
+ p:=read_property_dec(aktclass);
+ consume(_SEMICOLON);
+ if try_to_consume(_DEFAULT) then
+ begin
+ if oo_has_default_property in aktclass.objectoptions then
+ message(parser_e_only_one_default_property);
+ include(aktclass.objectoptions,oo_has_default_property);
+ include(p.propoptions,ppo_defaultproperty);
+ if not(ppo_hasparameters in p.propoptions) then
+ message(parser_e_property_need_paras);
+ consume(_SEMICOLON);
+ end;
+ { hint directives, these can be separated by semicolons here,
+ that needs to be handled here with a loop (PFV) }
+ while try_consume_hintdirective(p.symoptions) do
+ Consume(_SEMICOLON);
+ end;
+
+
+ function destructor_head:tprocdef;
+ var
+ pd : tprocdef;
+ begin
+ consume(_DESTRUCTOR);
+ parse_proc_head(aktclass,potype_destructor,pd);
+ if not assigned(pd) then
+ begin
+ consume(_SEMICOLON);
+ exit;
+ end;
+ if (cs_constructor_name in aktglobalswitches) and
+ (pd.procsym.name<>'DONE') then
+ Message(parser_e_destructorname_must_be_done);
+ if not(pd.maxparacount=0) and
+ (m_fpc in aktmodeswitches) then
+ Message(parser_e_no_paras_for_destructor);
+ consume(_SEMICOLON);
+ include(aktclass.objectoptions,oo_has_destructor);
+ { no return value }
+ pd.rettype:=voidtype;
+ destructor_head:=pd;
+ end;
+
+ var
+ pcrd : tclassrefdef;
+ tt : ttype;
+ old_object_option : tsymoptions;
+ oldparse_only : boolean;
+ storetypecanbeforward : boolean;
+
+ procedure setclassattributes;
+
+ begin
+ { publishable }
+ if classtype in [odt_interfacecom,odt_class] then
+ begin
+ aktclass.objecttype:=classtype;
+ if (cs_generate_rtti in aktlocalswitches) or
+ (assigned(aktclass.childof) and
+ (oo_can_have_published in aktclass.childof.objectoptions)) then
+ begin
+ include(aktclass.objectoptions,oo_can_have_published);
+ { in "publishable" classes the default access type is published }
+ current_object_option:=[sp_published];
+ end;
+ end;
+ end;
+
+ procedure setclassparent;
+
+ begin
+ if assigned(fd) then
+ aktclass:=fd
+ else
+ aktclass:=tobjectdef.create(classtype,n,nil);
+ { is the current class tobject? }
+ { so you could define your own tobject }
+ if (cs_compilesystem in aktmoduleswitches) and (classtype=odt_class) and (upper(n)='TOBJECT') then
+ class_tobject:=aktclass
+ else if (cs_compilesystem in aktmoduleswitches) and (classtype=odt_interfacecom) and (upper(n)='IUNKNOWN') then
+ interface_iunknown:=aktclass
+ else
+ begin
+ case classtype of
+ odt_class:
+ childof:=class_tobject;
+ odt_interfacecom:
+ childof:=interface_iunknown;
+ end;
+ if (oo_is_forward in childof.objectoptions) then
+ Message1(parser_e_forward_declaration_must_be_resolved,childof.objrealname^);
+ aktclass.set_parent(childof);
+ end;
+ end;
+
+ procedure setinterfacemethodoptions;
+
+ var
+ i: longint;
+ defs: TIndexArray;
+ pd: tdef;
+ begin
+ include(aktclass.objectoptions,oo_has_virtual);
+ defs:=aktclass.symtable.defindex;
+ for i:=1 to defs.count do
+ begin
+ pd:=tdef(defs.search(i));
+ if pd.deftype=procdef then
+ begin
+ tprocdef(pd).extnumber:=aktclass.lastvtableindex;
+ inc(aktclass.lastvtableindex);
+ include(tprocdef(pd).procoptions,po_virtualmethod);
+ tprocdef(pd).forwarddef:=false;
+ end;
+ end;
+ end;
+
+ function readobjecttype : boolean;
+
+ begin
+ readobjecttype:=true;
+ { distinguish classes and objects }
+ case token of
+ _OBJECT:
+ begin
+ classtype:=odt_object;
+ consume(_OBJECT)
+ end;
+ _CPPCLASS:
+ begin
+ classtype:=odt_cppclass;
+ consume(_CPPCLASS);
+ end;
+ _DISPINTERFACE:
+ begin
+ { need extra check here since interface is a keyword
+ in all pascal modes }
+ if not(m_class in aktmodeswitches) then
+ Message(parser_f_need_objfpc_or_delphi_mode);
+ classtype:=odt_dispinterface;
+ consume(_DISPINTERFACE);
+ { no forward declaration }
+ if not(assigned(fd)) and (token=_SEMICOLON) then
+ begin
+ { also anonym objects aren't allow (o : object a : longint; end;) }
+ if n='' then
+ Message(parser_f_no_anonym_objects);
+ aktclass:=tobjectdef.create(classtype,n,nil);
+ include(aktclass.objectoptions,oo_is_forward);
+ object_dec:=aktclass;
+ typecanbeforward:=storetypecanbeforward;
+ readobjecttype:=false;
+ exit;
+ end;
+ end;
+ _INTERFACE:
+ begin
+ { need extra check here since interface is a keyword
+ in all pascal modes }
+ if not(m_class in aktmodeswitches) then
+ Message(parser_f_need_objfpc_or_delphi_mode);
+ if aktinterfacetype=it_interfacecom then
+ classtype:=odt_interfacecom
+ else {it_interfacecorba}
+ classtype:=odt_interfacecorba;
+ consume(_INTERFACE);
+ { forward declaration }
+ if not(assigned(fd)) and (token=_SEMICOLON) then
+ begin
+ { also anonym objects aren't allow (o : object a : longint; end;) }
+ if n='' then
+ Message(parser_f_no_anonym_objects);
+ aktclass:=tobjectdef.create(classtype,n,nil);
+ if (cs_compilesystem in aktmoduleswitches) and
+ (classtype=odt_interfacecom) and (upper(n)='IUNKNOWN') then
+ interface_iunknown:=aktclass;
+ include(aktclass.objectoptions,oo_is_forward);
+ object_dec:=aktclass;
+ typecanbeforward:=storetypecanbeforward;
+ readobjecttype:=false;
+ exit;
+ end;
+ end;
+ _CLASS:
+ begin
+ classtype:=odt_class;
+ consume(_CLASS);
+ if not(assigned(fd)) and
+ (token=_OF) and
+ { Delphi only allows class of in type blocks.
+ Note that when parsing the type of a variable declaration
+ the blocktype is bt_type so the check for typecanbeforward
+ is also necessary (PFV) }
+ (((block_type=bt_type) and typecanbeforward) or
+ not(m_delphi in aktmodeswitches)) then
+ begin
+ { a hack, but it's easy to handle }
+ { class reference type }
+ consume(_OF);
+ single_type(tt,typecanbeforward);
+
+ { accept hp1, if is a forward def or a class }
+ if (tt.def.deftype=forwarddef) or
+ is_class(tt.def) then
+ begin
+ pcrd:=tclassrefdef.create(tt);
+ object_dec:=pcrd;
+ end
+ else
+ begin
+ object_dec:=generrortype.def;
+ Message1(type_e_class_type_expected,generrortype.def.typename);
+ end;
+ typecanbeforward:=storetypecanbeforward;
+ readobjecttype:=false;
+ exit;
+ end
+ { forward class }
+ else if not(assigned(fd)) and (token=_SEMICOLON) then
+ begin
+ { also anonym objects aren't allow (o : object a : longint; end;) }
+ if n='' then
+ Message(parser_f_no_anonym_objects);
+ aktclass:=tobjectdef.create(odt_class,n,nil);
+ if (cs_compilesystem in aktmoduleswitches) and (upper(n)='TOBJECT') then
+ class_tobject:=aktclass;
+ aktclass.objecttype:=odt_class;
+ include(aktclass.objectoptions,oo_is_forward);
+ { all classes must have a vmt !! at offset zero }
+ if not(oo_has_vmt in aktclass.objectoptions) then
+ aktclass.insertvmt;
+
+ object_dec:=aktclass;
+ typecanbeforward:=storetypecanbeforward;
+ readobjecttype:=false;
+ exit;
+ end;
+ end;
+ else
+ begin
+ classtype:=odt_class; { this is error but try to recover }
+ consume(_OBJECT);
+ end;
+ end;
+ end;
+
+ procedure handleimplementedinterface(implintf : tobjectdef);
+
+ begin
+ if not is_interface(implintf) then
+ begin
+ Message1(type_e_interface_type_expected,implintf.typename);
+ exit;
+ end;
+ if aktclass.implementedinterfaces.searchintf(implintf)<>-1 then
+ Message1(sym_e_duplicate_id,implintf.name)
+ else
+ begin
+ { allocate and prepare the GUID only if the class
+ implements some interfaces.
+ }
+ if aktclass.implementedinterfaces.count = 0 then
+ aktclass.prepareguid;
+ aktclass.implementedinterfaces.addintf(implintf);
+ end;
+ end;
+
+ procedure readimplementedinterfaces;
+ var
+ tt : ttype;
+ begin
+ while try_to_consume(_COMMA) do
+ begin
+ id_type(tt,false);
+ if (tt.def.deftype<>objectdef) then
+ begin
+ Message1(type_e_interface_type_expected,tt.def.typename);
+ continue;
+ end;
+ handleimplementedinterface(tobjectdef(tt.def));
+ end;
+ end;
+
+ procedure readinterfaceiid;
+ var
+ p : tnode;
+ valid : boolean;
+ begin
+ p:=comp_expr(true);
+ if p.nodetype=stringconstn then
+ begin
+ stringdispose(aktclass.iidstr);
+ aktclass.iidstr:=stringdup(strpas(tstringconstnode(p).value_str)); { or upper? }
+ p.free;
+ valid:=string2guid(aktclass.iidstr^,aktclass.iidguid^);
+ if (classtype=odt_interfacecom) and not assigned(aktclass.iidguid) and not valid then
+ Message(parser_e_improper_guid_syntax);
+ end
+ else
+ begin
+ p.free;
+ Message(parser_e_illegal_expression);
+ end;
+ end;
+
+
+ procedure readparentclasses;
+ var
+ hp : tobjectdef;
+ begin
+ hp:=nil;
+ { reads the parent class }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ id_type(tt,false);
+ childof:=tobjectdef(tt.def);
+ if (not assigned(childof)) or
+ (childof.deftype<>objectdef) then
+ begin
+ if assigned(childof) then
+ Message1(type_e_class_type_expected,childof.typename);
+ childof:=nil;
+ aktclass:=tobjectdef.create(classtype,n,nil);
+ end
+ else
+ begin
+ { a mix of class, interfaces, objects and cppclasses
+ isn't allowed }
+ case classtype of
+ odt_class:
+ if not(is_class(childof)) then
+ begin
+ if is_interface(childof) then
+ begin
+ { we insert the interface after the child
+ is set, see below
+ }
+ hp:=childof;
+ childof:=class_tobject;
+ end
+ else
+ Message(parser_e_mix_of_classes_and_objects);
+ end;
+ odt_interfacecorba,
+ odt_interfacecom:
+ if not(is_interface(childof)) then
+ Message(parser_e_mix_of_classes_and_objects);
+ odt_cppclass:
+ if not(is_cppclass(childof)) then
+ Message(parser_e_mix_of_classes_and_objects);
+ odt_object:
+ if not(is_object(childof)) then
+ Message(parser_e_mix_of_classes_and_objects);
+ odt_dispinterface:
+ Message(parser_e_dispinterface_cant_have_parent);
+ end;
+ { the forward of the child must be resolved to get
+ correct field addresses }
+ if assigned(fd) then
+ begin
+ if (oo_is_forward in childof.objectoptions) then
+ Message1(parser_e_forward_declaration_must_be_resolved,childof.objrealname^);
+ aktclass:=fd;
+ { we must inherit several options !!
+ this was missing !!
+ all is now done in set_parent
+ including symtable datasize setting PM }
+ fd.set_parent(childof);
+ end
+ else
+ aktclass:=tobjectdef.create(classtype,n,childof);
+ if aktclass.objecttype=odt_class then
+ begin
+ if assigned(hp) then
+ handleimplementedinterface(hp);
+ readimplementedinterfaces;
+ end;
+ end;
+ consume(_RKLAMMER);
+ end
+ { if no parent class, then a class get tobject as parent }
+ else if classtype in [odt_class,odt_interfacecom] then
+ setclassparent
+ else
+ aktclass:=tobjectdef.create(classtype,n,nil);
+ { read GUID }
+ if (classtype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface]) and
+ try_to_consume(_LECKKLAMMER) then
+ begin
+ readinterfaceiid;
+ consume(_RECKKLAMMER);
+ end
+ else if (classtype=odt_dispinterface) then
+ message(parser_e_dispinterface_needs_a_guid);
+ end;
+
+ procedure chkcpp(pd:tprocdef);
+ begin
+ if is_cppclass(pd._class) then
+ begin
+ pd.proccalloption:=pocall_cppdecl;
+ pd.setmangledname(target_info.Cprefix+pd.cplusplusmangledname);
+ end;
+ end;
+
+ var
+ pd : tprocdef;
+ dummysymoptions : tsymoptions;
+ begin
+ old_object_option:=current_object_option;
+
+ { forward is resolved }
+ if assigned(fd) then
+ exclude(fd.objectoptions,oo_is_forward);
+
+ { objects and class types can't be declared local }
+ if not(symtablestack.symtabletype in [globalsymtable,staticsymtable]) then
+ Message(parser_e_no_local_objects);
+
+ storetypecanbeforward:=typecanbeforward;
+ { for tp7 don't allow forward types }
+ if (m_tp7 in aktmodeswitches) then
+ typecanbeforward:=false;
+
+ if not(readobjecttype) then
+ exit;
+
+ { also anonym objects aren't allow (o : object a : longint; end;) }
+ if n='' then
+ Message(parser_f_no_anonym_objects);
+
+ { read list of parent classes }
+ readparentclasses;
+
+ { default access is public }
+ there_is_a_destructor:=false;
+ current_object_option:=[sp_public];
+
+ { set class flags and inherits published }
+ setclassattributes;
+
+ aktobjectdef:=aktclass;
+ aktclass.symtable.next:=symtablestack;
+ symtablestack:=aktclass.symtable;
+ testcurobject:=1;
+ curobjectname:=Upper(n);
+
+ { short class declaration ? }
+ if (classtype<>odt_class) or (token<>_SEMICOLON) then
+ begin
+ { Parse componenten }
+ repeat
+ case token of
+ _ID :
+ begin
+ case idtoken of
+ _PRIVATE :
+ begin
+ if is_interface(aktclass) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_PRIVATE);
+ current_object_option:=[sp_private];
+ include(aktclass.objectoptions,oo_has_private);
+ end;
+ _PROTECTED :
+ begin
+ if is_interface(aktclass) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_PROTECTED);
+ current_object_option:=[sp_protected];
+ include(aktclass.objectoptions,oo_has_protected);
+ end;
+ _PUBLIC :
+ begin
+ if is_interface(aktclass) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_PUBLIC);
+ current_object_option:=[sp_public];
+ end;
+ _PUBLISHED :
+ begin
+ { we've to check for a pushlished section in non- }
+ { publishable classes later, if a real declaration }
+ { this is the way, delphi does it }
+ if is_interface(aktclass) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_PUBLISHED);
+ current_object_option:=[sp_published];
+ end;
+ _STRICT :
+ begin
+ if is_interface(aktclass) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_STRICT);
+ if token=_ID then
+ begin
+ case idtoken of
+ _PRIVATE:
+ begin
+ consume(_PRIVATE);
+ current_object_option:=[sp_strictprivate];
+ include(aktclass.objectoptions,oo_has_strictprivate);
+ end;
+ _PROTECTED:
+ begin
+ consume(_PROTECTED);
+ current_object_option:=[sp_strictprotected];
+ include(aktclass.objectoptions,oo_has_strictprotected);
+ end;
+ else
+ message(parser_e_protected_or_private_expected);
+ end;
+ end
+ else
+ message(parser_e_protected_or_private_expected);
+ end;
+ else
+ begin
+ if is_interface(aktclass) then
+ Message(parser_e_no_vars_in_interfaces);
+
+ if (sp_published in current_object_option) and
+ not(oo_can_have_published in aktclass.objectoptions) then
+ Message(parser_e_cant_have_published);
+
+ read_var_decs([vd_object]);
+ end;
+ end;
+ end;
+ _PROPERTY :
+ begin
+ property_dec;
+ end;
+ _PROCEDURE,
+ _FUNCTION,
+ _CLASS :
+ begin
+ if (sp_published in current_object_option) and
+ not(oo_can_have_published in aktclass.objectoptions) then
+ Message(parser_e_cant_have_published);
+
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ pd:=parse_proc_dec(aktclass);
+
+ { this is for error recovery as well as forward }
+ { interface mappings, i.e. mapping to a method }
+ { which isn't declared yet }
+ if assigned(pd) then
+ begin
+ parse_object_proc_directives(pd);
+
+ { all Macintosh Object Pascal methods are virtual. }
+ { this can't be a class method, because macpas mode }
+ { has no m_class }
+ if (m_mac in aktmodeswitches) then
+ include(pd.procoptions,po_virtualmethod);
+
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+
+ { add procdef options to objectdef options }
+ if (po_msgint in pd.procoptions) then
+ include(aktclass.objectoptions,oo_has_msgint);
+ if (po_msgstr in pd.procoptions) then
+ include(aktclass.objectoptions,oo_has_msgstr);
+ if (po_virtualmethod in pd.procoptions) then
+ include(aktclass.objectoptions,oo_has_virtual);
+
+ chkcpp(pd);
+ end;
+
+ { Support hint directives }
+ dummysymoptions:=[];
+ while try_consume_hintdirective(dummysymoptions) do
+ Consume(_SEMICOLON);
+ if assigned(pd) then
+ pd.symoptions:=pd.symoptions+dummysymoptions;
+
+ parse_only:=oldparse_only;
+ end;
+ _CONSTRUCTOR :
+ begin
+ if (sp_published in current_object_option) and
+ not(oo_can_have_published in aktclass.objectoptions) then
+ Message(parser_e_cant_have_published);
+
+ if not(sp_public in current_object_option) and
+ not(sp_published in current_object_option) then
+ Message(parser_w_constructor_should_be_public);
+
+ if is_interface(aktclass) then
+ Message(parser_e_no_con_des_in_interfaces);
+
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ pd:=constructor_head;
+ parse_object_proc_directives(pd);
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+
+ { add procdef options to objectdef options }
+ if (po_virtualmethod in pd.procoptions) then
+ include(aktclass.objectoptions,oo_has_virtual);
+ chkcpp(pd);
+
+ { Support hint directives }
+ dummysymoptions:=[];
+ while try_consume_hintdirective(dummysymoptions) do
+ Consume(_SEMICOLON);
+ if assigned(pd) then
+ pd.symoptions:=pd.symoptions+dummysymoptions;
+
+ parse_only:=oldparse_only;
+ end;
+ _DESTRUCTOR :
+ begin
+ if (sp_published in current_object_option) and
+ not(oo_can_have_published in aktclass.objectoptions) then
+ Message(parser_e_cant_have_published);
+
+ if there_is_a_destructor then
+ Message(parser_n_only_one_destructor);
+
+ if is_interface(aktclass) then
+ Message(parser_e_no_con_des_in_interfaces);
+
+ if not(sp_public in current_object_option) then
+ Message(parser_w_destructor_should_be_public);
+
+ there_is_a_destructor:=true;
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ pd:=destructor_head;
+ parse_object_proc_directives(pd);
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+
+ { add procdef options to objectdef options }
+ if (po_virtualmethod in pd.procoptions) then
+ include(aktclass.objectoptions,oo_has_virtual);
+
+ chkcpp(pd);
+
+ { Support hint directives }
+ dummysymoptions:=[];
+ while try_consume_hintdirective(dummysymoptions) do
+ Consume(_SEMICOLON);
+ if assigned(pd) then
+ pd.symoptions:=pd.symoptions+dummysymoptions;
+
+ parse_only:=oldparse_only;
+ end;
+ _END :
+ begin
+ consume(_END);
+ break;
+ end;
+ else
+ consume(_ID); { Give a ident expected message, like tp7 }
+ end;
+ until false;
+ end;
+
+ { generate vmt space if needed }
+ if not(oo_has_vmt in aktclass.objectoptions) and
+ (([oo_has_virtual,oo_has_constructor,oo_has_destructor]*aktclass.objectoptions<>[]) or
+ (classtype in [odt_class])
+ ) then
+ aktclass.insertvmt;
+
+ if is_interface(aktclass) then
+ setinterfacemethodoptions;
+
+ { reset }
+ testcurobject:=0;
+ curobjectname:='';
+ typecanbeforward:=storetypecanbeforward;
+ { restore old state }
+ symtablestack:=symtablestack.next;
+ aktobjectdef:=nil;
+ current_object_option:=old_object_option;
+
+ object_dec:=aktclass;
+ end;
+
+end.
diff --git a/compiler/pdecsub.pas b/compiler/pdecsub.pas
new file mode 100644
index 0000000000..8f7cb5e9c5
--- /dev/null
+++ b/compiler/pdecsub.pas
@@ -0,0 +1,2467 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Daniel Mantione
+
+ Does the parsing of the procedures/functions
+
+ 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 pdecsub;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ tokens,symconst,symtype,symdef,symsym;
+
+ type
+ tpdflag=(
+ pd_body, { directive needs a body }
+ pd_implemen, { directive can be used implementation section }
+ pd_interface, { directive can be used interface section }
+ pd_object, { directive can be used object declaration }
+ pd_procvar, { directive can be used procvar declaration }
+ pd_notobject, { directive can not be used object declaration }
+ pd_notobjintf, { directive can not be used interface declaration }
+ pd_notprocvar { directive can not be used procvar declaration }
+ );
+ tpdflags=set of tpdflag;
+
+ function check_proc_directive(isprocvar:boolean):boolean;
+
+ procedure insert_funcret_local(pd:tprocdef);
+
+ function proc_add_definition(var pd:tprocdef):boolean;
+ function proc_get_importname(pd:tprocdef):string;
+ procedure proc_set_mangledname(pd:tprocdef);
+
+ procedure handle_calling_convention(pd:tabstractprocdef);
+
+ procedure parse_parameter_dec(pd:tabstractprocdef);
+ procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
+ procedure parse_var_proc_directives(sym:tsym);
+ procedure parse_object_proc_directives(pd:tabstractprocdef);
+ function parse_proc_head(aclass:tobjectdef;potype:tproctypeoption;var pd:tprocdef):boolean;
+ function parse_proc_dec(aclass:tobjectdef):tprocdef;
+
+implementation
+
+ uses
+ strings,
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ cpuinfo,
+ { symtable }
+ symbase,symtable,defutil,defcmp,paramgr,cpupara,
+ { pass 1 }
+ node,htypechk,
+ nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
+ { parser }
+ scanner,
+ pbase,pexpr,ptype,pdecl
+ ;
+
+ const
+ { Please leave this here, this module should NOT use
+ these variables.
+ Declaring it as string here results in an error when compiling (PFV) }
+ current_procinfo = 'error';
+
+
+ procedure insert_funcret_para(pd:tabstractprocdef);
+ var
+ storepos : tfileposinfo;
+ vs : tparavarsym;
+ paranr : word;
+ begin
+ if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
+ not is_void(pd.rettype.def) and
+ paramanager.ret_in_param(pd.rettype.def,pd.proccalloption) then
+ begin
+ storepos:=akttokenpos;
+ if pd.deftype=procdef then
+ akttokenpos:=tprocdef(pd).fileinfo;
+
+ { For left to right add it at the end to be delphi compatible }
+ if pd.proccalloption in pushleftright_pocalls then
+ paranr:=paranr_result_leftright
+ else
+ paranr:=paranr_result;
+ { Generate result variable accessing function result }
+ vs:=tparavarsym.create('$result',paranr,vs_var,pd.rettype,[vo_is_funcret,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ { Store the this symbol as funcretsym for procedures }
+ if pd.deftype=procdef then
+ tprocdef(pd).funcretsym:=vs;
+
+ akttokenpos:=storepos;
+ end;
+ end;
+
+
+ procedure insert_parentfp_para(pd:tabstractprocdef);
+ var
+ storepos : tfileposinfo;
+ vs : tparavarsym;
+ begin
+ if pd.parast.symtablelevel>normal_function_level then
+ begin
+ storepos:=akttokenpos;
+ if pd.deftype=procdef then
+ akttokenpos:=tprocdef(pd).fileinfo;
+
+ { Generate result variable accessing function result, it
+ can't be put in a register since it must be accessable
+ from the framepointer }
+ vs:=tparavarsym.create('$parentfp',paranr_parentfp,vs_var,voidpointertype,[vo_is_parentfp,vo_is_hidden_para]);
+ vs.varregable:=vr_none;
+ pd.parast.insert(vs);
+
+ akttokenpos:=storepos;
+ end;
+ end;
+
+
+ procedure insert_self_and_vmt_para(pd:tabstractprocdef);
+ var
+ storepos : tfileposinfo;
+ vs : tparavarsym;
+ tt : ttype;
+ vsp : tvarspez;
+ begin
+ if (pd.deftype=procvardef) and
+ pd.is_methodpointer then
+ begin
+ { Generate self variable }
+ tt:=voidpointertype;
+ vs:=tparavarsym.create('$self',paranr_self,vs_value,tt,[vo_is_self,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end
+ else
+ begin
+ if (pd.deftype=procdef) and
+ assigned(tprocdef(pd)._class) and
+ (pd.parast.symtablelevel=normal_function_level) then
+ begin
+ storepos:=akttokenpos;
+ akttokenpos:=tprocdef(pd).fileinfo;
+
+ { Generate VMT variable for constructor/destructor }
+ if pd.proctypeoption in [potype_constructor,potype_destructor] then
+ begin
+ { can't use classrefdef as type because inheriting
+ will then always file because of a type mismatch }
+ tt:=voidpointertype;
+ vs:=tparavarsym.create('$vmt',paranr_vmt,vs_value,tt,[vo_is_vmt,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end;
+
+ { Generate self variable, for classes we need
+ to use the generic voidpointer to be compatible with
+ methodpointers }
+ vsp:=vs_value;
+ if (po_staticmethod in pd.procoptions) or
+ (po_classmethod in pd.procoptions) then
+ begin
+ tt.setdef(tprocdef(pd)._class);
+ tt.setdef(tclassrefdef.create(tt));
+ end
+ else
+ begin
+ if is_object(tprocdef(pd)._class) then
+ vsp:=vs_var;
+ tt.setdef(tprocdef(pd)._class);
+ end;
+ vs:=tparavarsym.create('$self',paranr_self,vsp,tt,[vo_is_self,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+
+ akttokenpos:=storepos;
+ end;
+ end;
+ end;
+
+
+ procedure insert_funcret_local(pd:tprocdef);
+ var
+ storepos : tfileposinfo;
+ vs : tlocalvarsym;
+ aliasvs : tabsolutevarsym;
+ sl : tsymlist;
+ begin
+ { The result from constructors and destructors can't be accessed directly }
+ if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
+ not is_void(pd.rettype.def) then
+ begin
+ storepos:=akttokenpos;
+ akttokenpos:=pd.fileinfo;
+
+ { We always need a localsymtable }
+ if not assigned(pd.localst) then
+ pd.insert_localst;
+
+ { We need to insert a varsym for the result in the localst
+ when it is returning in a register }
+ if not paramanager.ret_in_param(pd.rettype.def,pd.proccalloption) then
+ begin
+ vs:=tlocalvarsym.create('$result',vs_value,pd.rettype,[vo_is_funcret]);
+ pd.localst.insert(vs);
+ pd.funcretsym:=vs;
+ end;
+
+ { insert the name of the procedure as alias for the function result,
+ we can't use realname because that will not work for compilerprocs
+ as the name is lowercase and unreachable from the code }
+ if pd.resultname='' then
+ pd.resultname:=pd.procsym.name;
+ sl:=tsymlist.create;
+ sl.addsym(sl_load,pd.funcretsym);
+ aliasvs:=tabsolutevarsym.create_ref(pd.resultname,pd.rettype,sl);
+ include(aliasvs.varoptions,vo_is_funcret);
+ pd.localst.insert(aliasvs);
+
+ { insert result also if support is on }
+ if (m_result in aktmodeswitches) then
+ begin
+ sl:=tsymlist.create;
+ sl.addsym(sl_load,pd.funcretsym);
+ aliasvs:=tabsolutevarsym.create_ref('RESULT',pd.rettype,sl);
+ include(aliasvs.varoptions,vo_is_funcret);
+ include(aliasvs.varoptions,vo_is_result);
+ pd.localst.insert(aliasvs);
+ end;
+
+ akttokenpos:=storepos;
+ end;
+ end;
+
+
+ procedure insert_hidden_para(p:tnamedindexitem;arg:pointer);
+ var
+ hvs : tparavarsym;
+ pd : tabstractprocdef absolute arg;
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ with tparavarsym(p) do
+ begin
+ { We need a local copy for a value parameter when only the
+ address is pushed. Open arrays and Array of Const are
+ an exception because they are allocated at runtime and the
+ address that is pushed is patched }
+ if (varspez=vs_value) and
+ paramanager.push_addr_param(varspez,vartype.def,pd.proccalloption) and
+ not(is_open_array(vartype.def) or
+ is_array_of_const(vartype.def)) then
+ include(varoptions,vo_has_local_copy);
+
+ { needs high parameter ? }
+ if paramanager.push_high_param(varspez,vartype.def,pd.proccalloption) then
+ begin
+ hvs:=tparavarsym.create('$high'+name,paranr+1,vs_const,sinttype,[vo_is_high_para,vo_is_hidden_para]);
+ owner.insert(hvs);
+ end
+ else
+ begin
+ { Give a warning that cdecl routines does not include high()
+ support }
+ if (pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ paramanager.push_high_param(varspez,vartype.def,pocall_default) then
+ begin
+ if is_open_string(vartype.def) then
+ Message(parser_w_cdecl_no_openstring);
+ if not (po_external in pd.procoptions) then
+ Message(parser_w_cdecl_has_no_high);
+ end;
+ end;
+ end;
+ end;
+
+ procedure check_c_para(p:tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ with tparavarsym(p) do
+ begin
+ case vartype.def.deftype of
+ arraydef :
+ begin
+ if not is_variant_array(vartype.def) and
+ not is_array_of_const(vartype.def) then
+ begin
+ if (varspez<>vs_var) then
+ Message(parser_h_c_arrays_are_references);
+ end;
+ if is_array_of_const(vartype.def) and
+ assigned(indexnext) and
+ (tsym(indexnext).typ=paravarsym) and
+ not(vo_is_high_para in tparavarsym(indexnext).varoptions) then
+ Message(parser_e_C_array_of_const_must_be_last);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure check_msg_para(p:tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ with tparavarsym(p) do
+ begin
+ { Count parameters }
+ if (paranr>=10) then
+ inc(plongint(arg)^);
+ { First parameter must be var }
+ if (paranr=10) and
+ (varspez<>vs_var) then
+ Message(parser_e_ill_msg_param);
+ end;
+ end;
+
+
+ procedure check_inline_para(p:tnamedindexitem;arg:pointer);
+ var
+ pd : tabstractprocdef absolute arg;
+ begin
+ if not(po_inline in pd.procoptions) or
+ (tsym(p).typ<>paravarsym) then
+ exit;
+ with tparavarsym(p) do
+ begin
+ case vartype.def.deftype of
+ arraydef :
+ begin
+ with tarraydef(vartype.def) do
+ if IsVariant or IsConstructor then
+ begin
+ Message1(parser_w_not_supported_for_inline,'array of const');
+ Message(parser_w_inlining_disabled);
+ pd.proccalloption:=pocall_default;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure set_addr_param_regable(p:tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ with tparavarsym(p) do
+ begin
+ if not vartype.def.needs_inittable and
+ paramanager.push_addr_param(varspez,vartype.def,tprocdef(arg).proccalloption) then
+ varregable:=vr_intreg;
+ end;
+ end;
+
+
+ procedure parse_parameter_dec(pd:tabstractprocdef);
+ {
+ handle_procvar needs the same changes
+ }
+ type
+ tppv = (pv_none,pv_proc,pv_func);
+ var
+ sc : tsinglelist;
+ tt : ttype;
+ arrayelementtype : ttype;
+ vs : tparavarsym;
+ srsym : tsym;
+ pv : tprocvardef;
+ varspez : Tvarspez;
+ defaultvalue : tconstsym;
+ defaultrequired : boolean;
+ old_object_option : tsymoptions;
+ currparast : tparasymtable;
+ parseprocvar : tppv;
+ explicit_paraloc : boolean;
+ locationstr : string;
+ paranr : integer;
+ dummytype : ttypesym;
+ begin
+ explicit_paraloc:=false;
+ consume(_LKLAMMER);
+ { Delphi/Kylix supports nonsense like }
+ { procedure p(); }
+ if try_to_consume(_RKLAMMER) and
+ not(m_tp7 in aktmodeswitches) then
+ exit;
+ { parsing a proc or procvar ? }
+ currparast:=tparasymtable(pd.parast);
+ { reset }
+ sc:=tsinglelist.create;
+ defaultrequired:=false;
+ paranr:=0;
+ { the variables are always public }
+ old_object_option:=current_object_option;
+ current_object_option:=[sp_public];
+ inc(testcurobject);
+ repeat
+ parseprocvar:=pv_none;
+ if try_to_consume(_VAR) then
+ varspez:=vs_var
+ else
+ if try_to_consume(_CONST) then
+ varspez:=vs_const
+ else
+ if (m_out in aktmodeswitches) and
+ try_to_consume(_OUT) then
+ varspez:=vs_out
+ else
+ if (m_mac in aktmodeswitches) and
+ try_to_consume(_POINTPOINTPOINT) then
+ begin
+ include(pd.procoptions,po_varargs);
+ break;
+ end
+ else
+ if (m_mac in aktmodeswitches) and
+ try_to_consume(_PROCEDURE) then
+ begin
+ parseprocvar:=pv_proc;
+ varspez:=vs_const;
+ end
+ else
+ if (m_mac in aktmodeswitches) and
+ try_to_consume(_FUNCTION) then
+ begin
+ parseprocvar:=pv_func;
+ varspez:=vs_const;
+ end
+ else
+ varspez:=vs_value;
+ defaultvalue:=nil;
+ tt.reset;
+ { read identifiers and insert with error type }
+ sc.reset;
+ repeat
+ inc(paranr);
+ vs:=tparavarsym.create(orgpattern,paranr*10,varspez,generrortype,[]);
+ currparast.insert(vs);
+ if assigned(vs.owner) then
+ sc.insert(vs)
+ else
+ vs.free;
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ locationstr:='';
+ { macpas anonymous procvar }
+ if parseprocvar<>pv_none then
+ begin
+ pv:=tprocvardef.create(normal_function_level);
+ if token=_LKLAMMER then
+ parse_parameter_dec(pv);
+ if parseprocvar=pv_func then
+ begin
+ consume(_COLON);
+ single_type(pv.rettype,false);
+ end;
+ tt.def:=pv;
+ { possible proc directives }
+ if check_proc_directive(true) then
+ begin
+ dummytype:=ttypesym.create('unnamed',tt);
+ parse_var_proc_directives(tsym(dummytype));
+ dummytype.restype.def:=nil;
+ tt.def.typesym:=nil;
+ dummytype.free;
+ end;
+ { Add implicit hidden parameters and function result }
+ handle_calling_convention(pv);
+ end
+ else
+ { read type declaration, force reading for value and const paras }
+ if (token=_COLON) or (varspez=vs_value) then
+ begin
+ consume(_COLON);
+ { check for an open array }
+ if token=_ARRAY then
+ begin
+ consume(_ARRAY);
+ consume(_OF);
+ { define range and type of range }
+ tt.setdef(tarraydef.create(0,-1,s32inttype));
+ { array of const ? }
+ if (token=_CONST) and (m_objpas in aktmodeswitches) then
+ begin
+ consume(_CONST);
+ srsym:=searchsymonlyin(systemunit,'TVARREC');
+ if not assigned(srsym) then
+ InternalError(200404181);
+ tarraydef(tt.def).setelementtype(ttypesym(srsym).restype);
+ tarraydef(tt.def).IsArrayOfConst:=true;
+ end
+ else
+ begin
+ { define field type }
+ single_type(arrayelementtype,false);
+ tarraydef(tt.def).setelementtype(arrayelementtype);
+ end;
+ end
+ else
+ begin
+ { open string ? }
+ if (varspez=vs_var) and
+ (
+ (
+ ((token=_STRING) or (idtoken=_SHORTSTRING)) and
+ (cs_openstring in aktmoduleswitches) and
+ not(cs_ansistrings in aktlocalswitches)
+ ) or
+ (idtoken=_OPENSTRING)) then
+ begin
+ consume(token);
+ tt:=openshortstringtype;
+ end
+ else
+ begin
+ { everything else }
+ if (m_mac in aktmodeswitches) then
+ try_to_consume(_UNIV); {currently does nothing}
+ single_type(tt,false);
+ end;
+
+ if (target_info.system in [system_powerpc_morphos,system_m68k_amiga]) then
+ begin
+ if (idtoken=_LOCATION) then
+ begin
+ consume(_LOCATION);
+ locationstr:=pattern;
+ consume(_CSTRING);
+ end
+ else
+ begin
+ if explicit_paraloc then
+ Message(parser_e_paraloc_all_paras);
+ locationstr:='';
+ end;
+ end
+ else
+ locationstr:='';
+
+ { default parameter }
+ if (m_default_para in aktmodeswitches) then
+ begin
+ if try_to_consume(_EQUAL) then
+ begin
+ vs:=tparavarsym(sc.first);
+ if assigned(vs.listnext) then
+ Message(parser_e_default_value_only_one_para);
+ { prefix 'def' to the parameter name }
+ defaultvalue:=ReadConstant('$def'+vs.name,vs.fileinfo);
+ if assigned(defaultvalue) then
+ begin
+ include(defaultvalue.symoptions,sp_internal);
+ pd.parast.insert(defaultvalue);
+ end;
+ defaultrequired:=true;
+ end
+ else
+ begin
+ if defaultrequired then
+ Message1(parser_e_default_value_expected_for_para,vs.name);
+ end;
+ end;
+ end;
+ end
+ else
+ tt:=cformaltype;
+
+ { File types are only allowed for var parameters }
+ if (tt.def.deftype=filedef) and
+ (varspez<>vs_var) then
+ CGMessage(cg_e_file_must_call_by_reference);
+
+ vs:=tparavarsym(sc.first);
+ while assigned(vs) do
+ begin
+ { update varsym }
+ vs.vartype:=tt;
+ vs.defaultconstsym:=defaultvalue;
+
+ if (target_info.system in [system_powerpc_morphos,system_m68k_amiga]) then
+ begin
+ if locationstr<>'' then
+ begin
+ if assigned(sc.first.listnext) then
+ Message(parser_e_paraloc_only_one_para);
+ if (paranr>1) and not(explicit_paraloc) then
+ Message(parser_e_paraloc_all_paras);
+ explicit_paraloc:=true;
+ include(vs.varoptions,vo_has_explicit_paraloc);
+ if not(paramanager.parseparaloc(vs,upper(locationstr))) then
+ message(parser_e_illegal_explicit_paraloc);
+ end
+ else
+ if explicit_paraloc then
+ Message(parser_e_paraloc_all_paras);
+ end;
+ vs:=tparavarsym(vs.listnext);
+ end;
+ until not try_to_consume(_SEMICOLON);
+
+ if explicit_paraloc then
+ begin
+ pd.has_paraloc_info:=true;
+ include(pd.procoptions,po_explicitparaloc);
+ end;
+ { remove parasymtable from stack }
+ sc.free;
+ { reset object options }
+ dec(testcurobject);
+ current_object_option:=old_object_option;
+ consume(_RKLAMMER);
+ end;
+
+
+ function parse_proc_head(aclass:tobjectdef;potype:tproctypeoption;var pd:tprocdef):boolean;
+ var
+ hs : string;
+ orgsp,sp : stringid;
+ sym : tsym;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ storepos,
+ procstartfilepos : tfileposinfo;
+ searchagain : boolean;
+ i : longint;
+ st : tsymtable;
+ aprocsym : tprocsym;
+ begin
+ { Save the position where this procedure really starts }
+ procstartfilepos:=akttokenpos;
+
+ result:=false;
+ pd:=nil;
+ aprocsym:=nil;
+
+ if (potype=potype_operator) then
+ begin
+ sp:=overloaded_names[optoken];
+ orgsp:=sp;
+ end
+ else
+ begin
+ sp:=pattern;
+ orgsp:=orgpattern;
+ consume(_ID);
+ end;
+
+ { examine interface map: function/procedure iname.functionname=locfuncname }
+ if assigned(aclass) and
+ assigned(aclass.implementedinterfaces) and
+ (aclass.implementedinterfaces.count>0) and
+ try_to_consume(_POINT) then
+ begin
+ storepos:=akttokenpos;
+ akttokenpos:=procstartfilepos;
+ { get interface syms}
+ searchsym(sp,sym,srsymtable);
+ if not assigned(sym) then
+ begin
+ identifier_not_found(orgsp);
+ sym:=generrorsym;
+ end;
+ akttokenpos:=storepos;
+ { qualifier is interface? }
+ if (sym.typ=typesym) and
+ (ttypesym(sym).restype.def.deftype=objectdef) then
+ i:=aclass.implementedinterfaces.searchintf(ttypesym(sym).restype.def)
+ else
+ i:=-1;
+ if (i=-1) then
+ Message(parser_e_interface_id_expected);
+ consume(_ID);
+ { Create unique name <interface>.<method> }
+ hs:=sp+'.'+pattern;
+ consume(_EQUAL);
+ if (token=_ID) then
+ aclass.implementedinterfaces.addmappings(i,hs,pattern);
+ consume(_ID);
+ result:=true;
+ exit;
+ end;
+
+ { method ? }
+ if not assigned(aclass) and
+ (potype<>potype_operator) and
+ (symtablestack.symtablelevel=main_program_level) and
+ try_to_consume(_POINT) then
+ begin
+ { search for object name }
+ storepos:=akttokenpos;
+ akttokenpos:=procstartfilepos;
+ searchsym(sp,sym,srsymtable);
+ if not assigned(sym) then
+ begin
+ identifier_not_found(orgsp);
+ sym:=generrorsym;
+ end;
+ akttokenpos:=storepos;
+ { consume proc name }
+ sp:=pattern;
+ orgsp:=orgpattern;
+ procstartfilepos:=akttokenpos;
+ consume(_ID);
+ { qualifier is class name ? }
+ if (sym.typ=typesym) and
+ (ttypesym(sym).restype.def.deftype=objectdef) then
+ begin
+ aclass:=tobjectdef(ttypesym(sym).restype.def);
+ aprocsym:=tprocsym(aclass.symtable.search(sp));
+ { we solve this below }
+ if assigned(aprocsym) then
+ begin
+ if aprocsym.typ<>procsym then
+ begin
+ { we use a different error message for tp7 so it looks more compatible }
+ if (m_fpc in aktmodeswitches) then
+ Message1(parser_e_overloaded_no_procedure,aprocsym.realname)
+ else
+ Message(parser_e_methode_id_expected);
+ { rename the name to an unique name to avoid an
+ error when inserting the symbol in the symtable }
+ orgsp:=orgsp+'$'+tostr(aktfilepos.line);
+ aprocsym:=nil;
+ end;
+ end
+ else
+ begin
+ Message(parser_e_methode_id_expected);
+ { recover by making it a normal procedure instead of method }
+ aclass:=nil;
+ end;
+ end
+ else
+ Message(parser_e_class_id_expected);
+ end
+ else
+ begin
+ { check for constructor/destructor which is not allowed here }
+ if (not parse_only) and
+ (potype in [potype_constructor,potype_destructor]) then
+ Message(parser_e_constructors_always_objects);
+
+ repeat
+ searchagain:=false;
+ akttokenpos:=procstartfilepos;
+ srsym:=tsym(symtablestack.search(sp));
+
+ if not(parse_only) and
+ not assigned(srsym) and
+ (symtablestack.symtabletype=staticsymtable) and
+ assigned(symtablestack.next) and
+ (symtablestack.next.iscurrentunit) then
+ begin
+ { The procedure we prepare for is in the implementation
+ part of the unit we compile. It is also possible that we
+ are compiling a program, which is also some kind of
+ implementaion part.
+
+ We need to find out if the procedure is global. If it is
+ global, it is in the global symtable.}
+ srsym:=tsym(symtablestack.next.search(sp));
+ end;
+
+ { Check if overloaded is a procsym }
+ if assigned(srsym) then
+ begin
+ if srsym.typ=procsym then
+ aprocsym:=tprocsym(srsym)
+ else
+ begin
+ { when the other symbol is a unit symbol then hide the unit
+ symbol }
+ if (srsym.typ=unitsym) then
+ begin
+ srsym.owner.rename(srsym.name,'hidden'+srsym.name);
+ searchagain:=true;
+ end
+ else
+ begin
+ { we use a different error message for tp7 so it looks more compatible }
+ if (m_fpc in aktmodeswitches) then
+ Message1(parser_e_overloaded_no_procedure,srsym.realname)
+ else
+ tstoredsymtable(symtablestack).DuplicateSym(nil,srsym);
+ { rename the name to an unique name to avoid an
+ error when inserting the symbol in the symtable }
+ orgsp:=orgsp+'$'+tostr(aktfilepos.line);
+ end;
+ end;
+ end;
+ until not searchagain;
+ end;
+
+ { test again if assigned, it can be reset to recover }
+ if not assigned(aprocsym) then
+ begin
+ { create a new procsym and set the real filepos }
+ akttokenpos:=procstartfilepos;
+ { for operator we have only one procsym for each overloaded
+ operation }
+ if (potype=potype_operator) then
+ begin
+ Aprocsym:=Tprocsym(symtablestack.search(sp));
+ if Aprocsym=nil then
+ Aprocsym:=tprocsym.create('$'+sp);
+ end
+ else
+ aprocsym:=tprocsym.create(orgsp);
+ symtablestack.insert(aprocsym);
+ end;
+
+ { to get the correct symtablelevel we must ignore objectsymtables }
+ st:=symtablestack;
+ while not(st.symtabletype in [staticsymtable,globalsymtable,localsymtable]) do
+ st:=st.next;
+ pd:=tprocdef.create(st.symtablelevel+1);
+ pd._class:=aclass;
+ pd.procsym:=aprocsym;
+ pd.proctypeoption:=potype;
+ { methods need to be exported }
+ if assigned(aclass) and
+ (
+ (symtablestack.symtabletype=objectsymtable) or
+ (symtablestack.symtablelevel=main_program_level)
+ ) then
+ include(pd.procoptions,po_global);
+
+ { symbol options that need to be kept per procdef }
+ pd.fileinfo:=procstartfilepos;
+ pd.symoptions:=current_object_option;
+
+ { parse parameters }
+ if token=_LKLAMMER then
+ parse_parameter_dec(pd);
+
+ result:=true;
+ end;
+
+
+ function parse_proc_dec(aclass:tobjectdef):tprocdef;
+ var
+ pd : tprocdef;
+ isclassmethod : boolean;
+ begin
+ pd:=nil;
+ isclassmethod:=false;
+ { read class method }
+ if try_to_consume(_CLASS) then
+ begin
+ { class method only allowed for procedures and functions }
+ if not(token in [_FUNCTION,_PROCEDURE]) then
+ Message(parser_e_procedure_or_function_expected);
+
+ if is_interface(aclass) then
+ Message(parser_e_no_static_method_in_interfaces)
+ else
+ isclassmethod:=true;
+ end;
+ case token of
+ _FUNCTION :
+ begin
+ consume(_FUNCTION);
+ if parse_proc_head(aclass,potype_function,pd) then
+ begin
+ { pd=nil when it is a interface mapping }
+ if assigned(pd) then
+ begin
+ if try_to_consume(_COLON) then
+ begin
+ inc(testcurobject);
+ single_type(pd.rettype,false);
+ pd.test_if_fpu_result;
+ dec(testcurobject);
+ end
+ else
+ begin
+ if (
+ parse_only and
+ not(is_interface(pd._class))
+ ) or
+ (m_repeat_forward in aktmodeswitches) then
+ begin
+ consume(_COLON);
+ consume_all_until(_SEMICOLON);
+ end;
+ end;
+ if isclassmethod then
+ include(pd.procoptions,po_classmethod);
+ end;
+ end
+ else
+ begin
+ { recover }
+ consume(_COLON);
+ consume_all_until(_SEMICOLON);
+ end;
+ end;
+
+ _PROCEDURE :
+ begin
+ consume(_PROCEDURE);
+ if parse_proc_head(aclass,potype_procedure,pd) then
+ begin
+ { pd=nil when it is a interface mapping }
+ if assigned(pd) then
+ begin
+ pd.rettype:=voidtype;
+ if isclassmethod then
+ include(pd.procoptions,po_classmethod);
+ end;
+ end;
+ end;
+
+ _CONSTRUCTOR :
+ begin
+ consume(_CONSTRUCTOR);
+ parse_proc_head(aclass,potype_constructor,pd);
+ if assigned(pd) and
+ assigned(pd._class) then
+ begin
+ { Set return type, class constructors return the
+ created instance, object constructors return boolean }
+ if is_class(pd._class) then
+ pd.rettype.setdef(pd._class)
+ else
+ pd.rettype:=booltype;
+ end;
+ end;
+
+ _DESTRUCTOR :
+ begin
+ consume(_DESTRUCTOR);
+ parse_proc_head(aclass,potype_destructor,pd);
+ if assigned(pd) then
+ pd.rettype:=voidtype;
+ end;
+
+ _OPERATOR :
+ begin
+ consume(_OPERATOR);
+ if (token in [first_overloaded..last_overloaded]) then
+ begin
+ optoken:=token;
+ end
+ else
+ begin
+ Message(parser_e_overload_operator_failed);
+ { Use the dummy NOTOKEN that is also declared
+ for the overloaded_operator[] }
+ optoken:=NOTOKEN;
+ end;
+ consume(token);
+ parse_proc_head(aclass,potype_operator,pd);
+ if assigned(pd) then
+ begin
+ if pd.parast.symtablelevel>normal_function_level then
+ Message(parser_e_no_local_operator);
+ if token<>_ID then
+ begin
+ if not(m_result in aktmodeswitches) then
+ consume(_ID);
+ end
+ else
+ begin
+ pd.resultname:=orgpattern;
+ consume(_ID);
+ end;
+ if not try_to_consume(_COLON) then
+ begin
+ consume(_COLON);
+ pd.rettype:=generrortype;
+ consume_all_until(_SEMICOLON);
+ end
+ else
+ begin
+ single_type(pd.rettype,false);
+ pd.test_if_fpu_result;
+ if (optoken in [_EQUAL,_GT,_LT,_GTE,_LTE]) and
+ ((pd.rettype.def.deftype<>orddef) or
+ (torddef(pd.rettype.def).typ<>bool8bit)) then
+ Message(parser_e_comparative_operator_return_boolean);
+ if (optoken=_ASSIGNMENT) and
+ equal_defs(pd.rettype.def,
+ tparavarsym(pd.parast.symindex.first).vartype.def) then
+ message(parser_e_no_such_assignment)
+ else if not isoperatoracceptable(pd,optoken) then
+ Message(parser_e_overload_impossible);
+ end;
+ end
+ else
+ begin
+ { recover }
+ try_to_consume(_ID);
+ consume(_COLON);
+ consume_all_until(_SEMICOLON);
+ end;
+ end;
+ end;
+ { support procedure proc stdcall export; }
+ if not(check_proc_directive(false)) then
+ consume(_SEMICOLON);
+ result:=pd;
+ end;
+
+
+{****************************************************************************
+ Procedure directive handlers
+****************************************************************************}
+
+procedure pd_far(pd:tabstractprocdef);
+begin
+ Message1(parser_w_proc_directive_ignored,'FAR');
+end;
+
+procedure pd_near(pd:tabstractprocdef);
+begin
+ Message1(parser_w_proc_directive_ignored,'NEAR');
+end;
+
+procedure pd_export(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200304264);
+ if assigned(tprocdef(pd)._class) then
+ Message(parser_e_methods_dont_be_export);
+ if pd.parast.symtablelevel>normal_function_level then
+ Message(parser_e_dont_nest_export);
+end;
+
+procedure pd_forward(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200304265);
+ tprocdef(pd).forwarddef:=true;
+end;
+
+
+procedure pd_alias(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200304266);
+ consume(_COLON);
+ tprocdef(pd).aliasnames.insert(get_stringconst);
+ include(pd.procoptions,po_has_public_name);
+end;
+
+
+procedure pd_public(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200304266);
+ if try_to_consume(_NAME) then
+ begin
+ tprocdef(pd).aliasnames.insert(get_stringconst);
+ include(pd.procoptions,po_has_public_name);
+ end;
+end;
+
+
+procedure pd_asmname(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200304267);
+ tprocdef(pd).aliasnames.insert(target_info.Cprefix+pattern);
+ if token=_CCHAR then
+ consume(_CCHAR)
+ else
+ consume(_CSTRING);
+ { we don't need anything else }
+ tprocdef(pd).forwarddef:=false;
+end;
+
+
+procedure pd_inline(pd:tabstractprocdef);
+begin
+ { Check if there are parameters that can't be inlined }
+ pd.parast.foreach_static(@check_inline_para,pd);
+end;
+
+procedure pd_internconst(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200304268);
+ consume(_COLON);
+ tprocdef(pd).extnumber:=get_intconst;
+end;
+
+procedure pd_internproc(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200304268);
+ consume(_COLON);
+ tprocdef(pd).extnumber:=get_intconst;
+ { the proc is defined }
+ tprocdef(pd).forwarddef:=false;
+end;
+
+procedure pd_interrupt(pd:tabstractprocdef);
+begin
+ if pd.parast.symtablelevel>normal_function_level then
+ Message(parser_e_dont_nest_interrupt);
+end;
+
+procedure pd_abstract(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200304269);
+ if (po_virtualmethod in pd.procoptions) then
+ include(pd.procoptions,po_abstractmethod)
+ else
+ Message(parser_e_only_virtual_methods_abstract);
+ { the method is defined }
+ tprocdef(pd).forwarddef:=false;
+end;
+
+procedure pd_virtual(pd:tabstractprocdef);
+{$ifdef WITHDMT}
+var
+ pt : tnode;
+{$endif WITHDMT}
+begin
+ if pd.deftype<>procdef then
+ internalerror(2003042610);
+ if (pd.proctypeoption=potype_constructor) and
+ is_object(tprocdef(pd)._class) then
+ Message(parser_e_constructor_cannot_be_not_virtual);
+{$ifdef WITHDMT}
+ if is_object(tprocdef(pd)._class) and
+ (token<>_SEMICOLON) then
+ begin
+ { any type of parameter is allowed here! }
+ pt:=comp_expr(true);
+ if is_constintnode(pt) then
+ begin
+ include(pd.procoptions,po_msgint);
+ pd.messageinf.i:=pt^.value;
+ end
+ else
+ Message(parser_e_ill_msg_expr);
+ disposetree(pt);
+ end;
+{$endif WITHDMT}
+end;
+
+procedure pd_static(pd:tabstractprocdef);
+begin
+ if (cs_static_keyword in aktmoduleswitches) then
+ begin
+ if pd.deftype=procdef then
+ include(tprocdef(pd).procsym.symoptions,sp_static);
+ include(pd.procoptions,po_staticmethod);
+ end;
+end;
+
+procedure pd_override(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(2003042611);
+ if not(is_class_or_interface(tprocdef(pd)._class)) then
+ Message(parser_e_no_object_override);
+end;
+
+procedure pd_overload(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(2003042612);
+ include(tprocdef(pd).procsym.symoptions,sp_has_overloaded);
+end;
+
+procedure pd_message(pd:tabstractprocdef);
+var
+ pt : tnode;
+ paracnt : longint;
+begin
+ if pd.deftype<>procdef then
+ internalerror(2003042613);
+ if not is_class(tprocdef(pd)._class) then
+ Message(parser_e_msg_only_for_classes);
+ { check parameter type }
+ paracnt:=0;
+ pd.parast.foreach_static(@check_msg_para,@paracnt);
+ if paracnt<>1 then
+ Message(parser_e_ill_msg_param);
+ pt:=comp_expr(true);
+ if pt.nodetype=stringconstn then
+ begin
+ include(pd.procoptions,po_msgstr);
+ tprocdef(pd).messageinf.str:=strnew(tstringconstnode(pt).value_str);
+ end
+ else
+ if is_constintnode(pt) then
+ begin
+ include(pd.procoptions,po_msgint);
+ tprocdef(pd).messageinf.i:=tordconstnode(pt).value;
+ end
+ else
+ Message(parser_e_ill_msg_expr);
+ pt.free;
+end;
+
+
+procedure pd_reintroduce(pd:tabstractprocdef);
+begin
+ if pd.deftype<>procdef then
+ internalerror(200401211);
+ if not(is_class_or_interface(tprocdef(pd)._class)) then
+ Message(parser_e_no_object_reintroduce);
+end;
+
+
+procedure pd_syscall(pd:tabstractprocdef);
+{$ifdef powerpc}
+var
+ vs : tparavarsym;
+ sym : tsym;
+ symtable : tsymtable;
+{$endif powerpc}
+begin
+ if pd.deftype<>procdef then
+ internalerror(2003042614);
+ tprocdef(pd).forwarddef:=false;
+{$ifdef powerpc}
+ if target_info.system in [system_powerpc_morphos] then
+ begin
+ if idtoken=_LEGACY then
+ begin
+ consume(_LEGACY);
+ include(pd.procoptions,po_syscall_legacy);
+ end
+ else if idtoken=_SYSV then
+ begin
+ consume(_SYSV);
+ include(pd.procoptions,po_syscall_sysv);
+ end
+ else if idtoken=_BASESYSV then
+ begin
+ consume(_BASESYSV);
+ include(pd.procoptions,po_syscall_basesysv);
+ end
+ else if idtoken=_SYSVBASE then
+ begin
+ consume(_SYSVBASE);
+ include(pd.procoptions,po_syscall_sysvbase);
+ end
+ else if idtoken=_R12BASE then
+ begin
+ consume(_R12BASE);
+ include(pd.procoptions,po_syscall_r12base);
+ end
+ else
+ if syscall_convention='LEGACY' then
+ include(pd.procoptions,po_syscall_legacy)
+ else if syscall_convention='SYSV' then
+ include(pd.procoptions,po_syscall_sysv)
+ else if syscall_convention='BASESYSV' then
+ include(pd.procoptions,po_syscall_basesysv)
+ else if syscall_convention='SYSVBASE' then
+ include(pd.procoptions,po_syscall_sysvbase)
+ else if syscall_convention='R12BASE' then
+ include(pd.procoptions,po_syscall_r12base)
+ else
+ internalerror(2005010404);
+
+ if consume_sym(sym,symtable) then
+ begin
+ if (sym.typ=globalvarsym) and
+ (
+ (tabstractvarsym(sym).vartype.def.deftype=pointerdef) or
+ is_32bitint(tabstractvarsym(sym).vartype.def)
+ ) then
+ begin
+ tprocdef(pd).libsym:=sym;
+ if po_syscall_legacy in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_legacy,vs_value,tabstractvarsym(sym).vartype,[vo_is_syscall_lib,vo_is_hidden_para,vo_has_explicit_paraloc]);
+ paramanager.parseparaloc(vs,'A6');
+ pd.parast.insert(vs);
+ end
+ else if po_syscall_sysv in tprocdef(pd).procoptions then
+ begin
+ { Nothing to be done for sysv here for now, but this might change }
+ end
+ else if po_syscall_basesysv in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_basesysv,vs_value,tabstractvarsym(sym).vartype,[vo_is_syscall_lib,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end
+ else if po_syscall_sysvbase in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_sysvbase,vs_value,tabstractvarsym(sym).vartype,[vo_is_syscall_lib,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end
+ else if po_syscall_r12base in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_r12base,vs_value,tabstractvarsym(sym).vartype,[vo_is_syscall_lib,vo_is_hidden_para,vo_has_explicit_paraloc]);
+ paramanager.parseparaloc(vs,'R12');
+ pd.parast.insert(vs);
+ end
+ else
+ internalerror(2005010501);
+ end
+ else
+ Message(parser_e_32bitint_or_pointer_variable_expected);
+ end;
+ (paramanager as tppcparamanager).create_funcretloc_info(pd,calleeside);
+ (paramanager as tppcparamanager).create_funcretloc_info(pd,callerside);
+ end;
+{$endif powerpc}
+ tprocdef(pd).extnumber:=get_intconst;
+end;
+
+
+procedure pd_external(pd:tabstractprocdef);
+{
+ If import_dll=nil the procedure is assumed to be in another
+ object file. In that object file it should have the name to
+ which import_name is pointing to. Otherwise, the procedure is
+ assumed to be in the DLL to which import_dll is pointing to. In
+ that case either import_nr<>0 or import_name<>nil is true, so
+ the procedure is either imported by number or by name. (DM)
+}
+begin
+ if pd.deftype<>procdef then
+ internalerror(2003042615);
+ with tprocdef(pd) do
+ begin
+ forwarddef:=false;
+ { forbid local external procedures }
+ if parast.symtablelevel>normal_function_level then
+ Message(parser_e_no_local_proc_external);
+ { If the procedure should be imported from a DLL, a constant string follows.
+ This isn't really correct, an contant string expression follows
+ so we check if an semicolon follows, else a string constant have to
+ follow (FK) }
+ if not(token=_SEMICOLON) and not(idtoken=_NAME) then
+ begin
+ import_dll:=stringdup(get_stringconst);
+ if (idtoken=_NAME) then
+ begin
+ consume(_NAME);
+ import_name:=stringdup(get_stringconst);
+ if import_name^='' then
+ message(parser_e_empty_import_name);
+ end;
+ if (idtoken=_INDEX) then
+ begin
+ {After the word index follows the index number in the DLL.}
+ consume(_INDEX);
+ import_nr:=get_intconst;
+ end;
+ { default is to used the realname of the procedure }
+ if (import_nr=0) and not assigned(import_name) then
+ import_name:=stringdup(procsym.realname);
+ end
+ else
+ begin
+ if (idtoken=_NAME) then
+ begin
+ consume(_NAME);
+ import_name:=stringdup(get_stringconst);
+ if import_name^='' then
+ message(parser_e_empty_import_name);
+ end;
+ end;
+ end;
+end;
+
+
+type
+ pd_handler=procedure(pd:tabstractprocdef);
+ proc_dir_rec=record
+ idtok : ttoken;
+ pd_flags : tpdflags;
+ handler : pd_handler;
+ pocall : tproccalloption;
+ pooption : tprocoptions;
+ mutexclpocall : tproccalloptions;
+ mutexclpotype : tproctypeoptions;
+ mutexclpo : tprocoptions;
+ end;
+const
+ {Should contain the number of procedure directives we support.}
+ num_proc_directives=37;
+ proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
+ (
+ (
+ idtok:_ABSTRACT;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf];
+ handler : @pd_abstract;
+ pocall : pocall_none;
+ pooption : [po_abstractmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_exports,po_interrupt,po_external,po_inline]
+ ),(
+ idtok:_ALIAS;
+ pd_flags : [pd_implemen,pd_body,pd_notobjintf];
+ handler : @pd_alias;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_ASMNAME;
+ pd_flags : [pd_interface,pd_implemen,pd_notobjintf];
+ handler : @pd_asmname;
+ pocall : pocall_cdecl;
+ pooption : [po_external];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_ASSEMBLER;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_assembler];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_C; {same as cdecl for mode mac}
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_cdecl;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_assembler,po_external]
+ ),(
+ idtok:_CDECL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_cdecl;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_assembler,po_external]
+ ),(
+ idtok:_DYNAMIC;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf];
+ handler : @pd_virtual;
+ pocall : pocall_none;
+ pooption : [po_virtualmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_exports,po_interrupt,po_external,po_overridingmethod,po_inline]
+ ),(
+ idtok:_EXPORT;
+ pd_flags : [pd_body,pd_interface,pd_implemen,pd_notobjintf];
+ handler : @pd_export;
+ pocall : pocall_none;
+ pooption : [po_exports,po_global];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_external,po_interrupt,po_inline]
+ ),(
+ idtok:_EXTERNAL;
+ pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf];
+ handler : @pd_external;
+ pocall : pocall_none;
+ pooption : [po_external];
+ mutexclpocall : [pocall_internproc,pocall_syscall];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_public,po_exports,po_interrupt,po_assembler,po_inline]
+ ),(
+ idtok:_FAR;
+ pd_flags : [pd_implemen,pd_body,pd_interface,pd_procvar,pd_notobject,pd_notobjintf];
+ handler : @pd_far;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_inline]
+ ),(
+ idtok:_FAR16;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar,pd_notobject];
+ handler : nil;
+ pocall : pocall_far16;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_FORWARD;
+ pd_flags : [pd_implemen,pd_notobject,pd_notobjintf];
+ handler : @pd_forward;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_OLDFPCCALL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_oldfpccall;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_INLINE;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
+ handler : @pd_inline;
+ pocall : pocall_none;
+ pooption : [po_inline];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_exports,po_external,po_interrupt,po_virtualmethod]
+ ),(
+ idtok:_INTERNCONST;
+ pd_flags : [pd_interface,pd_body,pd_notobject,pd_notobjintf];
+ handler : @pd_internconst;
+ pocall : pocall_none;
+ pooption : [po_internconst];
+ mutexclpocall : [];
+ mutexclpotype : [potype_operator];
+ mutexclpo : []
+ ),(
+ idtok:_INTERNPROC;
+ pd_flags : [pd_interface,pd_notobject,pd_notobjintf];
+ handler : @pd_internproc;
+ pocall : pocall_internproc;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
+ mutexclpo : [po_exports,po_external,po_interrupt,po_assembler,po_iocheck,po_virtualmethod]
+ ),(
+ idtok:_INTERRUPT;
+ pd_flags : [pd_implemen,pd_body,pd_notobject,pd_notobjintf];
+ handler : @pd_interrupt;
+ pocall : pocall_none;
+ pooption : [po_interrupt];
+ mutexclpocall : [pocall_internproc,pocall_cdecl,pocall_cppdecl,pocall_stdcall,
+ pocall_pascal,pocall_far16,pocall_oldfpccall];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_IOCHECK;
+ pd_flags : [pd_implemen,pd_body,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_iocheck];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_MESSAGE;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf];
+ handler : @pd_message;
+ pocall : pocall_none;
+ pooption : []; { can be po_msgstr or po_msgint }
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
+ mutexclpo : [po_interrupt,po_external,po_inline]
+ ),(
+ idtok:_MWPASCAL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_mwpascal;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_NEAR;
+ pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf];
+ handler : @pd_near;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_NOSTACKFRAME;
+ pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_nostackframe];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_OVERLOAD;
+ pd_flags : [pd_implemen,pd_interface,pd_body];
+ handler : @pd_overload;
+ pocall : pocall_none;
+ pooption : [po_overload];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_OVERRIDE;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf];
+ handler : @pd_override;
+ pocall : pocall_none;
+ pooption : [po_overridingmethod,po_virtualmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_exports,po_external,po_interrupt,po_virtualmethod,po_inline]
+ ),(
+ idtok:_PASCAL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_pascal;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_PUBLIC;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobject,pd_notobjintf];
+ handler : @pd_public;
+ pocall : pocall_none;
+ pooption : [po_public,po_global];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_REGISTER;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_register;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_REINTRODUCE;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf];
+ handler : @pd_reintroduce;
+ pocall : pocall_none;
+ pooption : [po_reintroduce];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_interrupt,po_exports,po_overridingmethod,po_inline]
+ ),(
+ idtok:_SAFECALL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_safecall;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_SOFTFLOAT;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_softfloat;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ { it's available with po_external because the libgcc floating point routines on the arm
+ uses this calling convention }
+ mutexclpo : []
+ ),(
+ idtok:_STATIC;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf];
+ handler : @pd_static;
+ pocall : pocall_none;
+ pooption : [po_staticmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_external,po_interrupt,po_exports,po_inline]
+ ),(
+ idtok:_STDCALL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_stdcall;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_SYSCALL;
+ pd_flags : [pd_interface,pd_implemen,pd_notobject,pd_notobjintf];
+ handler : @pd_syscall;
+ pocall : pocall_syscall;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_external,po_assembler,po_interrupt,po_exports]
+ ),(
+ idtok:_VIRTUAL;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf];
+ handler : @pd_virtual;
+ pocall : pocall_none;
+ pooption : [po_virtualmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_interrupt,po_exports,po_overridingmethod,po_inline]
+ ),(
+ idtok:_CPPDECL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_cppdecl;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_assembler,po_external,po_virtualmethod]
+ ),(
+ idtok:_VARARGS;
+ pd_flags : [pd_interface,pd_implemen,pd_procvar];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_varargs];
+ mutexclpocall : [pocall_internproc,pocall_stdcall,pocall_register,
+ pocall_far16,pocall_oldfpccall,pocall_mwpascal];
+ mutexclpotype : [];
+ mutexclpo : [po_assembler,po_interrupt,po_inline]
+ ),(
+ idtok:_COMPILERPROC;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_compilerproc];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor];
+ mutexclpo : [po_interrupt]
+ )
+ );
+
+
+ function check_proc_directive(isprocvar:boolean):boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ for i:=1 to num_proc_directives do
+ if proc_direcdata[i].idtok=idtoken then
+ begin
+ if ((not isprocvar) or
+ (pd_procvar in proc_direcdata[i].pd_flags)) and
+ { don't eat a public directive in classes }
+ not((idtoken=_PUBLIC) and (symtablestack.symtabletype=objectsymtable)) then
+ result:=true;
+ exit;
+ end;
+ end;
+
+
+ function parse_proc_direc(pd:tabstractprocdef;var pdflags:tpdflags):boolean;
+ {
+ Parse the procedure directive, returns true if a correct directive is found
+ }
+ var
+ p : longint;
+ found : boolean;
+ name : stringid;
+ begin
+ parse_proc_direc:=false;
+ name:=tokeninfo^[idtoken].str;
+ found:=false;
+
+ { Hint directive? Then exit immediatly }
+ if (m_hintdirective in aktmodeswitches) then
+ begin
+ case idtoken of
+ _LIBRARY,
+ _PLATFORM,
+ _UNIMPLEMENTED,
+ _DEPRECATED :
+ exit;
+ end;
+ end;
+
+ { C directive is MAC only, because it breaks too much existing code
+ on other platforms (PFV) }
+ if (idtoken=_C) and
+ not(m_mac in aktmodeswitches) then
+ exit;
+
+ { retrieve data for directive if found }
+ for p:=1 to num_proc_directives do
+ if proc_direcdata[p].idtok=idtoken then
+ begin
+ found:=true;
+ break;
+ end;
+
+ { Check if the procedure directive is known }
+ if not found then
+ begin
+ { parsing a procvar type the name can be any
+ next variable !! }
+ if ((pdflags * [pd_procvar,pd_object])=[]) and
+ not(idtoken=_PROPERTY) then
+ Message1(parser_w_unknown_proc_directive_ignored,name);
+ exit;
+ end;
+
+ { static needs a special treatment }
+ if (idtoken=_STATIC) and not (cs_static_keyword in aktmoduleswitches) then
+ exit;
+
+ { check if method and directive not for object, like public.
+ This needs to be checked also for procvars }
+ if (pd_notobject in proc_direcdata[p].pd_flags) and
+ (symtablestack.symtabletype=objectsymtable) then
+ exit;
+
+ { Conflicts between directives ? }
+ if (pd.proctypeoption in proc_direcdata[p].mutexclpotype) or
+ (pd.proccalloption in proc_direcdata[p].mutexclpocall) or
+ ((pd.procoptions*proc_direcdata[p].mutexclpo)<>[]) then
+ begin
+ Message1(parser_e_proc_dir_conflict,name);
+ exit;
+ end;
+
+ { set calling convention }
+ if proc_direcdata[p].pocall<>pocall_none then
+ begin
+ if (po_hascallingconvention in pd.procoptions) then
+ begin
+ Message2(parser_w_proc_overriding_calling,
+ proccalloptionStr[pd.proccalloption],
+ proccalloptionStr[proc_direcdata[p].pocall]);
+ end;
+ { check if the target processor supports this calling convention }
+ if not(proc_direcdata[p].pocall in supported_calling_conventions) then
+ begin
+ Message1(parser_e_illegal_calling_convention,proccalloptionStr[proc_direcdata[p].pocall]);
+ { recover }
+ proc_direcdata[p].pocall:=pocall_stdcall;
+ end;
+ pd.proccalloption:=proc_direcdata[p].pocall;
+ include(pd.procoptions,po_hascallingconvention);
+ end;
+
+ if pd.deftype=procdef then
+ begin
+ { Check if the directive is only for objects }
+ if (pd_object in proc_direcdata[p].pd_flags) and
+ not assigned(tprocdef(pd)._class) then
+ exit;
+
+ { check if method and directive not for interface }
+ if (pd_notobjintf in proc_direcdata[p].pd_flags) and
+ is_interface(tprocdef(pd)._class) then
+ exit;
+ end;
+
+ { consume directive, and turn flag on }
+ consume(token);
+ parse_proc_direc:=true;
+
+ { Check the pd_flags if the directive should be allowed }
+ if (pd_interface in pdflags) and
+ not(pd_interface in proc_direcdata[p].pd_flags) then
+ begin
+ Message1(parser_e_proc_dir_not_allowed_in_interface,name);
+ exit;
+ end;
+ if (pd_implemen in pdflags) and
+ not(pd_implemen in proc_direcdata[p].pd_flags) then
+ begin
+ Message1(parser_e_proc_dir_not_allowed_in_implementation,name);
+ exit;
+ end;
+ if (pd_procvar in pdflags) and
+ not(pd_procvar in proc_direcdata[p].pd_flags) then
+ begin
+ Message1(parser_e_proc_dir_not_allowed_in_procvar,name);
+ exit;
+ end;
+
+ { Return the new pd_flags }
+ if not(pd_body in proc_direcdata[p].pd_flags) then
+ exclude(pdflags,pd_body);
+
+ { Add the correct flag }
+ pd.procoptions:=pd.procoptions+proc_direcdata[p].pooption;
+
+ { Call the handler }
+ if pointer(proc_direcdata[p].handler)<>nil then
+ proc_direcdata[p].handler(pd);
+ end;
+
+
+
+ function proc_get_importname(pd:tprocdef):string;
+ begin
+ result:='';
+ if not(po_external in pd.procoptions) then
+ internalerror(200412151);
+ { import by number? }
+ if pd.import_nr<>0 then
+ begin
+ { Nothing to do }
+ end
+ else
+ { external name specified }
+ if assigned(pd.import_name) then
+ begin
+ { Win32 imports need to use the normal name since to functions
+ can refer to the same DLL function. This is also needed for compatability
+ with Delphi and TP7 }
+ if not(
+ assigned(pd.import_dll) and
+ (target_info.system in [system_i386_win32,system_i386_wdosx,
+ system_i386_emx,system_i386_os2,system_arm_wince,system_i386_wince])
+ ) then
+ begin
+ if not(pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ result:=pd.import_name^
+ else
+ result:=target_info.Cprefix+pd.import_name^;
+ end;
+ end
+ else
+ begin
+ { Default names when importing variables }
+ case pd.proccalloption of
+ pocall_cdecl :
+ begin
+ if assigned(pd._class) then
+ result:=target_info.Cprefix+pd._class.objrealname^+'_'+pd.procsym.realname
+ else
+ result:=target_info.Cprefix+pd.procsym.realname;
+ end;
+ pocall_cppdecl :
+ begin
+ result:=target_info.Cprefix+pd.cplusplusmangledname;
+ end;
+ else
+ begin
+ {In MacPas a single "external" has the same effect as "external name 'xxx'" }
+ if (m_mac in aktmodeswitches) then
+ result:=tprocdef(pd).procsym.realname;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure proc_set_mangledname(pd:tprocdef);
+ var
+ s : string;
+ begin
+ { When the mangledname is already set we aren't allowed to change
+ it because it can already be used somewhere (PFV) }
+ if not(po_has_mangledname in pd.procoptions) then
+ begin
+ if (po_external in pd.procoptions) then
+ begin
+ { External Procedures are only allowed to change the mangledname
+ in their first declaration }
+ if (pd.forwarddef or (not pd.hasforward)) then
+ begin
+ s:=proc_get_importname(pd);
+ if s<>'' then
+ pd.setmangledname(s);
+ end;
+ end
+ else
+ { Normal procedures }
+ begin
+ if (po_compilerproc in pd.procoptions) then
+ begin
+ pd.setmangledname(lower(pd.procsym.name));
+ end;
+ end;
+ end;
+
+ { Public/exported alias names }
+ if (([po_public,po_exports]*pd.procoptions)<>[]) and
+ not(po_has_public_name in pd.procoptions) then
+ begin
+ case pd.proccalloption of
+ pocall_cdecl :
+ begin
+ if assigned(pd._class) then
+ pd.aliasnames.insert(target_info.Cprefix+pd._class.objrealname^+'_'+pd.procsym.realname)
+ else
+ pd.aliasnames.insert(target_info.Cprefix+pd.procsym.realname);
+ end;
+ pocall_cppdecl :
+ begin
+ pd.aliasnames.insert(target_info.Cprefix+pd.cplusplusmangledname);
+ end;
+ end;
+ { prevent adding the alias a second time }
+ include(pd.procoptions,po_has_public_name);
+ end;
+ end;
+
+
+ procedure handle_calling_convention(pd:tabstractprocdef);
+ begin
+ { set the default calling convention if none provided }
+ if not(po_hascallingconvention in pd.procoptions) then
+ pd.proccalloption:=aktdefproccall
+ else
+ begin
+ if pd.proccalloption=pocall_none then
+ internalerror(200309081);
+ end;
+
+ { handle proccall specific settings }
+ case pd.proccalloption of
+ pocall_cdecl,
+ pocall_cppdecl :
+ begin
+ { check C cdecl para types }
+ pd.parast.foreach_static(@check_c_para,nil);
+ end;
+ pocall_far16 :
+ begin
+ { Temporary stub, must be rewritten to support OS/2 far16 }
+ Message1(parser_w_proc_directive_ignored,'FAR16');
+ end;
+ end;
+
+ if (po_inline in pd.procoptions) then
+ begin
+ if not(cs_support_inline in aktmoduleswitches) then
+ begin
+ Message(parser_e_proc_inline_not_supported);
+ exclude(pd.procoptions,po_inline);
+ end;
+ end;
+
+ { For varargs directive also cdecl and external must be defined }
+ if (po_varargs in pd.procoptions) then
+ begin
+ { check first for external in the interface, if available there
+ then the cdecl must also be there since there is no implementation
+ available to contain it }
+ if parse_only then
+ begin
+ { if external is available, then cdecl must also be available,
+ procvars don't need external }
+ if not((po_external in pd.procoptions) or
+ (pd.deftype=procvardef)) and
+ not(pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ Message(parser_e_varargs_need_cdecl_and_external);
+ end
+ else
+ begin
+ { both must be defined now }
+ if not((po_external in pd.procoptions) or
+ (pd.deftype=procvardef)) or
+ not(pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ Message(parser_e_varargs_need_cdecl_and_external);
+ end;
+ end;
+
+ { insert hidden high parameters }
+ pd.parast.foreach_static(@insert_hidden_para,pd);
+
+ { insert hidden self parameter }
+ insert_self_and_vmt_para(pd);
+
+ { insert funcret parameter if required }
+ insert_funcret_para(pd);
+
+ { Make var parameters regable, this must be done after the calling
+ convention is set. }
+ { this must be done before parentfp is insert, because getting all cases
+ where parentfp must be in a memory location isn't catched properly so
+ we put parentfp never in a register }
+ pd.parast.foreach_static(@set_addr_param_regable,pd);
+
+ { insert parentfp parameter if required }
+ insert_parentfp_para(pd);
+
+ { Calculate parameter tlist }
+ pd.calcparas;
+ end;
+
+
+ procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
+ {
+ Parse the procedure directives. It does not matter if procedure directives
+ are written using ;procdir; or ['procdir'] syntax.
+ }
+ var
+ res : boolean;
+ begin
+ if (m_mac in aktmodeswitches) and (cs_externally_visible in aktlocalswitches) then
+ begin
+ tprocdef(pd).aliasnames.insert(tprocdef(pd).procsym.realname);
+ include(pd.procoptions,po_public);
+ include(pd.procoptions,po_has_public_name);
+ include(pd.procoptions,po_global);
+ end;
+
+ while token in [_ID,_LECKKLAMMER] do
+ begin
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+ repeat
+ parse_proc_direc(pd,pdflags);
+ until not try_to_consume(_COMMA);
+ consume(_RECKKLAMMER);
+ { we always expect at least '[];' }
+ res:=true;
+ end
+ else
+ begin
+ res:=parse_proc_direc(pd,pdflags);
+ end;
+ { A procedure directive normally followed by a semicolon, but in
+ a const section or reading a type we should stop when _EQUAL is found,
+ because a constant/default value follows }
+ if res then
+ begin
+ if (block_type in [bt_const,bt_type]) and
+ (token=_EQUAL) then
+ break;
+ { support procedure proc;stdcall export; }
+ if not(check_proc_directive((pd.deftype=procvardef))) then
+ begin
+ { support "record p : procedure stdcall end;" and
+ "var p : procedure stdcall = nil;" }
+ if (pd_procvar in pdflags) and
+ (token in [_END,_RKLAMMER,_EQUAL]) then
+ break
+ else
+ consume(_SEMICOLON);
+ end;
+ end
+ else
+ break;
+ end;
+ end;
+
+
+ procedure parse_var_proc_directives(sym:tsym);
+ var
+ pdflags : tpdflags;
+ pd : tabstractprocdef;
+ begin
+ pdflags:=[pd_procvar];
+ pd:=nil;
+ case sym.typ of
+ fieldvarsym,
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ pd:=tabstractprocdef(tabstractvarsym(sym).vartype.def);
+ typedconstsym :
+ pd:=tabstractprocdef(ttypedconstsym(sym).typedconsttype.def);
+ typesym :
+ pd:=tabstractprocdef(ttypesym(sym).restype.def);
+ else
+ internalerror(2003042617);
+ end;
+ if pd.deftype<>procvardef then
+ internalerror(2003042618);
+ { names should never be used anyway }
+ parse_proc_directives(pd,pdflags);
+ end;
+
+
+ procedure parse_object_proc_directives(pd:tabstractprocdef);
+ var
+ pdflags : tpdflags;
+ begin
+ pdflags:=[pd_object];
+ parse_proc_directives(pd,pdflags);
+ end;
+
+
+ function proc_add_definition(var pd:tprocdef):boolean;
+ {
+ Add definition aprocdef to the overloaded definitions of aprocsym. If a
+ forwarddef is found and reused it returns true
+ }
+ var
+ hd : tprocdef;
+ ad,fd : tsym;
+ s1,s2 : stringid;
+ i : cardinal;
+ forwardfound : boolean;
+ po_comp : tprocoptions;
+ aprocsym : tprocsym;
+ begin
+ forwardfound:=false;
+ aprocsym:=tprocsym(pd.procsym);
+
+ { check overloaded functions if the same function already exists }
+ for i:=1 to aprocsym.procdef_count do
+ begin
+ hd:=aprocsym.procdef[i];
+
+ { Skip overloaded definitions that are declared in other
+ units }
+ if hd.procsym<>aprocsym then
+ continue;
+
+ { check the parameters, for delphi/tp it is possible to
+ leave the parameters away in the implementation (forwarddef=false).
+ But for an overload declared function this is not allowed }
+ if { check if empty implementation arguments match is allowed }
+ (
+ not(m_repeat_forward in aktmodeswitches) and
+ not(pd.forwarddef) and
+ (pd.maxparacount=0) and
+ not(po_overload in hd.procoptions)
+ ) or
+ { check arguments }
+ (
+ (compare_paras(pd.paras,hd.paras,cp_none,[cpo_comparedefaultvalue])>=te_equal) and
+ { for operators equal_paras is not enough !! }
+ ((pd.proctypeoption<>potype_operator) or (optoken<>_ASSIGNMENT) or
+ { be careful here, equal_defs doesn't take care of unique }
+ (hd.rettype.def=pd.rettype.def) or
+ (equal_defs(hd.rettype.def,pd.rettype.def) and
+ not(df_unique in hd.rettype.def.defoptions) and not(df_unique in pd.rettype.def.defoptions)
+ )
+ )
+ ) then
+ begin
+ { Check if we've found the forwarddef, if found then
+ we need to update the forward def with the current
+ implementation settings }
+ if hd.forwarddef then
+ begin
+ forwardfound:=true;
+
+ { Check if the procedure type and return type are correct,
+ also the parameters must match also with the type }
+ if (hd.proctypeoption<>pd.proctypeoption) or
+ (
+ (m_repeat_forward in aktmodeswitches) and
+ (not((pd.maxparacount=0) or
+ (compare_paras(pd.paras,hd.paras,cp_all,[cpo_comparedefaultvalue])>=te_equal)))
+ ) or
+ (
+ ((m_repeat_forward in aktmodeswitches) or
+ not(is_void(pd.rettype.def))) and
+ (not equal_defs(hd.rettype.def,pd.rettype.def))) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,
+ pd.fullprocname(false));
+ aprocsym.write_parameter_lists(pd);
+ break;
+ end;
+
+ { Check if both are declared forward }
+ if hd.forwarddef and pd.forwarddef then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_function_already_declared_public_forward,
+ pd.fullprocname(false));
+ end;
+
+ { internconst or internproc only need to be defined once }
+ if (hd.proccalloption=pocall_internproc) then
+ pd.proccalloption:=hd.proccalloption
+ else
+ if (pd.proccalloption=pocall_internproc) then
+ hd.proccalloption:=pd.proccalloption;
+
+ { Check calling convention }
+ if (hd.proccalloption<>pd.proccalloption) then
+ begin
+ { In delphi it is possible to specify the calling
+ convention in the interface or implementation if
+ there was no convention specified in the other
+ part }
+ if (m_delphi in aktmodeswitches) then
+ begin
+ if not(po_hascallingconvention in pd.procoptions) then
+ pd.proccalloption:=hd.proccalloption
+ else
+ if not(po_hascallingconvention in hd.procoptions) then
+ hd.proccalloption:=pd.proccalloption
+ else
+ begin
+ MessagePos(pd.fileinfo,parser_e_call_convention_dont_match_forward);
+ aprocsym.write_parameter_lists(pd);
+ { restore interface settings }
+ pd.proccalloption:=hd.proccalloption;
+ end;
+ end
+ else
+ begin
+ MessagePos(pd.fileinfo,parser_e_call_convention_dont_match_forward);
+ aprocsym.write_parameter_lists(pd);
+ { restore interface settings }
+ pd.proccalloption:=hd.proccalloption;
+ end;
+ end;
+
+ { Check procedure options, Delphi requires that class is
+ repeated in the implementation for class methods }
+ if (m_fpc in aktmodeswitches) then
+ po_comp:=[po_varargs,po_methodpointer,po_interrupt]
+ else
+ po_comp:=[po_classmethod,po_methodpointer];
+
+ if ((po_comp * hd.procoptions)<>(po_comp * pd.procoptions)) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,
+ pd.fullprocname(false));
+ aprocsym.write_parameter_lists(pd);
+ { This error is non-fatal, we can recover }
+ end;
+
+ { Forward declaration is external? }
+ if (po_external in hd.procoptions) then
+ MessagePos(pd.fileinfo,parser_e_proc_already_external);
+
+ { Check parameters }
+ if (m_repeat_forward in aktmodeswitches) or
+ (pd.minparacount>0) then
+ begin
+ { If mangled names are equal then they have the same amount of arguments }
+ { We can check the names of the arguments }
+ { both symtables are in the same order from left to right }
+ ad:=tsym(hd.parast.symindex.first);
+ fd:=tsym(pd.parast.symindex.first);
+ repeat
+ { skip default parameter constsyms }
+ while assigned(ad) and (ad.typ<>paravarsym) do
+ ad:=tsym(ad.indexnext);
+ while assigned(fd) and (fd.typ<>paravarsym) do
+ fd:=tsym(fd.indexnext);
+ { stop when one of the two lists is at the end }
+ if not assigned(ad) or not assigned(fd) then
+ break;
+ { retrieve names, remove reg for register parameters }
+ s1:=ad.name;
+ s2:=fd.name;
+ { compare names }
+ if (s1<>s2) then
+ begin
+ MessagePos3(pd.fileinfo,parser_e_header_different_var_names,
+ aprocsym.name,s1,s2);
+ break;
+ end;
+ ad:=tsym(ad.indexnext);
+ fd:=tsym(fd.indexnext);
+ until false;
+ if assigned(ad) xor assigned(fd) then
+ internalerror(200204178);
+ end;
+
+ { Everything is checked, now we can update the forward declaration
+ with the new data from the implementation }
+ hd.forwarddef:=pd.forwarddef;
+ hd.hasforward:=true;
+ hd.procoptions:=hd.procoptions+pd.procoptions;
+ if hd.extnumber=65535 then
+ hd.extnumber:=pd.extnumber;
+ while not pd.aliasnames.empty do
+ hd.aliasnames.insert(pd.aliasnames.getfirst);
+ { update fileinfo so position references the implementation,
+ also update funcretsym if it is already generated }
+ hd.fileinfo:=pd.fileinfo;
+ if assigned(hd.funcretsym) then
+ hd.funcretsym.fileinfo:=pd.fileinfo;
+ { import names }
+ if assigned(pd.import_dll) then
+ begin
+ stringdispose(hd.import_dll);
+ hd.import_dll:=stringdup(pd.import_dll^);
+ end;
+ if assigned(pd.import_name) then
+ begin
+ stringdispose(hd.import_name);
+ hd.import_name:=stringdup(pd.import_name^);
+ end;
+ hd.import_nr:=pd.import_nr;
+ { for compilerproc defines we need to rename and update the
+ symbolname to lowercase }
+ if (po_compilerproc in pd.procoptions) then
+ begin
+ { rename to lowercase so users can't access it }
+ aprocsym.owner.rename(aprocsym.name,lower(aprocsym.name));
+ { also update the realname that is stored in the ppu }
+ stringdispose(aprocsym._realname);
+ aprocsym._realname:=stringdup('$'+aprocsym.name);
+ { the mangeled name is already changed by the pd_compilerproc }
+ { handler. It must be done immediately because if we have a }
+ { call to a compilerproc before it's implementation is }
+ { encountered, it must already use the new mangled name (JM) }
+ end;
+
+ { the procdef will be released by the symtable, we release
+ at least the parast }
+ pd.releasemem;
+ pd:=hd;
+ end
+ else
+ begin
+ { abstract methods aren't forward defined, but this }
+ { needs another error message }
+ if (po_abstractmethod in hd.procoptions) then
+ MessagePos(pd.fileinfo,parser_e_abstract_no_definition)
+ else
+ begin
+ MessagePos(pd.fileinfo,parser_e_overloaded_have_same_parameters);
+ aprocsym.write_parameter_lists(pd);
+ end;
+ end;
+
+ { we found one proc with the same arguments, there are no others
+ so we can stop }
+ break;
+ end;
+
+ { check for allowing overload directive }
+ if not(m_fpc in aktmodeswitches) then
+ begin
+ { overload directive turns on overloading }
+ if ((po_overload in pd.procoptions) or
+ (po_overload in hd.procoptions)) then
+ begin
+ { check if all procs have overloading, but not if the proc is a method or
+ already declared forward, then the check is already done }
+ if not(hd.hasforward or
+ assigned(pd._class) or
+ (pd.forwarddef<>hd.forwarddef) or
+ ((po_overload in pd.procoptions) and
+ (po_overload in hd.procoptions))) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_no_overload_for_all_procs,aprocsym.realname);
+ break;
+ end;
+ end
+ else
+ begin
+ if not(hd.forwarddef) then
+ begin
+ MessagePos(pd.fileinfo,parser_e_procedure_overloading_is_off);
+ break;
+ end;
+ end;
+ end; { equal arguments }
+ end;
+
+ { if we didn't reuse a forwarddef then we add the procdef to the overloaded
+ list }
+ if not forwardfound then
+ aprocsym.addprocdef(pd);
+
+ proc_add_definition:=forwardfound;
+ end;
+
+end.
diff --git a/compiler/pdecvar.pas b/compiler/pdecvar.pas
new file mode 100644
index 0000000000..0540bdf91b
--- /dev/null
+++ b/compiler/pdecvar.pas
@@ -0,0 +1,1318 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Parses variable declarations. Used for var statement and record
+ definitions
+
+ 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 pdecvar;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symsym,symdef;
+
+ type Tvar_dec_option=(vd_record,vd_object,vd_threadvar);
+ Tvar_dec_options=set of Tvar_dec_option;
+
+ function read_property_dec(aclass:tobjectdef):tpropertysym;
+
+ procedure read_var_decs(options:Tvar_dec_options);
+
+
+implementation
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,tokens,verbose,
+ systems,
+ { symtable }
+ symconst,symbase,symtype,symtable,defutil,defcmp,
+ fmodule,
+ { pass 1 }
+ node,pass_1,
+ nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nmem,
+ { codegen }
+ ncgutil,
+ { parser }
+ scanner,
+ pbase,pexpr,ptype,ptconst,pdecsub,
+ { link }
+ import
+ ;
+
+
+ function read_property_dec(aclass:tobjectdef):tpropertysym;
+
+ { convert a node tree to symlist and return the last
+ symbol }
+ function parse_symlist(pl:tsymlist;var def:tdef):boolean;
+ var
+ idx : longint;
+ sym : tsym;
+ srsymtable : tsymtable;
+ st : tsymtable;
+ p : tnode;
+ begin
+ result:=true;
+ def:=nil;
+ if token=_ID then
+ begin
+ if assigned(aclass) then
+ sym:=search_class_member(aclass,pattern)
+ else
+ searchsym(pattern,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ fieldvarsym :
+ begin
+ pl.addsym(sl_load,sym);
+ def:=tfieldvarsym(sym).vartype.def;
+ end;
+ procsym :
+ begin
+ pl.addsym(sl_call,sym);
+ end;
+ else
+ begin
+ Message1(parser_e_illegal_field_or_method,orgpattern);
+ result:=false;
+ end;
+ end;
+ end
+ else
+ begin
+ Message1(parser_e_illegal_field_or_method,orgpattern);
+ result:=false;
+ end;
+ consume(_ID);
+ repeat
+ case token of
+ _ID,
+ _SEMICOLON :
+ begin
+ break;
+ end;
+ _POINT :
+ begin
+ consume(_POINT);
+ if assigned(def) then
+ begin
+ st:=def.getsymtable(gs_record);
+ if assigned(st) then
+ begin
+ sym:=searchsymonlyin(st,pattern);
+ if assigned(sym) then
+ begin
+ pl.addsym(sl_subscript,sym);
+ case sym.typ of
+ fieldvarsym :
+ def:=tfieldvarsym(sym).vartype.def;
+ else
+ begin
+ Message1(sym_e_illegal_field,orgpattern);
+ result:=false;
+ end;
+ end;
+ end
+ else
+ begin
+ Message1(sym_e_illegal_field,orgpattern);
+ result:=false;
+ end;
+ end
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ result:=false;
+ end;
+ end
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ result:=false;
+ end;
+ consume(_ID);
+ end;
+ _LECKKLAMMER :
+ begin
+ consume(_LECKKLAMMER);
+ repeat
+ if def.deftype=arraydef then
+ begin
+ idx:=0;
+ p:=comp_expr(true);
+ if (not codegenerror) then
+ begin
+ if (p.nodetype=ordconstn) then
+ begin
+ if compare_defs(p.resulttype.def,tarraydef(def).rangetype.def,nothingn)>=te_equal then
+ idx:=tordconstnode(p).value
+ else
+ IncompatibleTypes(p.resulttype.def,tarraydef(def).rangetype.def);
+ end
+ else
+ Message(type_e_ordinal_expr_expected)
+ end;
+ p.free;
+ pl.addconst(sl_vec,idx);
+ def:=tarraydef(def).elementtype.def;
+ end
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ result:=false;
+ end;
+ until not try_to_consume(_COMMA);
+ consume(_RECKKLAMMER);
+ end;
+ else
+ begin
+ Message(parser_e_ill_property_access_sym);
+ result:=false;
+ break;
+ end;
+ end;
+ until false;
+ end
+ else
+ begin
+ Message(parser_e_ill_property_access_sym);
+ result:=false;
+ end;
+ end;
+
+ var
+ sym : tsym;
+ p : tpropertysym;
+ overriden : tsym;
+ varspez : tvarspez;
+ tt : ttype;
+ arraytype : ttype;
+ def : tdef;
+ pt : tnode;
+ propname : stringid;
+ sc : tsinglelist;
+ paranr : word;
+ oldregisterdef : boolean;
+ hreadparavs,
+ hparavs : tparavarsym;
+ readprocdef,
+ writeprocdef : tprocvardef;
+ oldsymtablestack : tsymtable;
+ begin
+ { Generate temp procvardefs to search for matching read/write
+ procedures. the readprocdef will store all definitions }
+ oldregisterdef:=registerdef;
+ registerdef:=false;
+ paranr:=0;
+ readprocdef:=tprocvardef.create(normal_function_level);
+ writeprocdef:=tprocvardef.create(normal_function_level);
+ registerdef:=oldregisterdef;
+
+ { make it method pointers }
+ if assigned(aclass) then
+ begin
+ include(readprocdef.procoptions,po_methodpointer);
+ include(writeprocdef.procoptions,po_methodpointer);
+ end;
+
+ if token<>_ID then
+ begin
+ consume(_ID);
+ consume(_SEMICOLON);
+ exit;
+ end;
+ { Generate propertysym and insert in symtablestack }
+ p:=tpropertysym.create(orgpattern);
+ symtablestack.insert(p);
+ propname:=pattern;
+ consume(_ID);
+ { Set the symtablestack to the parast of readprop so
+ temp defs will be destroyed after declaration }
+ readprocdef.parast.next:=symtablestack;
+ symtablestack:=readprocdef.parast;
+ { property parameters ? }
+ if token=_LECKKLAMMER then
+ begin
+ if (sp_published in current_object_option) then
+ Message(parser_e_cant_publish_that_property);
+
+ { create a list of the parameters }
+ sc:=tsinglelist.create;
+ consume(_LECKKLAMMER);
+ inc(testcurobject);
+ repeat
+ if token=_VAR then
+ begin
+ consume(_VAR);
+ varspez:=vs_var;
+ end
+ else if token=_CONST then
+ begin
+ consume(_CONST);
+ varspez:=vs_const;
+ end
+ else if (idtoken=_OUT) and (m_out in aktmodeswitches) then
+ begin
+ consume(_OUT);
+ varspez:=vs_out;
+ end
+ else
+ varspez:=vs_value;
+ sc.reset;
+ repeat
+ inc(paranr);
+ hreadparavs:=tparavarsym.create(orgpattern,10*paranr,varspez,generrortype,[]);
+ readprocdef.parast.insert(hreadparavs);
+ sc.insert(hreadparavs);
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ if try_to_consume(_COLON) then
+ begin
+ { for records, don't search the recordsymtable for
+ the symbols of the types }
+ oldsymtablestack:=symtablestack;
+ symtablestack:=symtablestack.next;
+ if try_to_consume(_ARRAY) then
+ begin
+ consume(_OF);
+ { define range and type of range }
+ tt.setdef(tarraydef.create(0,-1,s32inttype));
+ { define field type }
+ single_type(arraytype,false);
+ tarraydef(tt.def).setelementtype(arraytype);
+ end
+ else
+ single_type(tt,false);
+ symtablestack:=oldsymtablestack;
+ end
+ else
+ tt:=cformaltype;
+ hreadparavs:=tparavarsym(sc.first);
+ while assigned(hreadparavs) do
+ begin
+ hreadparavs.vartype:=tt;
+ { also update the writeprocdef }
+ hparavs:=tparavarsym.create(hreadparavs.realname,hreadparavs.paranr,vs_value,tt,[]);
+ writeprocdef.parast.insert(hparavs);
+ hreadparavs:=tparavarsym(hreadparavs.listnext);
+ end;
+ until not try_to_consume(_SEMICOLON);
+ sc.free;
+ dec(testcurobject);
+ consume(_RECKKLAMMER);
+
+ { the parser need to know if a property has parameters, the
+ index parameter doesn't count (PFV) }
+ if paranr>0 then
+ include(p.propoptions,ppo_hasparameters);
+ end;
+ { overriden property ? }
+ { force property interface
+ there is a property parameter
+ a global property }
+ if (token=_COLON) or (paranr>0) or (aclass=nil) then
+ begin
+ consume(_COLON);
+ { insert types in global symtable }
+ oldsymtablestack:=symtablestack;
+ while not(symtablestack.symtabletype in [globalsymtable,staticsymtable]) do
+ symtablestack:=symtablestack.next;
+ single_type(p.proptype,false);
+ symtablestack:=oldsymtablestack;
+ if (idtoken=_INDEX) then
+ begin
+ consume(_INDEX);
+ pt:=comp_expr(true);
+ if is_constnode(pt) and
+ is_ordinal(pt.resulttype.def)
+{$ifndef cpu64bit}
+ and (not is_64bitint(pt.resulttype.def))
+{$endif}
+ then
+ p.index:=tordconstnode(pt).value
+ else
+ begin
+ Message(parser_e_invalid_property_index_value);
+ p.index:=0;
+ end;
+ p.indextype.setdef(pt.resulttype.def);
+ include(p.propoptions,ppo_indexed);
+ { concat a longint to the para templates }
+ inc(paranr);
+ hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indextype,[]);
+ readprocdef.parast.insert(hparavs);
+ hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indextype,[]);
+ writeprocdef.parast.insert(hparavs);
+ pt.free;
+ end;
+ end
+ else
+ begin
+ { do an property override }
+ overriden:=search_class_member(aclass.childof,propname);
+ if assigned(overriden) and (overriden.typ=propertysym) then
+ begin
+ p.dooverride(tpropertysym(overriden));
+ end
+ else
+ begin
+ p.proptype:=generrortype;
+ message(parser_e_no_property_found_to_override);
+ end;
+ end;
+ if (sp_published in current_object_option) and
+ not(p.proptype.def.is_publishable) then
+ Message(parser_e_cant_publish_that_property);
+
+ if try_to_consume(_READ) then
+ begin
+ p.readaccess.clear;
+ if parse_symlist(p.readaccess,def) then
+ begin
+ sym:=p.readaccess.firstsym^.sym;
+ case sym.typ of
+ procsym :
+ begin
+ { read is function returning the type of the property }
+ readprocdef.rettype:=p.proptype;
+ { Insert hidden parameters }
+ handle_calling_convention(readprocdef);
+ { search procdefs matching readprocdef }
+ { we ignore hidden stuff here because the property access symbol might have
+ non default calling conventions which might change the hidden stuff;
+ see tw3216.pp (FK) }
+ p.readaccess.procdef:=Tprocsym(sym).search_procdef_bypara(readprocdef.paras,p.proptype.def,[cpo_allowdefaults,cpo_ignorehidden,cpo_allowconvert]);
+ if not assigned(p.readaccess.procdef) then
+ Message(parser_e_ill_property_access_sym);
+ end;
+ fieldvarsym :
+ begin
+ if not assigned(def) then
+ internalerror(200310071);
+ if compare_defs(def,p.proptype.def,nothingn)>=te_equal then
+ begin
+ { property parameters are allowed if this is
+ an indexed property, because the index is then
+ the parameter.
+ Note: In the help of Kylix it is written
+ that it isn't allowed, but the compiler accepts it (PFV) }
+ if (ppo_hasparameters in p.propoptions) then
+ Message(parser_e_ill_property_access_sym);
+ end
+ else
+ IncompatibleTypes(def,p.proptype.def);
+ end;
+ else
+ Message(parser_e_ill_property_access_sym);
+ end;
+ end;
+ end;
+ if try_to_consume(_WRITE) then
+ begin
+ p.writeaccess.clear;
+ if parse_symlist(p.writeaccess,def) then
+ begin
+ sym:=p.writeaccess.firstsym^.sym;
+ case sym.typ of
+ procsym :
+ begin
+ { write is a procedure with an extra value parameter
+ of the of the property }
+ writeprocdef.rettype:=voidtype;
+ inc(paranr);
+ hparavs:=tparavarsym.create('$value',10*paranr,vs_value,p.proptype,[]);
+ writeprocdef.parast.insert(hparavs);
+ { Insert hidden parameters }
+ handle_calling_convention(writeprocdef);
+ { search procdefs matching writeprocdef }
+ p.writeaccess.procdef:=Tprocsym(sym).search_procdef_bypara(writeprocdef.paras,writeprocdef.rettype.def,[cpo_allowdefaults,cpo_allowconvert]);
+ if not assigned(p.writeaccess.procdef) then
+ Message(parser_e_ill_property_access_sym);
+ end;
+ fieldvarsym :
+ begin
+ if not assigned(def) then
+ internalerror(200310072);
+ if compare_defs(def,p.proptype.def,nothingn)>=te_equal then
+ begin
+ { property parameters are allowed if this is
+ an indexed property, because the index is then
+ the parameter.
+ Note: In the help of Kylix it is written
+ that it isn't allowed, but the compiler accepts it (PFV) }
+ if (ppo_hasparameters in p.propoptions) then
+ Message(parser_e_ill_property_access_sym);
+ end
+ else
+ IncompatibleTypes(def,p.proptype.def);
+ end;
+ else
+ Message(parser_e_ill_property_access_sym);
+ end;
+ end;
+ end;
+ if assigned(aclass) then
+ begin
+ include(p.propoptions,ppo_stored);
+ if try_to_consume(_STORED) then
+ begin
+ p.storedaccess.clear;
+ case token of
+ _ID:
+ begin
+ { in the case that idtoken=_DEFAULT }
+ { we have to do nothing except }
+ { setting ppo_stored, it's the same }
+ { as stored true }
+ if idtoken<>_DEFAULT then
+ begin
+ if parse_symlist(p.storedaccess,def) then
+ begin
+ sym:=p.storedaccess.firstsym^.sym;
+ case sym.typ of
+ procsym :
+ begin
+ p.storedaccess.procdef:=Tprocsym(sym).search_procdef_nopara_boolret;
+ if not assigned(p.storedaccess.procdef) then
+ message(parser_e_ill_property_storage_sym);
+ end;
+ fieldvarsym :
+ begin
+ if not assigned(def) then
+ internalerror(200310073);
+ if (ppo_hasparameters in p.propoptions) or
+ not(is_boolean(def)) then
+ Message(parser_e_stored_property_must_be_boolean);
+ end;
+ else
+ Message(parser_e_ill_property_access_sym);
+ end;
+ end;
+ end;
+ end;
+ _FALSE:
+ begin
+ consume(_FALSE);
+ exclude(p.propoptions,ppo_stored);
+ end;
+ _TRUE:
+ consume(_TRUE);
+ end;
+ end;
+ end;
+ if try_to_consume(_DEFAULT) then
+ begin
+ if not(is_ordinal(p.proptype.def) or
+{$ifndef cpu64bit}
+ is_64bitint(p.proptype.def) or
+{$endif cpu64bit}
+ is_class(p.proptype.def) or
+ is_single(p.proptype.def) or
+ (p.proptype.def.deftype in [classrefdef,pointerdef]) or
+ ((p.proptype.def.deftype=setdef) and
+ (tsetdef(p.proptype.def).settype=smallset))) or
+ ((p.proptype.def.deftype=arraydef) and
+ (ppo_indexed in p.propoptions)) or
+ (ppo_hasparameters in p.propoptions) then
+ begin
+ Message(parser_e_property_cant_have_a_default_value);
+ { Error recovery }
+ pt:=comp_expr(true);
+ pt.free;
+ end
+ else
+ begin
+ { Get the result of the default, the firstpass is
+ needed to support values like -1 }
+ pt:=comp_expr(true);
+ if (p.proptype.def.deftype=setdef) and
+ (pt.nodetype=arrayconstructorn) then
+ begin
+ arrayconstructor_to_set(pt);
+ do_resulttypepass(pt);
+ end;
+ inserttypeconv(pt,p.proptype);
+ if not(is_constnode(pt)) then
+ Message(parser_e_property_default_value_must_const);
+ { Set default value }
+ case pt.nodetype of
+ setconstn :
+ p.default:=plongint(tsetconstnode(pt).value_set)^;
+ ordconstn :
+ p.default:=longint(tordconstnode(pt).value);
+ niln :
+ p.default:=0;
+ realconstn:
+ p.default:=longint(single(trealconstnode(pt).value_real));
+ end;
+ pt.free;
+ end;
+ end
+ else if try_to_consume(_NODEFAULT) then
+ begin
+ p.default:=0;
+ end;
+ { remove temporary procvardefs }
+ symtablestack:=symtablestack.next;
+ readprocdef.free;
+ writeprocdef.free;
+ result:=p;
+ end;
+
+
+ const
+ variantrecordlevel : longint = 0;
+
+ procedure read_var_decs(options:Tvar_dec_options);
+ { reads the filed of a record into a }
+ { symtablestack, if record=false }
+ { variants are forbidden, so this procedure }
+ { can be used to read object fields }
+ { if absolute is true, ABSOLUTE and file }
+ { types are allowed }
+ { => the procedure is also used to read }
+ { a sequence of variable declaration }
+
+ procedure insert_syms(sc : tsinglelist;tt : ttype;is_threadvar : boolean; addsymopts : tsymoptions);
+ { inserts the symbols of sc in st with def as definition or sym as ttypesym, sc is disposed }
+ var
+ vs : tabstractvarsym;
+ hstaticvs : tglobalvarsym;
+ begin
+ vs:=tabstractvarsym(sc.first);
+ while assigned(vs) do
+ begin
+ vs.vartype:=tt;
+ { insert any additional hint directives }
+ vs.symoptions := vs.symoptions + addsymopts;
+ if (sp_static in current_object_option) then
+ include(vs.symoptions,sp_static);
+ if is_threadvar then
+ include(vs.varoptions,vo_is_thread_var);
+ { static data fields are inserted in the globalsymtable }
+ if (symtablestack.symtabletype=objectsymtable) and
+ (sp_static in current_object_option) then
+ begin
+ hstaticvs:=tglobalvarsym.create('$'+lower(symtablestack.name^)+'_'+vs.name,vs_value,tt,[]);
+ symtablestack.defowner.owner.insert(hstaticvs);
+ insertbssdata(hstaticvs);
+ end
+ else
+ begin
+ { external data is not possible here }
+ case symtablestack.symtabletype of
+ globalsymtable,
+ staticsymtable :
+ insertbssdata(tglobalvarsym(vs));
+ recordsymtable,
+ objectsymtable :
+ tabstractrecordsymtable(symtablestack).insertfield(tfieldvarsym(vs),false);
+ end;
+ end;
+ vs:=tabstractvarsym(vs.listnext);
+ end;
+ end;
+
+
+ procedure read_default_value(sc : tsinglelist;tt : ttype;is_threadvar : boolean);
+ var
+ vs : tabstractnormalvarsym;
+ tcsym : ttypedconstsym;
+ begin
+ vs:=tabstractnormalvarsym(sc.first);
+ if assigned(vs.listnext) then
+ Message(parser_e_initialized_only_one_var);
+ if is_threadvar then
+ Message(parser_e_initialized_not_for_threadvar);
+ if symtablestack.symtabletype=localsymtable then
+ begin
+ consume(_EQUAL);
+ tcsym:=ttypedconstsym.createtype('default'+vs.realname,tt,false);
+ vs.defaultconstsym:=tcsym;
+ symtablestack.insert(tcsym);
+ readtypedconst(tt,tcsym,false);
+ { The variable has a value assigned }
+ vs.varstate:=vs_assigned;
+ end
+ else
+ begin
+ tcsym:=ttypedconstsym.createtype(vs.realname,tt,true);
+ tcsym.fileinfo:=vs.fileinfo;
+ symtablestack.replace(vs,tcsym);
+ vs.free;
+ consume(_EQUAL);
+ readtypedconst(tt,tcsym,true);
+ end;
+ end;
+
+ var
+ sc : tsinglelist;
+ old_block_type : tblock_type;
+ symdone : boolean;
+ { to handle absolute }
+ abssym : tabsolutevarsym;
+ { c var }
+ newtype : ttypesym;
+ is_dll,
+ hasdefaultvalue,
+ is_gpc_name,is_cdecl,
+ extern_var,export_var : boolean;
+ old_current_object_option : tsymoptions;
+ hs,sorg,C_name,dll_name : string;
+ tt,casetype : ttype;
+ { maxsize contains the max. size of a variant }
+ { startvarrec contains the start of the variant part of a record }
+ maxsize, startvarrecsize : longint;
+ usedalign,
+ maxalignment,startvarrecalign,
+ maxpadalign, startpadalign: shortint;
+ hp,pt : tnode;
+ fieldvs : tfieldvarsym;
+ vs,vs2 : tabstractvarsym;
+ srsym : tsym;
+ oldsymtablestack,
+ srsymtable : tsymtable;
+ unionsymtable : trecordsymtable;
+ offset : longint;
+ uniondef : trecorddef;
+ unionsym : tfieldvarsym;
+ uniontype : ttype;
+ dummysymoptions : tsymoptions;
+ semicolonatend,semicoloneaten: boolean;
+{$ifdef powerpc}
+ tempdef: tdef;
+ is_first_field: boolean;
+{$endif powerpc}
+ begin
+{$ifdef powerpc}
+ is_first_field := true;
+{$endif powerpc}
+ old_current_object_option:=current_object_option;
+ { all variables are public if not in a object declaration }
+ if not(vd_object in options) then
+ current_object_option:=[sp_public];
+ old_block_type:=block_type;
+ block_type:=bt_type;
+ is_gpc_name:=false;
+ { Force an expected ID error message }
+ if not (token in [_ID,_CASE,_END]) then
+ consume(_ID);
+ { read vars }
+ sc:=tsinglelist.create;
+ while (token=_ID) and
+ not((vd_object in options) and
+ (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
+ begin
+ sorg:=orgpattern;
+ semicoloneaten:=false;
+ hasdefaultvalue:=false;
+ symdone:=false;
+ sc.reset;
+ repeat
+ case symtablestack.symtabletype of
+ localsymtable :
+ vs:=tlocalvarsym.create(orgpattern,vs_value,generrortype,[]);
+ staticsymtable,
+ globalsymtable :
+ vs:=tglobalvarsym.create(orgpattern,vs_value,generrortype,[]);
+ recordsymtable,
+ objectsymtable :
+ vs:=tfieldvarsym.create(orgpattern,vs_value,generrortype,[]);
+ else
+ internalerror(200411064);
+ end;
+ symtablestack.insert(vs);
+ if assigned(vs.owner) then
+ sc.insert(vs)
+ else
+ vs.free;
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ consume(_COLON);
+ if (m_gpc in aktmodeswitches) and (options=[]) and
+ (token=_ID) and (orgpattern='__asmname__') then
+ begin
+ consume(_ID);
+ C_name:=get_stringconst;
+ Is_gpc_name:=true;
+ end;
+ { this is needed for Delphi mode at least
+ but should be OK for all modes !! (PM) }
+ ignore_equal:=true;
+ if options*[vd_record,vd_object]<>[] then
+ begin
+ { for records, don't search the recordsymtable for
+ the symbols of the types }
+ oldsymtablestack:=symtablestack;
+ symtablestack:=symtablestack.next;
+ read_type(tt,'',false);
+ symtablestack:=oldsymtablestack;
+ end
+ else
+ read_type(tt,'',false);
+ ignore_equal:=false;
+ { Process procvar directives }
+ if (tt.def.deftype=procvardef) and
+ (tt.def.typesym=nil) and
+ check_proc_directive(true) then
+ begin
+ newtype:=ttypesym.create('unnamed',tt);
+ parse_var_proc_directives(tsym(newtype));
+ semicoloneaten:=true;
+ newtype.restype.def:=nil;
+ tt.def.typesym:=nil;
+ newtype.free;
+ end;
+
+{$ifdef powerpc}
+ { from gcc/gcc/config/rs6000/rs6000.h:
+ /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
+ /* Return the alignment of a struct based on the Macintosh PowerPC
+ alignment rules. In general the alignment of a struct is
+ determined by the greatest alignment of its elements. However, the
+ PowerPC rules cause the alignment of a struct to peg at word
+ alignment except when the first field has greater than word
+ (32-bit) alignment, in which case the alignment is determined by
+ the alignment of the first field. */
+ }
+ if (target_info.system in [system_powerpc_darwin, system_powerpc_macos]) and
+ (vd_record in options) and
+ is_first_field and
+ (trecordsymtable(symtablestack).usefieldalignment = -1) then
+ begin
+ tempdef := tt.def;
+ while tempdef.deftype = arraydef do
+ tempdef := tarraydef(tempdef).elementtype.def;
+ if tempdef.deftype <> recorddef then
+ maxpadalign := tempdef.alignment
+ else
+ maxpadalign := trecorddef(tempdef).padalignment;
+
+ if (maxpadalign > 4) and
+ (maxpadalign > trecordsymtable(symtablestack).padalignment) then
+ trecordsymtable(symtablestack).padalignment := maxpadalign;
+ is_first_field := false;
+ end;
+{$endif powerpc}
+
+ { types that use init/final are not allowed in variant parts, but
+ classes are allowed }
+ if (variantrecordlevel>0) and
+ (tt.def.needs_inittable and not is_class(tt.def)) then
+ Message(parser_e_cant_use_inittable_here);
+
+ if is_gpc_name then
+ begin
+ vs:=tabstractvarsym(sc.first);
+ if assigned(vs.listnext) then
+ Message(parser_e_absolute_only_one_var);
+ vs.vartype:=tt;
+ if vs.typ=globalvarsym then
+ begin
+ tglobalvarsym(vs).set_mangledname(target_info.Cprefix+sorg);
+ include(vs.varoptions,vo_is_C_var);
+ include(vs.varoptions,vo_is_external);
+ end
+ else
+ Message(parser_e_no_local_var_external);
+ symdone:=true;
+ end;
+
+ { check for absolute }
+ if not symdone and (idtoken=_ABSOLUTE) and (options=[]) then
+ begin
+ consume(_ABSOLUTE);
+ abssym:=nil;
+ { only allowed for one var }
+ vs:=tabstractvarsym(sc.first);
+ if assigned(vs.listnext) then
+ Message(parser_e_absolute_only_one_var);
+ { parse the rest }
+ pt:=expr;
+ { check allowed absolute types }
+ if (pt.nodetype=stringconstn) or
+ (is_constcharnode(pt)) then
+ begin
+ abssym:=tabsolutevarsym.create(vs.realname,tt);
+ abssym.fileinfo:=vs.fileinfo;
+ if pt.nodetype=stringconstn then
+ hs:=strpas(tstringconstnode(pt).value_str)
+ else
+ hs:=chr(tordconstnode(pt).value);
+ consume(token);
+ abssym.abstyp:=toasm;
+ abssym.asmname:=stringdup(hs);
+ { replace the varsym }
+ symtablestack.replace(vs,abssym);
+ vs.free;
+ end
+ { address }
+ else if is_constintnode(pt) and
+ ((target_info.system in [system_i386_go32v2,system_i386_watcom,
+ system_i386_wdosx,system_i386_win32,system_arm_wince,system_i386_wince]) or
+ (m_objfpc in aktmodeswitches) or
+ (m_delphi in aktmodeswitches)) then
+ begin
+ abssym:=tabsolutevarsym.create(vs.realname,tt);
+ abssym.fileinfo:=vs.fileinfo;
+ abssym.abstyp:=toaddr;
+ abssym.addroffset:=tordconstnode(pt).value;
+{$ifdef i386}
+ abssym.absseg:=false;
+ if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
+ try_to_consume(_COLON) then
+ begin
+ pt.free;
+ pt:=expr;
+ if is_constintnode(pt) then
+ begin
+ abssym.addroffset:=abssym.addroffset shl 4+tordconstnode(pt).value;
+ abssym.absseg:=true;
+ end
+ else
+ Message(type_e_ordinal_expr_expected);
+ end;
+{$endif i386}
+ symtablestack.replace(vs,abssym);
+ vs.free;
+ end
+ { variable }
+ else
+ begin
+ { remove subscriptn before checking for loadn }
+ hp:=pt;
+ while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
+ hp:=tunarynode(hp).left;
+ if (hp.nodetype=loadn) then
+ begin
+ { we should check the result type of loadn }
+ if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,globalvarsym,localvarsym,
+ paravarsym,typedconstsym]) then
+ Message(parser_e_absolute_only_to_var_or_const);
+ abssym:=tabsolutevarsym.create(vs.realname,tt);
+ abssym.fileinfo:=vs.fileinfo;
+ abssym.abstyp:=tovar;
+ abssym.ref:=node_to_symlist(pt);
+ symtablestack.replace(vs,abssym);
+ vs.free;
+ end
+ else
+ Message(parser_e_absolute_only_to_var_or_const);
+ end;
+ if assigned(abssym) then
+ begin
+ { try to consume the hint directives with absolute symbols }
+ dummysymoptions:=[];
+ try_consume_hintdirective(dummysymoptions);
+ abssym.symoptions := abssym.symoptions + dummysymoptions;
+ end;
+ pt.free;
+ symdone:=true;
+ end;
+
+ { Process procvar directives before = and ; }
+ if (tt.def.deftype=procvardef) and
+ (tt.def.typesym=nil) and
+ check_proc_directive(true) then
+ begin
+ newtype:=ttypesym.create('unnamed',tt);
+ parse_var_proc_directives(tsym(newtype));
+ newtype.restype.def:=nil;
+ tt.def.typesym:=nil;
+ newtype.free;
+ end;
+
+ { try to parse the hint directives }
+ dummysymoptions:=[];
+ try_consume_hintdirective(dummysymoptions);
+
+ { Records and objects can't have default values }
+ if options*[vd_record,vd_object]<>[] then
+ begin
+ { for a record there doesn't need to be a ; before the END or ) }
+ if not(token in [_END,_RKLAMMER]) and
+ not(semicoloneaten) then
+ consume(_SEMICOLON);
+ end
+ else
+ { Handling of Delphi typed const = initialized vars }
+ if (token=_EQUAL) and
+ not(m_tp7 in aktmodeswitches) and
+ (symtablestack.symtabletype<>parasymtable) then
+ begin
+ { Add calling convention for procvar }
+ if (tt.def.deftype=procvardef) and
+ (tt.def.typesym=nil) then
+ handle_calling_convention(tprocvardef(tt.def));
+ read_default_value(sc,tt,vd_threadvar in options);
+ consume(_SEMICOLON);
+ { for locals we've created typedconstsym with a different name }
+ if symtablestack.symtabletype<>localsymtable then
+ symdone:=true;
+ hasdefaultvalue:=true;
+ end
+ else
+ begin
+ if not(semicoloneaten) then
+ consume(_SEMICOLON);
+ end;
+
+ { Support calling convention for procvars after semicolon }
+ if not(hasdefaultvalue) and
+ (tt.def.deftype=procvardef) and
+ (tt.def.typesym=nil) then
+ begin
+ { Parse procvar directives after ; }
+ if check_proc_directive(true) then
+ begin
+ newtype:=ttypesym.create('unnamed',tt);
+ parse_var_proc_directives(tsym(newtype));
+ newtype.restype.def:=nil;
+ tt.def.typesym:=nil;
+ newtype.free;
+ end;
+ { Add calling convention for procvar }
+ handle_calling_convention(tprocvardef(tt.def));
+ { Handling of Delphi typed const = initialized vars }
+ if (token=_EQUAL) and (options*[vd_record,vd_object]=[]) and
+ not(m_tp7 in aktmodeswitches) and
+ (symtablestack.symtabletype<>parasymtable) then
+ begin
+ read_default_value(sc,tt,vd_threadvar in options);
+ consume(_SEMICOLON);
+ symdone:=true;
+ hasdefaultvalue:=true;
+ end;
+ end;
+
+ { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
+ if not symdone and (options=[]) then
+ begin
+ if (
+ (token=_ID) and
+ (m_cvar_support in aktmodeswitches) and
+ (idtoken in [_EXPORT,_EXTERNAL,_PUBLIC,_CVAR])
+ ) or
+ (
+ (m_mac in aktmodeswitches) and
+ ((cs_external_var in aktlocalswitches) or (cs_externally_visible in aktlocalswitches))
+ ) then
+ begin
+ { only allowed for one var }
+ vs:=tabstractvarsym(sc.first);
+ if assigned(vs.listnext) then
+ Message(parser_e_absolute_only_one_var);
+ { set type of the var }
+ vs.vartype:=tt;
+ vs.symoptions := vs.symoptions + dummysymoptions;
+ { defaults }
+ is_dll:=false;
+ is_cdecl:=false;
+ extern_var:=false;
+ export_var:=false;
+ C_name:=sorg;
+ semicolonatend:= false;
+ { cdecl }
+ if idtoken=_CVAR then
+ begin
+ consume(_CVAR);
+ consume(_SEMICOLON);
+ is_cdecl:=true;
+ C_name:=target_info.Cprefix+sorg;
+ end;
+ { external }
+ if idtoken=_EXTERNAL then
+ begin
+ consume(_EXTERNAL);
+ extern_var:=true;
+ semicolonatend:= true;
+ end;
+ { macpas specific handling due to some switches}
+ if (m_mac in aktmodeswitches) then
+ begin
+ if (cs_external_var in aktlocalswitches) then
+ begin {The effect of this is the same as if cvar; external; has been given as directives.}
+ is_cdecl:=true;
+ C_name:=target_info.Cprefix+sorg;
+ extern_var:=true;
+ end
+ else if (cs_externally_visible in aktlocalswitches) then
+ begin {The effect of this is the same as if cvar has been given as directives.}
+ is_cdecl:=true;
+ C_name:=target_info.Cprefix+sorg;
+ end;
+ vs.varregable := vr_none;
+ end;
+ { export }
+ if idtoken in [_EXPORT,_PUBLIC] then
+ begin
+ consume(_ID);
+ if extern_var then
+ Message(parser_e_not_external_and_export)
+ else
+ begin
+ export_var:=true;
+ semicolonatend:= true;
+ end;
+ end;
+ { external and export need a name after when no cdecl is used }
+ if not is_cdecl then
+ begin
+ { dll name ? }
+ if (extern_var) and (idtoken<>_NAME) then
+ begin
+ is_dll:=true;
+ dll_name:=get_stringconst;
+ end;
+ if try_to_consume(_NAME) then
+ C_name:=get_stringconst
+ else
+ C_name:=sorg;
+ end;
+ { consume the ; when export or external is used }
+ if semicolonatend then
+ consume(_SEMICOLON);
+
+ { set some vars options }
+ if is_dll then
+ include(vs.varoptions,vo_is_dll_var)
+ else
+ include(vs.varoptions,vo_is_C_var);
+
+ if (is_dll) and
+ (target_info.system = system_powerpc_darwin) then
+ C_Name := target_info.Cprefix+C_Name;
+
+ if export_var then
+ begin
+ inc(vs.refs);
+ include(vs.varoptions,vo_is_exported);
+ end;
+
+ if extern_var then
+ include(vs.varoptions,vo_is_external);
+
+ if vs.typ=globalvarsym then
+ begin
+ tglobalvarsym(vs).set_mangledname(C_Name);
+ { insert in the al_globals when it is not external }
+ if (not extern_var) then
+ insertbssdata(tglobalvarsym(vs));
+ { now we can insert it in the import lib if its a dll, or
+ add it to the externals }
+ if extern_var then
+ begin
+ vs.varregable := vr_none;
+ if is_dll then
+ begin
+ if not(current_module.uses_imports) then
+ begin
+ current_module.uses_imports:=true;
+ importlib.preparelib(current_module.realmodulename^);
+ end;
+ importlib.importvariable(tglobalvarsym(vs),C_name,dll_name);
+ end
+ else
+ if target_info.DllScanSupported then
+ current_module.Externals.insert(tExternalsItem.create(vs.mangledname));
+ end;
+ end
+ else
+ Message(parser_e_no_local_var_external);
+ symdone:=true;
+ end;
+ end;
+
+ { Check for STATIC directive }
+ if not symdone and (vd_object in options) and
+ (cs_static_keyword in aktmoduleswitches) and (idtoken=_STATIC) then
+ begin
+ include(current_object_option,sp_static);
+ insert_syms(sc,tt,false,dummysymoptions);
+ exclude(current_object_option,sp_static);
+ consume(_STATIC);
+ consume(_SEMICOLON);
+ symdone:=true;
+ end;
+
+ { insert it in the symtable, if not done yet }
+ if not symdone then
+ begin
+ { save object option, because we can turn of the sp_published }
+ if (sp_published in current_object_option) and
+ not(is_class(tt.def)) then
+ begin
+ Message(parser_e_cant_publish_that);
+ exclude(current_object_option,sp_published);
+ { recover by changing access type to public }
+ vs2:=tabstractvarsym(sc.first);
+ while assigned (vs2) do
+ begin
+ exclude(vs2.symoptions,sp_published);
+ include(vs2.symoptions,sp_public);
+ vs2:=tabstractvarsym(vs2.listnext);
+ end;
+ end
+ else
+ if (sp_published in current_object_option) and
+ not(oo_can_have_published in tobjectdef(tt.def).objectoptions) then
+ begin
+ Message(parser_e_only_publishable_classes_can__be_published);
+ exclude(current_object_option,sp_published);
+ end;
+ insert_syms(sc,tt,vd_threadvar in options,dummysymoptions);
+ current_object_option:=old_current_object_option;
+ end;
+
+ end;
+
+ { Check for Case }
+ if (vd_record in options) and (token=_CASE) then
+ begin
+ maxsize:=0;
+ maxalignment:=0;
+ maxpadalign:=0;
+ consume(_CASE);
+ sorg:=orgpattern;
+ hs:=pattern;
+ searchsym(hs,srsym,srsymtable);
+ { may be only a type: }
+ if assigned(srsym) and (srsym.typ in [typesym,unitsym]) then
+ begin
+ { for records, don't search the recordsymtable for
+ the symbols of the types }
+ oldsymtablestack:=symtablestack;
+ symtablestack:=symtablestack.next;
+ read_type(casetype,'',true);
+ symtablestack:=oldsymtablestack;
+ end
+ else
+ begin
+ consume(_ID);
+ consume(_COLON);
+ { for records, don't search the recordsymtable for
+ the symbols of the types }
+ oldsymtablestack:=symtablestack;
+ symtablestack:=symtablestack.next;
+ read_type(casetype,'',true);
+ symtablestack:=oldsymtablestack;
+ fieldvs:=tfieldvarsym.create(sorg,vs_value,casetype,[]);
+ tabstractrecordsymtable(symtablestack).insertfield(fieldvs,true);
+ end;
+ if not(is_ordinal(casetype.def))
+{$ifndef cpu64bit}
+ or is_64bitint(casetype.def)
+{$endif cpu64bit}
+ then
+ Message(type_e_ordinal_expr_expected);
+ consume(_OF);
+ UnionSymtable:=trecordsymtable.create(aktpackrecords);
+ Unionsymtable.next:=symtablestack;
+ registerdef:=false;
+ UnionDef:=trecorddef.create(unionsymtable);
+ uniondef.isunion:=true;
+ if assigned(symtablestack.defowner) then
+ Uniondef.owner:=symtablestack.defowner.owner;
+ registerdef:=true;
+ startvarrecsize:=UnionSymtable.datasize;
+ startvarrecalign:=UnionSymtable.fieldalignment;
+ startpadalign:=Unionsymtable.padalignment;
+ symtablestack:=UnionSymtable;
+ repeat
+ repeat
+ pt:=comp_expr(true);
+ if not(pt.nodetype=ordconstn) then
+ Message(parser_e_illegal_expression);
+ pt.free;
+ if token=_COMMA then
+ consume(_COMMA)
+ else
+ break;
+ until false;
+ consume(_COLON);
+ { read the vars }
+ consume(_LKLAMMER);
+ inc(variantrecordlevel);
+ if token<>_RKLAMMER then
+ read_var_decs([vd_record]);
+ dec(variantrecordlevel);
+ consume(_RKLAMMER);
+ { calculates maximal variant size }
+ maxsize:=max(maxsize,unionsymtable.datasize);
+ maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
+ maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
+ { the items of the next variant are overlayed }
+ unionsymtable.datasize:=startvarrecsize;
+ unionsymtable.fieldalignment:=startvarrecalign;
+ unionsymtable.padalignment:=startpadalign;
+ if (token<>_END) and (token<>_RKLAMMER) then
+ consume(_SEMICOLON)
+ else
+ break;
+ until (token=_END) or (token=_RKLAMMER);
+ { at last set the record size to that of the biggest variant }
+ unionsymtable.datasize:=maxsize;
+ unionsymtable.fieldalignment:=maxalignment;
+ uniontype.def:=uniondef;
+ uniontype.sym:=nil;
+ UnionSym:=tfieldvarsym.create('$case',vs_value,uniontype,[]);
+ symtablestack:=symtablestack.next;
+ unionsymtable.addalignmentpadding;
+{$ifdef powerpc}
+ { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
+ if (target_info.system in [system_powerpc_darwin, system_powerpc_macos]) and
+ is_first_field and
+ (trecordsymtable(symtablestack).usefieldalignment = -1) and
+ (maxpadalign > trecordsymtable(symtablestack).padalignment) then
+ trecordsymtable(symtablestack).padalignment:=maxpadalign;
+{$endif powerpc}
+ { Align the offset where the union symtable is added }
+ if (trecordsymtable(symtablestack).usefieldalignment=-1) then
+ usedalign:=used_align(unionsymtable.recordalignment,aktalignment.recordalignmin,aktalignment.maxCrecordalign)
+ else
+ usedalign:=used_align(unionsymtable.recordalignment,aktalignment.recordalignmin,aktalignment.recordalignmax);
+
+ offset:=align(trecordsymtable(symtablestack).datasize,usedalign);
+ trecordsymtable(symtablestack).datasize:=offset+unionsymtable.datasize;
+
+ if unionsymtable.recordalignment>trecordsymtable(symtablestack).fieldalignment then
+ trecordsymtable(symtablestack).fieldalignment:=unionsymtable.recordalignment;
+
+ trecordsymtable(symtablestack).insertunionst(Unionsymtable,offset);
+ Unionsym.owner:=nil;
+ unionsym.free;
+ uniondef.owner:=nil;
+ uniondef.free;
+ end;
+ block_type:=old_block_type;
+ current_object_option:=old_current_object_option;
+ { free the list }
+ sc.free;
+{$ifdef powerpc}
+ is_first_field := false;
+{$endif powerpc}
+ end;
+
+end.
diff --git a/compiler/pexports.pas b/compiler/pexports.pas
new file mode 100644
index 0000000000..02909f8bc6
--- /dev/null
+++ b/compiler/pexports.pas
@@ -0,0 +1,182 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit handles the exports parsing
+
+ 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 pexports;
+
+{$i fpcdefs.inc}
+
+interface
+
+ { reads an exports statement in a library }
+ procedure read_exports;
+
+ var
+ BinaryContainsExports: boolean = false;
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globals,tokens,verbose,
+ systems,
+ { symtable }
+ symconst,symbase,symtype,symsym,
+ { pass 1 }
+ node,
+ ncon,
+ { parser }
+ scanner,
+ pbase,pexpr,
+ { link }
+ gendef,export
+ ;
+
+
+ procedure read_exports;
+ var
+ hp : texported_item;
+ orgs,
+ DefString : string;
+ InternalProcName : string;
+ pt : tnode;
+ srsym : tsym;
+ srsymtable : tsymtable;
+
+ function IsGreater(hp1,hp2:texported_item):boolean;
+ var
+ i2 : boolean;
+ begin
+ i2:=(hp2.options and eo_index)<>0;
+ if (hp1.options and eo_index)<>0 then
+ begin
+ if i2 then
+ IsGreater:=hp1.index>hp2.index
+ else
+ IsGreater:=false;
+ end
+ else
+ IsGreater:=i2;
+ end;
+
+ begin
+ BinaryContainsExports:=true;
+ DefString:='';
+ InternalProcName:='';
+ consume(_EXPORTS);
+ repeat
+ hp:=texported_item.create;
+ if token=_ID then
+ begin
+ orgs:=orgpattern;
+ consume_sym(srsym,srsymtable);
+ hp.sym:=srsym;
+ InternalProcName:='';
+ case srsym.typ of
+ globalvarsym :
+ InternalProcName:=tglobalvarsym(srsym).mangledname;
+ typedconstsym :
+ InternalProcName:=ttypedconstsym(srsym).mangledname;
+ procsym :
+ begin
+ if (Tprocsym(srsym).procdef_count>1) or
+ ((tf_need_export in target_info.flags) and
+ not(po_exports in tprocsym(srsym).first_procdef.procoptions)) then
+ Message(parser_e_illegal_symbol_exported)
+ else
+ InternalProcName:=tprocsym(srsym).first_procdef.mangledname;
+ end;
+ else
+ Message(parser_e_illegal_symbol_exported)
+ end;
+ if InternalProcName<>'' then
+ begin
+ { This is wrong if the first is not
+ an underline }
+ if InternalProcName[1]='_' then
+ delete(InternalProcName,1,1)
+ else if (target_info.system in [system_i386_win32,system_i386_wdosx,system_arm_wince,system_i386_wince]) and UseDeffileForExports then
+ begin
+ Message(parser_e_dlltool_unit_var_problem);
+ Message(parser_e_dlltool_unit_var_problem2);
+ end;
+ if length(InternalProcName)<2 then
+ Message(parser_e_procname_to_short_for_export);
+ DefString:=srsym.realname+'='+InternalProcName;
+ end;
+ if try_to_consume(_INDEX) then
+ begin
+ pt:=comp_expr(true);
+ if pt.nodetype=ordconstn then
+ hp.index:=tordconstnode(pt).value
+ else
+ begin
+ hp.index:=0;
+ consume(_INTCONST);
+ end;
+ hp.options:=hp.options or eo_index;
+ pt.free;
+ if target_info.system in [system_i386_win32,system_i386_wdosx,system_arm_wince,system_i386_wince] then
+ DefString:=srsym.realname+'='+InternalProcName+' @ '+tostr(hp.index)
+ else
+ DefString:=srsym.realname+'='+InternalProcName; {Index ignored!}
+ end;
+ if try_to_consume(_NAME) then
+ begin
+ pt:=comp_expr(true);
+ if pt.nodetype=stringconstn then
+ hp.name:=stringdup(strpas(tstringconstnode(pt).value_str))
+ else
+ begin
+ hp.name:=stringdup('');
+ consume(_CSTRING);
+ end;
+ hp.options:=hp.options or eo_name;
+ pt.free;
+ DefString:=hp.name^+'='+InternalProcName;
+ end;
+ if try_to_consume(_RESIDENT) then
+ begin
+ hp.options:=hp.options or eo_resident;
+ DefString:=srsym.realname+'='+InternalProcName;{Resident ignored!}
+ end;
+ if (DefString<>'') and UseDeffileForExports then
+ DefFile.AddExport(DefString);
+ { Default to generate a name entry with the provided name }
+ if not assigned(hp.name) then
+ begin
+ hp.name:=stringdup(orgs);
+ hp.options:=hp.options or eo_name;
+ end;
+ if hp.sym.typ=procsym then
+ exportlib.exportprocedure(hp)
+ else
+ exportlib.exportvar(hp);
+ end
+ else
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ consume(_SEMICOLON);
+ if not DefFile.empty then
+ DefFile.writefile;
+ end;
+
+end.
diff --git a/compiler/pexpr.pas b/compiler/pexpr.pas
new file mode 100644
index 0000000000..2f3cde9aa8
--- /dev/null
+++ b/compiler/pexpr.pas
@@ -0,0 +1,2674 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does parsing of expression for Free Pascal
+
+ 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 pexpr;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symtype,symdef,symbase,
+ node,ncal,
+ tokens,globtype,globals;
+
+ { reads a whole expression }
+ function expr : tnode;
+
+ { reads an expression without assignements and .. }
+ function comp_expr(accept_equal : boolean):tnode;
+
+ { reads a single factor }
+ function factor(getaddr : boolean) : tnode;
+
+ procedure string_dec(var t: ttype);
+
+ procedure symlist_to_node(var p1:tnode;st:tsymtable;pl:tsymlist);
+
+ function node_to_symlist(p1:tnode):tsymlist;
+
+ function parse_paras(__colon : boolean;end_of_paras : ttoken) : tnode;
+
+ { the ID token has to be consumed before calling this function }
+ procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callflags:tcallnodeflags);
+
+{$ifdef int64funcresok}
+ function get_intconst:TConstExprInt;
+{$else int64funcresok}
+ function get_intconst:longint;
+{$endif int64funcresok}
+
+ function get_stringconst:string;
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ verbose,
+ systems,widestr,
+ { symtable }
+ symconst,symtable,symsym,defutil,defcmp,
+ { module }
+ fmodule,ppu,
+ { pass 1 }
+ pass_1,htypechk,
+ nmat,nadd,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils,
+ { parser }
+ scanner,
+ pbase,pinline,
+ { codegen }
+ cgbase,procinfo,cpuinfo
+ ;
+
+ { sub_expr(opmultiply) is need to get -1 ** 4 to be
+ read as - (1**4) and not (-1)**4 PM }
+ type
+ Toperator_precedence=(opcompare,opaddition,opmultiply,oppower);
+
+ const
+ highest_precedence = oppower;
+
+ function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):tnode;forward;
+
+ const
+ { true, if the inherited call is anonymous }
+ anon_inherited : boolean = false;
+
+
+
+ procedure string_dec(var t: ttype);
+ { reads a string type with optional length }
+ { and returns a pointer to the string }
+ { definition }
+ var
+ p : tnode;
+ begin
+ t:=cshortstringtype;
+ consume(_STRING);
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+ p:=comp_expr(true);
+ if not is_constintnode(p) then
+ begin
+ Message(parser_e_illegal_expression);
+ { error recovery }
+ consume(_RECKKLAMMER);
+ end
+ else
+ begin
+ if (tordconstnode(p).value<=0) then
+ begin
+ Message(parser_e_invalid_string_size);
+ tordconstnode(p).value:=255;
+ end;
+ consume(_RECKKLAMMER);
+ if tordconstnode(p).value>255 then
+ begin
+ { longstring is currently unsupported (CEC)! }
+{ t.setdef(tstringdef.createlong(tordconstnode(p).value))}
+ Message(parser_e_invalid_string_size);
+ tordconstnode(p).value:=255;
+ t.setdef(tstringdef.createshort(tordconstnode(p).value));
+ end
+ else
+ if tordconstnode(p).value<>255 then
+ t.setdef(tstringdef.createshort(tordconstnode(p).value));
+ end;
+ p.free;
+ end
+ else
+ begin
+ if cs_ansistrings in aktlocalswitches then
+ {$ifdef ansistring_bits}
+ case aktansistring_bits of
+ sb_16:
+ t:=cansistringtype16;
+ sb_32:
+ t:=cansistringtype32;
+ sb_64:
+ t:=cansistringtype64;
+ end
+ {$else}
+ t:=cansistringtype
+ {$endif}
+ else
+ t:=cshortstringtype;
+ end;
+ end;
+
+
+
+ procedure symlist_to_node(var p1:tnode;st:tsymtable;pl:tsymlist);
+ var
+ plist : psymlistitem;
+ begin
+ plist:=pl.firstsym;
+ while assigned(plist) do
+ begin
+ case plist^.sltype of
+ sl_load :
+ begin
+ if not assigned(st) then
+ st:=plist^.sym.owner;
+ { p1 can already contain the loadnode of
+ the class variable. When there is no tree yet we
+ may need to load it for with or objects }
+ if not assigned(p1) then
+ begin
+ case st.symtabletype of
+ withsymtable :
+ p1:=tnode(twithsymtable(st).withrefnode).getcopy;
+ objectsymtable :
+ p1:=load_self_node;
+ end;
+ end;
+ if assigned(p1) then
+ p1:=csubscriptnode.create(plist^.sym,p1)
+ else
+ p1:=cloadnode.create(plist^.sym,st);
+ end;
+ sl_subscript :
+ p1:=csubscriptnode.create(plist^.sym,p1);
+ sl_typeconv :
+ p1:=ctypeconvnode.create_explicit(p1,plist^.tt);
+ sl_absolutetype :
+ begin
+ p1:=ctypeconvnode.create(p1,plist^.tt);
+ include(p1.flags,nf_absolute);
+ end;
+ sl_vec :
+ p1:=cvecnode.create(p1,cordconstnode.create(plist^.value,s32inttype,true));
+ else
+ internalerror(200110205);
+ end;
+ plist:=plist^.next;
+ end;
+ end;
+
+
+ function node_to_symlist(p1:tnode):tsymlist;
+ var
+ sl : tsymlist;
+
+ procedure addnode(p:tnode);
+ begin
+ case p.nodetype of
+ subscriptn :
+ begin
+ addnode(tsubscriptnode(p).left);
+ sl.addsym(sl_subscript,tsubscriptnode(p).vs);
+ end;
+ typeconvn :
+ begin
+ addnode(ttypeconvnode(p).left);
+ if nf_absolute in ttypeconvnode(p).flags then
+ sl.addtype(sl_absolutetype,ttypeconvnode(p).totype)
+ else
+ sl.addtype(sl_typeconv,ttypeconvnode(p).totype);
+ end;
+ vecn :
+ begin
+ addnode(tvecnode(p).left);
+ if tvecnode(p).right.nodetype=ordconstn then
+ sl.addconst(sl_vec,tordconstnode(tvecnode(p).right).value)
+ else
+ begin
+ Message(parser_e_illegal_expression);
+ { recovery }
+ sl.addconst(sl_vec,0);
+ end;
+ end;
+ loadn :
+ sl.addsym(sl_load,tloadnode(p).symtableentry);
+ else
+ internalerror(200310282);
+ end;
+ end;
+
+ begin
+ sl:=tsymlist.create;
+ addnode(p1);
+ result:=sl;
+ end;
+
+
+ function parse_paras(__colon : boolean;end_of_paras : ttoken) : tnode;
+ var
+ p1,p2 : tnode;
+ prev_in_args : boolean;
+ old_allow_array_constructor : boolean;
+ begin
+ if token=end_of_paras then
+ begin
+ parse_paras:=nil;
+ exit;
+ end;
+ { save old values }
+ prev_in_args:=in_args;
+ old_allow_array_constructor:=allow_array_constructor;
+ { set para parsing values }
+ in_args:=true;
+ inc(parsing_para_level);
+ allow_array_constructor:=true;
+ p2:=nil;
+ repeat
+ p1:=comp_expr(true);
+ p2:=ccallparanode.create(p1,p2);
+ { it's for the str(l:5,s); }
+ if __colon and (token=_COLON) then
+ begin
+ consume(_COLON);
+ p1:=comp_expr(true);
+ p2:=ccallparanode.create(p1,p2);
+ include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
+ if try_to_consume(_COLON) then
+ begin
+ p1:=comp_expr(true);
+ p2:=ccallparanode.create(p1,p2);
+ include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
+ end
+ end;
+ until not try_to_consume(_COMMA);
+ allow_array_constructor:=old_allow_array_constructor;
+ dec(parsing_para_level);
+ in_args:=prev_in_args;
+ parse_paras:=p2;
+ end;
+
+
+ function gen_c_style_operator(ntyp:tnodetype;p1,p2:tnode) : tnode;
+ var
+ hp : tnode;
+ htype : ttype;
+ temp : ttempcreatenode;
+ newstatement : tstatementnode;
+ begin
+ { Properties are not allowed, because the write can
+ be different from the read }
+ if (nf_isproperty in p1.flags) then
+ begin
+ Message(type_e_variable_id_expected);
+ { We can continue with the loading,
+ it'll not create errors. Only the expected
+ result can be wrong }
+ end;
+
+ hp:=p1;
+ while assigned(hp) and
+ (hp.nodetype in [derefn,subscriptn,vecn,typeconvn]) do
+ hp:=tunarynode(hp).left;
+ if not assigned(hp) then
+ internalerror(200410121);
+ if (hp.nodetype=calln) then
+ begin
+ resulttypepass(p1);
+ result:=internalstatements(newstatement);
+ htype.setdef(tpointerdef.create(p1.resulttype));
+ temp:=ctempcreatenode.create(htype,sizeof(aint),tt_persistent,false);
+ addstatement(newstatement,temp);
+ addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(temp),caddrnode.create_internal(p1)));
+ addstatement(newstatement,cassignmentnode.create(
+ cderefnode.create(ctemprefnode.create(temp)),
+ caddnode.create(ntyp,
+ cderefnode.create(ctemprefnode.create(temp)),
+ p2)));
+ addstatement(newstatement,ctempdeletenode.create(temp));
+ end
+ else
+ result:=cassignmentnode.create(p1,caddnode.create(ntyp,p1.getcopy,p2));
+ end;
+
+
+ function statement_syssym(l : longint) : tnode;
+ var
+ p1,p2,paras : tnode;
+ err,
+ prev_in_args : boolean;
+ begin
+ prev_in_args:=in_args;
+ case l of
+
+ in_new_x :
+ begin
+ if afterassignment or in_args then
+ statement_syssym:=new_function
+ else
+ statement_syssym:=new_dispose_statement(true);
+ end;
+
+ in_dispose_x :
+ begin
+ statement_syssym:=new_dispose_statement(false);
+ end;
+
+ in_ord_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ consume(_RKLAMMER);
+ p1:=geninlinenode(in_ord_x,false,p1);
+ statement_syssym := p1;
+ end;
+
+ in_exit :
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ if not (m_mac in aktmodeswitches) then
+ begin
+ p1:=comp_expr(true);
+ consume(_RKLAMMER);
+ if (block_type=bt_except) then
+ begin
+ Message(parser_e_exit_with_argument_not__possible);
+ { recovery }
+ p1.free;
+ p1:=nil;
+ end
+ else if (not assigned(current_procinfo) or
+ is_void(current_procinfo.procdef.rettype.def)) then
+ begin
+ Message(parser_e_void_function);
+ { recovery }
+ p1.free;
+ p1:=nil;
+ end;
+ end
+ else
+ begin
+ if not (current_procinfo.procdef.procsym.name = pattern) then
+ Message(parser_e_macpas_exit_wrong_param);
+ consume(_ID);
+ consume(_RKLAMMER);
+ p1:=nil;
+ end
+ end
+ else
+ p1:=nil;
+ statement_syssym:=cexitnode.create(p1);
+ end;
+
+ in_break :
+ begin
+ if not (m_mac in aktmodeswitches) then
+ statement_syssym:=cbreaknode.create
+ else
+ begin
+ Message1(sym_e_id_not_found, orgpattern);
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_continue :
+ begin
+ if not (m_mac in aktmodeswitches) then
+ statement_syssym:=ccontinuenode.create
+ else
+ begin
+ Message1(sym_e_id_not_found, orgpattern);
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_leave :
+ begin
+ if m_mac in aktmodeswitches then
+ statement_syssym:=cbreaknode.create
+ else
+ begin
+ Message1(sym_e_id_not_found, orgpattern);
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_cycle :
+ begin
+ if m_mac in aktmodeswitches then
+ statement_syssym:=ccontinuenode.create
+ else
+ begin
+ Message1(sym_e_id_not_found, orgpattern);
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_typeof_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ consume(_RKLAMMER);
+ if p1.nodetype=typen then
+ ttypenode(p1).allowed:=true;
+ { Allow classrefdef, which is required for
+ Typeof(self) in static class methods }
+ if (p1.resulttype.def.deftype = objectdef) or
+ (assigned(current_procinfo) and
+ ((po_classmethod in current_procinfo.procdef.procoptions) or
+ (po_staticmethod in current_procinfo.procdef.procoptions)) and
+ (p1.resulttype.def.deftype=classrefdef)) then
+ statement_syssym:=geninlinenode(in_typeof_x,false,p1)
+ else
+ begin
+ Message(parser_e_class_id_expected);
+ p1.destroy;
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_sizeof_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ consume(_RKLAMMER);
+ if (p1.nodetype<>typen) and
+ (
+ (is_object(p1.resulttype.def) and
+ (oo_has_constructor in tobjectdef(p1.resulttype.def).objectoptions)) or
+ is_open_array(p1.resulttype.def) or
+ is_open_string(p1.resulttype.def)
+ ) then
+ statement_syssym:=geninlinenode(in_sizeof_x,false,p1)
+ else
+ begin
+ statement_syssym:=cordconstnode.create(p1.resulttype.def.size,sinttype,true);
+ { p1 not needed !}
+ p1.destroy;
+ end;
+ end;
+
+ in_typeinfo_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ { When reading a class type it is parsed as loadvmtaddrn,
+ typeinfo only needs the type so we remove the loadvmtaddrn }
+ if p1.nodetype=loadvmtaddrn then
+ begin
+ p2:=tloadvmtaddrnode(p1).left;
+ tloadvmtaddrnode(p1).left:=nil;
+ p1.free;
+ p1:=p2;
+ end;
+ if p1.nodetype=typen then
+ ttypenode(p1).allowed:=true
+ else
+ begin
+ p1.destroy;
+ p1:=cerrornode.create;
+ Message(parser_e_illegal_parameter_list);
+ end;
+ consume(_RKLAMMER);
+ p2:=geninlinenode(in_typeinfo_x,false,p1);
+ statement_syssym:=p2;
+ end;
+
+ in_assigned_x :
+ begin
+ err:=false;
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ { When reading a class type it is parsed as loadvmtaddrn,
+ typeinfo only needs the type so we remove the loadvmtaddrn }
+ if p1.nodetype=loadvmtaddrn then
+ begin
+ p2:=tloadvmtaddrnode(p1).left;
+ tloadvmtaddrnode(p1).left:=nil;
+ p1.free;
+ p1:=p2;
+ end;
+ if not codegenerror then
+ begin
+ case p1.resulttype.def.deftype of
+ procdef, { procvar }
+ pointerdef,
+ procvardef,
+ classrefdef : ;
+ objectdef :
+ if not is_class_or_interface(p1.resulttype.def) then
+ begin
+ Message(parser_e_illegal_parameter_list);
+ err:=true;
+ end;
+ arraydef :
+ if not is_dynamic_array(p1.resulttype.def) then
+ begin
+ Message(parser_e_illegal_parameter_list);
+ err:=true;
+ end;
+ else
+ begin
+ Message(parser_e_illegal_parameter_list);
+ err:=true;
+ end;
+ end;
+ end
+ else
+ err:=true;
+ if not err then
+ begin
+ p2:=ccallparanode.create(p1,nil);
+ p2:=geninlinenode(in_assigned_x,false,p2);
+ end
+ else
+ begin
+ p1.free;
+ p2:=cerrornode.create;
+ end;
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_addr_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ p1:=caddrnode.create(p1);
+ if cs_typed_addresses in aktlocalswitches then
+ include(p1.flags,nf_typedaddr);
+ consume(_RKLAMMER);
+ statement_syssym:=p1;
+ end;
+
+ in_ofs_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ p1:=caddrnode.create(p1);
+ do_resulttypepass(p1);
+ { Ofs() returns a cardinal/qword, not a pointer }
+ p1.resulttype:=uinttype;
+ consume(_RKLAMMER);
+ statement_syssym:=p1;
+ end;
+
+ in_seg_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ p1:=geninlinenode(in_seg_x,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p1;
+ end;
+
+ in_high_x,
+ in_low_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ p2:=geninlinenode(l,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_succ_x,
+ in_pred_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ p2:=geninlinenode(l,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_inc_x,
+ in_dec_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ if try_to_consume(_COMMA) then
+ p2:=ccallparanode.create(comp_expr(true),nil)
+ else
+ p2:=nil;
+ p2:=ccallparanode.create(p1,p2);
+ statement_syssym:=geninlinenode(l,false,p2);
+ consume(_RKLAMMER);
+ end;
+
+ in_slice_x:
+ begin
+ if not(in_args) then
+ begin
+ message(parser_e_illegal_slice);
+ consume(_LKLAMMER);
+ in_args:=true;
+ comp_expr(true).free;
+ if try_to_consume(_COMMA) then
+ comp_expr(true).free;
+ statement_syssym:=cerrornode.create;
+ consume(_RKLAMMER);
+ end
+ else
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ if try_to_consume(_COMMA) then
+ p2:=ccallparanode.create(comp_expr(true),nil)
+ else
+ p2:=nil;
+ p2:=ccallparanode.create(p1,p2);
+ statement_syssym:=geninlinenode(l,false,p2);
+ consume(_RKLAMMER);
+ end;
+ end;
+
+ in_initialize_x:
+ begin
+ statement_syssym:=inline_initialize;
+ end;
+
+ in_finalize_x:
+ begin
+ statement_syssym:=inline_finalize;
+ end;
+
+ in_copy_x:
+ begin
+ statement_syssym:=inline_copy;
+ end;
+
+ in_concat_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ { Translate to x:=x+y[+z]. The addnode will do the
+ type checking }
+ p2:=nil;
+ repeat
+ p1:=comp_expr(true);
+ if p2<>nil then
+ p2:=caddnode.create(addn,p2,p1)
+ else
+ begin
+ { Force string type if it isn't yet }
+ if not(
+ (p1.resulttype.def.deftype=stringdef) or
+ is_chararray(p1.resulttype.def) or
+ is_char(p1.resulttype.def)
+ ) then
+ inserttypeconv(p1,cshortstringtype);
+ p2:=p1;
+ end;
+ until not try_to_consume(_COMMA);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_read_x,
+ in_readln_x :
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ paras:=parse_paras(false,_RKLAMMER);
+ consume(_RKLAMMER);
+ end
+ else
+ paras:=nil;
+ p1:=geninlinenode(l,false,paras);
+ statement_syssym := p1;
+ end;
+
+ in_setlength_x:
+ begin
+ statement_syssym := inline_setlength;
+ end;
+
+ in_length_x:
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ p2:=geninlinenode(l,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_write_x,
+ in_writeln_x :
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ paras:=parse_paras(true,_RKLAMMER);
+ consume(_RKLAMMER);
+ end
+ else
+ paras:=nil;
+ p1 := geninlinenode(l,false,paras);
+ statement_syssym := p1;
+ end;
+
+ in_str_x_string :
+ begin
+ consume(_LKLAMMER);
+ paras:=parse_paras(true,_RKLAMMER);
+ consume(_RKLAMMER);
+ p1 := geninlinenode(l,false,paras);
+ statement_syssym := p1;
+ end;
+
+ in_val_x:
+ Begin
+ consume(_LKLAMMER);
+ in_args := true;
+ p1:= ccallparanode.create(comp_expr(true), nil);
+ consume(_COMMA);
+ p2 := ccallparanode.create(comp_expr(true),p1);
+ if try_to_consume(_COMMA) then
+ p2 := ccallparanode.create(comp_expr(true),p2);
+ consume(_RKLAMMER);
+ p2 := geninlinenode(l,false,p2);
+ statement_syssym := p2;
+ End;
+
+ in_include_x_y,
+ in_exclude_x_y :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ consume(_COMMA);
+ p2:=comp_expr(true);
+ statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
+ consume(_RKLAMMER);
+ end;
+
+ in_assert_x_y :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true);
+ if try_to_consume(_COMMA) then
+ p2:=comp_expr(true)
+ else
+ begin
+ { then insert an empty string }
+ p2:=cstringconstnode.createstr('',st_conststring);
+ end;
+ statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
+ consume(_RKLAMMER);
+ end;
+
+ else
+ internalerror(15);
+
+ end;
+ in_args:=prev_in_args;
+ end;
+
+
+ function maybe_load_methodpointer(st:tsymtable;var p1:tnode):boolean;
+ begin
+ maybe_load_methodpointer:=false;
+ if not assigned(p1) then
+ begin
+ case st.symtabletype of
+ withsymtable :
+ begin
+ if (st.defowner.deftype=objectdef) then
+ p1:=tnode(twithsymtable(st).withrefnode).getcopy;
+ end;
+ objectsymtable :
+ begin
+ p1:=load_self_node;
+ { We are calling a member }
+ maybe_load_methodpointer:=true;
+ end;
+ end;
+ end;
+ end;
+
+
+ { reads the parameter for a subroutine call }
+ procedure do_proc_call(sym:tsym;st:tsymtable;obj:tobjectdef;getaddr:boolean;var again : boolean;var p1:tnode;callflags:tcallnodeflags);
+ var
+ membercall,
+ prevafterassn : boolean;
+ i : integer;
+ para,p2 : tnode;
+ currpara : tparavarsym;
+ aprocdef : tprocdef;
+ begin
+ prevafterassn:=afterassignment;
+ afterassignment:=false;
+ membercall:=false;
+ aprocdef:=nil;
+
+ { when it is a call to a member we need to load the
+ methodpointer first }
+ membercall:=maybe_load_methodpointer(st,p1);
+
+ { When we are expecting a procvar we also need
+ to get the address in some cases }
+ if assigned(getprocvardef) then
+ begin
+ if (block_type=bt_const) or
+ getaddr then
+ begin
+ aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef);
+ getaddr:=true;
+ end
+ else
+ if (m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches) then
+ begin
+ aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef);
+ if assigned(aprocdef) then
+ getaddr:=true;
+ end;
+ end;
+
+ { only need to get the address of the procedure? }
+ if getaddr then
+ begin
+ { Retrieve info which procvar to call. For tp_procvar the
+ aprocdef is already loaded above so we can reuse it }
+ if not assigned(aprocdef) and
+ assigned(getprocvardef) then
+ aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef);
+
+ { generate a methodcallnode or proccallnode }
+ { we shouldn't convert things like @tcollection.load }
+ p2:=cloadnode.create_procvar(sym,aprocdef,st);
+ if assigned(p1) then
+ begin
+ if (p1.nodetype<>typen) then
+ tloadnode(p2).set_mp(p1)
+ else
+ p1.free;
+ end;
+ p1:=p2;
+
+ { no postfix operators }
+ again:=false;
+ end
+ else
+ begin
+ para:=nil;
+ if anon_inherited then
+ begin
+ if not assigned(current_procinfo) then
+ internalerror(200305054);
+ for i:=0 to current_procinfo.procdef.paras.count-1 do
+ begin
+ currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+ if not(vo_is_hidden_para in currpara.varoptions) then
+ para:=ccallparanode.create(cloadnode.create(currpara,currpara.owner),para);
+ end;
+ end
+ else
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ para:=parse_paras(false,_RKLAMMER);
+ consume(_RKLAMMER);
+ end;
+ end;
+ { indicate if this call was generated by a member and
+ no explicit self is used, this is needed to determine
+ how to handle a destructor call (PFV) }
+ if membercall then
+ include(callflags,cnf_member_call);
+ if assigned(obj) then
+ begin
+ if (st.symtabletype<>objectsymtable) then
+ internalerror(200310031);
+ p1:=ccallnode.create(para,tprocsym(sym),obj.symtable,p1,callflags);
+ end
+ else
+ p1:=ccallnode.create(para,tprocsym(sym),st,p1,callflags);
+ end;
+ afterassignment:=prevafterassn;
+ end;
+
+
+ procedure handle_procvar(pv : tprocvardef;var p2 : tnode);
+ var
+ hp,hp2 : tnode;
+ hpp : ^tnode;
+ currprocdef : tprocdef;
+ begin
+ if not assigned(pv) then
+ internalerror(200301121);
+ if (m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches) then
+ begin
+ hp:=p2;
+ hpp:=@p2;
+ while assigned(hp) and
+ (hp.nodetype=typeconvn) do
+ begin
+ hp:=ttypeconvnode(hp).left;
+ { save orignal address of the old tree so we can replace the node }
+ hpp:=@hp;
+ end;
+ if (hp.nodetype=calln) and
+ { a procvar can't have parameters! }
+ not assigned(tcallnode(hp).left) then
+ begin
+ currprocdef:=tcallnode(hp).symtableprocentry.search_procdef_byprocvardef(pv);
+ if assigned(currprocdef) then
+ begin
+ hp2:=cloadnode.create_procvar(tprocsym(tcallnode(hp).symtableprocentry),currprocdef,tcallnode(hp).symtableproc);
+ if (po_methodpointer in pv.procoptions) then
+ tloadnode(hp2).set_mp(tcallnode(hp).get_load_methodpointer);
+ hp.destroy;
+ { replace the old callnode with the new loadnode }
+ hpp^:=hp2;
+ end;
+ end;
+ end;
+ end;
+
+
+ { the following procedure handles the access to a property symbol }
+ procedure handle_propertysym(sym : tsym;st : tsymtable;var p1 : tnode);
+ var
+ paras : tnode;
+ p2 : tnode;
+ membercall : boolean;
+ callflags : tcallnodeflags;
+ begin
+ paras:=nil;
+ { property parameters? read them only if the property really }
+ { has parameters }
+ if (ppo_hasparameters in tpropertysym(sym).propoptions) then
+ begin
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+ paras:=parse_paras(false,_RECKKLAMMER);
+ consume(_RECKKLAMMER);
+ end;
+ end;
+ { indexed property }
+ if (ppo_indexed in tpropertysym(sym).propoptions) then
+ begin
+ p2:=cordconstnode.create(tpropertysym(sym).index,tpropertysym(sym).indextype,true);
+ paras:=ccallparanode.create(p2,paras);
+ end;
+ { we need only a write property if a := follows }
+ { if not(afterassignment) and not(in_args) then }
+ if token=_ASSIGNMENT then
+ begin
+ { write property: }
+ if not tpropertysym(sym).writeaccess.empty then
+ begin
+ case tpropertysym(sym).writeaccess.firstsym^.sym.typ of
+ procsym :
+ begin
+ callflags:=[];
+ { generate the method call }
+ membercall:=maybe_load_methodpointer(st,p1);
+ if membercall then
+ include(callflags,cnf_member_call);
+ p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).writeaccess.firstsym^.sym),st,p1,callflags);
+ paras:=nil;
+ consume(_ASSIGNMENT);
+ { read the expression }
+ if tpropertysym(sym).proptype.def.deftype=procvardef then
+ getprocvardef:=tprocvardef(tpropertysym(sym).proptype.def);
+ p2:=comp_expr(true);
+ if assigned(getprocvardef) then
+ handle_procvar(getprocvardef,p2);
+ tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
+ { mark as property, both the tcallnode and the real call block }
+ include(p1.flags,nf_isproperty);
+ getprocvardef:=nil;
+ end;
+ fieldvarsym :
+ begin
+ { generate access code }
+ symlist_to_node(p1,st,tpropertysym(sym).writeaccess);
+ include(p1.flags,nf_isproperty);
+ consume(_ASSIGNMENT);
+ { read the expression }
+ p2:=comp_expr(true);
+ p1:=cassignmentnode.create(p1,p2);
+ end
+ else
+ begin
+ p1:=cerrornode.create;
+ Message(parser_e_no_procedure_to_access_property);
+ end;
+ end;
+ end
+ else
+ begin
+ p1:=cerrornode.create;
+ Message(parser_e_no_procedure_to_access_property);
+ end;
+ end
+ else
+ begin
+ { read property: }
+ if not tpropertysym(sym).readaccess.empty then
+ begin
+ case tpropertysym(sym).readaccess.firstsym^.sym.typ of
+ fieldvarsym :
+ begin
+ { generate access code }
+ symlist_to_node(p1,st,tpropertysym(sym).readaccess);
+ include(p1.flags,nf_isproperty);
+ end;
+ procsym :
+ begin
+ callflags:=[];
+ { generate the method call }
+ membercall:=maybe_load_methodpointer(st,p1);
+ if membercall then
+ include(callflags,cnf_member_call);
+ p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).readaccess.firstsym^.sym),st,p1,callflags);
+ paras:=nil;
+ include(p1.flags,nf_isproperty);
+ end
+ else
+ begin
+ p1:=cerrornode.create;
+ Message(type_e_mismatch);
+ end;
+ end;
+ end
+ else
+ begin
+ { error, no function to read property }
+ p1:=cerrornode.create;
+ Message(parser_e_no_procedure_to_access_property);
+ end;
+ end;
+ { release paras if not used }
+ if assigned(paras) then
+ paras.free;
+ end;
+
+
+ { the ID token has to be consumed before calling this function }
+ procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callflags:tcallnodeflags);
+
+ var
+ static_name : string;
+ isclassref : boolean;
+ srsymtable : tsymtable;
+ begin
+ if sym=nil then
+ begin
+ { pattern is still valid unless
+ there is another ID just after the ID of sym }
+ Message1(sym_e_id_no_member,orgpattern);
+ p1.free;
+ p1:=cerrornode.create;
+ { try to clean up }
+ again:=false;
+ end
+ else
+ begin
+ if assigned(p1) then
+ begin
+ if not assigned(p1.resulttype.def) then
+ do_resulttypepass(p1);
+ isclassref:=(p1.resulttype.def.deftype=classrefdef);
+ end
+ else
+ isclassref:=false;
+
+ { we assume, that only procsyms and varsyms are in an object }
+ { symbol table, for classes, properties are allowed }
+ case sym.typ of
+ procsym:
+ begin
+ do_proc_call(sym,sym.owner,classh,
+ (getaddr and not(token in [_CARET,_POINT])),
+ again,p1,callflags);
+ { we need to know which procedure is called }
+ do_resulttypepass(p1);
+ { calling using classref? }
+ if isclassref and
+ (p1.nodetype=calln) and
+ assigned(tcallnode(p1).procdefinition) and
+ not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and
+ not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
+ Message(parser_e_only_class_methods_via_class_ref);
+ end;
+ fieldvarsym:
+ begin
+ if (sp_static in sym.symoptions) then
+ begin
+ static_name:=lower(sym.owner.name^)+'_'+sym.name;
+ searchsym(static_name,sym,srsymtable);
+ check_hints(sym);
+ p1.free;
+ p1:=cloadnode.create(sym,srsymtable);
+ end
+ else
+ begin
+ if isclassref then
+ Message(parser_e_only_class_methods_via_class_ref);
+ p1:=csubscriptnode.create(sym,p1);
+ end;
+ end;
+ propertysym:
+ begin
+ if isclassref then
+ Message(parser_e_only_class_methods_via_class_ref);
+ handle_propertysym(sym,sym.owner,p1);
+ end;
+ else internalerror(16);
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ Factor
+****************************************************************************}
+{$ifdef fpc}
+ {$maxfpuregisters 0}
+{$endif fpc}
+
+ function factor(getaddr : boolean) : tnode;
+
+ {---------------------------------------------
+ Factor_read_id
+ ---------------------------------------------}
+
+ procedure factor_read_id(var p1:tnode;var again:boolean);
+ var
+ pc : pchar;
+ len : longint;
+ srsym : tsym;
+ possible_error : boolean;
+ srsymtable : tsymtable;
+ storesymtablestack : tsymtable;
+ htype : ttype;
+ static_name : string;
+ begin
+ { allow post fix operators }
+ again:=true;
+ consume_sym(srsym,srsymtable);
+
+ { Access to funcret or need to call the function? }
+ if (srsym.typ in [absolutevarsym,localvarsym,paravarsym]) and
+ (vo_is_funcret in tabstractvarsym(srsym).varoptions) and
+ (
+ (token=_LKLAMMER) or
+ (
+ (
+ (m_tp7 in aktmodeswitches) or
+ (m_delphi in aktmodeswitches)
+ ) and
+ (afterassignment or in_args) and
+ not(vo_is_result in tabstractvarsym(srsym).varoptions)
+ )
+ ) then
+ begin
+ storesymtablestack:=symtablestack;
+ symtablestack:=srsym.owner.next;
+ searchsym(srsym.name,srsym,srsymtable);
+ if not assigned(srsym) then
+ srsym:=generrorsym;
+ if (srsym.typ<>procsym) then
+ Message(parser_e_illegal_expression);
+ symtablestack:=storesymtablestack;
+ end;
+
+ begin
+ case srsym.typ of
+ absolutevarsym :
+ begin
+ if (tabsolutevarsym(srsym).abstyp=tovar) then
+ begin
+ p1:=nil;
+ symlist_to_node(p1,nil,tabsolutevarsym(srsym).ref);
+ p1:=ctypeconvnode.create(p1,tabsolutevarsym(srsym).vartype);
+ include(p1.flags,nf_absolute);
+ end
+ else
+ p1:=cloadnode.create(srsym,srsymtable);
+ end;
+
+ globalvarsym,
+ localvarsym,
+ paravarsym,
+ fieldvarsym :
+ begin
+ if (sp_static in srsym.symoptions) then
+ begin
+ static_name:=lower(srsym.owner.name^)+'_'+srsym.name;
+ searchsym(static_name,srsym,srsymtable);
+ check_hints(srsym);
+ end
+ else
+ begin
+ { are we in a class method, we check here the
+ srsymtable, because a field in another object
+ also has objectsymtable. And withsymtable is
+ not possible for self in class methods (PFV) }
+ if (srsymtable.symtabletype=objectsymtable) and
+ assigned(current_procinfo) and
+ (po_classmethod in current_procinfo.procdef.procoptions) then
+ Message(parser_e_only_class_methods);
+ end;
+
+ case srsymtable.symtabletype of
+ objectsymtable :
+ begin
+ p1:=csubscriptnode.create(srsym,load_self_node);
+ node_tree_set_filepos(p1,aktfilepos);
+ end;
+ withsymtable :
+ begin
+ p1:=csubscriptnode.create(srsym,tnode(twithsymtable(srsymtable).withrefnode).getcopy);
+ node_tree_set_filepos(p1,aktfilepos);
+ end;
+ else
+ p1:=cloadnode.create(srsym,srsymtable);
+ end;
+ end;
+
+ typedconstsym :
+ begin
+ p1:=cloadnode.create(srsym,srsymtable);
+ end;
+
+ syssym :
+ begin
+ p1:=statement_syssym(tsyssym(srsym).number);
+ end;
+
+ typesym :
+ begin
+ htype.setsym(srsym);
+ if not assigned(htype.def) then
+ begin
+ again:=false;
+ end
+ else
+ begin
+ { We need to know if this unit uses Variants }
+ if (htype.def=cvarianttype.def) and
+ not(cs_compilesystem in aktmoduleswitches) then
+ current_module.flags:=current_module.flags or uf_uses_variants;
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=comp_expr(true);
+ consume(_RKLAMMER);
+ p1:=ctypeconvnode.create_explicit(p1,htype);
+ end
+ else { not LKLAMMER }
+ if (token=_POINT) and
+ is_object(htype.def) then
+ begin
+ consume(_POINT);
+ if assigned(current_procinfo) and
+ assigned(current_procinfo.procdef._class) and
+ not(getaddr) then
+ begin
+ if current_procinfo.procdef._class.is_related(tobjectdef(htype.def)) then
+ begin
+ p1:=ctypenode.create(htype);
+ { search also in inherited methods }
+ srsym:=searchsym_in_class(tobjectdef(htype.def),pattern);
+ check_hints(srsym);
+ consume(_ID);
+ do_member_read(tobjectdef(htype.def),false,srsym,p1,again,[]);
+ end
+ else
+ begin
+ Message(parser_e_no_super_class);
+ again:=false;
+ end;
+ end
+ else
+ begin
+ { allows @TObject.Load }
+ { also allows static methods and variables }
+ p1:=ctypenode.create(htype);
+ { TP allows also @TMenu.Load if Load is only }
+ { defined in an anchestor class }
+ srsym:=search_class_member(tobjectdef(htype.def),pattern);
+ check_hints(srsym);
+ if not assigned(srsym) then
+ Message1(sym_e_id_no_member,orgpattern)
+ else if not(getaddr) and not(sp_static in srsym.symoptions) then
+ Message(sym_e_only_static_in_static)
+ else
+ begin
+ consume(_ID);
+ do_member_read(tobjectdef(htype.def),getaddr,srsym,p1,again,[]);
+ end;
+ end;
+ end
+ else
+ begin
+ { class reference ? }
+ if is_class(htype.def) then
+ begin
+ if getaddr and (token=_POINT) then
+ begin
+ consume(_POINT);
+ { allows @Object.Method }
+ { also allows static methods and variables }
+ p1:=ctypenode.create(htype);
+ { TP allows also @TMenu.Load if Load is only }
+ { defined in an anchestor class }
+ srsym:=search_class_member(tobjectdef(htype.def),pattern);
+ check_hints(srsym);
+ if not assigned(srsym) then
+ Message1(sym_e_id_no_member,orgpattern)
+ else
+ begin
+ consume(_ID);
+ do_member_read(tobjectdef(htype.def),getaddr,srsym,p1,again,[]);
+ end;
+ end
+ else
+ begin
+ p1:=ctypenode.create(htype);
+ { For a type block we simply return only
+ the type. For all other blocks we return
+ a loadvmt node }
+ if (block_type<>bt_type) then
+ p1:=cloadvmtaddrnode.create(p1);
+ end;
+ end
+ else
+ p1:=ctypenode.create(htype);
+ end;
+ end;
+ end;
+
+ enumsym :
+ begin
+ p1:=genenumnode(tenumsym(srsym));
+ end;
+
+ constsym :
+ begin
+ case tconstsym(srsym).consttyp of
+ constord :
+ begin
+ if tconstsym(srsym).consttype.def=nil then
+ internalerror(200403232);
+ p1:=cordconstnode.create(tconstsym(srsym).value.valueord,tconstsym(srsym).consttype,true);
+ end;
+ conststring :
+ begin
+ len:=tconstsym(srsym).value.len;
+ if not(cs_ansistrings in aktlocalswitches) and (len>255) then
+ len:=255;
+ getmem(pc,len+1);
+ move(pchar(tconstsym(srsym).value.valueptr)^,pc^,len);
+ pc[len]:=#0;
+ p1:=cstringconstnode.createpchar(pc,len,st_conststring);
+ end;
+ constwstring :
+ p1:=cstringconstnode.createwstr(pcompilerwidestring(tconstsym(srsym).value.valueptr));
+ constreal :
+ p1:=crealconstnode.create(pbestreal(tconstsym(srsym).value.valueptr)^,pbestrealtype^);
+ constset :
+ p1:=csetconstnode.create(pconstset(tconstsym(srsym).value.valueptr),tconstsym(srsym).consttype);
+ constpointer :
+ p1:=cpointerconstnode.create(tconstsym(srsym).value.valueordptr,tconstsym(srsym).consttype);
+ constnil :
+ p1:=cnilnode.create;
+ constresourcestring:
+ begin
+ p1:=cloadnode.create(srsym,srsymtable);
+ do_resulttypepass(p1);
+ {$ifdef ansistring_bits}
+ case aktansistring_bits of
+ sb_16:
+ p1.resulttype:=cansistringtype16;
+ sb_32:
+ p1.resulttype:=cansistringtype32;
+ sb_64:
+ p1.resulttype:=cansistringtype64;
+ end;
+ {$else}
+ p1.resulttype:=cansistringtype;
+ {$endif}
+ end;
+ constguid :
+ p1:=cguidconstnode.create(pguid(tconstsym(srsym).value.valueptr)^);
+ else
+ internalerror(200507181);
+ end;
+ end;
+
+ procsym :
+ begin
+ { are we in a class method ? }
+ possible_error:=(srsymtable.symtabletype<>withsymtable) and
+ (srsym.owner.symtabletype=objectsymtable) and
+ not(is_interface(tdef(srsym.owner.defowner))) and
+ assigned(current_procinfo) and
+ (po_classmethod in current_procinfo.procdef.procoptions);
+ do_proc_call(srsym,srsymtable,nil,
+ (getaddr and not(token in [_CARET,_POINT])),
+ again,p1,[]);
+ { we need to know which procedure is called }
+ if possible_error then
+ begin
+ do_resulttypepass(p1);
+ if (p1.nodetype=calln) and
+ assigned(tcallnode(p1).procdefinition) and
+ not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) and
+ not(po_classmethod in tcallnode(p1).procdefinition.procoptions) then
+ Message(parser_e_only_class_methods);
+ end;
+ end;
+
+ propertysym :
+ begin
+ { access to property in a method }
+ { are we in a class method ? }
+ if (srsymtable.symtabletype=objectsymtable) and
+ assigned(current_procinfo) and
+ (po_classmethod in current_procinfo.procdef.procoptions) then
+ Message(parser_e_only_class_methods);
+ { no method pointer }
+ p1:=nil;
+ handle_propertysym(srsym,srsymtable,p1);
+ end;
+
+ labelsym :
+ begin
+ { Support @label }
+ if getaddr then
+ p1:=cloadnode.create(srsym,srsym.owner)
+ else
+ begin
+ consume(_COLON);
+ if tlabelsym(srsym).defined then
+ Message(sym_e_label_already_defined);
+ tlabelsym(srsym).defined:=true;
+ p1:=clabelnode.create(nil);
+ tlabelsym(srsym).code:=p1;
+ end;
+ end;
+
+ errorsym :
+ begin
+ p1:=cerrornode.create;
+ if try_to_consume(_LKLAMMER) then
+ begin
+ parse_paras(false,_RKLAMMER);
+ consume(_RKLAMMER);
+ end;
+ end;
+
+ else
+ begin
+ p1:=cerrornode.create;
+ Message(parser_e_illegal_expression);
+ end;
+ end; { end case }
+ end;
+ end;
+
+ {---------------------------------------------
+ Factor_Read_Set
+ ---------------------------------------------}
+
+ { Read a set between [] }
+ function factor_read_set:tnode;
+ var
+ p1,p2 : tnode;
+ lastp,
+ buildp : tarrayconstructornode;
+ begin
+ buildp:=nil;
+ { be sure that a least one arrayconstructn is used, also for an
+ empty [] }
+ if token=_RECKKLAMMER then
+ buildp:=carrayconstructornode.create(nil,buildp)
+ else
+ repeat
+ p1:=comp_expr(true);
+ if try_to_consume(_POINTPOINT) then
+ begin
+ p2:=comp_expr(true);
+ p1:=carrayconstructorrangenode.create(p1,p2);
+ end;
+ { insert at the end of the tree, to get the correct order }
+ if not assigned(buildp) then
+ begin
+ buildp:=carrayconstructornode.create(p1,nil);
+ lastp:=buildp;
+ end
+ else
+ begin
+ lastp.right:=carrayconstructornode.create(p1,nil);
+ lastp:=tarrayconstructornode(lastp.right);
+ end;
+ { there could be more elements }
+ until not try_to_consume(_COMMA);
+ factor_read_set:=buildp;
+ end;
+
+
+ {---------------------------------------------
+ PostFixOperators
+ ---------------------------------------------}
+
+ procedure postfixoperators(var p1:tnode;var again:boolean);
+
+ { tries to avoid syntax errors after invalid qualifiers }
+ procedure recoverconsume_postfixops;
+ begin
+ repeat
+ if not try_to_consume(_CARET) then
+ if try_to_consume(_POINT) then
+ try_to_consume(_ID)
+ else if try_to_consume(_LECKKLAMMER) then
+ begin
+ repeat
+ comp_expr(true);
+ until not try_to_consume(_COMMA);
+ consume(_RECKKLAMMER);
+ end
+ else
+ break;
+ until false;
+ end;
+
+
+ procedure handle_variantarray;
+ var
+ p4 : tnode;
+ newstatement : tstatementnode;
+ tempresultvariant,
+ temp : ttempcreatenode;
+ paras : tcallparanode;
+ newblock : tnode;
+ countindices : aint;
+ begin
+ { create statements with call initialize the arguments and
+ call fpc_dynarr_setlength }
+ newblock:=internalstatements(newstatement);
+
+ { get temp for array of indicies,
+ we set the real size later }
+ temp:=ctempcreatenode.create(sinttype,4,tt_persistent,false);
+ addstatement(newstatement,temp);
+
+ countindices:=0;
+ repeat
+ p4:=comp_expr(true);
+
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create_offset(temp,countindices*sinttype.def.size),p4));
+ inc(countindices);
+ until not try_to_consume(_COMMA);
+
+ { set real size }
+ temp.size:=countindices*sinttype.def.size;
+
+ consume(_RECKKLAMMER);
+
+ { we need only a write access if a := follows }
+ if token=_ASSIGNMENT then
+ begin
+ consume(_ASSIGNMENT);
+ p4:=comp_expr(true);
+
+ { create call to fpc_vararray_put }
+ paras:=ccallparanode.create(cordconstnode.create
+ (countindices,sinttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp)),
+ ccallparanode.create(ctypeconvnode.create_internal(p4,cvarianttype),
+ ccallparanode.create(p1
+ ,nil))));
+
+ addstatement(newstatement,ccallnode.createintern('fpc_vararray_put',paras));
+ addstatement(newstatement,ctempdeletenode.create(temp));
+ end
+ else
+ begin
+ { create temp for result }
+ tempresultvariant:=ctempcreatenode.create(cvarianttype,cvarianttype.def.size,tt_persistent,true);
+ addstatement(newstatement,tempresultvariant);
+
+ { create call to fpc_vararray_get }
+ paras:=ccallparanode.create(cordconstnode.create
+ (countindices,sinttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp)),
+ ccallparanode.create(p1,
+ ccallparanode.create(
+ ctemprefnode.create(tempresultvariant)
+ ,nil))));
+
+ addstatement(newstatement,ccallnode.createintern('fpc_vararray_get',paras));
+ addstatement(newstatement,ctempdeletenode.create(temp));
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(tempresultvariant));
+ addstatement(newstatement,ctemprefnode.create(tempresultvariant));
+ end;
+ p1:=newblock;
+ end;
+
+ var
+ store_static : boolean;
+ protsym : tpropertysym;
+ p2,p3 : tnode;
+ hsym : tsym;
+ classh : tobjectdef;
+
+ label
+ skipreckklammercheck;
+ begin
+ again:=true;
+ while again do
+ begin
+ { we need the resulttype }
+ do_resulttypepass(p1);
+
+ if codegenerror then
+ begin
+ recoverconsume_postfixops;
+ exit;
+ end;
+ { handle token }
+ case token of
+ _CARET:
+ begin
+ consume(_CARET);
+
+ { support tp/mac procvar^ if the procvar returns a
+ pointer type }
+ if ((m_tp_procvar in aktmodeswitches) or
+ (m_mac_procvar in aktmodeswitches)) and
+ (p1.resulttype.def.deftype=procvardef) and
+ (tprocvardef(p1.resulttype.def).rettype.def.deftype=pointerdef) then
+ begin
+ p1:=ccallnode.create_procvar(nil,p1);
+ resulttypepass(p1);
+ end;
+
+ if (p1.resulttype.def.deftype<>pointerdef) then
+ begin
+ { ^ as binary operator is a problem!!!! (FK) }
+ again:=false;
+ Message(parser_e_invalid_qualifier);
+ recoverconsume_postfixops;
+ p1.destroy;
+ p1:=cerrornode.create;
+ end
+ else
+ p1:=cderefnode.create(p1);
+ end;
+
+ _LECKKLAMMER:
+ begin
+ if is_class_or_interface(p1.resulttype.def) then
+ begin
+ { default property }
+ protsym:=search_default_property(tobjectdef(p1.resulttype.def));
+ if not(assigned(protsym)) then
+ begin
+ p1.destroy;
+ p1:=cerrornode.create;
+ again:=false;
+ message(parser_e_no_default_property_available);
+ end
+ else
+ begin
+ { The property symbol is referenced indirect }
+ inc(protsym.refs);
+ handle_propertysym(protsym,protsym.owner,p1);
+ end;
+ end
+ else
+ begin
+ consume(_LECKKLAMMER);
+ repeat
+ case p1.resulttype.def.deftype of
+ pointerdef:
+ begin
+ { support delphi autoderef }
+ if (tpointerdef(p1.resulttype.def).pointertype.def.deftype=arraydef) and
+ (m_autoderef in aktmodeswitches) then
+ begin
+ p1:=cderefnode.create(p1);
+ end;
+ p2:=comp_expr(true);
+ p1:=cvecnode.create(p1,p2);
+ end;
+ variantdef:
+ begin
+ handle_variantarray;
+ { the RECKKLAMMER is already read }
+ goto skipreckklammercheck;
+ end;
+ stringdef :
+ begin
+ p2:=comp_expr(true);
+ p1:=cvecnode.create(p1,p2);
+ end;
+ arraydef :
+ begin
+ p2:=comp_expr(true);
+ { support SEG:OFS for go32v2 Mem[] }
+ if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
+ (p1.nodetype=loadn) and
+ assigned(tloadnode(p1).symtableentry) and
+ assigned(tloadnode(p1).symtableentry.owner.name) and
+ (tloadnode(p1).symtableentry.owner.name^='SYSTEM') and
+ ((tloadnode(p1).symtableentry.name='MEM') or
+ (tloadnode(p1).symtableentry.name='MEMW') or
+ (tloadnode(p1).symtableentry.name='MEML')) then
+ begin
+ if try_to_consume(_COLON) then
+ begin
+ p3:=caddnode.create(muln,cordconstnode.create($10,s32inttype,false),p2);
+ p2:=comp_expr(true);
+ p2:=caddnode.create(addn,p2,p3);
+ p1:=cvecnode.create(p1,p2);
+ include(tvecnode(p1).flags,nf_memseg);
+ include(tvecnode(p1).flags,nf_memindex);
+ end
+ else
+ begin
+ p1:=cvecnode.create(p1,p2);
+ include(tvecnode(p1).flags,nf_memindex);
+ end;
+ end
+ else
+ p1:=cvecnode.create(p1,p2);
+ end;
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ p1.destroy;
+ p1:=cerrornode.create;
+ comp_expr(true);
+ again:=false;
+ end;
+ end;
+ do_resulttypepass(p1);
+ until not try_to_consume(_COMMA);
+ consume(_RECKKLAMMER);
+ { handle_variantarray eats the RECKKLAMMER and jumps here }
+ skipreckklammercheck:
+ end;
+ end;
+
+ _POINT :
+ begin
+ consume(_POINT);
+ if (p1.resulttype.def.deftype=pointerdef) and
+ (m_autoderef in aktmodeswitches) then
+ begin
+ p1:=cderefnode.create(p1);
+ do_resulttypepass(p1);
+ end;
+ case p1.resulttype.def.deftype of
+ recorddef:
+ begin
+ if token=_ID then
+ begin
+ hsym:=tsym(trecorddef(p1.resulttype.def).symtable.search(pattern));
+ check_hints(hsym);
+ if assigned(hsym) and
+ (hsym.typ=fieldvarsym) then
+ p1:=csubscriptnode.create(hsym,p1)
+ else
+ begin
+ Message1(sym_e_illegal_field,pattern);
+ p1.destroy;
+ p1:=cerrornode.create;
+ end;
+ end;
+ consume(_ID);
+ end;
+ variantdef:
+ begin
+ end;
+ classrefdef:
+ begin
+ if token=_ID then
+ begin
+ classh:=tobjectdef(tclassrefdef(p1.resulttype.def).pointertype.def);
+ hsym:=searchsym_in_class(classh,pattern);
+ check_hints(hsym);
+ if hsym=nil then
+ begin
+ Message1(sym_e_id_no_member,orgpattern);
+ p1.destroy;
+ p1:=cerrornode.create;
+ { try to clean up }
+ consume(_ID);
+ end
+ else
+ begin
+ consume(_ID);
+ do_member_read(classh,getaddr,hsym,p1,again,[]);
+ end;
+ end
+ else { Error }
+ Consume(_ID);
+ end;
+ objectdef:
+ begin
+ if token=_ID then
+ begin
+ store_static:=allow_only_static;
+ allow_only_static:=false;
+ classh:=tobjectdef(p1.resulttype.def);
+ hsym:=searchsym_in_class(classh,pattern);
+ check_hints(hsym);
+ allow_only_static:=store_static;
+ if hsym=nil then
+ begin
+ Message1(sym_e_id_no_member,orgpattern);
+ p1.destroy;
+ p1:=cerrornode.create;
+ { try to clean up }
+ consume(_ID);
+ end
+ else
+ begin
+ consume(_ID);
+ do_member_read(classh,getaddr,hsym,p1,again,[]);
+ end;
+ end
+ else { Error }
+ Consume(_ID);
+ end;
+ pointerdef:
+ begin
+ Message(parser_e_invalid_qualifier);
+ if tpointerdef(p1.resulttype.def).pointertype.def.deftype in [recorddef,objectdef,classrefdef] then
+ Message(parser_h_maybe_deref_caret_missing);
+ end;
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ p1.destroy;
+ p1:=cerrornode.create;
+ { Error }
+ consume(_ID);
+ end;
+ end;
+ end;
+
+ else
+ begin
+ { is this a procedure variable ? }
+ if assigned(p1.resulttype.def) and
+ (p1.resulttype.def.deftype=procvardef) then
+ begin
+ if assigned(getprocvardef) and
+ equal_defs(p1.resulttype.def,getprocvardef) then
+ again:=false
+ else
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p2:=parse_paras(false,_RKLAMMER);
+ consume(_RKLAMMER);
+ p1:=ccallnode.create_procvar(p2,p1);
+ { proc():= is never possible }
+ if token=_ASSIGNMENT then
+ begin
+ Message(parser_e_illegal_expression);
+ p1.free;
+ p1:=cerrornode.create;
+ again:=false;
+ end;
+ end
+ else
+ again:=false;
+ end;
+ end
+ else
+ again:=false;
+ end;
+ end;
+ end; { while again }
+ end;
+
+
+ {---------------------------------------------
+ Factor (Main)
+ ---------------------------------------------}
+
+ var
+ l : longint;
+ ic : int64;
+ qc : qword;
+{$ifndef cpu64}
+ card : cardinal;
+{$endif cpu64}
+ oldp1,
+ p1 : tnode;
+ code : integer;
+ again : boolean;
+ sym : tsym;
+ pd : tprocdef;
+ classh : tobjectdef;
+ d : bestreal;
+ hs,hsorg : string;
+ htype : ttype;
+ filepos : tfileposinfo;
+
+ {---------------------------------------------
+ Helpers
+ ---------------------------------------------}
+
+ procedure check_tokenpos;
+ begin
+ if (p1<>oldp1) then
+ begin
+ if assigned(p1) then
+ p1.fileinfo:=filepos;
+ oldp1:=p1;
+ filepos:=akttokenpos;
+ end;
+ end;
+
+ begin
+ oldp1:=nil;
+ p1:=nil;
+ filepos:=akttokenpos;
+ again:=false;
+ if token=_ID then
+ begin
+ again:=true;
+ { Handle references to self }
+ if (idtoken=_SELF) and
+ not(block_type in [bt_const,bt_type]) and
+ assigned(current_procinfo) and
+ assigned(current_procinfo.procdef._class) then
+ begin
+ p1:=load_self_node;
+ consume(_ID);
+ again:=true;
+ end
+ else
+ factor_read_id(p1,again);
+ if again then
+ begin
+ check_tokenpos;
+
+ { handle post fix operators }
+ postfixoperators(p1,again);
+ end;
+ end
+ else
+ case token of
+ _INHERITED :
+ begin
+ again:=true;
+ consume(_INHERITED);
+ if assigned(current_procinfo) and
+ assigned(current_procinfo.procdef._class) then
+ begin
+ classh:=current_procinfo.procdef._class.childof;
+ { if inherited; only then we need the method with
+ the same name }
+ if token in endtokens then
+ begin
+ hs:=current_procinfo.procdef.procsym.name;
+ hsorg:=current_procinfo.procdef.procsym.realname;
+ anon_inherited:=true;
+ { For message methods we need to search using the message
+ number or string }
+ pd:=tprocsym(current_procinfo.procdef.procsym).first_procdef;
+ if (po_msgint in pd.procoptions) then
+ sym:=searchsym_in_class_by_msgint(classh,pd.messageinf.i)
+ else
+ if (po_msgstr in pd.procoptions) then
+ sym:=searchsym_in_class_by_msgstr(classh,pd.messageinf.str)
+ else
+ sym:=searchsym_in_class(classh,hs);
+ end
+ else
+ begin
+ hs:=pattern;
+ hsorg:=orgpattern;
+ consume(_ID);
+ anon_inherited:=false;
+ sym:=searchsym_in_class(classh,hs);
+ end;
+ if assigned(sym) then
+ begin
+ check_hints(sym);
+ { load the procdef from the inherited class and
+ not from self }
+ if sym.typ in [procsym,propertysym] then
+ begin
+ if (sym.typ = procsym) then
+ begin
+ htype.setdef(classh);
+ if (po_classmethod in current_procinfo.procdef.procoptions) or
+ (po_staticmethod in current_procinfo.procdef.procoptions) then
+ htype.setdef(tclassrefdef.create(htype));
+ p1:=ctypenode.create(htype);
+ end;
+ end
+ else
+ begin
+ Message(parser_e_methode_id_expected);
+ p1:=cerrornode.create;
+ end;
+ do_member_read(classh,false,sym,p1,again,[cnf_inherited,cnf_anon_inherited]);
+ end
+ else
+ begin
+ if anon_inherited then
+ begin
+ { For message methods we need to call DefaultHandler }
+ if (po_msgint in pd.procoptions) or
+ (po_msgstr in pd.procoptions) then
+ begin
+ sym:=searchsym_in_class(classh,'DEFAULTHANDLER');
+ if not assigned(sym) or
+ (sym.typ<>procsym) then
+ internalerror(200303171);
+ p1:=nil;
+ do_proc_call(sym,sym.owner,classh,false,again,p1,[]);
+ end
+ else
+ begin
+ { we need to ignore the inherited; }
+ p1:=cnothingnode.create;
+ end;
+ end
+ else
+ begin
+ Message1(sym_e_id_no_member,hsorg);
+ p1:=cerrornode.create;
+ end;
+ again:=false;
+ end;
+ { turn auto inheriting off }
+ anon_inherited:=false;
+ end
+ else
+ begin
+ Message(parser_e_generic_methods_only_in_methods);
+ again:=false;
+ p1:=cerrornode.create;
+ end;
+ postfixoperators(p1,again);
+ end;
+
+ _INTCONST :
+ begin
+{$ifdef cpu64}
+ { when already running under 64bit must read int64 constant, because reading
+ cardinal first will also succeed (code=0) for values > maxcardinal, because
+ range checking is off by default (PFV) }
+ val(pattern,ic,code);
+ if code=0 then
+ begin
+ consume(_INTCONST);
+ int_to_type(ic,htype);
+ p1:=cordconstnode.create(ic,htype,true);
+ end
+ else
+ begin
+ { try qword next }
+ val(pattern,qc,code);
+ if code=0 then
+ begin
+ consume(_INTCONST);
+ htype:=u64inttype;
+ p1:=cordconstnode.create(qc,htype,true);
+ end;
+ end;
+{$else}
+ { try cardinal first }
+ val(pattern,card,code);
+ if code=0 then
+ begin
+ consume(_INTCONST);
+ int_to_type(card,htype);
+ p1:=cordconstnode.create(card,htype,true);
+ end
+ else
+ begin
+ { then longint }
+ val(pattern,l,code);
+ if code = 0 then
+ begin
+ consume(_INTCONST);
+ int_to_type(l,htype);
+ p1:=cordconstnode.create(l,htype,true);
+ end
+ else
+ begin
+ { then int64 }
+ val(pattern,ic,code);
+ if code=0 then
+ begin
+ consume(_INTCONST);
+ int_to_type(ic,htype);
+ p1:=cordconstnode.create(ic,htype,true);
+ end
+ else
+ begin
+ { try qword next }
+ val(pattern,qc,code);
+ if code=0 then
+ begin
+ consume(_INTCONST);
+ htype:=u64inttype;
+ p1:=cordconstnode.create(tconstexprint(qc),htype,true);
+ end;
+ end;
+ end;
+ end;
+{$endif}
+ if code<>0 then
+ begin
+ { finally float }
+ val(pattern,d,code);
+ if code<>0 then
+ begin
+ Message(parser_e_invalid_integer);
+ consume(_INTCONST);
+ l:=1;
+ p1:=cordconstnode.create(l,sinttype,true);
+ end
+ else
+ begin
+ consume(_INTCONST);
+ p1:=crealconstnode.create(d,pbestrealtype^);
+ end;
+ end;
+ end;
+
+ _REALNUMBER :
+ begin
+ val(pattern,d,code);
+ if code<>0 then
+ begin
+ Message(parser_e_error_in_real);
+ d:=1.0;
+ end;
+ consume(_REALNUMBER);
+ p1:=crealconstnode.create(d,pbestrealtype^);
+ end;
+
+ _STRING :
+ begin
+ string_dec(htype);
+ { STRING can be also a type cast }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=comp_expr(true);
+ consume(_RKLAMMER);
+ p1:=ctypeconvnode.create_explicit(p1,htype);
+ { handle postfix operators here e.g. string(a)[10] }
+ again:=true;
+ postfixoperators(p1,again);
+ end
+ else
+ p1:=ctypenode.create(htype);
+ end;
+
+ _FILE :
+ begin
+ htype:=cfiletype;
+ consume(_FILE);
+ { FILE can be also a type cast }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=comp_expr(true);
+ consume(_RKLAMMER);
+ p1:=ctypeconvnode.create_explicit(p1,htype);
+ { handle postfix operators here e.g. string(a)[10] }
+ again:=true;
+ postfixoperators(p1,again);
+ end
+ else
+ begin
+ p1:=ctypenode.create(htype);
+ end;
+ end;
+
+ _CSTRING :
+ begin
+ p1:=cstringconstnode.createstr(pattern,st_conststring);
+ consume(_CSTRING);
+ end;
+
+ _CCHAR :
+ begin
+ p1:=cordconstnode.create(ord(pattern[1]),cchartype,true);
+ consume(_CCHAR);
+ end;
+
+ _CWSTRING:
+ begin
+ p1:=cstringconstnode.createwstr(patternw);
+ consume(_CWSTRING);
+ end;
+
+ _CWCHAR:
+ begin
+ p1:=cordconstnode.create(ord(getcharwidestring(patternw,0)),cwidechartype,true);
+ consume(_CWCHAR);
+ end;
+
+ _KLAMMERAFFE :
+ begin
+ consume(_KLAMMERAFFE);
+ got_addrn:=true;
+ { support both @<x> and @(<x>) }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=factor(true);
+ if token in [_CARET,_POINT,_LECKKLAMMER] then
+ begin
+ again:=true;
+ postfixoperators(p1,again);
+ end;
+ consume(_RKLAMMER);
+ end
+ else
+ p1:=factor(true);
+ if token in [_CARET,_POINT,_LECKKLAMMER] then
+ begin
+ again:=true;
+ postfixoperators(p1,again);
+ end;
+ got_addrn:=false;
+ p1:=caddrnode.create(p1);
+ if cs_typed_addresses in aktlocalswitches then
+ include(p1.flags,nf_typedaddr);
+ { Store the procvar that we are expecting, the
+ addrn will use the information to find the correct
+ procdef or it will return an error }
+ if assigned(getprocvardef) and
+ (taddrnode(p1).left.nodetype = loadn) then
+ taddrnode(p1).getprocvardef:=getprocvardef;
+ end;
+
+ _LKLAMMER :
+ begin
+ consume(_LKLAMMER);
+ p1:=comp_expr(true);
+ consume(_RKLAMMER);
+ { it's not a good solution }
+ { but (a+b)^ makes some problems }
+ if token in [_CARET,_POINT,_LECKKLAMMER] then
+ begin
+ again:=true;
+ postfixoperators(p1,again);
+ end;
+ end;
+
+ _LECKKLAMMER :
+ begin
+ consume(_LECKKLAMMER);
+ p1:=factor_read_set;
+ consume(_RECKKLAMMER);
+ end;
+
+ _PLUS :
+ begin
+ consume(_PLUS);
+ p1:=factor(false);
+ end;
+
+ _MINUS :
+ begin
+ consume(_MINUS);
+ if (token = _INTCONST) then
+ begin
+ { ugly hack, but necessary to be able to parse }
+ { -9223372036854775808 as int64 (JM) }
+ pattern := '-'+pattern;
+ p1:=sub_expr(oppower,false);
+ { -1 ** 4 should be - (1 ** 4) and not
+ (-1) ** 4
+ This was the reason of tw0869.pp test failure PM }
+ if p1.nodetype=starstarn then
+ begin
+ if tbinarynode(p1).left.nodetype=ordconstn then
+ begin
+ tordconstnode(tbinarynode(p1).left).value:=-tordconstnode(tbinarynode(p1).left).value;
+ p1:=cunaryminusnode.create(p1);
+ end
+ else if tbinarynode(p1).left.nodetype=realconstn then
+ begin
+ trealconstnode(tbinarynode(p1).left).value_real:=-trealconstnode(tbinarynode(p1).left).value_real;
+ p1:=cunaryminusnode.create(p1);
+ end
+ else
+ internalerror(20021029);
+ end;
+ end
+ else
+ begin
+ p1:=sub_expr(oppower,false);
+ p1:=cunaryminusnode.create(p1);
+ end;
+ end;
+
+ _OP_NOT :
+ begin
+ consume(_OP_NOT);
+ p1:=factor(false);
+ p1:=cnotnode.create(p1);
+ end;
+
+ _TRUE :
+ begin
+ consume(_TRUE);
+ p1:=cordconstnode.create(1,booltype,false);
+ end;
+
+ _FALSE :
+ begin
+ consume(_FALSE);
+ p1:=cordconstnode.create(0,booltype,false);
+ end;
+
+ _NIL :
+ begin
+ consume(_NIL);
+ p1:=cnilnode.create;
+ { It's really ugly code nil^, but delphi allows it }
+ if token in [_CARET] then
+ begin
+ again:=true;
+ postfixoperators(p1,again);
+ end;
+ end;
+
+ else
+ begin
+ p1:=cerrornode.create;
+ consume(token);
+ Message(parser_e_illegal_expression);
+ end;
+ end;
+
+ { generate error node if no node is created }
+ if not assigned(p1) then
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'factor: p1=nil');
+{$endif}
+ p1:=cerrornode.create;
+ end;
+
+ { get the resulttype for the node }
+ if (not assigned(p1.resulttype.def)) then
+ do_resulttypepass(p1);
+
+ factor:=p1;
+ check_tokenpos;
+ end;
+{$ifdef fpc}
+ {$maxfpuregisters default}
+{$endif fpc}
+
+{****************************************************************************
+ Sub_Expr
+****************************************************************************}
+ const
+ { Warning these stay be ordered !! }
+ operator_levels:array[Toperator_precedence] of set of Ttoken=
+ ([_LT,_LTE,_GT,_GTE,_EQUAL,_UNEQUAL,_OP_IN],
+ [_PLUS,_MINUS,_OP_OR,_PIPE,_OP_XOR],
+ [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,
+ _OP_AS,_OP_IS,_OP_AND,_AMPERSAND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR],
+ [_STARSTAR] );
+
+ function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):tnode;
+ {Reads a subexpression while the operators are of the current precedence
+ level, or any higher level. Replaces the old term, simpl_expr and
+ simpl2_expr.}
+ var
+ p1,p2 : tnode;
+ oldt : Ttoken;
+ filepos : tfileposinfo;
+ begin
+ if pred_level=highest_precedence then
+ p1:=factor(false)
+ else
+ p1:=sub_expr(succ(pred_level),true);
+ repeat
+ if (token in operator_levels[pred_level]) and
+ ((token<>_EQUAL) or accept_equal) then
+ begin
+ oldt:=token;
+ filepos:=akttokenpos;
+ consume(token);
+ if pred_level=highest_precedence then
+ p2:=factor(false)
+ else
+ p2:=sub_expr(succ(pred_level),true);
+ case oldt of
+ _PLUS :
+ p1:=caddnode.create(addn,p1,p2);
+ _MINUS :
+ p1:=caddnode.create(subn,p1,p2);
+ _STAR :
+ p1:=caddnode.create(muln,p1,p2);
+ _SLASH :
+ p1:=caddnode.create(slashn,p1,p2);
+ _EQUAL :
+ p1:=caddnode.create(equaln,p1,p2);
+ _GT :
+ p1:=caddnode.create(gtn,p1,p2);
+ _LT :
+ p1:=caddnode.create(ltn,p1,p2);
+ _GTE :
+ p1:=caddnode.create(gten,p1,p2);
+ _LTE :
+ p1:=caddnode.create(lten,p1,p2);
+ _SYMDIF :
+ p1:=caddnode.create(symdifn,p1,p2);
+ _STARSTAR :
+ p1:=caddnode.create(starstarn,p1,p2);
+ _OP_AS :
+ p1:=casnode.create(p1,p2);
+ _OP_IN :
+ p1:=cinnode.create(p1,p2);
+ _OP_IS :
+ p1:=cisnode.create(p1,p2);
+ _OP_OR,
+ _PIPE {macpas only} :
+ p1:=caddnode.create(orn,p1,p2);
+ _OP_AND,
+ _AMPERSAND {macpas only} :
+ p1:=caddnode.create(andn,p1,p2);
+ _OP_DIV :
+ p1:=cmoddivnode.create(divn,p1,p2);
+ _OP_NOT :
+ p1:=cnotnode.create(p1);
+ _OP_MOD :
+ p1:=cmoddivnode.create(modn,p1,p2);
+ _OP_SHL :
+ p1:=cshlshrnode.create(shln,p1,p2);
+ _OP_SHR :
+ p1:=cshlshrnode.create(shrn,p1,p2);
+ _OP_XOR :
+ p1:=caddnode.create(xorn,p1,p2);
+ _ASSIGNMENT :
+ p1:=cassignmentnode.create(p1,p2);
+ _CARET :
+ p1:=caddnode.create(caretn,p1,p2);
+ _UNEQUAL :
+ p1:=caddnode.create(unequaln,p1,p2);
+ end;
+ p1.fileinfo:=filepos;
+ end
+ else
+ break;
+ until false;
+ sub_expr:=p1;
+ end;
+
+
+ function comp_expr(accept_equal : boolean):tnode;
+ var
+ oldafterassignment : boolean;
+ p1 : tnode;
+ begin
+ oldafterassignment:=afterassignment;
+ afterassignment:=true;
+ p1:=sub_expr(opcompare,accept_equal);
+ { get the resulttype for this expression }
+ if not assigned(p1.resulttype.def) then
+ do_resulttypepass(p1);
+ afterassignment:=oldafterassignment;
+ comp_expr:=p1;
+ end;
+
+
+ function expr : tnode;
+
+ var
+ p1,p2 : tnode;
+ oldafterassignment : boolean;
+ oldp1 : tnode;
+ filepos : tfileposinfo;
+
+ begin
+ oldafterassignment:=afterassignment;
+ p1:=sub_expr(opcompare,true);
+ { get the resulttype for this expression }
+ if not assigned(p1.resulttype.def) then
+ do_resulttypepass(p1);
+ filepos:=akttokenpos;
+ if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
+ afterassignment:=true;
+ oldp1:=p1;
+ case token of
+ _POINTPOINT :
+ begin
+ consume(_POINTPOINT);
+ p2:=sub_expr(opcompare,true);
+ p1:=crangenode.create(p1,p2);
+ end;
+ _ASSIGNMENT :
+ begin
+ consume(_ASSIGNMENT);
+ if (p1.resulttype.def.deftype=procvardef) then
+ getprocvardef:=tprocvardef(p1.resulttype.def);
+ p2:=sub_expr(opcompare,true);
+ if assigned(getprocvardef) then
+ handle_procvar(getprocvardef,p2);
+ getprocvardef:=nil;
+ p1:=cassignmentnode.create(p1,p2);
+ end;
+ _PLUSASN :
+ begin
+ consume(_PLUSASN);
+ p2:=sub_expr(opcompare,true);
+ p1:=gen_c_style_operator(addn,p1,p2);
+ end;
+ _MINUSASN :
+ begin
+ consume(_MINUSASN);
+ p2:=sub_expr(opcompare,true);
+ p1:=gen_c_style_operator(subn,p1,p2);
+ end;
+ _STARASN :
+ begin
+ consume(_STARASN );
+ p2:=sub_expr(opcompare,true);
+ p1:=gen_c_style_operator(muln,p1,p2);
+ end;
+ _SLASHASN :
+ begin
+ consume(_SLASHASN );
+ p2:=sub_expr(opcompare,true);
+ p1:=gen_c_style_operator(slashn,p1,p2);
+ end;
+ end;
+ { get the resulttype for this expression }
+ if not assigned(p1.resulttype.def) then
+ do_resulttypepass(p1);
+ afterassignment:=oldafterassignment;
+ if p1<>oldp1 then
+ p1.fileinfo:=filepos;
+ expr:=p1;
+ end;
+
+{$ifdef int64funcresok}
+ function get_intconst:TConstExprInt;
+{$else int64funcresok}
+ function get_intconst:longint;
+{$endif int64funcresok}
+ {Reads an expression, tries to evalute it and check if it is an integer
+ constant. Then the constant is returned.}
+ var
+ p:tnode;
+ begin
+ result:=0;
+ p:=comp_expr(true);
+ if not codegenerror then
+ begin
+ if (p.nodetype<>ordconstn) or
+ not(is_integer(p.resulttype.def)) then
+ Message(parser_e_illegal_expression)
+ else
+ result:=tordconstnode(p).value;
+ end;
+ p.free;
+ end;
+
+
+ function get_stringconst:string;
+ {Reads an expression, tries to evaluate it and checks if it is a string
+ constant. Then the constant is returned.}
+ var
+ p:tnode;
+ begin
+ get_stringconst:='';
+ p:=comp_expr(true);
+ if p.nodetype<>stringconstn then
+ begin
+ if (p.nodetype=ordconstn) and is_char(p.resulttype.def) then
+ get_stringconst:=char(tordconstnode(p).value)
+ else
+ Message(parser_e_illegal_expression);
+ end
+ else
+ get_stringconst:=strpas(tstringconstnode(p).value_str);
+ p.free;
+ end;
+
+end.
diff --git a/compiler/pinline.pas b/compiler/pinline.pas
new file mode 100644
index 0000000000..27bed0aab8
--- /dev/null
+++ b/compiler/pinline.pas
@@ -0,0 +1,796 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generates nodes for routines that need compiler support
+
+ 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 pinline;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symtype,
+ node,
+ globals,
+ cpuinfo;
+
+ function new_dispose_statement(is_new:boolean) : tnode;
+ function new_function : tnode;
+
+ function inline_setlength : tnode;
+ function inline_initialize : tnode;
+ function inline_finalize : tnode;
+ function inline_copy : tnode;
+
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globtype,tokens,verbose,
+ systems,
+ { symtable }
+ symconst,symdef,symsym,symtable,defutil,
+ { pass 1 }
+ pass_1,htypechk,
+ nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils,
+ { parser }
+ scanner,
+ pbase,pexpr,
+ { codegen }
+ cgbase
+ ;
+
+
+ function new_dispose_statement(is_new:boolean) : tnode;
+ var
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ para : tcallparanode;
+ p,p2 : tnode;
+ again : boolean; { dummy for do_proc_call }
+ destructorname : stringid;
+ sym : tsym;
+ classh : tobjectdef;
+ callflag : tcallnodeflag;
+ destructorpos,
+ storepos : tfileposinfo;
+ begin
+ consume(_LKLAMMER);
+ p:=comp_expr(true);
+ { calc return type }
+ if is_new then
+ set_varstate(p,vs_assigned,[])
+ else
+ set_varstate(p,vs_used,[vsf_must_be_valid]);
+ if (m_mac in aktmodeswitches) and
+ is_class(p.resulttype.def) then
+ begin
+ classh:=tobjectdef(p.resulttype.def);
+
+ if is_new then
+ begin
+ sym:=search_class_member(classh,'CREATE');
+ p2 := cloadvmtaddrnode.create(ctypenode.create(p.resulttype));;
+ end
+ else
+ begin
+ sym:=search_class_member(classh,'FREE');
+ p2 := p;
+ end;
+
+ if not(assigned(sym)) then
+ begin
+ p.free;
+ if is_new then
+ p2.free;
+ new_dispose_statement := cerrornode.create;
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ exit;
+ end;
+
+ do_member_read(classh,false,sym,p2,again,[]);
+
+ { we need the real called method }
+ do_resulttypepass(p2);
+
+ if (p2.nodetype=calln) and
+ assigned(tcallnode(p2).procdefinition) then
+ begin
+ if is_new then
+ begin
+ if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then
+ Message(parser_e_expr_have_to_be_constructor_call);
+ p2.resulttype:=p.resulttype;
+ p2:=cassignmentnode.create(p,p2);
+ resulttypepass(p2);
+ end
+ else
+ begin
+ { Free is not a destructor
+ if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then
+ Message(parser_e_expr_have_to_be_destructor_call);
+ }
+ end
+ end
+ else
+ internalerror(2005061202);
+ new_dispose_statement := p2;
+ end
+ { constructor,destructor specified }
+ else if not(m_mac in aktmodeswitches) and
+ try_to_consume(_COMMA) then
+ begin
+ { extended syntax of new and dispose }
+ { function styled new is handled in factor }
+ { destructors have no parameters }
+ destructorname:=pattern;
+ destructorpos:=akttokenpos;
+ consume(_ID);
+
+ if (p.resulttype.def.deftype<>pointerdef) then
+ begin
+ Message1(type_e_pointer_type_expected,p.resulttype.def.typename);
+ p.free;
+ p:=factor(false);
+ p.free;
+ consume(_RKLAMMER);
+ new_dispose_statement:=cerrornode.create;
+ exit;
+ end;
+ { first parameter must be an object or class }
+ if tpointerdef(p.resulttype.def).pointertype.def.deftype<>objectdef then
+ begin
+ Message(parser_e_pointer_to_class_expected);
+ p.free;
+ new_dispose_statement:=factor(false);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ exit;
+ end;
+ { check, if the first parameter is a pointer to a _class_ }
+ classh:=tobjectdef(tpointerdef(p.resulttype.def).pointertype.def);
+ if is_class(classh) then
+ begin
+ Message(parser_e_no_new_or_dispose_for_classes);
+ new_dispose_statement:=factor(false);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ exit;
+ end;
+ { search cons-/destructor, also in parent classes }
+ storepos:=akttokenpos;
+ akttokenpos:=destructorpos;
+ sym:=search_class_member(classh,destructorname);
+ akttokenpos:=storepos;
+
+ { the second parameter of new/dispose must be a call }
+ { to a cons-/destructor }
+ if (not assigned(sym)) or (sym.typ<>procsym) then
+ begin
+ if is_new then
+ Message(parser_e_expr_have_to_be_constructor_call)
+ else
+ Message(parser_e_expr_have_to_be_destructor_call);
+ p.free;
+ new_dispose_statement:=cerrornode.create;
+ end
+ else
+ begin
+ { For new(var,constructor) we need to take a copy because
+ p is also used in the assignmentn below }
+ if is_new then
+ p2:=cderefnode.create(p.getcopy)
+ else
+ p2:=cderefnode.create(p);
+ do_resulttypepass(p2);
+ if is_new then
+ callflag:=cnf_new_call
+ else
+ callflag:=cnf_dispose_call;
+ if is_new then
+ do_member_read(classh,false,sym,p2,again,[callflag])
+ else
+ begin
+ if not(m_fpc in aktmodeswitches) then
+ do_member_read(classh,false,sym,p2,again,[callflag])
+ else
+ begin
+ p2:=ccallnode.create(nil,tprocsym(sym),sym.owner,p2,[callflag]);
+ { support dispose(p,done()); }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ if not try_to_consume(_RKLAMMER) then
+ begin
+ Message(parser_e_no_paras_for_destructor);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ end;
+ end;
+ end;
+ end;
+
+ { we need the real called method }
+ do_resulttypepass(p2);
+
+ if (p2.nodetype=calln) and
+ assigned(tcallnode(p2).procdefinition) then
+ begin
+ if is_new then
+ begin
+ if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then
+ Message(parser_e_expr_have_to_be_constructor_call);
+ p2.resulttype:=p.resulttype;
+ p2:=cassignmentnode.create(p,p2);
+ end
+ else
+ begin
+ if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then
+ Message(parser_e_expr_have_to_be_destructor_call);
+ end;
+ end
+ else
+ begin
+ if is_new then
+ CGMessage(parser_e_expr_have_to_be_constructor_call)
+ else
+ CGMessage(parser_e_expr_have_to_be_destructor_call);
+ end;
+
+ result:=p2;
+ end;
+ end
+ else
+ begin
+ if (p.resulttype.def.deftype<>pointerdef) then
+ Begin
+ Message1(type_e_pointer_type_expected,p.resulttype.def.typename);
+ new_dispose_statement:=cerrornode.create;
+ end
+ else
+ begin
+ if (tpointerdef(p.resulttype.def).pointertype.def.deftype=objectdef) and
+ (oo_has_vmt in tobjectdef(tpointerdef(p.resulttype.def).pointertype.def).objectoptions) then
+ Message(parser_w_use_extended_syntax_for_objects);
+ if (tpointerdef(p.resulttype.def).pointertype.def.deftype=orddef) and
+ (torddef(tpointerdef(p.resulttype.def).pointertype.def).typ=uvoid) then
+ begin
+ if (m_tp7 in aktmodeswitches) or
+ (m_delphi in aktmodeswitches) then
+ Message(parser_w_no_new_dispose_on_void_pointers)
+ else
+ Message(parser_e_no_new_dispose_on_void_pointers);
+ end;
+
+ { create statements with call to getmem+initialize or
+ finalize+freemem }
+ new_dispose_statement:=internalstatements(newstatement);
+
+ if is_new then
+ begin
+ { create temp for result }
+ temp := ctempcreatenode.create(p.resulttype,p.resulttype.def.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ { create call to fpc_getmem }
+ para := ccallparanode.create(cordconstnode.create
+ (tpointerdef(p.resulttype.def).pointertype.def.size,s32inttype,true),nil);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(temp),
+ ccallnode.createintern('fpc_getmem',para)));
+
+ { create call to fpc_initialize }
+ if tpointerdef(p.resulttype.def).pointertype.def.needs_inittable then
+ addstatement(newstatement,initialize_data_node(cderefnode.create(ctemprefnode.create(temp))));
+
+ { copy the temp to the destination }
+ addstatement(newstatement,cassignmentnode.create(
+ p,
+ ctemprefnode.create(temp)));
+
+ { release temp }
+ addstatement(newstatement,ctempdeletenode.create(temp));
+ end
+ else
+ begin
+ { create call to fpc_finalize }
+ if tpointerdef(p.resulttype.def).pointertype.def.needs_inittable then
+ addstatement(newstatement,finalize_data_node(cderefnode.create(p.getcopy)));
+
+ { create call to fpc_freemem }
+ para := ccallparanode.create(p,nil);
+ addstatement(newstatement,ccallnode.createintern('fpc_freemem',para));
+ end;
+ end;
+ end;
+ consume(_RKLAMMER);
+ end;
+
+
+ function new_function : tnode;
+ var
+ newstatement : tstatementnode;
+ newblock : tblocknode;
+ temp : ttempcreatenode;
+ para : tcallparanode;
+ p1,p2 : tnode;
+ classh : tobjectdef;
+ sym : tsym;
+ again : boolean; { dummy for do_proc_call }
+ begin
+ consume(_LKLAMMER);
+ p1:=factor(false);
+ if p1.nodetype<>typen then
+ begin
+ Message(type_e_type_id_expected);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ p1.destroy;
+ new_function:=cerrornode.create;
+ exit;
+ end;
+
+ if (p1.resulttype.def.deftype<>pointerdef) then
+ begin
+ Message1(type_e_pointer_type_expected,p1.resulttype.def.typename);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ p1.destroy;
+ new_function:=cerrornode.create;
+ exit;
+ end;
+
+ if try_to_consume(_RKLAMMER) then
+ begin
+ if (tpointerdef(p1.resulttype.def).pointertype.def.deftype=objectdef) and
+ (oo_has_vmt in tobjectdef(tpointerdef(p1.resulttype.def).pointertype.def).objectoptions) then
+ Message(parser_w_use_extended_syntax_for_objects);
+
+ { create statements with call to getmem+initialize }
+ newblock:=internalstatements(newstatement);
+
+ { create temp for result }
+ temp := ctempcreatenode.create(p1.resulttype,p1.resulttype.def.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ { create call to fpc_getmem }
+ para := ccallparanode.create(cordconstnode.create
+ (tpointerdef(p1.resulttype.def).pointertype.def.size,s32inttype,true),nil);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(temp),
+ ccallnode.createintern('fpc_getmem',para)));
+
+ { create call to fpc_initialize }
+ if tpointerdef(p1.resulttype.def).pointertype.def.needs_inittable then
+ begin
+ para := ccallparanode.create(caddrnode.create_internal(crttinode.create
+ (tstoreddef(tpointerdef(p1.resulttype.def).pointertype.def),initrtti)),
+ ccallparanode.create(ctemprefnode.create
+ (temp),nil));
+ addstatement(newstatement,ccallnode.createintern('fpc_initialize',para));
+ end;
+
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+
+ p1.destroy;
+ p1:=newblock;
+ end
+ else
+ begin
+ consume(_COMMA);
+ if tpointerdef(p1.resulttype.def).pointertype.def.deftype<>objectdef then
+ begin
+ Message(parser_e_pointer_to_class_expected);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ p1.destroy;
+ new_function:=cerrornode.create;
+ exit;
+ end;
+ classh:=tobjectdef(tpointerdef(p1.resulttype.def).pointertype.def);
+ { use the objectdef for loading the VMT }
+ p2:=p1;
+ p1:=ctypenode.create(tpointerdef(p1.resulttype.def).pointertype);
+ do_resulttypepass(p1);
+ { search the constructor also in the symbol tables of
+ the parents }
+ afterassignment:=false;
+ sym:=searchsym_in_class(classh,pattern);
+ consume(_ID);
+ do_member_read(classh,false,sym,p1,again,[cnf_new_call]);
+ { we need to know which procedure is called }
+ do_resulttypepass(p1);
+ if not(
+ (p1.nodetype=calln) and
+ assigned(tcallnode(p1).procdefinition) and
+ (tcallnode(p1).procdefinition.proctypeoption=potype_constructor)
+ ) then
+ Message(parser_e_expr_have_to_be_constructor_call);
+ { constructors return boolean, update resulttype to return
+ the pointer to the object }
+ p1.resulttype:=p2.resulttype;
+ p2.free;
+ consume(_RKLAMMER);
+ end;
+ new_function:=p1;
+ end;
+
+
+ function inline_setlength : tnode;
+ var
+ paras : tnode;
+ npara,
+ ppn : tcallparanode;
+ dims,
+ counter : integer;
+ isarray : boolean;
+ def : tdef;
+ destppn : tnode;
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ newblock : tnode;
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ consume(_LKLAMMER);
+ paras:=parse_paras(false,_RKLAMMER);
+ consume(_RKLAMMER);
+ if not assigned(paras) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ exit;
+ end;
+
+ dims:=0;
+ if assigned(paras) then
+ begin
+ { check type of lengths }
+ ppn:=tcallparanode(paras);
+ while assigned(ppn.right) do
+ begin
+ set_varstate(ppn.left,vs_used,[vsf_must_be_valid]);
+ inserttypeconv(ppn.left,sinttype);
+ inc(dims);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ end;
+ if dims=0 then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ paras.free;
+ exit;
+ end;
+ { last param must be var }
+ destppn:=ppn.left;
+ inc(parsing_para_level);
+ valid_for_var(destppn);
+ set_varstate(destppn,vs_assigned,[]);
+ dec(parsing_para_level);
+ { first param must be a string or dynamic array ...}
+ isarray:=is_dynamic_array(destppn.resulttype.def);
+ if not((destppn.resulttype.def.deftype=stringdef) or
+ isarray) then
+ begin
+ CGMessage(type_e_mismatch);
+ paras.free;
+ exit;
+ end;
+
+ { only dynamic arrays accept more dimensions }
+ if (dims>1) then
+ begin
+ if (not isarray) then
+ CGMessage(type_e_mismatch)
+ else
+ begin
+ { check if the amount of dimensions is valid }
+ def := tarraydef(destppn.resulttype.def).elementtype.def;
+ counter:=dims;
+ while counter > 1 do
+ begin
+ if not(is_dynamic_array(def)) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ break;
+ end;
+ dec(counter);
+ def := tarraydef(def).elementtype.def;
+ end;
+ end;
+ end;
+
+ if isarray then
+ begin
+ { create statements with call initialize the arguments and
+ call fpc_dynarr_setlength }
+ newblock:=internalstatements(newstatement);
+
+ { get temp for array of lengths }
+ temp := ctempcreatenode.create(sinttype,dims*sinttype.def.size,tt_persistent,false);
+ addstatement(newstatement,temp);
+
+ { load array of lengths }
+ ppn:=tcallparanode(paras);
+ counter:=0;
+ while assigned(ppn.right) do
+ begin
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create_offset(temp,counter*sinttype.def.size),
+ ppn.left));
+ ppn.left:=nil;
+ inc(counter);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ { destppn is also reused }
+ ppn.left:=nil;
+
+ { create call to fpc_dynarr_setlength }
+ npara:=ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp)),
+ ccallparanode.create(cordconstnode.create
+ (counter,s32inttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(destppn.resulttype.def),initrtti)),
+ ccallparanode.create(ctypeconvnode.create_internal(destppn,voidpointertype),nil))));
+ addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',npara));
+ addstatement(newstatement,ctempdeletenode.create(temp));
+
+ { we don't need original the callparanodes tree }
+ paras.free;
+ end
+ else
+ begin
+ { we can reuse the supplied parameters }
+ newblock:=ccallnode.createintern(
+ 'fpc_'+tstringdef(destppn.resulttype.def).stringtypname+'_setlength',paras);
+ end;
+
+ result.free;
+ result:=newblock;
+ end;
+
+
+ function inline_initialize : tnode;
+ var
+ newblock,
+ paras : tnode;
+ ppn : tcallparanode;
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ consume(_LKLAMMER);
+ paras:=parse_paras(false,_RKLAMMER);
+ consume(_RKLAMMER);
+ if not assigned(paras) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ exit;
+ end;
+
+ ppn:=tcallparanode(paras);
+ { 2 arguments? }
+ if assigned(ppn.right) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ paras.free;
+ exit;
+ end;
+
+ newblock:=initialize_data_node(ppn.left);
+ ppn.left:=nil;
+
+ paras.free;
+ result.free;
+ result:=newblock;
+ end;
+
+
+ function inline_finalize : tnode;
+ var
+ newblock,
+ paras : tnode;
+ npara,
+ destppn,
+ ppn : tcallparanode;
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ consume(_LKLAMMER);
+ paras:=parse_paras(false,_RKLAMMER);
+ consume(_RKLAMMER);
+ if not assigned(paras) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ exit;
+ end;
+
+ ppn:=tcallparanode(paras);
+ { 2 arguments? }
+ if assigned(ppn.right) then
+ begin
+ destppn:=tcallparanode(ppn.right);
+ { 3 arguments is invalid }
+ if assigned(destppn.right) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ paras.free;
+ exit;
+ end;
+ { create call to fpc_finalize_array }
+ npara:=ccallparanode.create(cordconstnode.create
+ (destppn.left.resulttype.def.size,s32inttype,true),
+ ccallparanode.create(ctypeconvnode.create
+ (ppn.left,s32inttype),
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(destppn.left.resulttype.def),initrtti)),
+ ccallparanode.create(caddrnode.create_internal
+ (destppn.left),nil))));
+ newblock:=ccallnode.createintern('fpc_finalize_array',npara);
+ destppn.left:=nil;
+ ppn.left:=nil;
+ end
+ else
+ begin
+ newblock:=finalize_data_node(ppn.left);
+ ppn.left:=nil;
+ end;
+ paras.free;
+ result.free;
+ result:=newblock;
+ end;
+
+
+ function inline_copy : tnode;
+ var
+ copynode,
+ lowppn,
+ highppn,
+ npara,
+ paras : tnode;
+ ppn : tcallparanode;
+ paradef : tdef;
+ counter : integer;
+{$ifdef ansistring_bits}
+ mode : byte;
+{$endif ansistring_bits}
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ consume(_LKLAMMER);
+ paras:=parse_paras(false,_RKLAMMER);
+ consume(_RKLAMMER);
+ if not assigned(paras) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ exit;
+ end;
+
+ { determine copy function to use based on the first argument,
+ also count the number of arguments in this loop }
+ counter:=1;
+ ppn:=tcallparanode(paras);
+ while assigned(ppn.right) do
+ begin
+ inc(counter);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ paradef:=ppn.left.resulttype.def;
+{$ifdef ansistring_bits}
+ if is_ansistring(paradef) then
+ case Tstringdef(paradef).string_typ of
+ st_ansistring16:
+ mode:=16;
+ st_ansistring32:
+ mode:=32;
+ st_ansistring64:
+ mode:=64;
+ end;
+ if (is_chararray(paradef) and (paradef.size>255)) or
+ ((cs_ansistrings in aktlocalswitches) and is_pchar(paradef)) then
+ case aktansistring_bits of
+ sb_16:
+ mode:=16;
+ sb_32:
+ mode:=32;
+ sb_64:
+ mode:=64;
+ end;
+ if mode=16 then
+ copynode:=ccallnode.createintern('fpc_ansistr16_copy',paras)
+ else if mode=32 then
+ copynode:=ccallnode.createintern('fpc_ansistr32_copy',paras)
+ else if mode=64 then
+ copynode:=ccallnode.createintern('fpc_ansistr64_copy',paras)
+{$else}
+ if is_ansistring(paradef) or
+ (is_chararray(paradef) and
+ (paradef.size>255)) or
+ ((cs_ansistrings in aktlocalswitches) and
+ is_pchar(paradef)) then
+ copynode:=ccallnode.createintern('fpc_ansistr_copy',paras)
+{$endif}
+ else
+ if is_widestring(paradef) or
+ is_widechararray(paradef) or
+ is_pwidechar(paradef) then
+ copynode:=ccallnode.createintern('fpc_widestr_copy',paras)
+ else
+ if is_char(paradef) then
+ copynode:=ccallnode.createintern('fpc_char_copy',paras)
+ else
+ if is_dynamic_array(paradef) then
+ begin
+ { Only allow 1 or 3 arguments }
+ if (counter<>1) and (counter<>3) then
+ begin
+ CGMessage(parser_e_wrong_parameter_size);
+ exit;
+ end;
+
+ { create statements with call }
+
+ if (counter=3) then
+ begin
+ highppn:=tcallparanode(paras).left.getcopy;
+ lowppn:=tcallparanode(tcallparanode(paras).right).left.getcopy;
+ end
+ else
+ begin
+ { use special -1,-1 argument to copy the whole array }
+ highppn:=cordconstnode.create(-1,s32inttype,false);
+ lowppn:=cordconstnode.create(-1,s32inttype,false);
+ end;
+
+ { create call to fpc_dynarray_copy }
+ npara:=ccallparanode.create(highppn,
+ ccallparanode.create(lowppn,
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(ppn.left.resulttype.def),initrtti)),
+ ccallparanode.create
+ (ctypeconvnode.create_internal(ppn.left,voidpointertype),nil))));
+ copynode:=ccallnode.createinternres('fpc_dynarray_copy',npara,ppn.left.resulttype);
+
+ ppn.left:=nil;
+ paras.free;
+ end
+ else
+ begin
+ { generic fallback that will give an error if a wrong
+ type is passed }
+ copynode:=ccallnode.createintern('fpc_shortstr_copy',paras)
+ end;
+
+ result.free;
+ result:=copynode;
+ end;
+
+end.
diff --git a/compiler/pmodules.pas b/compiler/pmodules.pas
new file mode 100644
index 0000000000..5128a68646
--- /dev/null
+++ b/compiler/pmodules.pas
@@ -0,0 +1,1564 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Handles the parsing and loading of the modules (ppufiles)
+
+ 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 pmodules;
+
+{$i fpcdefs.inc}
+
+interface
+
+ procedure proc_unit;
+ procedure proc_program(islibrary : boolean);
+
+
+implementation
+
+ uses
+ globtype,version,systems,tokens,
+ cutils,cclasses,comphook,
+ globals,verbose,fmodule,finput,fppu,
+ symconst,symbase,symtype,symdef,symsym,symtable,
+ aasmtai,aasmcpu,aasmbase,
+ cgbase,cgobj,
+ nbas,ncgutil,
+ link,assemble,import,export,gendef,ppu,comprsrc,dbgbase,
+ cresstr,procinfo,
+ dwarf,pexports,
+ scanner,pbase,pexpr,psystem,psub,pdecsub;
+
+
+ procedure create_objectfile;
+ var
+ DLLScanner : TDLLScanner;
+ s : string;
+ KeepShared : TStringList;
+ begin
+ { try to create import entries from system dlls }
+ if target_info.DllScanSupported and
+ (not current_module.linkOtherSharedLibs.Empty) then
+ begin
+ { Init DLLScanner }
+ if assigned(CDLLScanner[target_info.system]) then
+ DLLScanner:=CDLLScanner[target_info.system].Create
+ else
+ internalerror(200104121);
+ KeepShared:=TStringList.Create;
+ { Walk all shared libs }
+ While not current_module.linkOtherSharedLibs.Empty do
+ begin
+ S:=current_module.linkOtherSharedLibs.Getusemask(link_allways);
+ if not DLLScanner.scan(s) then
+ KeepShared.Concat(s);
+ end;
+ DLLscanner.Free;
+ { Recreate import section }
+ if (target_info.system in [system_i386_win32,system_i386_wdosx]) then
+ begin
+ if assigned(asmlist[al_imports]) then
+ asmlist[al_imports].clear
+ else
+ asmlist[al_imports]:=taasmoutput.Create;
+ importlib.generatelib;
+ end;
+ { Readd the not processed files }
+ while not KeepShared.Empty do
+ begin
+ s:=KeepShared.GetFirst;
+ current_module.linkOtherSharedLibs.add(s,link_allways);
+ end;
+ KeepShared.Free;
+ end;
+
+ { Start and end module debuginfo, at least required for stabs
+ to insert n_sourcefile lines }
+ if (cs_debuginfo in aktmoduleswitches) or
+ (cs_use_lineinfo in aktglobalswitches) then
+ debuginfo.insertmoduleinfo;
+
+ { create the .s file and assemble it }
+ GenerateAsm(false);
+
+ { Also create a smartlinked version ? }
+ if (cs_create_smart in aktmoduleswitches) and
+ not(af_smartlink_sections in target_asm.flags) then
+ begin
+ { regenerate the importssection for win32 }
+ if assigned(asmlist[al_imports]) and
+ (target_info.system in [system_i386_win32,system_i386_wdosx, system_arm_wince,system_i386_wince]) then
+ begin
+ asmlist[al_imports].clear;
+ importlib.generatesmartlib;
+ end;
+
+ GenerateAsm(true);
+ if (af_needar in target_asm.flags) then
+ Linker.MakeStaticLibrary;
+ end;
+
+ { resource files }
+ CompileResourceFiles;
+ end;
+
+
+ procedure insertobjectfile;
+ { Insert the used object file for this unit in the used list for this unit }
+ begin
+ current_module.linkunitofiles.add(current_module.objfilename^,link_static);
+ current_module.flags:=current_module.flags or uf_static_linked;
+
+ if (cs_create_smart in aktmoduleswitches) and
+ not(af_smartlink_sections in target_asm.flags) then
+ begin
+ current_module.linkunitstaticlibs.add(current_module.staticlibfilename^,link_smart);
+ current_module.flags:=current_module.flags or uf_smart_linked;
+ end;
+ end;
+
+
+ procedure create_dwarf;
+ begin
+ asmlist[al_dwarf]:=taasmoutput.create;
+ { Call frame information }
+ if (tf_needs_dwarf_cfi in target_info.flags) and
+ (af_supports_dwarf in target_asm.flags) then
+ dwarfcfi.generate_code(asmlist[al_dwarf]);
+ end;
+
+
+{$ifndef segment_threadvars}
+ procedure InsertThreadvarTablesTable;
+ var
+ hp : tused_unit;
+ ltvTables : taasmoutput;
+ count : longint;
+ begin
+ ltvTables:=TAAsmOutput.Create;
+ count:=0;
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ If (hp.u.flags and uf_threadvars)=uf_threadvars then
+ begin
+ ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',hp.u.globalsymtable,''),AT_DATA,0));
+ inc(count);
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+ { Add program threadvars, if any }
+ If (current_module.flags and uf_threadvars)=uf_threadvars then
+ begin
+ ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',current_module.localsymtable,''),AT_DATA,0));
+ inc(count);
+ end;
+ { Insert TableCount at start }
+ ltvTables.insert(Tai_const.Create_32bit(count));
+ { insert in data segment }
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_data,'FPC_THREADVARTABLES',sizeof(aint));
+ asmlist[al_globals].concat(Tai_symbol.Createname_global('FPC_THREADVARTABLES',AT_DATA,0));
+ asmlist[al_globals].concatlist(ltvTables);
+ asmlist[al_globals].concat(Tai_symbol_end.Createname('FPC_THREADVARTABLES'));
+ ltvTables.free;
+ end;
+
+ procedure AddToThreadvarList(p:tnamedindexitem;arg:pointer);
+ var
+ ltvTable : taasmoutput;
+ begin
+ ltvTable:=taasmoutput(arg);
+ if (tsym(p).typ=globalvarsym) and
+ (vo_is_thread_var in tglobalvarsym(p).varoptions) then
+ begin
+ { address of threadvar }
+ ltvTable.concat(tai_const.Createname(tglobalvarsym(p).mangledname,AT_DATA,0));
+ { size of threadvar }
+ ltvTable.concat(tai_const.create_32bit(tglobalvarsym(p).getsize));
+ end;
+ end;
+
+
+ procedure InsertThreadvars;
+ var
+ s : string;
+ ltvTable : TAAsmoutput;
+ begin
+ ltvTable:=TAAsmoutput.create;
+ if assigned(current_module.globalsymtable) then
+ current_module.globalsymtable.foreach_static(@AddToThreadvarList,ltvTable);
+ current_module.localsymtable.foreach_static(@AddToThreadvarList,ltvTable);
+ if ltvTable.first<>nil then
+ begin
+ s:=make_mangledname('THREADVARLIST',current_module.localsymtable,'');
+ { end of the list marker }
+ ltvTable.concat(tai_const.create_sym(nil));
+ { add to datasegment }
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_data,s,sizeof(aint));
+ asmlist[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
+ asmlist[al_globals].concatlist(ltvTable);
+ asmlist[al_globals].concat(Tai_symbol_end.Createname(s));
+ current_module.flags:=current_module.flags or uf_threadvars;
+ end;
+ ltvTable.Free;
+ end;
+{$endif}
+
+ Procedure InsertResourceInfo;
+
+ var
+ hp : tused_unit;
+ found : Boolean;
+ I : Integer;
+ ResourceInfo : taasmoutput;
+
+ begin
+ if target_res.id=res_elf then
+ begin
+ hp:=tused_unit(usedunits.first);
+ found:=false;
+ Found:=((current_module.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
+ If not found then
+ While Assigned(hp) and not Found do
+ begin
+ Found:=((hp.u.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
+ hp:=tused_unit(hp.next);
+ end;
+ ResourceInfo:=TAAsmOutput.Create;
+ if found then
+ begin
+ { Valid pointer to resource information }
+ ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESLOCATION',AT_DATA,0));
+ ResourceInfo.concat(Tai_const.Createname('FPC_RESSYMBOL',AT_DATA,0));
+{$ifdef EXTERNALRESPTRS}
+ current_module.linkotherofiles.add('resptrs.o',link_allways);
+{$else EXTERNALRESPTRS}
+ new_section(ResourceInfo,sec_fpc,'resptrs',4);
+ ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESSYMBOL',AT_DATA,0));
+ For I:=1 to 32 do
+ ResourceInfo.Concat(Tai_const.Create_32bit(0));
+{$endif EXTERNALRESPTRS}
+ end
+ else
+ begin
+ { Nil pointer to resource information }
+ ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESLOCATION',AT_DATA,0));
+ ResourceInfo.Concat(Tai_const.Create_32bit(0));
+ end;
+ maybe_new_object_file(asmlist[al_globals]);
+ asmlist[al_globals].concatlist(ResourceInfo);
+ ResourceInfo.free;
+ end;
+ end;
+
+ Procedure InsertResourceTablesTable;
+ var
+ hp : tused_unit;
+ ResourceStringTables : taasmoutput;
+ count : longint;
+ begin
+ ResourceStringTables:=TAAsmOutput.Create;
+ count:=0;
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ If (hp.u.flags and uf_has_resources)=uf_has_resources then
+ begin
+ ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',hp.u.globalsymtable,''),AT_DATA,0));
+ inc(count);
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+ { Add program resources, if any }
+ If resourcestrings.ResStrCount>0 then
+ begin
+ ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',current_module.localsymtable,''),AT_DATA,0));
+ Inc(Count);
+ end;
+ { Insert TableCount at start }
+ ResourceStringTables.insert(Tai_const.Create_32bit(count));
+ { Add to data segment }
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_data,'FPC_RESOURCESTRINGTABLES',sizeof(aint));
+ asmlist[al_globals].concat(Tai_symbol.Createname_global('FPC_RESOURCESTRINGTABLES',AT_DATA,0));
+ asmlist[al_globals].concatlist(ResourceStringTables);
+ asmlist[al_globals].concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
+ ResourceStringTables.free;
+ end;
+
+
+ procedure InsertInitFinalTable;
+ var
+ hp : tused_unit;
+ unitinits : taasmoutput;
+ count : longint;
+ begin
+ unitinits:=TAAsmOutput.Create;
+ count:=0;
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ { call the unit init code and make it external }
+ if (hp.u.flags and (uf_init or uf_finalize))<>0 then
+ begin
+ if (hp.u.flags and uf_init)<>0 then
+ unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',hp.u.globalsymtable,''),AT_FUNCTION,0))
+ else
+ unitinits.concat(Tai_const.Create_sym(nil));
+ if (hp.u.flags and uf_finalize)<>0 then
+ unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',hp.u.globalsymtable,''),AT_FUNCTION,0))
+ else
+ unitinits.concat(Tai_const.Create_sym(nil));
+ inc(count);
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+ { Insert initialization/finalization of the program }
+ if (current_module.flags and (uf_init or uf_finalize))<>0 then
+ begin
+ if (current_module.flags and uf_init)<>0 then
+ unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',current_module.localsymtable,''),AT_FUNCTION,0))
+ else
+ unitinits.concat(Tai_const.Create_sym(nil));
+ if (current_module.flags and uf_finalize)<>0 then
+ unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',current_module.localsymtable,''),AT_FUNCTION,0))
+ else
+ unitinits.concat(Tai_const.Create_sym(nil));
+ inc(count);
+ end;
+ { Insert TableCount,InitCount at start }
+ unitinits.insert(Tai_const.Create_32bit(0));
+ unitinits.insert(Tai_const.Create_32bit(count));
+ { Add to data segment }
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_data,'INITFINAL',sizeof(aint));
+ asmlist[al_globals].concat(Tai_symbol.Createname_global('INITFINAL',AT_DATA,0));
+ asmlist[al_globals].concatlist(unitinits);
+ asmlist[al_globals].concat(Tai_symbol_end.Createname('INITFINAL'));
+ unitinits.free;
+ end;
+
+
+ procedure insertmemorysizes;
+ begin
+ { stacksize can be specified and is now simulated }
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_data,'__stklen',4);
+ asmlist[al_globals].concat(Tai_symbol.Createname_global('__stklen',AT_DATA,4));
+ asmlist[al_globals].concat(Tai_const.Create_32bit(stacksize));
+ { Initial heapsize }
+ maybe_new_object_file(asmlist[al_globals]);
+ new_section(asmlist[al_globals],sec_data,'__heapsize',4);
+ asmlist[al_globals].concat(Tai_symbol.Createname_global('__heapsize',AT_DATA,4));
+ asmlist[al_globals].concat(Tai_const.Create_32bit(heapsize));
+ end;
+
+
+
+ procedure AddUnit(const s:string);
+ var
+ hp : tppumodule;
+ unitsym : tunitsym;
+ begin
+ { load unit }
+ hp:=registerunit(current_module,s,'');
+ hp.loadppu;
+ hp.adddependency(current_module);
+ { add to symtable stack }
+ tsymtable(hp.globalsymtable).next:=symtablestack;
+ symtablestack:=hp.globalsymtable;
+ if (m_mac in aktmodeswitches) and assigned(hp.globalmacrosymtable) then
+ begin
+ tsymtable(hp.globalmacrosymtable).next:=macrosymtablestack;
+ macrosymtablestack:=hp.globalmacrosymtable;
+ end;
+ { insert unitsym }
+ unitsym:=tunitsym.create(s,hp.globalsymtable);
+ inc(unitsym.refs);
+ refsymtable.insert(unitsym);
+ { add to used units }
+ current_module.addusedunit(hp,false,unitsym);
+ end;
+
+
+ procedure maybeloadvariantsunit;
+ var
+ hp : tmodule;
+ begin
+ { Do we need the variants unit? Skip this
+ for VarUtils unit for bootstrapping }
+ if (current_module.flags and uf_uses_variants=0) or
+ (current_module.modulename^='VARUTILS') then
+ exit;
+ { Variants unit already loaded? }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.modulename^='VARIANTS' then
+ exit;
+ hp:=tmodule(hp.next);
+ end;
+ { Variants unit is not loaded yet, load it now }
+ Message(parser_w_implicit_uses_of_variants_unit);
+ AddUnit('Variants');
+ end;
+
+
+ procedure loaddefaultunits;
+ begin
+ { are we compiling the system unit? }
+ if (cs_compilesystem in aktmoduleswitches) then
+ begin
+ { create system defines }
+ createconstdefs;
+ { we don't need to reset anything, it's already done in parser.pas }
+ exit;
+ end;
+ { insert the system unit, it is allways the first }
+ symtablestack:=nil;
+ macrosymtablestack:=initialmacrosymtable;
+ AddUnit('System');
+ SystemUnit:=TGlobalSymtable(Symtablestack);
+ { read default constant definitions }
+ make_ref:=false;
+ readconstdefs;
+ make_ref:=true;
+ { Set the owner of errorsym and errortype to symtable to
+ prevent crashes when accessing .owner }
+ generrorsym.owner:=systemunit;
+ generrortype.def.owner:=systemunit;
+ { Units only required for main module }
+ { load heaptrace before any other units especially objpas }
+ if not(current_module.is_unit) then
+ begin
+ { Heaptrc unit }
+ if (cs_use_heaptrc in aktglobalswitches) then
+ AddUnit('HeapTrc');
+ { Lineinfo unit }
+ if (cs_use_lineinfo in aktglobalswitches) then
+ AddUnit('LineInfo');
+ { Lineinfo unit }
+ if (cs_gdb_valgrind in aktglobalswitches) then
+ AddUnit('CMem');
+{$ifdef cpufpemu}
+ { Floating point emulation unit? }
+ if (cs_fp_emulation in aktmoduleswitches) and not(target_info.system in system_wince) then
+ AddUnit('SoftFpu');
+{$endif cpufpemu}
+ end;
+ { Objpas unit? }
+ if m_objpas in aktmodeswitches then
+ AddUnit('ObjPas');
+ { Macpas unit? }
+ if m_mac in aktmodeswitches then
+ AddUnit('MacPas');
+ { Profile unit? Needed for go32v2 only }
+ if (cs_profile in aktmoduleswitches) and
+ (target_info.system in [system_i386_go32v2,system_i386_watcom]) then
+ AddUnit('Profile');
+ if (cs_load_fpcylix_unit in aktglobalswitches) then
+ begin
+ AddUnit('FPCylix');
+ AddUnit('DynLibs');
+ end;
+ { save default symtablestack }
+ defaultsymtablestack:=symtablestack;
+ defaultmacrosymtablestack:=macrosymtablestack;
+ end;
+
+
+ procedure loadautounits;
+ var
+ hs,s : string;
+ begin
+ hs:=autoloadunits;
+ repeat
+ s:=GetToken(hs,',');
+ if s='' then
+ break;
+ AddUnit(s);
+ until false;
+ end;
+
+
+ procedure loadunits;
+ var
+ s,sorg : stringid;
+ fn : string;
+ pu : tused_unit;
+ hp2 : tmodule;
+ hp3 : tsymtable;
+ unitsym : tunitsym;
+ top_of_macrosymtable : tsymtable;
+
+ begin
+ consume(_USES);
+{$ifdef DEBUG}
+ test_symtablestack;
+{$endif DEBUG}
+ repeat
+ s:=pattern;
+ sorg:=orgpattern;
+ consume(_ID);
+ { support "<unit> in '<file>'" construct, but not for tp7 }
+ if not(m_tp7 in aktmodeswitches) then
+ begin
+ if try_to_consume(_OP_IN) then
+ fn:=FixFileName(get_stringconst)
+ else
+ fn:='';
+ end;
+ { Give a warning if objpas is loaded }
+ if s='OBJPAS' then
+ Message(parser_w_no_objpas_use_mode);
+ { Using the unit itself is not possible }
+ if (s<>current_module.modulename^) then
+ begin
+ { check if the unit is already used }
+ hp2:=nil;
+ pu:=tused_unit(current_module.used_units.first);
+ while assigned(pu) do
+ begin
+ if (pu.u.modulename^=s) then
+ begin
+ hp2:=pu.u;
+ break;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ if not assigned(hp2) then
+ hp2:=registerunit(current_module,sorg,fn)
+ else
+ Message1(sym_e_duplicate_id,s);
+ { Create unitsym, we need to use the name as specified, we
+ can not use the modulename because that can be different
+ when -Un is used }
+ unitsym:=tunitsym.create(sorg,nil);
+ refsymtable.insert(unitsym);
+ { the current module uses the unit hp2 }
+ current_module.addusedunit(hp2,true,unitsym);
+ end
+ else
+ Message1(sym_e_duplicate_id,s);
+ if token=_COMMA then
+ begin
+ pattern:='';
+ consume(_COMMA);
+ end
+ else
+ break;
+ until false;
+
+ { Load the units }
+ top_of_macrosymtable:= macrosymtablestack;
+ pu:=tused_unit(current_module.used_units.first);
+ while assigned(pu) do
+ begin
+ { Only load the units that are in the current
+ (interface/implementation) uses clause }
+ if pu.in_uses and
+ (pu.in_interface=current_module.in_interface) then
+ begin
+ tppumodule(pu.u).loadppu;
+ { is our module compiled? then we can stop }
+ if current_module.state=ms_compiled then
+ exit;
+ { add this unit to the dependencies }
+ pu.u.adddependency(current_module);
+ { save crc values }
+ pu.checksum:=pu.u.crc;
+ pu.interface_checksum:=pu.u.interface_crc;
+ { connect unitsym to the globalsymtable of the unit }
+ pu.unitsym.unitsymtable:=pu.u.globalsymtable;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+
+ { set the symtable to systemunit so it gets reorderd correctly,
+ then insert the units in the symtablestack }
+ pu:=tused_unit(current_module.used_units.first);
+ symtablestack:=defaultsymtablestack;
+ macrosymtablestack:=defaultmacrosymtablestack;
+ while assigned(pu) do
+ begin
+ if pu.in_uses then
+ begin
+ { Reinsert in symtablestack }
+ hp3:=symtablestack;
+ while assigned(hp3) do
+ begin
+ { insert units only once ! }
+ if pu.u.globalsymtable=hp3 then
+ break;
+ hp3:=hp3.next;
+ { unit isn't inserted }
+ if hp3=nil then
+ begin
+ tsymtable(pu.u.globalsymtable).next:=symtablestack;
+ symtablestack:=tsymtable(pu.u.globalsymtable);
+ if (m_mac in aktmodeswitches) and assigned(pu.u.globalmacrosymtable) then
+ begin
+ tsymtable(pu.u.globalmacrosymtable).next:=macrosymtablestack;
+ macrosymtablestack:=tsymtable(pu.u.globalmacrosymtable);
+ end;
+{$ifdef DEBUG}
+ test_symtablestack;
+{$endif DEBUG}
+ end;
+ end;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+
+ if assigned (current_module.globalmacrosymtable) then
+ top_of_macrosymtable.next.next:= macrosymtablestack
+ else
+ top_of_macrosymtable.next:= macrosymtablestack;
+ macrosymtablestack:= top_of_macrosymtable;
+ consume(_SEMICOLON);
+ end;
+
+
+ procedure reset_all_defs;
+
+ procedure reset_used_unit_defs(hp:tmodule);
+ var
+ pu : tused_unit;
+ begin
+ pu:=tused_unit(hp.used_units.first);
+ while assigned(pu) do
+ begin
+ if not pu.u.is_reset then
+ begin
+ { prevent infinte loop for circular dependencies }
+ pu.u.is_reset:=true;
+ if assigned(pu.u.globalsymtable) then
+ begin
+ tglobalsymtable(pu.u.globalsymtable).reset_all_defs;
+ reset_used_unit_defs(pu.u);
+ end;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ end;
+
+ var
+ hp2 : tmodule;
+ begin
+ hp2:=tmodule(loaded_units.first);
+ while assigned(hp2) do
+ begin
+ hp2.is_reset:=false;
+ hp2:=tmodule(hp2.next);
+ end;
+ reset_used_unit_defs(current_module);
+ end;
+
+
+ procedure free_localsymtables(st:tsymtable);
+ var
+ def : tstoreddef;
+ pd : tprocdef;
+ begin
+ def:=tstoreddef(st.defindex.first);
+ while assigned(def) do
+ begin
+ if def.deftype=procdef then
+ begin
+ pd:=tprocdef(def);
+ if assigned(pd.localst) and
+ (pd.localst.symtabletype<>staticsymtable) and
+ not((po_inline in pd.procoptions) or
+ ((current_module.flags and uf_local_browser)<>0)) then
+ begin
+ free_localsymtables(pd.localst);
+ pd.localst.free;
+ pd.localst:=nil;
+ end;
+ end;
+ def:=tstoreddef(def.indexnext);
+ end;
+ end;
+
+
+ procedure parse_implementation_uses;
+ begin
+ if token=_USES then
+ begin
+ loadunits;
+{$ifdef DEBUG}
+ test_symtablestack;
+{$endif DEBUG}
+ end;
+ end;
+
+
+ procedure setupglobalswitches;
+ begin
+ { can't have local browser when no global browser }
+ if (cs_local_browser in aktmoduleswitches) and
+ not(cs_browser in aktmoduleswitches) then
+ exclude(aktmoduleswitches,cs_local_browser);
+ if (cs_create_pic in aktmoduleswitches) then
+ def_system_macro('FPC_PIC');
+ end;
+
+
+ function create_main_proc(const name:string;potype:tproctypeoption;st:tsymtable):tprocdef;
+ var
+ stt : tsymtable;
+ ps : tprocsym;
+ pd : tprocdef;
+ begin
+ { there should be no current_procinfo available }
+ if assigned(current_procinfo) then
+ internalerror(200304275);
+ {Generate a procsym for main}
+ make_ref:=false;
+ { try to insert in in static symtable ! }
+ stt:=symtablestack;
+ symtablestack:=st;
+ { generate procsym }
+ ps:=tprocsym.create('$'+name);
+ { main are allways used }
+ inc(ps.refs);
+ symtablestack.insert(ps);
+ pd:=tprocdef.create(main_program_level);
+ include(pd.procoptions,po_global);
+ pd.procsym:=ps;
+ ps.addprocdef(pd);
+ { restore symtable }
+ make_ref:=true;
+ symtablestack:=stt;
+ { set procdef options }
+ pd.proctypeoption:=potype;
+ pd.proccalloption:=pocall_default;
+ pd.forwarddef:=false;
+ pd.setmangledname(target_info.cprefix+name);
+ pd.aliasnames.insert(pd.mangledname);
+ handle_calling_convention(pd);
+ { We don't need is a local symtable. Change it into the static
+ symtable }
+ pd.localst.free;
+ pd.localst:=st;
+ { set procinfo and current_procinfo.procdef }
+ current_procinfo:=cprocinfo.create(nil);
+ current_module.procinfo:=current_procinfo;
+ current_procinfo.procdef:=pd;
+ { return procdef }
+ create_main_proc:=pd;
+ { main proc does always a call e.g. to init system unit }
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure release_main_proc(pd:tprocdef);
+ begin
+ { this is a main proc, so there should be no parent }
+ if not(assigned(current_procinfo)) or
+ assigned(current_procinfo.parent) or
+ not(current_procinfo.procdef=pd) then
+ internalerror(200304276);
+ { remove procinfo }
+ current_module.procinfo:=nil;
+ current_procinfo.free;
+ current_procinfo:=nil;
+ { remove localst as it was replaced by staticsymtable }
+ pd.localst:=nil;
+ end;
+
+
+ procedure gen_implicit_initfinal(flag:word;st:tsymtable);
+ var
+ pd : tprocdef;
+ begin
+ { update module flags }
+ current_module.flags:=current_module.flags or flag;
+ { create procdef }
+ case flag of
+ uf_init :
+ begin
+ pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'init_implicit'),potype_unitinit,st);
+ pd.aliasnames.insert(make_mangledname('INIT$',current_module.localsymtable,''));
+ end;
+ uf_finalize :
+ begin
+ pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize_implicit'),potype_unitfinalize,st);
+ pd.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
+ end;
+ else
+ internalerror(200304253);
+ end;
+ tcgprocinfo(current_procinfo).code:=cnothingnode.create;
+ tcgprocinfo(current_procinfo).generate_code;
+ release_main_proc(pd);
+ end;
+
+ procedure delete_duplicate_macros(p:TNamedIndexItem; arg:pointer);
+ var
+ hp: tsymentry;
+ begin
+ hp:= current_module.localmacrosymtable.search(p.name);
+ if assigned(hp) then
+ current_module.localmacrosymtable.delete(hp);
+ end;
+
+ procedure proc_unit;
+
+ function is_assembler_generated:boolean;
+ var
+ hal : tasmlist;
+ begin
+ result:=false;
+ if Errorcount=0 then
+ begin
+ for hal:=low(Tasmlist) to high(Tasmlist) do
+ if not asmlist[hal].empty then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+
+ var
+ main_file: tinputfile;
+ st : tsymtable;
+ unitst : tglobalsymtable;
+{$ifdef EXTDEBUG}
+ store_crc,
+{$endif EXTDEBUG}
+ store_interface_crc : cardinal;
+ s1,s2 : ^string; {Saves stack space}
+ force_init_final : boolean;
+ pd : tprocdef;
+ unitname8 : string[8];
+ has_impl,ag: boolean;
+ begin
+ if m_mac in aktmodeswitches then
+ begin
+ ConsolidateMode;
+ current_module.mode_switch_allowed:= false;
+ end;
+
+ consume(_UNIT);
+ if compile_level=1 then
+ Status.IsExe:=false;
+
+ if token=_ID then
+ begin
+ { create filenames and unit name }
+ main_file := current_scanner.inputfile;
+ while assigned(main_file.next) do
+ main_file := main_file.next;
+
+ new(s1);
+ s1^:=current_module.modulename^;
+ current_module.SetFileName(main_file.path^+main_file.name^,true);
+ current_module.SetModuleName(orgpattern);
+
+ { check for system unit }
+ new(s2);
+ s2^:=upper(SplitName(main_file.name^));
+ unitname8:=copy(current_module.modulename^,1,8);
+ if (cs_check_unit_name in aktglobalswitches) and
+ (
+ not(
+ (current_module.modulename^=s2^) or
+ (
+ (length(current_module.modulename^)>8) and
+ (unitname8=s2^)
+ )
+ )
+ or
+ (
+ (length(s1^)>8) and
+ (s1^<>current_module.modulename^)
+ )
+ ) then
+ Message1(unit_e_illegal_unit_name,current_module.realmodulename^);
+ if (current_module.modulename^='SYSTEM') then
+ include(aktmoduleswitches,cs_compilesystem);
+ dispose(s2);
+ dispose(s1);
+ end;
+
+ if (target_info.system in system_unit_program_exports) then
+ exportlib.preparelib(current_module.realmodulename^);
+
+ consume(_ID);
+ consume(_SEMICOLON);
+ consume(_INTERFACE);
+ { global switches are read, so further changes aren't allowed }
+ current_module.in_global:=false;
+
+ { handle the global switches }
+ ConsolidateMode;
+ setupglobalswitches;
+
+ message1(unit_u_loading_interface_units,current_module.modulename^);
+
+ { update status }
+ status.currentmodule:=current_module.realmodulename^;
+
+ { maybe turn off m_objpas if we are compiling objpas }
+ if (current_module.modulename^='OBJPAS') then
+ exclude(aktmodeswitches,m_objpas);
+
+ { maybe turn off m_mac if we are compiling macpas }
+ if (current_module.modulename^='MACPAS') then
+ exclude(aktmodeswitches,m_mac);
+
+ parse_only:=true;
+
+ { generate now the global symboltable }
+ st:=tglobalsymtable.create(current_module.modulename^,current_module.moduleid);
+ refsymtable:=st;
+ unitst:=tglobalsymtable(st);
+ { define first as local to overcome dependency conflicts }
+ current_module.localsymtable:=st;
+
+ { the unit name must be usable as a unit specifier }
+ { inside the unit itself (PM) }
+ { this also forbids to have another symbol }
+ { with the same name as the unit }
+ refsymtable.insert(tunitsym.create(current_module.realmodulename^,unitst));
+
+ macrosymtablestack:= initialmacrosymtable;
+
+ { load default units, like the system unit }
+ loaddefaultunits;
+
+ current_module.localmacrosymtable.next:=macrosymtablestack;
+ if assigned(current_module.globalmacrosymtable) then
+ begin
+ current_module.globalmacrosymtable.next:= current_module.localmacrosymtable;
+ macrosymtablestack:=current_module.globalmacrosymtable;
+ end
+ else
+ macrosymtablestack:=current_module.localmacrosymtable;
+
+ { reset }
+ make_ref:=true;
+
+ { insert qualifier for the system unit (allows system.writeln) }
+ if not(cs_compilesystem in aktmoduleswitches) then
+ begin
+ if token=_USES then
+ begin
+ loadunits;
+ { has it been compiled at a higher level ?}
+ if current_module.state=ms_compiled then
+ exit;
+ end;
+ { ... but insert the symbol table later }
+ st.next:=symtablestack;
+ symtablestack:=st;
+ end
+ else
+ { while compiling a system unit, some types are directly inserted }
+ begin
+ st.next:=symtablestack;
+ symtablestack:=st;
+ insert_intern_types(st);
+ end;
+
+ { now we know the place to insert the constants }
+ constsymtable:=symtablestack;
+
+ { move the global symtab from the temporary local to global }
+ current_module.globalsymtable:=current_module.localsymtable;
+ current_module.localsymtable:=nil;
+
+ reset_all_defs;
+
+ { number all units, so we know if a unit is used by this unit or
+ needs to be added implicitly }
+ current_module.updatemaps;
+
+ { ... parse the declarations }
+ Message1(parser_u_parsing_interface,current_module.realmodulename^);
+ read_interface_declarations;
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ { Our interface is compiled, generate CRC and switch to implementation }
+ if not(cs_compilesystem in aktmoduleswitches) and
+ (Errorcount=0) then
+ tppumodule(current_module).getppucrc;
+ current_module.in_interface:=false;
+ current_module.interface_compiled:=true;
+
+ { First reload all units depending on our interface, we need to do this
+ in the implementation part to prevent errorneous circular references }
+ reload_flagged_units;
+
+ { Parse the implementation section }
+ if (m_mac in aktmodeswitches) and try_to_consume(_END) then
+ has_impl:= false
+ else
+ has_impl:= true;
+
+ parse_only:=false;
+
+ { generates static symbol table }
+ st:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
+ current_module.localsymtable:=st;
+
+ { Swap the positions of the local and global macro sym table}
+ if assigned(current_module.globalmacrosymtable) then
+ begin
+ macrosymtablestack:=current_module.localmacrosymtable;
+ current_module.globalmacrosymtable.next:= current_module.localmacrosymtable.next;
+ current_module.localmacrosymtable.next:=current_module.globalmacrosymtable;
+
+ current_module.globalmacrosymtable.foreach_static(@delete_duplicate_macros, nil);
+ end;
+
+ { remove the globalsymtable from the symtable stack }
+ { to reinsert it after loading the implementation units }
+ symtablestack:=unitst.next;
+
+ { we don't want implementation units symbols in unitsymtable !! PM }
+ refsymtable:=st;
+
+ if has_impl then
+ begin
+ consume(_IMPLEMENTATION);
+ Message1(unit_u_loading_implementation_units,current_module.modulename^);
+ { Read the implementation units }
+ parse_implementation_uses;
+ end;
+
+ if current_module.state=ms_compiled then
+ exit;
+
+ { reset ranges/stabs in exported definitions }
+ reset_all_defs;
+
+ { All units are read, now give them a number }
+ current_module.updatemaps;
+
+ { now we can change refsymtable }
+ refsymtable:=st;
+
+ { but reinsert the global symtable as lasts }
+ unitst.next:=symtablestack;
+ symtablestack:=unitst;
+
+{$ifdef DEBUG}
+ test_symtablestack;
+{$endif DEBUG}
+ constsymtable:=symtablestack;
+
+ if has_impl then
+ begin
+ Message1(parser_u_parsing_implementation,current_module.modulename^);
+ if current_module.in_interface then
+ internalerror(200212285);
+
+ { Compile the unit }
+ pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'init'),potype_unitinit,st);
+ pd.aliasnames.insert(make_mangledname('INIT$',current_module.localsymtable,''));
+ tcgprocinfo(current_procinfo).parse_body;
+ tcgprocinfo(current_procinfo).generate_code;
+ tcgprocinfo(current_procinfo).resetprocdef;
+ { save file pos for debuginfo }
+ current_module.mainfilepos:=current_procinfo.entrypos;
+ release_main_proc(pd);
+ end;
+
+ { if the unit contains ansi/widestrings, initialization and
+ finalization code must be forced }
+ force_init_final:=tglobalsymtable(current_module.globalsymtable).needs_init_final or
+ tstaticsymtable(current_module.localsymtable).needs_init_final;
+
+ { should we force unit initialization? }
+ { this is a hack, but how can it be done better ? }
+ if force_init_final and ((current_module.flags and uf_init)=0) then
+ gen_implicit_initfinal(uf_init,st);
+ { finalize? }
+ if has_impl and (token=_FINALIZATION) then
+ begin
+ { set module options }
+ current_module.flags:=current_module.flags or uf_finalize;
+
+ { Compile the finalize }
+ pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,st);
+ pd.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
+ tcgprocinfo(current_procinfo).parse_body;
+ tcgprocinfo(current_procinfo).generate_code;
+ tcgprocinfo(current_procinfo).resetprocdef;
+ release_main_proc(pd);
+ end
+ else if force_init_final then
+ gen_implicit_initfinal(uf_finalize,st);
+
+ { the last char should always be a point }
+ consume(_POINT);
+
+ { Generate resoucestrings }
+ If resourcestrings.ResStrCount>0 then
+ begin
+ resourcestrings.CreateResourceStringList;
+ current_module.flags:=current_module.flags or uf_has_resources;
+ { only write if no errors found }
+ if (Errorcount=0) then
+ resourcestrings.WriteResourceFile(ForceExtension(current_module.ppufilename^,'.rst'));
+ end;
+
+ if (Errorcount=0) then
+ begin
+ { tests, if all (interface) forwards are resolved }
+ tstoredsymtable(symtablestack).check_forwards;
+ { check if all private fields are used }
+ tstoredsymtable(symtablestack).allprivatesused;
+ { remove cross unit overloads }
+ tstoredsymtable(symtablestack).unchain_overloaded;
+
+ { test static symtable }
+ tstoredsymtable(st).allsymbolsused;
+ tstoredsymtable(st).allprivatesused;
+ tstoredsymtable(st).check_forwards;
+ tstoredsymtable(st).checklabels;
+ tstoredsymtable(st).unchain_overloaded;
+
+ { used units }
+ current_module.allunitsused;
+ end;
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ { do we need to add the variants unit? }
+ maybeloadvariantsunit;
+
+ { generate debuginfo }
+ if (cs_debuginfo in aktmoduleswitches) then
+ debuginfo.inserttypeinfo;
+
+ { generate wrappers for interfaces }
+ gen_intf_wrappers(asmlist[al_procedures],current_module.globalsymtable);
+ gen_intf_wrappers(asmlist[al_procedures],current_module.localsymtable);
+
+ { generate a list of threadvars }
+{$ifndef segment_threadvars}
+ InsertThreadvars;
+{$endif}
+
+ { generate imports }
+ if current_module.uses_imports then
+ importlib.generatelib;
+
+ { insert own objectfile, or say that it's in a library
+ (no check for an .o when loading) }
+ ag:=is_assembler_generated;
+ if ag then
+ insertobjectfile
+ else
+ begin
+ current_module.flags:=current_module.flags or uf_no_link;
+ current_module.flags:=current_module.flags and not uf_has_debuginfo;
+ end;
+
+ if cs_local_browser in aktmoduleswitches then
+ current_module.localsymtable:=refsymtable;
+
+ if ag then
+ begin
+ { create dwarf debuginfo }
+ create_dwarf;
+ { finish asmlist by adding segment starts }
+// insertsegment;
+ { assemble }
+ create_objectfile;
+ end;
+
+ { Write out the ppufile after the object file has been created }
+ store_interface_crc:=current_module.interface_crc;
+{$ifdef EXTDEBUG}
+ store_crc:=current_module.crc;
+{$endif EXTDEBUG}
+ if (Errorcount=0) then
+ tppumodule(current_module).writeppu;
+
+ if not(cs_compilesystem in aktmoduleswitches) then
+ if store_interface_crc<>current_module.interface_crc then
+ Message1(unit_u_interface_crc_changed,current_module.ppufilename^);
+{$ifdef EXTDEBUG}
+ if not(cs_compilesystem in aktmoduleswitches) then
+ if (store_crc<>current_module.crc) and simplify_ppu then
+ Message1(unit_u_implementation_crc_changed,current_module.ppufilename^);
+{$endif EXTDEBUG}
+
+ { release all overload references and local symtables that
+ are not needed anymore }
+ tstoredsymtable(current_module.localsymtable).unchain_overloaded;
+ tstoredsymtable(current_module.globalsymtable).unchain_overloaded;
+ free_localsymtables(current_module.globalsymtable);
+ free_localsymtables(current_module.localsymtable);
+
+ { remove static symtable (=refsymtable) here to save some mem, possible references
+ (like procsym overloads) should already have been freed above }
+ if not (cs_local_browser in aktmoduleswitches) then
+ begin
+ st.free;
+ current_module.localsymtable:=nil;
+ end;
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ Message1(unit_u_finished_compiling,current_module.modulename^);
+ end;
+
+
+ procedure proc_program(islibrary : boolean);
+ var
+ main_file : tinputfile;
+ st : tsymtable;
+ hp,hp2 : tmodule;
+ pd : tprocdef;
+ begin
+ DLLsource:=islibrary;
+ Status.IsLibrary:=IsLibrary;
+ Status.IsExe:=true;
+ parse_only:=false;
+
+ { DLL defaults to create reloc info }
+ if islibrary then
+ begin
+ if not RelocSectionSetExplicitly then
+ RelocSection:=true;
+ end;
+
+ { relocation works only without stabs under win32 !! PM }
+ { internal assembler uses rva for stabs info
+ so it should work with relocated DLLs }
+ if RelocSection and
+ (target_info.system in [system_i386_win32,system_i386_wdosx]) and
+ (target_info.assem<>as_i386_pecoff) then
+ begin
+ include(aktglobalswitches,cs_link_strip);
+ { Warning stabs info does not work with reloc section !! }
+ if cs_debuginfo in aktmoduleswitches then
+ begin
+ Message1(parser_w_parser_reloc_no_debug,current_module.mainsource^);
+ Message(parser_w_parser_win32_debug_needs_WN);
+ exclude(aktmoduleswitches,cs_debuginfo);
+ end;
+ end;
+
+ { get correct output names }
+ main_file := current_scanner.inputfile;
+ while assigned(main_file.next) do
+ main_file := main_file.next;
+
+ current_module.SetFileName(main_file.path^+main_file.name^,true);
+
+ if islibrary then
+ begin
+ consume(_LIBRARY);
+ stringdispose(current_module.modulename);
+ stringdispose(current_module.realmodulename);
+ current_module.modulename:=stringdup(pattern);
+ current_module.realmodulename:=stringdup(orgpattern);
+ current_module.islibrary:=true;
+ exportlib.preparelib(orgpattern);
+
+ if tf_library_needs_pic in target_info.flags then
+ include(aktmoduleswitches,cs_create_pic);
+
+ consume(_ID);
+ consume(_SEMICOLON);
+ end
+ else
+ { is there an program head ? }
+ if token=_PROGRAM then
+ begin
+ consume(_PROGRAM);
+ stringdispose(current_module.modulename);
+ stringdispose(current_module.realmodulename);
+ current_module.modulename:=stringdup(pattern);
+ current_module.realmodulename:=stringdup(orgpattern);
+ if (target_info.system in system_unit_program_exports) then
+ exportlib.preparelib(orgpattern);
+ consume(_ID);
+ if token=_LKLAMMER then
+ begin
+ consume(_LKLAMMER);
+ repeat
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ consume(_RKLAMMER);
+ end;
+ consume(_SEMICOLON);
+ end
+ else if (target_info.system in system_unit_program_exports) then
+ exportlib.preparelib(current_module.realmodulename^);
+
+ { global switches are read, so further changes aren't allowed }
+ current_module.in_global:=false;
+
+ { setup things using the switches }
+ ConsolidateMode;
+ setupglobalswitches;
+
+ { set implementation flag }
+ current_module.in_interface:=false;
+ current_module.interface_compiled:=true;
+
+ { insert after the unit symbol tables the static symbol table }
+ { of the program }
+ st:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
+ current_module.localsymtable:=st;
+ refsymtable:=st;
+
+ macrosymtablestack:= nil;
+
+ { load standard units (system,objpas,profile unit) }
+ loaddefaultunits;
+
+ current_module.localmacrosymtable.next:=macrosymtablestack;
+ macrosymtablestack:=current_module.localmacrosymtable;
+
+ { Load units provided on the command line }
+ loadautounits;
+
+ {Load the units used by the program we compile.}
+ if token=_USES then
+ loadunits;
+
+ { reset ranges/stabs in exported definitions }
+ reset_all_defs;
+
+ { All units are read, now give them a number }
+ current_module.updatemaps;
+
+ {Insert the name of the main program into the symbol table.}
+ if current_module.realmodulename^<>'' then
+ st.insert(tunitsym.create(current_module.realmodulename^,st));
+
+ { ...is also constsymtable, this is the symtable where }
+ { the elements of enumeration types are inserted }
+ constsymtable:=st;
+
+ Message1(parser_u_parsing_implementation,current_module.mainsource^);
+
+ { The program intialization needs an alias, so it can be called
+ from the bootstrap code.}
+
+ if islibrary then
+ begin
+ pd:=create_main_proc(make_mangledname('',current_module.localsymtable,mainaliasname),potype_proginit,st);
+ { Win32 startup code needs a single name }
+// if (target_info.system in [system_i386_win32,system_i386_wdosx]) then
+ pd.aliasnames.insert('PASCALMAIN');
+ end
+ else if (target_info.system = system_i386_netware) or
+ (target_info.system = system_i386_netwlibc) then
+ begin
+ pd:=create_main_proc('PASCALMAIN',potype_proginit,st); { main is need by the netware rtl }
+ end
+ else
+ begin
+ pd:=create_main_proc(mainaliasname,potype_proginit,st);
+ pd.aliasnames.insert('PASCALMAIN');
+ end;
+ tcgprocinfo(current_procinfo).parse_body;
+ tcgprocinfo(current_procinfo).generate_code;
+ tcgprocinfo(current_procinfo).resetprocdef;
+ { save file pos for debuginfo }
+ current_module.mainfilepos:=current_procinfo.entrypos;
+ release_main_proc(pd);
+
+ { should we force unit initialization? }
+ if tstaticsymtable(current_module.localsymtable).needs_init_final then
+ begin
+ { initialize section }
+ gen_implicit_initfinal(uf_init,st);
+ { finalize section }
+ gen_implicit_initfinal(uf_finalize,st);
+ end;
+
+ { Add symbol to the exports section for win32 so smartlinking a
+ DLL will include the edata section }
+ if assigned(exportlib) and
+ (target_info.system in [system_i386_win32,system_i386_wdosx]) and
+ BinaryContainsExports then
+ asmlist[al_procedures].concat(tai_const.create_sym(exportlib.edatalabel));
+
+ If resourcestrings.ResStrCount>0 then
+ begin
+ resourcestrings.CreateResourceStringList;
+ { only write if no errors found }
+ if (Errorcount=0) then
+ resourcestrings.WriteResourceFile(ForceExtension(current_module.ppufilename^,'.rst'));
+ end;
+
+ { finalize? }
+ if token=_FINALIZATION then
+ begin
+ { set module options }
+ current_module.flags:=current_module.flags or uf_finalize;
+
+ { Compile the finalize }
+ pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,st);
+ pd.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
+ tcgprocinfo(current_procinfo).parse_body;
+ tcgprocinfo(current_procinfo).generate_code;
+ tcgprocinfo(current_procinfo).resetprocdef;
+ release_main_proc(pd);
+ end;
+
+ { consume the last point }
+ consume(_POINT);
+
+ if (Errorcount=0) then
+ begin
+ { test static symtable }
+ tstoredsymtable(st).allsymbolsused;
+ tstoredsymtable(st).allprivatesused;
+ tstoredsymtable(st).check_forwards;
+ tstoredsymtable(st).checklabels;
+ tstoredsymtable(st).unchain_overloaded;
+ current_module.allunitsused;
+ end;
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ { remove all unused units, this happends when units are removed
+ from the uses clause in the source and the ppu was already being loaded }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ hp2:=hp;
+ hp:=tmodule(hp.next);
+ if hp2.is_unit and
+ not assigned(hp2.globalsymtable) then
+ loaded_units.remove(hp2);
+ end;
+
+ { do we need to add the variants unit? }
+ maybeloadvariantsunit;
+
+ { generate debuginfo }
+ if (cs_debuginfo in aktmoduleswitches) then
+ debuginfo.inserttypeinfo;
+
+ { generate wrappers for interfaces }
+ gen_intf_wrappers(asmlist[al_procedures],current_module.localsymtable);
+
+{$ifndef segment_threadvars}
+ { generate a list of threadvars }
+ InsertThreadvars;
+{$endif}
+
+ { generate imports }
+ if current_module.uses_imports then
+ importlib.generatelib;
+
+ if islibrary or
+ (target_info.system in [system_i386_WIN32,system_i386_wdosx]) or
+ (target_info.system=system_i386_NETWARE) then
+ exportlib.generatelib;
+
+ { insert Tables and StackLength }
+{$ifndef segment_threadvars}
+ insertThreadVarTablesTable;
+{$endif}
+ insertResourceTablesTable;
+ insertinitfinaltable;
+ insertmemorysizes;
+ { Insert symbol to resource info }
+
+ InsertResourceInfo;
+
+ { create dwarf debuginfo }
+ create_dwarf;
+
+ { finish asmlist by adding segment starts }
+// insertsegment;
+
+ { insert own objectfile }
+ insertobjectfile;
+
+ { assemble and link }
+ create_objectfile;
+
+ { release all local symtables that are not needed anymore }
+ free_localsymtables(current_module.localsymtable);
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ { create the executable when we are at level 1 }
+ if (compile_level=1) then
+ begin
+ { insert all .o files from all loaded units }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ linker.AddModuleFiles(hp);
+ hp:=tmodule(hp.next);
+ end;
+ { write .def file }
+ if (cs_link_deffile in aktglobalswitches) then
+ deffile.writefile;
+ { finally we can create a executable }
+ if (not current_module.is_unit) then
+ begin
+ if DLLSource then
+ linker.MakeSharedLibrary
+ else
+ linker.MakeExecutable;
+ BinaryContainsExports:=false;
+ end;
+ end;
+ end;
+
+end.
diff --git a/compiler/powerpc/aasmcpu.pas b/compiler/powerpc/aasmcpu.pas
new file mode 100644
index 0000000000..341d5b1580
--- /dev/null
+++ b/compiler/powerpc/aasmcpu.pas
@@ -0,0 +1,508 @@
+{
+ Copyright (c) 1999-2002 by Jonas Maebe
+
+ Contains the assembler object for the PowerPC
+
+ 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;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,verbose,
+ aasmbase,aasmtai,
+ cpubase,cgbase,cgutils;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 1;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 0;
+
+
+ type
+ taicpu = class(tai_cpu_abstract)
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : 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: aint);
+ constructor op_const_reg(op:tasmop; _op1: aint; _op2: tregister);
+
+ constructor op_const_const(op : tasmop;_op1,_op2 : aint);
+
+ 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: aint);
+ constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+ constructor op_const_reg_reg(op : tasmop;_op1 : aint;_op2, _op3 : tregister);
+ constructor op_const_reg_const(op : tasmop;_op1 : aint;_op2 : tregister;_op3 : aint);
+ constructor op_const_const_const(op : tasmop;_op1 : aint;_op2 : aint;_op3 : aint);
+
+ constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+ constructor op_reg_bool_reg_reg(op : tasmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
+ constructor op_reg_bool_reg_const(op : tasmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: aint);
+
+ constructor op_reg_reg_reg_const_const(op : tasmop;_op1,_op2,_op3 : tregister;_op4,_op5 : aint);
+ constructor op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : aint);
+
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ constructor op_const_const_sym(op : tasmop;_op1,_op2 : aint;_op3: tasmsymbol);
+
+
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint);
+ constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : aint);
+ constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint;const _op2 : treference);
+
+ procedure loadbool(opidx:aint;_b:boolean);
+
+
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ { register spilling code }
+ function spilling_get_operation_type(opnr: aint): topertype;override;
+ function spilling_get_operation_type_ref(opnr: aint; reg: tregister): topertype;override;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+
+ function spilling_create_load(const ref:treference;r:tregister): tai;
+ function spilling_create_store(r:tregister; const ref:treference): tai;
+
+ procedure fixup_jmps(list: taasmoutput);
+
+implementation
+
+uses cutils, cclasses;
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+ procedure taicpu.loadbool(opidx:aint;_b:boolean);
+ begin
+ if opidx>=ops then
+ ops:=opidx+1;
+ with oper[opidx]^ do
+ begin
+ if typ=top_ref then
+ dispose(ref);
+ b:=_b;
+ typ:=top_bool;
+ end;
+ end;
+
+
+ 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_const(op : tasmop;_op1 : aint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(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_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+ constructor taicpu.op_const_reg(op:tasmop; _op1: aint; _op2: tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ 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_const_const(op : tasmop;_op1,_op2 : aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(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_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: aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadsymbol(0,_op3,_op3ofs);
+ 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_const_reg_reg(op : tasmop;_op1 : aint;_op2, _op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+ constructor taicpu.op_const_reg_const(op : tasmop;_op1 : aint;_op2 : tregister;_op3 : aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_const_const(op : tasmop;_op1 : aint;_op2 : aint;_op3 : aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ loadconst(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadreg(3,_op4);
+ end;
+
+ constructor taicpu.op_reg_bool_reg_reg(op : tasmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadbool(1,_op2);
+ loadreg(2,_op3);
+ loadreg(3,_op4);
+ end;
+
+ constructor taicpu.op_reg_bool_reg_const(op : tasmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: aint);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadbool(0,_op2);
+ loadreg(0,_op3);
+ loadconst(0,cardinal(_op4));
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg_const_const(op : tasmop;_op1,_op2,_op3 : tregister;_op4,_op5 : aint);
+ begin
+ inherited create(op);
+ ops:=5;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadconst(3,cardinal(_op4));
+ loadconst(4,cardinal(_op5));
+ end;
+
+ constructor taicpu.op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : aint);
+ begin
+ inherited create(op);
+ ops:=5;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,_op3);
+ loadconst(3,_op4);
+ loadconst(4,_op5);
+ 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_const_const_sym(op : tasmop;_op1,_op2 : aint; _op3: tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ loadsymbol(2,_op3,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:aint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+
+ constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : aint);
+ 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:aint;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
+ result :=
+ (((opcode=A_MR) and
+ (regtype = R_INTREGISTER)) or
+ ((opcode = A_FMR) and
+ (regtype = R_FPUREGISTER))) and
+ { these opcodes can only have registers as operands }
+ (oper[0]^.reg=oper[1]^.reg);
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: aint): topertype;
+ begin
+ result := operand_read;
+ case opcode of
+ A_STMW,A_LMW:
+ internalerror(2005021805);
+ A_STBU, A_STBUX, A_STHU, A_STHUX, A_STWU, A_STWUX, A_STFSU, A_STFSUX, A_STFDU, A_STFDUX, A_STB, A_STBX, A_STH, A_STHX, A_STW, A_STWX, A_STFS, A_STFSX, A_STFD, A_STFDX, A_STFIWX, A_STHBRX, A_STWBRX, A_STWCX_, A_CMP, A_CMPI, A_CMPL, A_CMPLI, A_DCBA, A_DCBI, A_DCBST, A_DCBT, A_DCBTST, A_DCBZ, A_ECOWX, A_FCMPO, A_FCMPU, A_MTMSR, A_TLBIE, A_TW, A_TWI, A_CMPWI, A_CMPW, A_CMPLWI, A_CMPLW, A_MT, A_MTLR, A_MTCTR:;
+ else
+ if opnr = 0 then
+ result := operand_write;
+ end;
+ end;
+
+
+ function taicpu.spilling_get_operation_type_ref(opnr: aint; reg: tregister): topertype;
+ begin
+ result := operand_read;
+ case opcode of
+ A_STBU, A_STBUX, A_STHU, A_STHUX, A_STWU, A_STWUX, A_STFSU, A_STFSUX, A_STFDU, A_STFDUX:
+ if (oper[opnr]^.ref^.base = reg) then
+ result := operand_readwrite;
+ end;
+ end;
+
+ function spilling_create_load(const ref:treference;r:tregister): tai;
+ begin
+ result:=taicpu.op_reg_ref(A_LWZ,r,ref);
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference): tai;
+ begin
+ result:=taicpu.op_reg_ref(A_STW,r,ref);
+ end;
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+
+ procedure fixup_jmps(list: taasmoutput);
+ var
+ p: tai;
+ newjmp: taicpu;
+ labelpositions: tlist;
+ instrpos: ptrint;
+ l: tasmlabel;
+ inserted_something: boolean;
+ begin
+ // if certainly not enough instructions to cause an overflow, don't bother
+ if (list.count <= (high(smallint) div 4)) then
+ exit;
+ labelpositions := tlist.create;
+ p := tai(list.first);
+ instrpos := 1;
+ // record label positions
+ while assigned(p) do
+ begin
+ if p.typ = ait_label then
+ begin
+ if (tai_label(p).l.labelnr > labelpositions.count) then
+ labelpositions.count := tai_label(p).l.labelnr * 2;
+ labelpositions[tai_label(p).l.labelnr] := pointer(instrpos);
+ end;
+ if p.typ = ait_instruction then
+ inc(instrpos);
+ p := tai(p.next);
+ end;
+
+ // check and fix distances
+ repeat
+ inserted_something := false;
+ p := tai(list.first);
+ instrpos := 1;
+ while assigned(p) do
+ begin
+ case p.typ of
+ ait_label:
+ // update labelposition in case it changed due to insertion
+ // of jumps
+ begin
+ // can happen because of newly inserted labels
+ if (tai_label(p).l.labelnr > labelpositions.count) then
+ labelpositions.count := tai_label(p).l.labelnr * 2;
+ labelpositions[tai_label(p).l.labelnr] := pointer(instrpos);
+ end;
+ ait_instruction:
+ begin
+ inc(instrpos);
+ case taicpu(p).opcode of
+ A_BC:
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ assigned(taicpu(p).oper[0]^.ref^.symbol) and
+ (taicpu(p).oper[0]^.ref^.symbol is tasmlabel) and
+ (labelpositions[tasmlabel(taicpu(p).oper[0]^.ref^.symbol).labelnr] <> NIL) and
+ (ptruint(abs(ptrint(labelpositions[tasmlabel(taicpu(p).oper[0]^.ref^.symbol).labelnr]-instrpos)) - (low(smallint) div 4)) > ptruint((high(smallint) - low(smallint)) div 4)) then
+ begin
+ // add a new label after this jump
+ objectlibrary.getjumplabel(l);
+ list.insertafter(tai_label.create(l),p);
+ // add a new unconditional jump between this jump and the label
+ newjmp := taicpu.op_sym(A_B,taicpu(p).oper[0]^.ref^.symbol);
+ newjmp.is_jmp := true;
+ newjmp.fileinfo := taicpu(p).fileinfo;
+ list.insertafter(newjmp,p);
+ inc(instrpos);
+ // change the conditional jump to point to the newly inserted label
+ tasmlabel(taicpu(p).oper[0]^.ref^.symbol).decrefs;
+ taicpu(p).oper[0]^.ref^.symbol := l;
+ l.increfs;
+ // and invert its condition code
+ taicpu(p).condition := inverse_cond(taicpu(p).condition);
+ // we inserted an instruction, so will have to check everything again
+ inserted_something := true;
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next);
+ end;
+ until not inserted_something;
+ labelpositions.free;
+ end;
+
+
+begin
+ cai_align:=tai_align;
+ cai_cpu:=taicpu;
+end.
diff --git a/compiler/powerpc/agppcgas.pas b/compiler/powerpc/agppcgas.pas
new file mode 100644
index 0000000000..a3662774e3
--- /dev/null
+++ b/compiler/powerpc/agppcgas.pas
@@ -0,0 +1,376 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asm for the PowerPC
+
+ 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 GNU Assembler writer for the PowerPC
+}
+
+unit agppcgas;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,
+ aasmtai,
+ aggas,
+ cpubase;
+
+ type
+ PPPCGNUAssembler=^TPPCGNUAssembler;
+ TPPCGNUAssembler=class(TGNUassembler)
+ function sectionname(atype:tasmsectiontype;const aname:string):string;override;
+ procedure WriteExtraHeader;override;
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+
+ implementation
+
+ uses
+ cutils,globals,verbose,globtype,
+ cgbase,cgutils,systems,
+ assemble,
+ itcpugas,
+ aasmcpu;
+
+ procedure TPPCGNUAssembler.WriteExtraHeader;
+ var
+ i : longint;
+ begin
+ if (target_info.system <> system_powerpc_darwin) then
+ begin
+ for i:=0 to 31 do
+ AsmWriteln(#9'.set'#9'r'+tostr(i)+','+tostr(i));
+ for i:=0 to 31 do
+ AsmWriteln(#9'.set'#9'f'+tostr(i)+','+tostr(i));
+ end;
+ end;
+
+ const
+ as_ppc_gas_info : tasminfo =
+ (
+ id : as_gas;
+
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+
+ as_ppc_gas_darwin_info : tasminfo =
+ (
+ id : as_darwin;
+
+ idtxt : 'AS-Darwin';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : 'L';
+ comment : '# ';
+ );
+
+
+ refaddr2str: array[trefaddr] of string[3] = ('','','@ha','@l','');
+ refaddr2str_darwin: array[trefaddr] of string[4] = ('','','ha16','lo16','');
+
+
+
+ function TPPCGNUAssembler.sectionname(atype:tasmsectiontype;const aname:string):string;
+ begin
+ if (target_info.system = system_powerpc_darwin) and
+ (atype = sec_bss) then
+ atype := sec_code;
+ result := inherited sectionname(atype,aname);
+ end;
+
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+ if ((offset < -32768) or (offset > 32767)) and
+ (refaddr = addr_no) then
+ internalerror(19991);
+ if (refaddr = addr_no) then
+ s := ''
+ else
+ begin
+ if target_info.system = system_powerpc_darwin then
+ s := refaddr2str_darwin[refaddr]
+ else
+ s :='';
+ s := s+'(';
+ if assigned(symbol) then
+ begin
+ s:=s+symbol.name;
+ if assigned(relsymbol) then
+ s:=s+'-'+relsymbol.name;
+ end;
+ end;
+ if offset<0 then
+ s:=s+tostr(offset)
+ else
+ if (offset>0) then
+ begin
+ if assigned(symbol) then
+ s:=s+'+'+tostr(offset)
+ else
+ s:=s+tostr(offset);
+ end;
+
+ if (refaddr in [addr_lo,addr_hi]) then
+ begin
+ s := s+')';
+ if (target_info.system <> system_powerpc_darwin) then
+ s := s+refaddr2str[refaddr];
+ end;
+
+ if (index=NR_NO) and (base<>NR_NO) then
+ begin
+ if offset=0 then
+ begin
+ if assigned(symbol) then
+ begin
+ if target_info.system <> system_powerpc_darwin then
+ s:=s+'+0'
+ end
+ else
+ s:=s+'0';
+ end;
+ s:=s+'('+gas_regname(base)+')';
+ end
+ else if (index<>NR_NO) and (base<>NR_NO) then
+ begin
+ if (offset=0) then
+ s:=s+gas_regname(base)+','+gas_regname(index)
+ else
+ internalerror(19992);
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ function getopstr_jmp(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg :
+ getopstr_jmp:=gas_regname(o.reg);
+ { no top_ref jumping for powerpc }
+ top_const :
+ getopstr_jmp:=tostr(o.val);
+ top_ref :
+ begin
+ if o.ref^.refaddr<>addr_full then
+ internalerror(200402262);
+ hs:=o.ref^.symbol.name;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr_jmp:=hs;
+ end;
+ top_none:
+ getopstr_jmp:='';
+ else
+ internalerror(2002070603);
+ end;
+ end;
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_const:
+ getopstr:=tostr(longint(o.val));
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=o.ref^.symbol.name;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(o.ref^);
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+ function branchmode(o: tasmop): string[4];
+ var tempstr: string[4];
+ begin
+ tempstr := '';
+ case o of
+ A_BCCTR,A_BCCTRL: tempstr := 'ctr';
+ A_BCLR,A_BCLRL: tempstr := 'lr';
+ end;
+ case o of
+ A_BL,A_BLA,A_BCL,A_BCLA,A_BCCTRL,A_BCLRL: tempstr := tempstr+'l';
+ end;
+ case o of
+ A_BA,A_BLA,A_BCA,A_BCLA: tempstr:=tempstr+'a';
+ end;
+ branchmode := tempstr;
+ end;
+
+ function cond2str(op: tasmop; c: tasmcond): string;
+ { note: no checking is performed whether the given combination of }
+ { conditions is valid }
+ var
+ tempstr: string;
+ begin
+ tempstr:=#9;
+ case c.simple of
+ false:
+ begin
+ cond2str := tempstr+gas_op2str[op];
+ case c.dirhint of
+ DH_None:;
+ DH_Minus:
+ cond2str:=cond2str+'-';
+ DH_Plus:
+ cond2str:=cond2str+'+';
+ else
+ internalerror(2003112901);
+ end;
+ cond2str:=cond2str+#9+tostr(c.bo)+','+tostr(c.bi);
+ end;
+ true:
+ if (op >= A_B) and (op <= A_BCLRL) then
+ case c.cond of
+ { unconditional branch }
+ C_NONE:
+ cond2str := tempstr+gas_op2str[op];
+ { bdnzt etc }
+ else
+ begin
+ tempstr := tempstr+'b'+asmcondflag2str[c.cond]+
+ branchmode(op);
+ case c.dirhint of
+ DH_None:
+ tempstr:=tempstr+#9;
+ DH_Minus:
+ tempstr:=tempstr+('-'+#9);
+ DH_Plus:
+ tempstr:=tempstr+('+'+#9);
+ else
+ internalerror(2003112901);
+ end;
+ case c.cond of
+ C_LT..C_NU:
+ cond2str := tempstr+gas_regname(newreg(R_SPECIALREGISTER,c.cr,R_SUBWHOLE));
+ C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
+ cond2str := tempstr+tostr(c.crbit);
+ else
+ cond2str := tempstr;
+ end;
+ end;
+ end
+ { we have a trap instruction }
+ else
+ begin
+ internalerror(2002070601);
+ { not yet implemented !!!!!!!!!!!!!!!!!!!!! }
+ { case tempstr := 'tw';}
+ end;
+ end;
+ end;
+
+ Procedure TPPCGNUAssembler.WriteInstruction(hp : tai);
+ var op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ op:=taicpu(hp).opcode;
+ if is_calljmp(op) then
+ begin
+ { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
+ case op of
+ A_B,A_BA,A_BL,A_BLA:
+ s:=#9+gas_op2str[op]+#9;
+ A_BCTR,A_BCTRL,A_BLR,A_BLRL:
+ s:=#9+gas_op2str[op]
+ else
+ begin
+ s:=cond2str(op,taicpu(hp).condition);
+ if (s[length(s)] <> #9) and
+ (taicpu(hp).ops>0) then
+ s := s + ',';
+ end;
+ end;
+
+ if (taicpu(hp).ops>0) and (taicpu(hp).oper[0]^.typ<>top_none) then
+ begin
+ { first write the current contents of s, because the symbol }
+ { may be 255 characters }
+ asmwrite(s);
+ s:=getopstr_jmp(taicpu(hp).oper[0]^);
+ end;
+ end
+ else
+ { process operands }
+ begin
+ s:=#9+gas_op2str[op];
+ if taicpu(hp).ops<>0 then
+ begin
+ {
+ if not is_calljmp(op) then
+ sep:=','
+ else
+ }
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ // debug code
+ // writeln(s);
+ // writeln(taicpu(hp).fileinfo.line);
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+ sep:=',';
+ end;
+ end;
+ end;
+ AsmWriteLn(s);
+ end;
+
+begin
+ RegisterAssembler(as_ppc_gas_info,TPPCGNUAssembler);
+ RegisterAssembler(as_ppc_gas_darwin_info,TPPCGNUAssembler);
+end.
diff --git a/compiler/powerpc/agppcmpw.pas b/compiler/powerpc/agppcmpw.pas
new file mode 100644
index 0000000000..6ec390d346
--- /dev/null
+++ b/compiler/powerpc/agppcmpw.pas
@@ -0,0 +1,1295 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for PowerPC with MPW 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.
+
+ ****************************************************************************
+}
+{
+ This unit implements an asmoutput class for PowerPC with MPW syntax
+}
+unit agppcmpw;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmtai,
+ globals,aasmbase,aasmcpu,assemble,
+ cpubase;
+
+ type
+ TPPCMPWAssembler = class(TExternalAssembler)
+ procedure WriteTree(p:TAAsmoutput);override;
+ procedure WriteAsmList;override;
+ Function DoAssemble:boolean;override;
+ procedure WriteExternals;
+ procedure WriteAsmFileHeader;
+ private
+ procedure WriteInstruction(hp : tai);
+ procedure WriteProcedureHeader(var hp:tai);
+ procedure WriteDataHeader(var s:string; isExported, isConst:boolean);
+ cur_CSECT_name: String;
+ cur_CSECT_class: String;
+ end;
+
+
+ implementation
+
+ uses
+ cutils,globtype,systems,cclasses,
+ verbose,finput,fmodule,script,cpuinfo,
+ cgbase,cgutils,
+ itcpugas
+ ;
+
+ const
+ line_length = 70;
+
+ {Whether internal procedure references should be xxx[PR]: }
+ use_PR = false;
+
+ const_storage_class = '';
+ var_storage_class = '';
+
+ secnames : array[TAsmSectionType] of string[10] = (
+ '', {none}
+ 'csect', {code}
+ 'csect', {data}
+ 'csect', {read only data}
+ 'csect', {bss} 'csect',
+ 'csect','csect','csect','csect','','','','','','','','','',''
+ );
+
+ type
+ t64bitarray = array[0..7] of byte;
+ t32bitarray = array[0..3] of byte;
+
+ function ReplaceForbiddenChars(var s: string):Boolean;
+ {Returns wheater a replacement has occured.}
+
+ var
+ i:Integer;
+
+ {The dollar sign is not allowed in MPW PPCAsm}
+
+ begin
+ ReplaceForbiddenChars:=false;
+ for i:=1 to Length(s) do
+ if s[i]='$' then
+ begin
+ s[i]:='s';
+ ReplaceForbiddenChars:=true;
+ end;
+ end;
+
+
+{*** From here is copyed from agppcgas.pp, except where marked with CHANGED.
+ Perhaps put in a third common file. ***}
+
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+ if (refaddr <> addr_no) then
+ InternalError(2002110301)
+ else if ((offset < -32768) or (offset > 32767)) then
+ InternalError(19991);
+
+
+ if assigned(symbol) then
+ begin
+ s:= symbol.name;
+ ReplaceForbiddenChars(s);
+ {if symbol.typ = AT_FUNCTION then
+ ;}
+
+ s:= s+'[TC]' {ref to TOC entry }
+ end
+ else
+ s:= '';
+
+
+ if offset<0 then
+ s:=s+tostr(offset)
+ else
+ if (offset>0) then
+ begin
+ if assigned(symbol) then
+ s:=s+'+'+tostr(offset)
+ else
+ s:=s+tostr(offset);
+ end;
+
+ if (index=NR_NO) and (base<>NR_NO) then
+ begin
+ if offset=0 then
+ if not assigned(symbol) then
+ s:=s+'0';
+ s:=s+'('+gas_regname(base)+')';
+ end
+ else if (index<>NR_NO) and (base<>NR_NO) and (offset=0) then
+ begin
+ if (offset=0) then
+ s:=s+gas_regname(base)+','+gas_regname(index)
+ else
+ internalerror(19992);
+ end
+ else if (base=NR_NO) and (offset=0) then
+ begin
+ {Temporary fix for inline asm, where a local var is referenced.}
+ //if assigned(symbol) then
+ // s:= s+'(rtoc)';
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+ function getopstr_jmp(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg :
+ getopstr_jmp:=gas_regname(o.reg);
+ { no top_ref jumping for powerpc }
+ top_const :
+ getopstr_jmp:=tostr(o.val);
+ top_ref :
+ begin
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=o.ref^.symbol.name;
+ ReplaceForbiddenChars(hs);
+ case o.ref^.symbol.typ of
+ AT_FUNCTION:
+ begin
+ if hs[1] <> '@' then {if not local label}
+ if use_PR then
+ hs:= '.'+hs+'[PR]'
+ else
+ hs:= '.'+hs
+ end
+ else
+ ;
+ end;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr_jmp:=hs;
+ end
+ else
+ internalerror(200402263);
+ end;
+ top_none:
+ getopstr_jmp:='';
+ else
+ internalerror(2002070603);
+ end;
+ end;
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_const:
+ getopstr:=tostr(longint(o.val));
+ top_ref:
+ if o.ref^.refaddr=addr_no then
+ getopstr:=getreferencestring(o.ref^)
+ else
+ begin
+ hs:=o.ref^.symbol.name;
+ ReplaceForbiddenChars(hs);
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end;
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+ function branchmode(o: tasmop): string[4];
+ var tempstr: string[4];
+ begin
+ tempstr := '';
+ case o of
+ A_BCCTR,A_BCCTRL: tempstr := 'ctr';
+ A_BCLR,A_BCLRL: tempstr := 'lr';
+ end;
+ case o of
+ A_BL,A_BLA,A_BCL,A_BCLA,A_BCCTRL,A_BCLRL: tempstr := tempstr+'l';
+ end;
+ case o of
+ A_BA,A_BLA,A_BCA,A_BCLA: tempstr:=tempstr+'a';
+ end;
+ branchmode := tempstr;
+ end;
+
+ function cond2str(op: tasmop; c: tasmcond): string;
+ { note: no checking is performed whether the given combination of }
+ { conditions is valid }
+ var
+ tempstr: string;
+ begin
+ tempstr:=#9;
+ case c.simple of
+ false:
+ begin
+ cond2str := tempstr+gas_op2str[op];
+ case c.dirhint of
+ DH_None:;
+ DH_Minus:
+ cond2str:=cond2str+'-';
+ DH_Plus:
+ cond2str:=cond2str+'+';
+ else
+ internalerror(2003112901);
+ end;
+ cond2str:=cond2str+#9+tostr(c.bo)+','+tostr(c.bi)+',';
+ end;
+ true:
+ if (op >= A_B) and (op <= A_BCLRL) then
+ case c.cond of
+ { unconditional branch }
+ C_NONE:
+ cond2str := tempstr+gas_op2str[op];
+ { bdnzt etc }
+ else
+ begin
+ tempstr := tempstr+'b'+asmcondflag2str[c.cond]+
+ branchmode(op);
+ case c.dirhint of
+ DH_None:
+ tempstr:=tempstr+#9;
+ DH_Minus:
+ tempstr:=tempstr+('-'+#9);
+ DH_Plus:
+ tempstr:=tempstr+('+'+#9);
+ else
+ internalerror(2003112901);
+ end;
+ case c.cond of
+ C_LT..C_NU:
+ cond2str := tempstr+gas_regname(newreg(R_SPECIALREGISTER,c.cr,R_SUBWHOLE));
+ C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
+ cond2str := tempstr+tostr(c.crbit);
+ else
+ cond2str := tempstr;
+ end;
+ end;
+ end
+ { we have a trap instruction }
+ else
+ begin
+ internalerror(2002070601);
+ { not yet implemented !!!!!!!!!!!!!!!!!!!!! }
+ { case tempstr := 'tw';}
+ end;
+ end;
+ end;
+
+ procedure TPPCMPWAssembler.WriteInstruction(hp : tai);
+ var op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ op:=taicpu(hp).opcode;
+ if is_calljmp(op) then
+ begin
+ { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
+ case op of
+ A_B,A_BA:
+ s:=#9+gas_op2str[op]+#9;
+ A_BCTR,A_BCTRL,A_BLR,A_BLRL:
+ s:=#9+gas_op2str[op];
+ A_BL,A_BLA:
+ s:=#9+gas_op2str[op]+#9;
+ else
+ begin
+ s:=cond2str(op,taicpu(hp).condition);
+ if (s[length(s)] <> #9) and
+ (taicpu(hp).ops>0) then
+ s := s + ',';
+ end;
+ end;
+ if (taicpu(hp).ops>0) and (taicpu(hp).oper[0]^.typ<>top_none) then
+ begin
+ { first write the current contents of s, because the symbol }
+ { may be 255 characters }
+ asmwrite(s);
+ s:=getopstr_jmp(taicpu(hp).oper[0]^);
+ end;
+ end
+ else
+ { process operands }
+ begin
+ s:=#9+gas_op2str[op];
+ if taicpu(hp).ops<>0 then
+ begin
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+ sep:=',';
+ end;
+ end;
+ end;
+ AsmWriteLn(s);
+ end;
+
+ {*** Until here is copyed from agppcgas.pp. ***}
+
+
+ function single2str(d : single) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ single2str:=lower(hs);
+ end;
+
+ function double2str(d : double) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ double2str:=lower(hs);
+ end;
+
+ { convert floating point values }
+ { to correct endian }
+ procedure swap64bitarray(var t: t64bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[7];
+ t[7] := t[0];
+ t[0] := b;
+
+ b := t[6];
+ t[6] := t[1];
+ t[1] := b;
+
+ b:= t[5];
+ t[5] := t[2];
+ t[2] := b;
+
+ b:= t[4];
+ t[4] := t[3];
+ t[3] := b;
+ end;
+
+ procedure swap32bitarray(var t: t32bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[1];
+ t[1]:= t[2];
+ t[2]:= b;
+
+ b:= t[0];
+ t[0]:= t[3];
+ t[3]:= b;
+ end;
+
+ function fixline(s:string):string;
+ {
+ return s with all leading and ending spaces and tabs removed
+ }
+ var
+ i,j,k : longint;
+ begin
+ i:=length(s);
+ while (i>0) and (s[i] in [#9,' ']) do
+ dec(i);
+ j:=1;
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ for k:=j to i do
+ if s[k] in [#0..#31,#127..#255] then
+ s[k]:='.';
+ fixline:=Copy(s,j,i-j+1);
+ end;
+
+ Function PadTabs(const p:string;addch:char):string;
+ var
+ s : string;
+ i : longint;
+ begin
+ i:=length(p);
+ if addch<>#0 then
+ begin
+ inc(i);
+ s:=p+addch;
+ end
+ else
+ s:=p;
+ if i<8 then
+ PadTabs:=s+#9#9
+ else
+ PadTabs:=s+#9;
+ end;
+
+{****************************************************************************
+ PowerPC MPW Assembler
+ ****************************************************************************}
+ procedure TPPCMPWAssembler.WriteProcedureHeader(var hp:tai);
+ {Returns the current hp where the caller should continue from}
+ {For multiple entry procedures, only the last is exported as xxx[PR]
+ (if use_PR is set) }
+
+ procedure WriteExportHeader(hp:tai);
+
+ var
+ s: string;
+ replaced: boolean;
+
+ begin
+ s:= tai_symbol(hp).sym.name;
+ replaced:= ReplaceForbiddenChars(s);
+
+ if not use_PR then
+ begin
+ AsmWrite(#9'export'#9'.');
+ AsmWrite(s);
+ if replaced then
+ begin
+ AsmWrite(' => ''.');
+ AsmWrite(tai_symbol(hp).sym.name);
+ AsmWrite('''');
+ end;
+ AsmLn;
+ end;
+
+ AsmWrite(#9'export'#9);
+ AsmWrite(s);
+ AsmWrite('[DS]');
+ if replaced then
+ begin
+ AsmWrite(' => ''');
+ AsmWrite(tai_symbol(hp).sym.name);
+ AsmWrite('[DS]''');
+ end;
+ AsmLn;
+
+ {Entry in transition vector: }
+ AsmWrite(#9'csect'#9); AsmWrite(s); AsmWriteLn('[DS]');
+
+ AsmWrite(#9'dc.l'#9'.'); AsmWriteLn(s);
+
+ AsmWriteln(#9'dc.l'#9'TOC[tc0]');
+
+ {Entry in TOC: }
+ AsmWriteLn(#9'toc');
+
+ AsmWrite(#9'tc'#9);
+ AsmWrite(s); AsmWrite('[TC],');
+ AsmWrite(s); AsmWriteln('[DS]');
+ end;
+
+ function GetAdjacentTaiSymbol(var hp:tai):Boolean;
+
+ begin
+ GetAdjacentTaiSymbol:= false;
+ while assigned(hp.next) do
+ case tai(hp.next).typ of
+ ait_symbol:
+ begin
+ hp:=tai(hp.next);
+ GetAdjacentTaiSymbol:= true;
+ Break;
+ end;
+ ait_function_name:
+ hp:=tai(hp.next);
+ else
+ begin
+ //AsmWriteln(' ;#*#*# ' + tostr(Ord(tai(hp.next).typ)));
+ Break;
+ end;
+ end;
+ end;
+
+ var
+ first,last: tai;
+ s: string;
+ replaced: boolean;
+
+
+ begin
+ s:= tai_symbol(hp).sym.name;
+ {Write all headers}
+ first:= hp;
+ repeat
+ WriteExportHeader(hp);
+ last:= hp;
+ until not GetAdjacentTaiSymbol(hp);
+
+ {Start the section of the body of the proc: }
+ s:= tai_symbol(last).sym.name;
+ replaced:= ReplaceForbiddenChars(s);
+
+ if use_PR then
+ begin
+ AsmWrite(#9'export'#9'.'); AsmWrite(s); AsmWrite('[PR]');
+ if replaced then
+ begin
+ AsmWrite(' => ''.');
+ AsmWrite(tai_symbol(last).sym.name);
+ AsmWrite('[PR]''');
+ end;
+ AsmLn;
+ end;
+
+ {Starts the section: }
+ AsmWrite(#9'csect'#9'.');
+ AsmWrite(s);
+ AsmWriteLn('[PR]');
+
+ {Info for the debugger: }
+ AsmWrite(#9'function'#9'.');
+ AsmWrite(s);
+ AsmWriteLn('[PR]');
+
+ {Write all labels: }
+ hp:= first;
+ repeat
+ s:= tai_symbol(hp).sym.name;
+ ReplaceForbiddenChars(s);
+ AsmWrite('.'); AsmWrite(s); AsmWriteLn(':');
+ until not GetAdjacentTaiSymbol(hp);
+ end;
+
+ procedure TPPCMPWAssembler.WriteDataHeader(var s:string; isExported, isConst:boolean);
+ // Returns in s the changed string
+ var
+ sym: string;
+ replaced: boolean;
+
+ begin
+ sym:= s;
+ replaced:= ReplaceForbiddenChars(s);
+
+ if isExported then
+ begin
+ AsmWrite(#9'export'#9);
+ AsmWrite(s);
+ if isConst then
+ AsmWrite(const_storage_class)
+ else
+ AsmWrite(var_storage_class);
+ if replaced then
+ begin
+ AsmWrite(' => ''');
+ AsmWrite(sym);
+ AsmWrite('''');
+ end;
+ AsmLn;
+ end;
+
+ if not macos_direct_globals then
+ begin
+ {The actual section is here interrupted, by inserting a "tc" entry}
+ AsmWriteLn(#9'toc');
+
+ AsmWrite(#9'tc'#9);
+ AsmWrite(s);
+ AsmWrite('[TC], ');
+ AsmWrite(s);
+ if isConst then
+ AsmWrite(const_storage_class)
+ else
+ AsmWrite(var_storage_class);
+ AsmLn;
+
+ {The interrupted section is here continued.}
+ AsmWrite(#9'csect'#9);
+ AsmWriteln(cur_CSECT_name+cur_CSECT_class);
+ AsmWrite(PadTabs(s+':',#0));
+ end
+ else
+ begin
+ AsmWrite(#9'csect'#9);
+ AsmWrite(s);
+ AsmWrite('[TC]');
+ end;
+
+ AsmLn;
+ end;
+
+ var
+ LasTSec : TAsmSectionType;
+ lastfileinfo : tfileposinfo;
+ infile,
+ lastinfile : tinputfile;
+
+ const
+ ait_const2str:array[ait_const_32bit..ait_const_8bit] of string[8]=
+ (#9'dc.l'#9,#9'dc.w'#9,#9'dc.b'#9);
+
+
+ procedure TPPCMPWAssembler.WriteTree(p:TAAsmoutput);
+ var
+ s,
+ prefix,
+ suffix : string;
+ hp : tai;
+ hp1 : tailineinfo;
+ counter,
+ lines,
+ InlineLevel : longint;
+ i,j,l : longint;
+ consttyp : taitype;
+ found,
+ do_line,DoNotSplitLine,
+ quoted : boolean;
+ sep : char;
+ replaced : boolean;
+ sin : single;
+ d : double;
+
+ begin
+ if not assigned(p) then
+ exit;
+ InlineLevel:=0;
+ { lineinfo is only needed for al_procedures (PFV) }
+ do_line:=((cs_asm_source in aktglobalswitches) or
+ (cs_lineinfo in aktmoduleswitches))
+ and (p=asmlist[al_procedures]);
+ DoNotSplitLine:=false;
+ hp:=tai(p.first);
+ while assigned(hp) do
+ begin
+ if not(hp.typ in SkipLineInfo) and
+ not DoNotSplitLine then
+ begin
+ hp1 := hp as tailineinfo;
+
+ if do_line then
+ begin
+ { load infile }
+ if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
+ begin
+ infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
+ if assigned(infile) then
+ begin
+ { open only if needed !! }
+ if (cs_asm_source in aktglobalswitches) then
+ infile.open;
+ end;
+ { avoid unnecessary reopens of the same file !! }
+ lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
+ { be sure to change line !! }
+ lastfileinfo.line:=-1;
+ end;
+ { write source }
+ if (cs_asm_source in aktglobalswitches) and
+ assigned(infile) then
+ begin
+ if (infile<>lastinfile) then
+ begin
+ AsmWriteLn(target_asm.comment+'['+infile.name^+']');
+ if assigned(lastinfile) then
+ lastinfile.close;
+ end;
+ if (hp1.fileinfo.line<>lastfileinfo.line) and
+ ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
+ begin
+ if (hp1.fileinfo.line<>0) and
+ ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
+ AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
+ fixline(infile.GetLineStr(hp1.fileinfo.line)));
+ { set it to a negative value !
+ to make that is has been read already !! PM }
+ if (infile.linebuf^[hp1.fileinfo.line]>=0) then
+ infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
+ end;
+ end;
+ lastfileinfo:=hp1.fileinfo;
+ lastinfile:=infile;
+ end;
+ end;
+
+ DoNotSplitLine:=false;
+
+ case hp.typ of
+ ait_comment:
+ begin
+ AsmWrite(target_asm.comment);
+ AsmWritePChar(tai_comment(hp).str);
+ AsmLn;
+ end;
+ ait_regalloc,
+ ait_tempalloc:
+ ;
+ ait_section:
+ begin
+ {if LasTSec<>sec_none then
+ AsmWriteLn('_'+target_asm.secnames[LasTSec]+#9#9'ENDS');}
+
+ if tai_section(hp).sectype<>sec_none then
+ begin
+ if tai_section(hp).sectype in [sec_data,sec_rodata,sec_bss] then
+ cur_CSECT_class:= '[RW]'
+ else if tai_section(hp).sectype in [sec_code] then
+ cur_CSECT_class:= ''
+ else
+ cur_CSECT_class:= '[RO]';
+
+ s:= tai_section(hp).name^;
+ if s = '' then
+ InternalError(2004101001); {Nameless sections should not occur on MPW}
+ ReplaceForbiddenChars(s);
+ cur_CSECT_name:= s;
+
+ AsmLn;
+ AsmWriteLn(#9+secnames[tai_section(hp).sectype]+' '+cur_CSECT_name+cur_CSECT_class);
+ end;
+ LasTSec:=tai_section(hp).sectype;
+ end;
+ ait_align:
+ begin
+ case tai_align(hp).aligntype of
+ 1:AsmWriteLn(#9'align 0');
+ 2:AsmWriteLn(#9'align 1');
+ 4:AsmWriteLn(#9'align 2');
+ otherwise internalerror(2002110302);
+ end;
+ end;
+ ait_datablock: {Storage for global variables.}
+ begin
+ s:= tai_datablock(hp).sym.name;
+
+ WriteDataHeader(s, tai_datablock(hp).is_global, false);
+ if not macos_direct_globals then
+ begin
+ AsmWriteLn(#9'ds.b '+tostr(tai_datablock(hp).size));
+ end
+ else
+ begin
+ AsmWriteLn(PadTabs(s+':',#0)+'ds.b '+tostr(tai_datablock(hp).size));
+ {TODO: ? PadTabs(s,#0) }
+ end;
+ end;
+
+ ait_const_128bit:
+ begin
+ internalerror(200404291);
+ end;
+ ait_const_64bit:
+ begin
+ if assigned(tai_const(hp).sym) then
+ internalerror(200404292);
+ AsmWrite(ait_const2str[ait_const_32bit]);
+ if target_info.endian = endian_little then
+ begin
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ end
+ else
+ begin
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ end;
+ AsmLn;
+ end;
+
+ ait_const_uleb128bit,
+ ait_const_sleb128bit,
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_const_indirect_symbol :
+ begin
+ AsmWrite(ait_const2str[hp.typ]);
+ consttyp:=hp.typ;
+ l:=0;
+ repeat
+ if assigned(tai_const(hp).sym) then
+ begin
+ if assigned(tai_const(hp).endsym) then
+ begin
+ if (tai_const(hp).endsym.typ = AT_FUNCTION) and use_PR then
+ AsmWrite('.');
+
+ s:=tai_const(hp).endsym.name;
+ ReplaceForbiddenChars(s);
+ AsmWrite(s);
+ inc(l,length(s));
+
+ if tai_const(hp).endsym.typ = AT_FUNCTION then
+ begin
+ if use_PR then
+ AsmWrite('[PR]')
+ else
+ AsmWrite('[DS]');
+ end;
+
+ AsmWrite('-');
+ inc(l,5); {Approx 5 extra, no need to be exactly}
+ end;
+
+ if (tai_const(hp).sym.typ = AT_FUNCTION) and use_PR then
+ AsmWrite('.');
+
+ s:= tai_const(hp).sym.name;
+ ReplaceForbiddenChars(s);
+ AsmWrite(s);
+ inc(l,length(s));
+
+ if tai_const(hp).sym.typ = AT_FUNCTION then
+ begin
+ if use_PR then
+ AsmWrite('[PR]')
+ else
+ AsmWrite('[DS]');
+ end;
+ inc(l,5); {Approx 5 extra, no need to be exactly}
+
+ if tai_const(hp).value > 0 then
+ s:= '+'+tostr(tai_const(hp).value)
+ else if tai_const(hp).value < 0 then
+ s:= '-'+tostr(tai_const(hp).value)
+ else
+ s:= '';
+ if s<>'' then
+ begin
+ AsmWrite(s);
+ inc(l,length(s));
+ end;
+ end
+ else
+ begin
+ s:= tostr(tai_const(hp).value);
+ AsmWrite(s);
+ inc(l,length(s));
+ end;
+
+ if (l>line_length) or
+ (hp.next=nil) or
+ (tai(hp.next).typ<>consttyp) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmLn;
+ end;
+
+ ait_real_64bit :
+ begin
+ AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
+ d:=tai_real_64bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap64bitarray(t64bitarray(d));
+ AsmWrite(#9'dc.b'#9);
+ begin
+ for i:=0 to 7 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ end;
+ AsmLn;
+ end;
+
+ ait_real_32bit :
+ begin
+ AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
+ sin:=tai_real_32bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap32bitarray(t32bitarray(sin));
+ AsmWrite(#9'dc.b'#9);
+ for i:=0 to 3 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t32bitarray(sin)[i]));
+ end;
+ AsmLn;
+ end;
+
+ ait_string:
+ begin
+ {NOTE When a single quote char is encountered, it is
+ replaced with a numeric ascii value. It could also
+ have been replaced with the escape seq of double quotes.
+ Backslash seems to be used as an escape char, although
+ this is not mentioned in the PPCAsm documentation.}
+ counter := 0;
+ lines := tai_string(hp).len div line_length;
+ { separate lines in different parts }
+ if tai_string(hp).len > 0 then
+ begin
+ for j := 0 to lines-1 do
+ begin
+ AsmWrite(#9'dc.b'#9);
+ quoted:=false;
+ for i:=counter to counter+line_length-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'''') and
+ (tai_string(hp).str[i]<>'\') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('''');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and ord('"') }
+ else
+ begin
+ if quoted then
+ AsmWrite('''');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then AsmWrite('''');
+ AsmLn;
+ counter := counter+line_length;
+ end; { end for j:=0 ... }
+
+ { do last line of lines }
+ if counter < tai_string(hp).len then
+ AsmWrite(#9'dc.b'#9);
+ quoted:=false;
+ for i:=counter to tai_string(hp).len-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'''') and
+ (tai_string(hp).str[i]<>'\') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('''');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and " }
+ else
+ begin
+ if quoted then
+ AsmWrite('''');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then
+ AsmWrite('''');
+ end;
+ AsmLn;
+ end;
+ ait_label:
+ begin
+ if tai_label(hp).l.is_used then
+ begin
+ s:= tai_label(hp).l.name;
+ if s[1] = '@' then
+ begin
+ ReplaceForbiddenChars(s);
+ //Local labels:
+ AsmWriteLn(s+':')
+ end
+ else
+ begin
+ //Procedure entry points:
+ if not macos_direct_globals then
+ begin
+ WriteDataHeader(s, tai_label(hp).is_global, true);
+ end
+ else
+ begin
+ ReplaceForbiddenChars(s);
+ AsmWrite(#9'csect'#9); AsmWrite(s);
+ AsmWriteLn('[TC]');
+
+ AsmWriteLn(PadTabs(s+':',#0));
+ end;
+ end;
+ end;
+ end;
+ ait_symbol:
+ begin
+ if tai_symbol(hp).sym.typ=AT_FUNCTION then
+ WriteProcedureHeader(hp)
+ else if tai_symbol(hp).sym.typ=AT_DATA then
+ begin
+ s:= tai_symbol(hp).sym.name;
+ WriteDataHeader(s, tai_symbol(hp).is_global, true);
+ if macos_direct_globals then
+ begin
+ AsmWrite(s);
+ AsmWriteLn(':');
+ end;
+ end
+ else
+ InternalError(2003071301);
+ end;
+ ait_symbol_end:
+ ;
+ ait_instruction:
+ WriteInstruction(hp);
+ ait_stab,
+ ait_force_line,
+ ait_function_name : ;
+ ait_cutobject :
+ begin
+ InternalError(2004101101); {Smart linking is done transparently by the MPW linker.}
+ end;
+ ait_marker :
+ begin
+ if tai_marker(hp).kind=InlineStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=InlineEnd then
+ dec(InlineLevel);
+ end;
+ else
+ internalerror(2002110303);
+ end;
+ hp:=tai(hp.next);
+ end;
+ end;
+
+ var
+ currentasmlist : TExternalAssembler;
+
+ procedure writeexternal(p:tnamedindexitem;arg:pointer);
+
+ var
+ s:string;
+ replaced: boolean;
+
+ begin
+ if tasmsymbol(p).defbind=AB_EXTERNAL then
+ begin
+ //Writeln('ZZZ ',p.name,' ',p.classname,' ',Ord(tasmsymbol(p).typ));
+ s:= p.name;
+ replaced:= ReplaceForbiddenChars(s);
+
+ with currentasmlist do
+ case tasmsymbol(p).typ of
+ AT_FUNCTION:
+ begin
+ AsmWrite(#9'import'#9'.');
+ AsmWrite(s);
+ if use_PR then
+ AsmWrite('[PR]');
+
+ if replaced then
+ begin
+ AsmWrite(' <= ''.');
+ AsmWrite(p.name);
+ if use_PR then
+ AsmWrite('[PR]''')
+ else
+ AsmWrite('''');
+ end;
+ AsmLn;
+
+ AsmWrite(#9'import'#9);
+ AsmWrite(s);
+ AsmWrite('[DS]');
+ if replaced then
+ begin
+ AsmWrite(' <= ''');
+ AsmWrite(p.name);
+ AsmWrite('[DS]''');
+ end;
+ AsmLn;
+
+ AsmWriteLn(#9'toc');
+
+ AsmWrite(#9'tc'#9);
+ AsmWrite(s);
+ AsmWrite('[TC],');
+ AsmWrite(s);
+ AsmWriteLn('[DS]');
+ end;
+ AT_DATA:
+ begin
+ AsmWrite(#9'import'#9);
+ AsmWrite(s);
+ AsmWrite(var_storage_class);
+ if replaced then
+ begin
+ AsmWrite(' <= ''');
+ AsmWrite(p.name);
+ AsmWrite('''');
+ end;
+ AsmLn;
+
+ AsmWriteLn(#9'toc');
+ AsmWrite(#9'tc'#9);
+ AsmWrite(s);
+ AsmWrite('[TC],');
+ AsmWrite(s);
+ AsmWriteLn(var_storage_class);
+ end
+ else
+ InternalError(2003090901);
+ end;
+ end;
+ end;
+
+ procedure TPPCMPWAssembler.WriteExternals;
+ begin
+ currentasmlist:=self;
+ objectlibrary.symbolsearch.foreach_static(@writeexternal,nil);
+ end;
+
+
+ function TPPCMPWAssembler.DoAssemble : boolean;
+ var f : file;
+ begin
+ DoAssemble:=Inherited DoAssemble;
+ (*
+ { masm does not seem to recognize specific extensions and uses .obj allways PM }
+ if (target_asm.id = as_i386_masm) then
+ begin
+ if not(cs_asm_extern in aktglobalswitches) then
+ begin
+ if Not FileExists(objfile) and
+ FileExists(ForceExtension(objfile,'.obj')) then
+ begin
+ Assign(F,ForceExtension(objfile,'.obj'));
+ Rename(F,objfile);
+ end;
+ end
+ else
+ AsmRes.AddAsmCommand('mv',ForceExtension(objfile,'.obj')+' '+objfile,objfile);
+ end;
+ *)
+ end;
+
+ procedure TPPCMPWAssembler.WriteAsmFileHeader;
+
+ begin
+ (*
+ AsmWriteLn(#9'.386p');
+ { masm 6.11 does not seem to like LOCALS PM }
+ if (target_asm.id = as_i386_tasm) then
+ begin
+ AsmWriteLn(#9'LOCALS '+target_asm.labelprefix);
+ end;
+ AsmWriteLn('DGROUP'#9'GROUP'#9'_BSS,_DATA');
+ AsmWriteLn(#9'ASSUME'#9'CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP');
+ AsmLn;
+ *)
+
+ AsmWriteLn(#9'string asis'); {Interpret strings just to be the content between the quotes.}
+ AsmWriteLn(#9'aligning off'); {We do our own aligning.}
+ AsmLn;
+ end;
+
+ procedure TPPCMPWAssembler.WriteAsmList;
+ var
+ hal : tasmlist;
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Start writing MPW-styled assembler output for '+current_module.mainsource^);
+{$endif}
+ LasTSec:=sec_none;
+
+ WriteAsmFileHeader;
+ WriteExternals;
+
+ for hal:=low(Tasmlist) to high(Tasmlist) do
+ begin
+ AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
+ writetree(asmlist[hal]);
+ AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
+ end;
+
+ AsmWriteLn(#9'end');
+ AsmLn;
+
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Done writing MPW-styled assembler output for '+current_module.mainsource^);
+{$endif EXTDEBUG}
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_powerpc_mpw_info : tasminfo =
+ (
+ id : as_powerpc_mpw;
+ idtxt : 'MPW';
+ asmbin : 'PPCAsm';
+ asmcmd : '-case on $ASM -o $OBJ';
+ supported_target : system_any; { what should I write here ?? }
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_labelprefix_only_inside_procedure];
+ labelprefix : '@';
+ comment : '; ';
+ );
+
+initialization
+ RegisterAssembler(as_powerpc_mpw_info,TPPCMPWAssembler);
+end.
diff --git a/compiler/powerpc/aoptcpu.pas b/compiler/powerpc/aoptcpu.pas
new file mode 100644
index 0000000000..832ff7edcc
--- /dev/null
+++ b/compiler/powerpc/aoptcpu.pas
@@ -0,0 +1,451 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the PowerPC optimizer object
+
+ 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;
+
+Interface
+
+{$i fpcdefs.inc}
+
+uses cpubase, aoptobj, aoptcpub, aopt, aasmtai, aasmcpu;
+
+Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
+
+ function PostPeepHoleOptsCpu(var p: tai): boolean; override;
+
+ private
+ function cmpi_mfcr_opt(p, next1, next2: taicpu): boolean;
+ End;
+
+Implementation
+
+ uses
+ cutils, cgbase;
+
+const
+ calculation_target_op0: array[tasmop] of tasmop = (a_none,
+ a_add, a_add_, a_addo, a_addo_, a_addc, a_addc_, a_addco, a_addco_,
+ a_adde, a_adde_, a_addeo, a_addeo_, a_addi, a_addic, a_addic_, a_addis,
+ a_addme, a_addme_, a_addmeo, a_addmeo_, a_addze, a_addze_, a_addzeo,
+ a_addzeo_, a_and, a_and_, a_andc, a_andc_, a_andi_, a_andis_, 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, a_none, a_none, a_cntlzw, a_cntlzw_, 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, a_none, a_divw, a_divw_, a_divwo, a_divwo_,
+ a_divwu, a_divwu_, a_divwuo, a_divwuo_, a_none, a_none, a_none, a_eqv,
+ a_eqv_, a_extsb, a_extsb_, a_extsh, a_extsh_, a_fabs, a_fabs_, a_fadd,
+ a_fadd_, a_fadds, a_fadds_, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_fdiv, a_fdiv_, a_fdivs, a_fdivs_, a_fmadd, a_fmadd_, a_fmadds,
+ a_fmadds_, a_none, a_fmsub, a_fmsub_, a_fmsubs, a_fmsubs_, a_fmul, a_fmul_,
+ a_fmuls, a_fmuls_, a_fnabs, a_fnabs_, a_fneg, a_fneg_, a_fnmadd,
+ a_fnmadd_, a_fnmadds, a_fnmadds_, a_fnmsub, a_fnmsub_, a_fnmsubs,
+ a_fnmsubs_, a_fres, a_fres_, a_frsp, a_frsp_, a_frsqrte, a_frsqrte_,
+ a_none, a_none, a_fsqrt, a_fsqrt_, a_fsqrts, a_fsqrts_, a_fsub, a_fsub_,
+ a_fsubs, a_fsubs_, 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, 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, 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, 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_mulhw,
+ a_mulhw_, a_mulhwu, a_mulhwu_, a_mulli, a_mullw, a_mullw_, a_mullwo,
+ a_mullwo_, a_nand, a_nand_, a_neg, a_neg_, a_nego, a_nego_, a_nor, a_nor_,
+ a_or, a_or_, a_orc, a_orc_, a_ori, a_oris, a_rfi, a_rlwimi, a_rlwimi_,
+ a_rlwinm, a_rlwinm_, a_rlwnm, a_rlwnm_, a_none, a_slw, a_slw_, a_sraw, a_sraw_,
+ a_srawi, a_srawi_,a_srw, a_srw_, a_stb, 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, 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_subf, a_subf_, a_subfo,
+ a_subfo_, a_subfc, a_subfc_, a_subfco, a_subfco_, a_subfe, a_subfe_,
+ a_subfeo, a_subfeo_, a_subfic, a_subfme, a_subfme_, a_subfmeo, a_subfmeo_,
+ a_subfze, a_subfze_, a_subfzeo, a_subfzeo_, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_xor, a_xor_, a_xori, a_xoris,
+ { simplified mnemonics }
+ a_subi, a_subis, a_subic, a_subic_, a_sub, a_sub_, a_subo, a_subo_,
+ a_subc, a_subc_, a_subco, a_subco_, a_none, a_none, a_none, a_none,
+ a_extlwi, a_extlwi_, a_extrwi, a_extrwi_, a_inslwi, a_inslwi_, a_insrwi,
+ a_insrwi_, a_rotlwi, a_rotlwi_, a_rotlw, a_rotlw_, a_slwi, a_slwi_,
+ a_srwi, a_srwi_, a_clrlwi, a_clrlwi_, a_clrrwi, a_clrrwi_, a_clrslwi,
+ a_clrslwi_, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none {move to special prupose reg}, a_none {move from special purpose reg},
+ a_none, a_none, a_none, a_none, a_none, a_none, a_not, a_not_, a_none, a_none, a_none,
+ a_none, a_none);
+
+ function TCpuAsmOptimizer.cmpi_mfcr_opt(p, next1, next2: taicpu): boolean;
+ var
+ next3: tai;
+ inverse: boolean;
+ begin
+ result := true;
+ inverse :=
+ getnextinstruction(next2,next3) and
+ (next3.typ = ait_instruction) and
+ (taicpu(next3).opcode = A_XORI) and
+ (taicpu(next3).oper[0]^.reg = taicpu(next3).oper[1]^.reg) and
+ (taicpu(next3).oper[0]^.reg = taicpu(next2).oper[0]^.reg);
+ case taicpu(next2).oper[2]^.val of
+ 1:
+ begin
+ // less than zero or greater/equal than zero (the xori remains in
+ // in the latter case). Doesn't make sense for unsigned comparisons.
+ if (p.opcode = A_CMPWI) then
+ begin
+ p.opcode := A_SRWI;
+ p.ops := 3;
+ p.loadreg(1,p.oper[0]^.reg);
+ p.loadreg(0,next1.oper[0]^.reg);
+ p.loadconst(2,31);
+ asml.remove(next1);
+ next1.free;
+ asml.remove(next2);
+ next2.free;
+ end
+ else
+ result := false;
+ end;
+{
+ needs two registers to work with
+ 2:
+ begin
+ // greater or less/equal to zero
+ end;
+}
+ 3:
+ begin
+ // equal/not equal to zero (the xori remains in the latter case;
+ // there's a more optimal sequence without it, but needs extra
+ // register)
+ p.opcode := A_CNTLZW;
+ p.loadreg(1,p.oper[0]^.reg);
+ p.loadreg(0,next1.oper[0]^.reg);
+ next1.ops := 3;
+ next1.opcode := A_SRWI;
+ next1.loadreg(1,next1.oper[0]^.reg);
+ next1.loadconst(2,5);
+ asml.remove(next2);
+ next2.free;
+ end;
+ else
+ result := false;
+ end;
+ end;
+
+
+ function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+ var
+ next1, next2: tai;
+ l1, l2: longint;
+ begin
+ result := false;
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_CMPWI,
+ A_CMPLWI:
+ begin
+ if (taicpu(p).oper[1]^.typ = top_const) and
+ (taicpu(p).oper[1]^.val = 0) and
+ getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (taicpu(next1).opcode = A_MFCR) and
+ getnextinstruction(next1,next2) and
+ (taicpu(next2).opcode = A_RLWINM) and
+ (taicpu(next2).oper[0]^.reg = taicpu(next2).oper[1]^.reg) and
+ (taicpu(next2).oper[0]^.reg = taicpu(next1).oper[0]^.reg) and
+ (taicpu(next2).oper[3]^.val = 31) and
+ (taicpu(next2).oper[4]^.val = 31) and
+ cmpi_mfcr_opt(taicpu(p),taicpu(next1),taicpu(next2)) then
+ result := true;
+ end;
+{ seems the register allocator doesn't generate superfluous fmr's }
+{ A_FMR, }
+ A_MR:
+ begin
+ if getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (calculation_target_op0[taicpu(next1).opcode] <> a_none) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg) then
+ begin
+ for l1 := 1 to taicpu(next1).ops - 1 do
+ if (taicpu(next1).oper[l1]^.typ = top_reg) and
+ (taicpu(next1).oper[l1]^.reg = taicpu(p).oper[0]^.reg) then
+ taicpu(next1).loadreg(l1,taicpu(p).oper[1]^.reg);
+ asml.remove(p);
+ p.free;
+ p := next1;
+ result := true;
+ end;
+ end;
+ A_SLWI:
+ begin
+ if getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (taicpu(next1).opcode = A_RLWINM) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
+ (taicpu(next1).oper[1]^.reg = taicpu(p).oper[0]^.reg) then
+ begin
+ if (taicpu(next1).oper[2]^.val = 0) then
+ begin
+ { convert slwi to rlwinm and see if the rlwinm }
+ { optimization can do something with it }
+ taicpu(p).opcode := A_RLWINM;
+ taicpu(p).ops := 5;
+ taicpu(p).loadconst(2,taicpu(p).oper[2]^.val);
+ taicpu(p).loadconst(3,0);
+ taicpu(p).loadconst(4,31-taicpu(p).oper[2]^.val);
+ result := true;
+ end;
+ end;
+ end;
+ A_SRWI:
+ begin
+ if getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ ((taicpu(next1).opcode = A_SLWI) or
+ (taicpu(next1).opcode = A_RLWINM)) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
+ (taicpu(next1).oper[1]^.reg = taicpu(p).oper[0]^.reg) then
+ case taicpu(next1).opcode of
+ A_SLWI:
+ begin
+ taicpu(p).opcode := A_RLWINM;
+ taicpu(p).ops := 5;
+ taicpu(p).loadconst(2,taicpu(next1).oper[2]^.val-taicpu(p).oper[2]^.val);
+ if (taicpu(p).oper[2]^.val < 0) then
+ begin
+ taicpu(p).loadconst(3,-taicpu(p).oper[2]^.val);
+ taicpu(p).loadconst(4,31-taicpu(next1).oper[2]^.val);
+ inc(taicpu(p).oper[2]^.val,32);
+ end
+ else
+ begin
+ taicpu(p).loadconst(3,0);
+ taicpu(p).loadconst(4,31-taicpu(next1).oper[2]^.val);
+ end;
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end;
+ A_RLWINM:
+ begin
+ if (taicpu(next1).oper[2]^.val = 0) then
+ begin
+ { convert srwi to rlwinm and see if the rlwinm }
+ { optimization can do something with it }
+ taicpu(p).opcode := A_RLWINM;
+ taicpu(p).ops := 5;
+ taicpu(p).loadconst(3,taicpu(p).oper[2]^.val);
+ taicpu(p).loadconst(4,31);
+ taicpu(p).loadconst(2,(32-taicpu(p).oper[2]^.val) and 31);
+ result := true;
+ end;
+ end;
+ end;
+ end;
+ A_RLWINM:
+ begin
+ if getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (taicpu(next1).opcode = A_RLWINM) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
+ // both source and target of next1 must equal target of p
+ (taicpu(next1).oper[1]^.reg = taicpu(p).oper[0]^.reg) and
+ (taicpu(next1).oper[2]^.val = 0) then
+ begin
+ l1 := taicpu(p).oper[4]^.val;
+ if (l1 < taicpu(p).oper[3]^.val) then
+ inc(l1,32);
+ l2 := taicpu(next1).oper[4]^.val;
+ if (l2 < taicpu(next1).oper[3]^.val) then
+ inc(l2,32);
+
+ if (taicpu(p).oper[3]^.val > l2) or
+ (taicpu(next1).oper[3]^.val > l1) then
+ begin
+ // masks have no bits in common
+ taicpu(p).opcode := A_LI;
+ taicpu(p).loadconst(1,0);
+ taicpu(p).clearop(2);
+ taicpu(p).clearop(3);
+ taicpu(p).clearop(4);
+ taicpu(p).ops := 2;
+ taicpu(p).opercnt := 2;
+ asml.remove(next1);
+ next1.free;
+ end
+ else
+ // some of the cases with l1>32 or l2>32 can be
+ // optimized, but others can't (like 19,17 and 25,23)
+ if (l1 < 32) and
+ (l2 < 32) then
+ begin
+ taicpu(p).oper[3]^.val := max(taicpu(p).oper[3]^.val,taicpu(next1).oper[3]^.val);
+ taicpu(p).oper[4]^.val := min(taicpu(p).oper[4]^.val,taicpu(next1).oper[4]^.val);
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ const
+ modifyflags: array[tasmop] of tasmop =
+ (a_none, a_add_, a_add_, a_addo_, a_addo_, a_addc_, a_addc_, a_addco_, a_addco_,
+ a_adde_, a_adde_, a_addeo_, a_addeo_, {a_addi could be addic_ if sure doesn't disturb carry} a_none, a_addic_, a_addic_, a_none,
+ a_addme_, a_addme_, a_addmeo_, a_addmeo_, a_addze_, a_addze_, a_addzeo_,
+ a_addzeo_, a_and_, a_and_, a_andc_, a_andc_, a_andi_, a_andis_, 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, a_none, a_none, a_cntlzw_, a_cntlzw_, 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, a_none, a_divw_, a_divw_, a_divwo_, a_divwo_,
+ a_divwu_, a_divwu_, a_divwuo_, a_divwuo_, a_none, a_none, a_none, a_eqv_,
+ a_eqv_, a_extsb_, a_extsb_, a_extsh_, a_extsh_, 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, 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, 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, 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, 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, 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, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_mffs, a_mffs_, a_mfmsr, a_mfspr, a_mfsr,
+ a_mfsrin, a_mftb, a_mtcrf, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_mulhw_,
+ a_mulhw_, a_mulhwu_, a_mulhwu_, a_none, a_mullw_, a_mullw_, a_mullwo_,
+ a_mullwo_, a_nand_, a_nand_, a_neg_, a_neg_, a_nego_, a_nego_, a_nor_, a_nor_,
+ a_or_, a_or_, a_orc_, a_orc_, a_none, a_none, a_none, a_rlwimi_, a_rlwimi_,
+ a_rlwinm_, a_rlwinm_, a_rlwnm_, a_rlwnm_, a_none, a_slw_, a_slw_, a_sraw_, a_sraw_,
+ a_srawi_, a_srawi_,a_srw_, a_srw_, 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, 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_subf_, a_subf_, a_subfo_,
+ a_subfo_, a_subfc_, a_subfc_, a_subfco_, a_subfco_, a_subfe_, a_subfe_,
+ a_subfeo_, a_subfeo_, a_none, a_subfme_, a_subfme_, a_subfmeo_, a_subfmeo_,
+ a_subfze_, a_subfze_, a_subfzeo_, a_subfzeo_, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_xor_, a_xor_, a_none, a_none,
+ { simplified mnemonics }
+ a_none, a_none, a_subic_, a_subic_, a_sub_, a_sub_, a_subo_, a_subo_,
+ a_subc_, a_subc_, a_subco_, a_subco_, a_none, a_none, a_none, a_none,
+ a_extlwi_, a_extlwi_, a_extrwi_, a_extrwi_, a_inslwi_, a_inslwi_, a_insrwi_,
+ a_insrwi_, a_rotlwi_, a_rotlwi_, a_rotlw_, a_rotlw_, a_slwi_, a_slwi_,
+ a_srwi_, a_srwi_, a_clrlwi_, a_clrlwi_, a_clrrwi_, a_clrrwi_, a_clrslwi_,
+ a_clrslwi_, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none {move to special prupose reg}, a_none {move from special purpose reg},
+ a_none, a_none, a_none, a_none, a_mr_, a_mr_, a_not_, a_not_, a_none, a_none, a_none,
+ a_none, a_none);
+
+ function changetomodifyflags(p: taicpu): boolean;
+ begin
+ result := false;
+ if (modifyflags[p.opcode] <> a_none) then
+ begin
+ p.opcode := modifyflags[p.opcode];
+ result := true;
+ end;
+ end;
+
+ function TCpuAsmOptimizer.PostPeepHoleOptsCpu(var p: tai): boolean;
+ var
+ next1: tai;
+ begin
+ result := false;
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_RLWINM_:
+ begin
+ // rlwinm_ is cracked on the G5, andi_/andis_ aren't
+ if (taicpu(p).oper[2]^.val = 0) then
+ if (taicpu(p).oper[3]^.val < 16) and
+ (taicpu(p).oper[4]^.val < 16) then
+ begin
+ taicpu(p).opcode := A_ANDIS_;
+ taicpu(p).oper[2]^.val :=
+ ((1 shl (16-taicpu(p).oper[3]^.val)) - 1) and
+ not((1 shl (15-taicpu(p).oper[4]^.val)) - 1);
+ taicpu(p).clearop(3);
+ taicpu(p).clearop(4);
+ taicpu(p).ops := 3;
+ taicpu(p).opercnt := 2;
+ end
+ else if (taicpu(p).oper[3]^.val >= 16) and
+ (taicpu(p).oper[4]^.val >= 16) then
+ begin
+ taicpu(p).opcode := A_ANDI_;
+ taicpu(p).oper[2]^.val :=
+ ((1 shl (32-taicpu(p).oper[3]^.val)) - 1) and
+ not((1 shl (31-taicpu(p).oper[4]^.val)) - 1);
+ taicpu(p).clearop(3);
+ taicpu(p).clearop(4);
+ taicpu(p).ops := 3;
+ taicpu(p).opercnt := 2;
+ end;
+ end;
+ end;
+
+ // change "integer operation with destination reg" followed by a
+ // comparison to zero of that reg, with a variant of that integer
+ // operation which sets the flags (if it exists)
+ if not(result) and
+ (taicpu(p).ops >= 2) and
+ (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (taicpu(next1).opcode = A_CMPWI) and
+ // make sure it the result goes to cr0
+ (((taicpu(next1).ops = 2) and
+ (taicpu(next1).oper[1]^.val = 0) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg)) or
+ ((taicpu(next1).ops = 3) and
+ (taicpu(next1).oper[2]^.val = 0) and
+ (taicpu(next1).oper[0]^.typ = top_reg) and
+ (getsupreg(taicpu(next1).oper[0]^.reg) = RS_CR0) and
+ (taicpu(next1).oper[1]^.reg = taicpu(p).oper[0]^.reg))) and
+ changetomodifyflags(taicpu(p)) then
+ begin
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end;
+ end;
+ end;
+ end;
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+End.
diff --git a/compiler/powerpc/aoptcpub.pas b/compiler/powerpc/aoptcpub.pas
new file mode 100644
index 0000000000..26507ec19d
--- /dev/null
+++ b/compiler/powerpc/aoptcpub.pas
@@ -0,0 +1,121 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the 80x86 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
+ aasmcpu,AOptBase, cpubase;
+
+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 = 5;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 1;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 0;
+
+{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_B;
+ aopt_condjmp = A_BC;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/compiler/powerpc/aoptcpuc.pas b/compiler/powerpc/aoptcpuc.pas
new file mode 100644
index 0000000000..4b82e87f4a
--- /dev/null
+++ b/compiler/powerpc/aoptcpuc.pas
@@ -0,0 +1,40 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ 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 aoptcpuc;
+
+Interface
+
+{$i fpcdefs.inc}
+
+Uses
+ AOptCs;
+
+Type
+ TRegInfoCpu = Object(TRegInfo)
+ End;
+
+
+Implementation
+
+End.
diff --git a/compiler/powerpc/aoptcpud.pas b/compiler/powerpc/aoptcpud.pas
new file mode 100644
index 0000000000..2df7e2e49e
--- /dev/null
+++ b/compiler/powerpc/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ 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.
diff --git a/compiler/powerpc/cgcpu.pas b/compiler/powerpc/cgcpu.pas
new file mode 100644
index 0000000000..9c49618cdb
--- /dev/null
+++ b/compiler/powerpc/cgcpu.pas
@@ -0,0 +1,2403 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the PowerPC
+
+ 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 cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,symtype,symdef,
+ cgbase,cgobj,
+ aasmbase,aasmcpu,aasmtai,
+ cpubase,cpuinfo,cgutils,cg64f32,rgcpu,
+ parabase;
+
+ type
+ tcgppc = class(tcg)
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+
+ { passing parameters, per default the parameter is pushed }
+ { nr gives the number of the parameter (enumerated from }
+ { left to right), this allows to move the parameter to }
+ { register, if the cpu supports register calling }
+ { conventions }
+ procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : tcgpara);override;
+ procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : tcgpara);override;
+ procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);override;
+
+
+ procedure a_call_name(list : taasmoutput;const s : string);override;
+ procedure a_call_reg(list : taasmoutput;reg: tregister); override;
+
+ procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
+ procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+
+ procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister); override;
+
+ { move instructions }
+ procedure a_load_const_reg(list : taasmoutput; size: tcgsize; a : aint;reg : tregister);override;
+ procedure a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
+ procedure a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
+ procedure a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+
+ procedure a_jmp_name(list : taasmoutput;const s : string); override;
+ procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
+ procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
+
+ procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+
+ procedure g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean); override;
+ procedure g_save_standard_registers(list:Taasmoutput); override;
+ procedure g_restore_standard_registers(list:Taasmoutput); override;
+
+ procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
+
+ procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);override;
+
+ procedure g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef); override;
+ { find out whether a is of the form 11..00..11b or 00..11...00. If }
+ { that's the case, we can use rlwinm to do an AND operation }
+ function get_rlwi_const(a: aint; var l1, l2: longint): boolean;
+
+ procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
+
+ procedure g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ private
+
+ (* NOT IN USE: *)
+ procedure g_stackframe_entry_mac(list : taasmoutput;localsize : longint);
+ (* NOT IN USE: *)
+ procedure g_return_from_proc_mac(list : taasmoutput;parasize : aint);
+
+
+ { Make sure ref is a valid reference for the PowerPC and sets the }
+ { base to the value of the index if (base = R_NO). }
+ { Returns true if the reference contained a base, index and an }
+ { offset or symbol, in which case the base will have been changed }
+ { to a tempreg (which has to be freed by the caller) containing }
+ { the sum of part of the original reference }
+ function fixref(list: taasmoutput; var ref: treference): boolean;
+
+ { returns whether a reference can be used immediately in a powerpc }
+ { instruction }
+ function issimpleref(const ref: treference): boolean;
+
+ { contains the common code of a_load_reg_ref and a_load_ref_reg }
+ procedure a_load_store(list:taasmoutput;op: tasmop;reg:tregister;
+ ref: treference);
+
+ { creates the correct branch instruction for a given combination }
+ { of asmcondflags and destination addressing mode }
+ procedure a_jmp(list: taasmoutput; op: tasmop;
+ c: tasmcondflag; crval: longint; l: tasmlabel);
+
+ function save_regs(list : taasmoutput):longint;
+ procedure restore_regs(list : taasmoutput);
+
+ function get_darwin_call_stub(const s: string): tasmsymbol;
+ end;
+
+ tcg64fppc = class(tcg64f32)
+ procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+ procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
+ procedure a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
+ end;
+
+
+const
+ TOpCG2AsmOpConstLo: Array[topcg] of TAsmOp = (A_NONE,A_ADDI,A_ANDI_,A_DIVWU,
+ A_DIVW,A_MULLW, A_MULLW, A_NONE,A_NONE,A_ORI,
+ A_SRAWI,A_SLWI,A_SRWI,A_SUBI,A_XORI);
+ TOpCG2AsmOpConstHi: Array[topcg] of TAsmOp = (A_NONE,A_ADDIS,A_ANDIS_,
+ A_DIVWU,A_DIVW, A_MULLW,A_MULLW,A_NONE,A_NONE,
+ A_ORIS,A_NONE, A_NONE,A_NONE,A_SUBIS,A_XORIS);
+
+ TOpCmp2AsmCond: Array[topcmp] of TAsmCondFlag = (C_NONE,C_EQ,C_GT,
+ C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
+
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ symconst,symsym,fmodule,
+ rgobj,tgobj,cpupi,procinfo,paramgr;
+
+
+ procedure tcgppc.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ if target_info.system=system_powerpc_darwin then
+ begin
+{
+ if pi_needs_got in current_procinfo.flags then
+ begin
+ current_procinfo.got:=NR_R31;
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R11,RS_R12,RS_R30,RS_R29,
+ RS_R28,RS_R27,RS_R26,RS_R25,RS_R24,RS_R23,RS_R22,
+ RS_R21,RS_R20,RS_R19,RS_R18,RS_R17,RS_R16,RS_R15,
+ RS_R14,RS_R13],first_int_imreg,[]);
+ end
+ else}
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R11,RS_R12,RS_R31,RS_R30,RS_R29,
+ RS_R28,RS_R27,RS_R26,RS_R25,RS_R24,RS_R23,RS_R22,
+ RS_R21,RS_R20,RS_R19,RS_R18,RS_R17,RS_R16,RS_R15,
+ RS_R14,RS_R13],first_int_imreg,[]);
+ end
+ else
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R11,RS_R12,RS_R31,RS_R30,RS_R29,
+ RS_R28,RS_R27,RS_R26,RS_R25,RS_R24,RS_R23,RS_R22,
+ RS_R21,RS_R20,RS_R19,RS_R18,RS_R17,RS_R16,RS_R15,
+ RS_R14,RS_R13],first_int_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,RS_F8,RS_F9,
+ RS_F10,RS_F11,RS_F12,RS_F13,RS_F31,RS_F30,RS_F29,RS_F28,RS_F27,
+ RS_F26,RS_F25,RS_F24,RS_F23,RS_F22,RS_F21,RS_F20,RS_F19,RS_F18,
+ RS_F17,RS_F16,RS_F15,RS_F14],first_fpu_imreg,[]);
+ {$warning FIX ME}
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
+ [RS_M0,RS_M1,RS_M2],first_mm_imreg,[]);
+ end;
+
+
+ procedure tcgppc.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_MMREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ procedure tcgppc.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : tcgpara);
+ var
+ ref: treference;
+ begin
+ paraloc.check_simple_location;
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,size,a,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref);
+ ref.base:=paraloc.location^.reference.index;
+ ref.offset:=paraloc.location^.reference.offset;
+ a_load_const_ref(list,size,a,ref);
+ end;
+ else
+ internalerror(2002081101);
+ end;
+ end;
+
+
+ procedure tcgppc.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : tcgpara);
+
+ var
+ tmpref, ref: treference;
+ location: pcgparalocation;
+ sizeleft: aint;
+
+ begin
+ location := paraloc.location;
+ tmpref := r;
+ sizeleft := paraloc.intsize;
+ while assigned(location) do
+ begin
+ case location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ begin
+{$ifndef cpu64bit}
+ if (sizeleft <> 3) then
+ begin
+ a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+ { the following is only for AIX abi systems, but the }
+ { conditions should never be true for SYSV (if they }
+ { are, there is a bug in cpupara) }
+
+ { update: this doesn't work yet (we have to shift }
+ { right again in ncgutil when storing the parameters, }
+ { and additionally Apple's documentation seems to be }
+ { wrong, in that these values are always kept in the }
+ { lower bytes of the registers }
+
+{
+ if (paraloc.composite) and
+ (sizeleft <= 2) and
+ ((paraloc.intsize > 4) or
+ (target_info.system <> system_powerpc_darwin)) then
+ begin
+ case sizeleft of
+ 1:
+ a_op_const_reg(list,OP_SHL,OS_INT,24,location^.register);
+ 2:
+ a_op_const_reg(list,OP_SHL,OS_INT,16,location^.register);
+ else
+ internalerror(2005010910);
+ end;
+ end;
+}
+ end
+ else
+ begin
+ a_load_ref_reg(list,OS_16,OS_16,tmpref,location^.register);
+ a_reg_alloc(list,NR_R0);
+ inc(tmpref.offset,2);
+ a_load_ref_reg(list,OS_8,OS_8,tmpref,newreg(R_INTREGISTER,RS_R0,R_SUBNONE));
+ a_op_const_reg(list,OP_SHL,OS_INT,16,location^.register);
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWIMI,location^.register,newreg(R_INTREGISTER,RS_R0,R_SUBNONE),8,16,31-8));
+ a_reg_dealloc(list,NR_R0);
+ dec(tmpref.offset,2);
+ end;
+{$else not cpu64bit}
+{$error add 64 bit support for non power of 2 loads in a_param_ref}
+{$endif not cpu64bit}
+ end;
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(ref,location^.reference.index,location^.reference.offset);
+ g_concatcopy(list,tmpref,ref,sizeleft);
+ if assigned(location^.next) then
+ internalerror(2005010710);
+ end;
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ case location^.size of
+ OS_F32, OS_F64:
+ a_loadfpu_ref_reg(list,location^.size,tmpref,location^.register);
+ else
+ internalerror(2002072801);
+ end;
+ LOC_VOID:
+ begin
+ // nothing to do
+ end;
+ else
+ internalerror(2002081103);
+ end;
+ inc(tmpref.offset,tcgsize2size[location^.size]);
+ dec(sizeleft,tcgsize2size[location^.size]);
+ location := location^.next;
+ end;
+ end;
+
+
+ procedure tcgppc.a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);
+ var
+ ref: treference;
+ tmpreg: tregister;
+
+ begin
+ paraloc.check_simple_location;
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadaddr_ref_reg(list,r,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+
+
+ function tcgppc.get_darwin_call_stub(const s: string): tasmsymbol;
+ var
+ stubname: string;
+ href: treference;
+ l1: tasmsymbol;
+ begin
+ { function declared in the current unit? }
+ { doesn't work correctly, because this will also return a hit if we }
+ { previously took the address of an external procedure. It doesn't }
+ { really matter, the linker will remove all unnecessary stubs. }
+{ result := objectlibrary.getasmsymbol(s);
+ if not(assigned(result)) then
+ begin }
+ stubname := 'L'+s+'$stub';
+ result := objectlibrary.getasmsymbol(stubname);
+{ end; }
+ if assigned(result) then
+ exit;
+
+ if asmlist[al_imports]=nil then
+ asmlist[al_imports]:=TAAsmoutput.create;
+
+ asmlist[al_imports].concat(Tai_section.Create(sec_data,'',0));
+ asmlist[al_imports].concat(Tai_section.create(sec_stub,'',0));
+ asmlist[al_imports].concat(Tai_align.Create(4));
+ result := objectlibrary.newasmsymbol(stubname,AB_EXTERNAL,AT_FUNCTION);
+ asmlist[al_imports].concat(Tai_symbol.Create(result,0));
+ asmlist[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
+ l1 := objectlibrary.newasmsymbol('L'+s+'$lazy_ptr',AB_EXTERNAL,AT_FUNCTION);
+ reference_reset_symbol(href,l1,0);
+ href.refaddr := addr_hi;
+ asmlist[al_imports].concat(taicpu.op_reg_ref(A_LIS,NR_R11,href));
+ href.refaddr := addr_lo;
+ href.base := NR_R11;
+ asmlist[al_imports].concat(taicpu.op_reg_ref(A_LWZU,NR_R12,href));
+ asmlist[al_imports].concat(taicpu.op_reg(A_MTCTR,NR_R12));
+ asmlist[al_imports].concat(taicpu.op_none(A_BCTR));
+ asmlist[al_imports].concat(Tai_section.Create(sec_data,'',0));
+ asmlist[al_imports].concat(tai_directive.create(asd_lazy_symbol_pointer,''));
+ asmlist[al_imports].concat(Tai_symbol.Create(l1,0));
+ asmlist[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
+ asmlist[al_imports].concat(tai_const.createname(strpnew('dyld_stub_binding_helper'),AT_FUNCTION,0));
+ end;
+
+
+ { calling a procedure by name }
+ procedure tcgppc.a_call_name(list : taasmoutput;const s : string);
+ begin
+ { MacOS: The linker on MacOS (PPCLink) inserts a call to glue code,
+ if it is a cross-TOC call. If so, it also replaces the NOP
+ with some restore code.}
+ if (target_info.system <> system_powerpc_darwin) then
+ begin
+ list.concat(taicpu.op_sym(A_BL,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
+ if target_info.system=system_powerpc_macos then
+ list.concat(taicpu.op_none(A_NOP));
+ end
+ else
+ list.concat(taicpu.op_sym(A_BL,get_darwin_call_stub(s)));
+{
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+}
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+ { calling a procedure by address }
+ procedure tcgppc.a_call_reg(list : taasmoutput;reg: tregister);
+
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+
+ begin
+ if target_info.system=system_powerpc_macos then
+ begin
+ {Generate instruction to load the procedure address from
+ the transition vector.}
+ //TODO: Support cross-TOC calls.
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ reference_reset(tmpref);
+ tmpref.offset := 0;
+ //tmpref.symaddr := refs_full;
+ tmpref.base:= reg;
+ list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
+ list.concat(taicpu.op_reg(A_MTCTR,tmpreg));
+ end
+ else
+ list.concat(taicpu.op_reg(A_MTCTR,reg));
+ list.concat(taicpu.op_none(A_BCTRL));
+ //if target_info.system=system_powerpc_macos then
+ // //NOP is not needed here.
+ // list.concat(taicpu.op_none(A_NOP));
+ include(current_procinfo.flags,pi_do_call);
+{
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060704);
+}
+ //list.concat(tai_comment.create(strpnew('***** a_call_reg')));
+ end;
+
+
+{********************** load instructions ********************}
+
+ procedure tcgppc.a_load_const_reg(list : taasmoutput; size: TCGSize; a : aint; reg : TRegister);
+
+ begin
+ if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
+ internalerror(2002090902);
+ if (a >= low(smallint)) and
+ (a <= high(smallint)) then
+ list.concat(taicpu.op_reg_const(A_LI,reg,smallint(a)))
+ else if ((a and $ffff) <> 0) then
+ begin
+ list.concat(taicpu.op_reg_const(A_LI,reg,smallint(a and $ffff)));
+ if ((a shr 16) <> 0) or
+ (smallint(a and $ffff) < 0) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS,reg,reg,
+ smallint((a shr 16)+ord(smallint(a and $ffff) < 0))))
+ end
+ else
+ list.concat(taicpu.op_reg_const(A_LIS,reg,smallint(a shr 16)));
+ end;
+
+
+ procedure tcgppc.a_load_reg_ref(list : taasmoutput; fromsize, tosize: TCGSize; reg : tregister;const ref : treference);
+
+ const
+ StoreInstr: Array[OS_8..OS_32,boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_STB,A_STBU),(A_STBX,A_STBUX)),
+ ((A_STH,A_STHU),(A_STHX,A_STHUX)),
+ ((A_STW,A_STWU),(A_STWX,A_STWUX)));
+ var
+ op: TAsmOp;
+ ref2: TReference;
+ begin
+ ref2 := ref;
+ fixref(list,ref2);
+ if tosize in [OS_S8..OS_S16] then
+ { storing is the same for signed and unsigned values }
+ tosize := tcgsize(ord(tosize)-(ord(OS_S8)-ord(OS_8)));
+ { 64 bit stuff should be handled separately }
+ if tosize in [OS_64,OS_S64] then
+ internalerror(200109236);
+ op := storeinstr[tcgsize2unsigned[tosize],ref2.index<>NR_NO,false];
+ a_load_store(list,op,reg,ref2);
+ End;
+
+
+ procedure tcgppc.a_load_ref_reg(list : taasmoutput; fromsize,tosize : tcgsize;const ref: treference;reg : tregister);
+
+ const
+ LoadInstr: Array[OS_8..OS_S32,boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_LBZ,A_LBZU),(A_LBZX,A_LBZUX)),
+ ((A_LHZ,A_LHZU),(A_LHZX,A_LHZUX)),
+ ((A_LWZ,A_LWZU),(A_LWZX,A_LWZUX)),
+ { 64bit stuff should be handled separately }
+ ((A_NONE,A_NONE),(A_NONE,A_NONE)),
+ { 128bit stuff too }
+ ((A_NONE,A_NONE),(A_NONE,A_NONE)),
+ { there's no load-byte-with-sign-extend :( }
+ ((A_LBZ,A_LBZU),(A_LBZX,A_LBZUX)),
+ ((A_LHA,A_LHAU),(A_LHAX,A_LHAUX)),
+ ((A_LWZ,A_LWZU),(A_LWZX,A_LWZUX)));
+ var
+ op: tasmop;
+ ref2: treference;
+
+ begin
+ { TODO: optimize/take into consideration fromsize/tosize. Will }
+ { probably only matter for OS_S8 loads though }
+ if not(fromsize in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
+ internalerror(2002090902);
+ ref2 := ref;
+ fixref(list,ref2);
+ { the caller is expected to have adjusted the reference already }
+ { in this case }
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ op := loadinstr[fromsize,ref2.index<>NR_NO,false];
+ a_load_store(list,op,reg,ref2);
+ { sign extend shortint if necessary, since there is no }
+ { load instruction that does that automatically (JM) }
+ if fromsize = OS_S8 then
+ list.concat(taicpu.op_reg_reg(A_EXTSB,reg,reg));
+ end;
+
+
+ procedure tcgppc.a_load_reg_reg(list : taasmoutput;fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+
+ var
+ instr: taicpu;
+ begin
+ case tosize of
+ OS_8:
+ instr := taicpu.op_reg_reg_const_const_const(A_RLWINM,
+ reg2,reg1,0,31-8+1,31);
+ OS_S8:
+ instr := taicpu.op_reg_reg(A_EXTSB,reg2,reg1);
+ OS_16:
+ instr := taicpu.op_reg_reg_const_const_const(A_RLWINM,
+ reg2,reg1,0,31-16+1,31);
+ OS_S16:
+ instr := taicpu.op_reg_reg(A_EXTSH,reg2,reg1);
+ OS_32,OS_S32:
+ instr := taicpu.op_reg_reg(A_MR,reg2,reg1);
+ else internalerror(2002090901);
+ end;
+ list.concat(instr);
+ rg[R_INTREGISTER].add_move_instruction(instr);
+ end;
+
+
+ procedure tcgppc.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
+
+ var
+ instr: taicpu;
+ begin
+ instr := taicpu.op_reg_reg(A_FMR,reg2,reg1);
+ list.concat(instr);
+ rg[R_FPUREGISTER].add_move_instruction(instr);
+ end;
+
+
+ procedure tcgppc.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
+
+ const
+ FpuLoadInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_LFS,A_LFSU),(A_LFSX,A_LFSUX)),
+ ((A_LFD,A_LFDU),(A_LFDX,A_LFDUX)));
+ var
+ op: tasmop;
+ ref2: treference;
+
+ begin
+ { several functions call this procedure with OS_32 or OS_64 }
+ { so this makes life easier (FK) }
+ case size of
+ OS_32,OS_F32:
+ size:=OS_F32;
+ OS_64,OS_F64,OS_C64:
+ size:=OS_F64;
+ else
+ internalerror(200201121);
+ end;
+ ref2 := ref;
+ fixref(list,ref2);
+ op := fpuloadinstr[size,ref2.index <> NR_NO,false];
+ a_load_store(list,op,reg,ref2);
+ end;
+
+
+ procedure tcgppc.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
+
+ const
+ FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_STFS,A_STFSU),(A_STFSX,A_STFSUX)),
+ ((A_STFD,A_STFDU),(A_STFDX,A_STFDUX)));
+ var
+ op: tasmop;
+ ref2: treference;
+
+ begin
+ if not(size in [OS_F32,OS_F64]) then
+ internalerror(200201122);
+ ref2 := ref;
+ fixref(list,ref2);
+ op := fpustoreinstr[size,ref2.index <> NR_NO,false];
+ a_load_store(list,op,reg,ref2);
+ end;
+
+
+ procedure tcgppc.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
+
+ begin
+ a_op_const_reg_reg(list,op,size,a,reg,reg);
+ end;
+
+
+ procedure tcgppc.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+
+ begin
+ a_op_reg_reg_reg(list,op,size,src,dst,dst);
+ end;
+
+
+ procedure tcgppc.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister);
+ var
+ l1,l2: longint;
+ oplo, ophi: tasmop;
+ scratchreg: tregister;
+ useReg, gotrlwi: boolean;
+
+
+ procedure do_lo_hi;
+ begin
+ list.concat(taicpu.op_reg_reg_const(oplo,dst,src,word(a)));
+ list.concat(taicpu.op_reg_reg_const(ophi,dst,dst,word(a shr 16)));
+ end;
+
+ begin
+ if op = OP_SUB then
+ begin
+ a_op_const_reg_reg(list,OP_ADD,size,-a,src,dst);
+ exit;
+ end;
+ ophi := TOpCG2AsmOpConstHi[op];
+ oplo := TOpCG2AsmOpConstLo[op];
+ gotrlwi := get_rlwi_const(a,l1,l2);
+ if (op in [OP_AND,OP_OR,OP_XOR]) then
+ begin
+ if (a = 0) then
+ begin
+ if op = OP_AND then
+ list.concat(taicpu.op_reg_const(A_LI,dst,0))
+ else
+ a_load_reg_reg(list,size,size,src,dst);
+ exit;
+ end
+ else if (a = -1) then
+ begin
+ case op of
+ OP_OR:
+ list.concat(taicpu.op_reg_const(A_LI,dst,-1));
+ OP_XOR:
+ list.concat(taicpu.op_reg_reg(A_NOT,dst,src));
+ OP_AND:
+ a_load_reg_reg(list,size,size,src,dst);
+ end;
+ exit;
+ end
+ else if (aword(a) <= high(word)) and
+ ((op <> OP_AND) or
+ not gotrlwi) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(oplo,dst,src,word(a)));
+ exit;
+ end;
+ { all basic constant instructions also have a shifted form that }
+ { works only on the highest 16bits, so if lo(a) is 0, we can }
+ { use that one }
+ if (word(a) = 0) and
+ (not(op = OP_AND) or
+ not gotrlwi) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(ophi,dst,src,word(a shr 16)));
+ exit;
+ end;
+ end
+ else if (op = OP_ADD) then
+ if a = 0 then
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ exit
+ end
+ else if (a >= low(smallint)) and
+ (a <= high(smallint)) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,dst,src,smallint(a)));
+ exit;
+ end;
+
+ { otherwise, the instructions we can generate depend on the }
+ { operation }
+ useReg := false;
+ case op of
+ OP_DIV,OP_IDIV:
+ if (a = 0) then
+ internalerror(200208103)
+ else if (a = 1) then
+ begin
+ a_load_reg_reg(list,OS_INT,OS_INT,src,dst);
+ exit
+ end
+ else if ispowerof2(a,l1) then
+ begin
+ case op of
+ OP_DIV:
+ list.concat(taicpu.op_reg_reg_const(A_SRWI,dst,src,l1));
+ OP_IDIV:
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_SRAWI,dst,src,l1));
+ list.concat(taicpu.op_reg_reg(A_ADDZE,dst,dst));
+ end;
+ end;
+ exit;
+ end
+ else
+ usereg := true;
+ OP_IMUL, OP_MUL:
+ if (a = 0) then
+ begin
+ list.concat(taicpu.op_reg_const(A_LI,dst,0));
+ exit
+ end
+ else if (a = 1) then
+ begin
+ a_load_reg_reg(list,OS_INT,OS_INT,src,dst);
+ exit
+ end
+ else if ispowerof2(a,l1) then
+ list.concat(taicpu.op_reg_reg_const(A_SLWI,dst,src,l1))
+ else if (longint(a) >= low(smallint)) and
+ (longint(a) <= high(smallint)) then
+ list.concat(taicpu.op_reg_reg_const(A_MULLI,dst,src,smallint(a)))
+ else
+ usereg := true;
+ OP_ADD:
+ begin
+ list.concat(taicpu.op_reg_reg_const(oplo,dst,src,smallint(a)));
+ list.concat(taicpu.op_reg_reg_const(ophi,dst,dst,
+ smallint((a shr 16) + ord(smallint(a) < 0))));
+ end;
+ OP_OR:
+ { try to use rlwimi }
+ if gotrlwi and
+ (src = dst) then
+ begin
+ scratchreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ list.concat(taicpu.op_reg_const(A_LI,scratchreg,-1));
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWIMI,dst,
+ scratchreg,0,l1,l2));
+ end
+ else
+ do_lo_hi;
+ OP_AND:
+ { try to use rlwinm }
+ if gotrlwi then
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,dst,
+ src,0,l1,l2))
+ else
+ useReg := true;
+ OP_XOR:
+ do_lo_hi;
+ OP_SHL,OP_SHR,OP_SAR:
+ begin
+ if (a and 31) <> 0 Then
+ list.concat(taicpu.op_reg_reg_const(
+ TOpCG2AsmOpConstLo[Op],dst,src,a and 31))
+ else
+ a_load_reg_reg(list,size,size,src,dst);
+ if (a shr 5) <> 0 then
+ internalError(68991);
+ end
+ else
+ internalerror(200109091);
+ end;
+ { if all else failed, load the constant in a register and then }
+ { perform the operation }
+ if useReg then
+ begin
+ scratchreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,a,scratchreg);
+ a_op_reg_reg_reg(list,op,OS_32,scratchreg,src,dst);
+ end;
+ end;
+
+
+ procedure tcgppc.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister);
+
+ const
+ op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
+ (A_NONE,A_ADD,A_AND,A_DIVWU,A_DIVW,A_MULLW,A_MULLW,A_NEG,A_NOT,A_OR,
+ A_SRAW,A_SLW,A_SRW,A_SUB,A_XOR);
+
+ begin
+ case op of
+ OP_NEG,OP_NOT:
+ begin
+ list.concat(taicpu.op_reg_reg(op_reg_reg_opcg2asmop[op],dst,src1));
+ if (op = OP_NOT) and
+ not(size in [OS_32,OS_S32]) then
+ { zero/sign extend result again }
+ a_load_reg_reg(list,OS_32,size,dst,dst);
+ end;
+ else
+ list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
+ end;
+ end;
+
+
+{*************** compare instructructions ****************}
+
+ procedure tcgppc.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);
+
+ var
+ scratch_register: TRegister;
+ signed: boolean;
+
+ begin
+ signed := cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE];
+ { in the following case, we generate more efficient code when }
+ { signed is true }
+ if (cmp_op in [OC_EQ,OC_NE]) and
+ (aword(a) > $ffff) then
+ signed := true;
+ if signed then
+ if (a >= low(smallint)) and (a <= high(smallint)) Then
+ list.concat(taicpu.op_reg_reg_const(A_CMPWI,NR_CR0,reg,a))
+ else
+ begin
+ scratch_register := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,a,scratch_register);
+ list.concat(taicpu.op_reg_reg_reg(A_CMPW,NR_CR0,reg,scratch_register));
+ end
+ else
+ if (aword(a) <= $ffff) then
+ list.concat(taicpu.op_reg_reg_const(A_CMPLWI,NR_CR0,reg,aword(a)))
+ else
+ begin
+ scratch_register := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,a,scratch_register);
+ list.concat(taicpu.op_reg_reg_reg(A_CMPLW,NR_CR0,reg,scratch_register));
+ end;
+ a_jmp(list,A_BC,TOpCmp2AsmCond[cmp_op],0,l);
+ end;
+
+
+ procedure tcgppc.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;
+ reg1,reg2 : tregister;l : tasmlabel);
+
+ var
+ op: tasmop;
+
+ begin
+ if cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE] then
+ op := A_CMPW
+ else
+ op := A_CMPLW;
+ list.concat(taicpu.op_reg_reg_reg(op,NR_CR0,reg2,reg1));
+ a_jmp(list,A_BC,TOpCmp2AsmCond[cmp_op],0,l);
+ end;
+
+
+ procedure tcgppc.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
+
+ begin
+ a_jmp(list,A_BC,TOpCmp2AsmCond[cond],0,l);
+ end;
+
+
+ procedure tcgppc.a_jmp_name(list : taasmoutput;const s : string);
+ var
+ p : taicpu;
+ begin
+ if (target_info.system = system_powerpc_darwin) then
+ p := taicpu.op_sym(A_B,get_darwin_call_stub(s))
+ else
+ p := taicpu.op_sym(A_B,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION));
+ p.is_jmp := true;
+ list.concat(p)
+ end;
+
+
+ procedure tcgppc.a_jmp_always(list : taasmoutput;l: tasmlabel);
+
+ begin
+ a_jmp(list,A_B,C_None,0,l);
+ end;
+
+ procedure tcgppc.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
+
+ var
+ c: tasmcond;
+ begin
+ c := flags_to_cond(f);
+ a_jmp(list,A_BC,c.cond,c.cr-RS_CR0,l);
+ end;
+
+ procedure tcgppc.g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister);
+
+ var
+ testbit: byte;
+ bitvalue: boolean;
+
+ begin
+ { get the bit to extract from the conditional register + its }
+ { requested value (0 or 1) }
+ testbit := ((f.cr-RS_CR0) * 4);
+ case f.flag of
+ F_EQ,F_NE:
+ begin
+ inc(testbit,2);
+ bitvalue := f.flag = F_EQ;
+ end;
+ F_LT,F_GE:
+ begin
+ bitvalue := f.flag = F_LT;
+ end;
+ F_GT,F_LE:
+ begin
+ inc(testbit);
+ bitvalue := f.flag = F_GT;
+ end;
+ else
+ internalerror(200112261);
+ end;
+ { load the conditional register in the destination reg }
+ list.concat(taicpu.op_reg(A_MFCR,reg));
+ { we will move the bit that has to be tested to bit 0 by rotating }
+ { left }
+ testbit := (testbit + 1) and 31;
+ { extract bit }
+ list.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,reg,reg,testbit,31,31));
+ { if we need the inverse, xor with 1 }
+ if not bitvalue then
+ list.concat(taicpu.op_reg_reg_const(A_XORI,reg,reg,1));
+ end;
+
+(*
+ procedure tcgppc.g_cond2reg(list: taasmoutput; const f: TAsmCond; reg: TRegister);
+
+ var
+ testbit: byte;
+ bitvalue: boolean;
+
+ begin
+ { get the bit to extract from the conditional register + its }
+ { requested value (0 or 1) }
+ case f.simple of
+ false:
+ begin
+ { we don't generate this in the compiler }
+ internalerror(200109062);
+ end;
+ true:
+ case f.cond of
+ C_None:
+ internalerror(200109063);
+ C_LT..C_NU:
+ begin
+ testbit := (ord(f.cr) - ord(R_CR0))*4;
+ inc(testbit,AsmCondFlag2BI[f.cond]);
+ bitvalue := AsmCondFlagTF[f.cond];
+ end;
+ C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
+ begin
+ testbit := f.crbit
+ bitvalue := AsmCondFlagTF[f.cond];
+ end;
+ else
+ internalerror(200109064);
+ end;
+ end;
+ { load the conditional register in the destination reg }
+ list.concat(taicpu.op_reg_reg(A_MFCR,reg));
+ { we will move the bit that has to be tested to bit 31 -> rotate }
+ { left by bitpos+1 (remember, this is big-endian!) }
+ if bitpos <> 31 then
+ inc(bitpos)
+ else
+ bitpos := 0;
+ { extract bit }
+ list.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,reg,reg,bitpos,31,31));
+ { if we need the inverse, xor with 1 }
+ if not bitvalue then
+ list.concat(taicpu.op_reg_reg_const(A_XORI,reg,reg,1));
+ end;
+*)
+
+{ *********** entry/exit code and address loading ************ }
+
+ procedure tcgppc.g_save_standard_registers(list:Taasmoutput);
+ begin
+ { this work is done in g_proc_entry }
+ end;
+
+
+ procedure tcgppc.g_restore_standard_registers(list:Taasmoutput);
+ begin
+ { this work is done in g_proc_exit }
+ end;
+
+
+ procedure tcgppc.g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);
+ { generated the entry code of a procedure/function. Note: localsize is the }
+ { sum of the size necessary for local variables and the maximum possible }
+ { combined size of ALL the parameters of a procedure called by the current }
+ { one. }
+ { This procedure may be called before, as well as after g_return_from_proc }
+ { is called. NOTE registers are not to be allocated through the register }
+ { allocator here, because the register colouring has already occured !! }
+
+
+ var regcounter,firstregfpu,firstreggpr: TSuperRegister;
+ href : treference;
+ usesfpr,usesgpr,gotgot : boolean;
+ regcounter2, firstfpureg: Tsuperregister;
+ cond : tasmcond;
+ instr : taicpu;
+
+ begin
+ { CR and LR only have to be saved in case they are modified by the current }
+ { procedure, but currently this isn't checked, so save them always }
+ { following is the entry code as described in "Altivec Programming }
+ { Interface Manual", bar the saving of AltiVec registers }
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+ a_reg_alloc(list,NR_R0);
+
+ usesfpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ { FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
+ case target_info.abi of
+ abi_powerpc_aix:
+ firstfpureg := RS_F14;
+ abi_powerpc_sysv:
+ firstfpureg := RS_F14;
+ else
+ internalerror(2003122903);
+ end;
+ for regcounter:=firstfpureg to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ usesfpr:= true;
+ firstregfpu:=regcounter;
+ break;
+ end;
+ end;
+
+ usesgpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for regcounter2:=RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr:=true;
+ firstreggpr:=regcounter2;
+ break;
+ end;
+ end;
+
+ { save link register? }
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ if (pi_do_call in current_procinfo.flags) or
+ ([cs_lineinfo,cs_debuginfo] * aktmoduleswitches <> []) then
+ begin
+ { save return address... }
+ list.concat(taicpu.op_reg(A_MFLR,NR_R0));
+ { ... in caller's frame }
+ case target_info.abi of
+ abi_powerpc_aix:
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_AIX);
+ abi_powerpc_sysv:
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_SYSV);
+ end;
+ list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
+ a_reg_dealloc(list,NR_R0);
+ end;
+
+ { save the CR if necessary in callers frame. }
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ if target_info.abi = abi_powerpc_aix then
+ if false then { Not needed at the moment. }
+ begin
+ a_reg_alloc(list,NR_R0);
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_CR));
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
+ list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
+ a_reg_dealloc(list,NR_R0);
+ end;
+
+ { !!! always allocate space for all registers for now !!! }
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+{ if usesfpr or usesgpr then }
+ begin
+ a_reg_alloc(list,NR_R12);
+ { save end of fpr save area }
+ list.concat(taicpu.op_reg_reg(A_MR,NR_R12,NR_STACK_POINTER_REG));
+ end;
+
+
+ if (not nostackframe) and
+ (localsize <> 0) then
+ begin
+ if (localsize <= high(smallint)) then
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,-localsize);
+ a_load_store(list,A_STWU,NR_STACK_POINTER_REG,href);
+ end
+ else
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,0);
+ { can't use getregisterint here, the register colouring }
+ { is already done when we get here }
+ href.index := NR_R11;
+ a_reg_alloc(list,href.index);
+ a_load_const_reg(list,OS_S32,-localsize,href.index);
+ a_load_store(list,A_STWUX,NR_STACK_POINTER_REG,href);
+ a_reg_dealloc(list,href.index);
+ end;
+ end;
+
+ { no GOT pointer loaded yet }
+ gotgot:=false;
+ if usesfpr then
+ begin
+ { save floating-point registers
+ if (cs_create_pic in aktmoduleswitches) and not(usesgpr) then
+ begin
+ a_call_name(objectlibrary.newasmsymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+'_g',AB_EXTERNAL,AT_FUNCTION));
+ gotgot:=true;
+ end
+ else
+ a_call_name(objectlibrary.newasmsymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14),AB_EXTERNAL,AT_FUNCTION));
+ }
+ reference_reset_base(href,NR_R12,-8);
+ for regcounter:=firstregfpu to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ a_loadfpu_reg_ref(list,OS_F64,newreg(R_FPUREGISTER,regcounter,R_SUBNONE),href);
+ dec(href.offset,8);
+ end;
+ end;
+
+ { compute start of gpr save area }
+ inc(href.offset,4);
+ end
+ else
+ { compute start of gpr save area }
+ reference_reset_base(href,NR_R12,-4);
+
+ { save gprs and fetch GOT pointer }
+ if usesgpr then
+ begin
+ {
+ if cs_create_pic in aktmoduleswitches then
+ begin
+ a_call_name(objectlibrary.newasmsymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14)+'_g',AB_EXTERNAL,AT_FUNCTION));
+ gotgot:=true;
+ end
+ else
+ a_call_name(objectlibrary.newasmsymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14),AB_EXTERNAL,AT_FUNCTION))
+ }
+ for regcounter2:=RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr:=true;
+ a_load_reg_ref(list,OS_INT,OS_INT,newreg(R_INTREGISTER,regcounter2,R_SUBNONE),href);
+ dec(href.offset,4);
+ end;
+ end;
+{
+ r.enum:=R_INTREGISTER;
+ r.:=;
+ reference_reset_base(href,NR_R12,-((NR_R31-firstreggpr) shr 8+1)*4);
+ list.concat(taicpu.op_reg_ref(A_STMW,firstreggpr,href));
+}
+ end;
+
+{ see "!!! always allocate space for all registers for now !!!" above }
+
+{ done in ncgutil because it may only be released after the parameters }
+{ have been moved to their final resting place }
+{ if usesfpr or usesgpr then }
+{ a_reg_dealloc(list,NR_R12); }
+
+
+ { if we didn't get the GOT pointer till now, we've to calculate it now }
+(*
+ if not(gotgot) and (pi_needs_got in current_procinfo.flags) then
+ case target_info.system of
+ system_powerpc_darwin:
+ begin
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_LR));
+ fillchar(cond,sizeof(cond),0);
+ cond.simple:=false;
+ cond.bo:=20;
+ cond.bi:=31;
+ instr:=taicpu.op_sym(A_BCL,current_procinfo.gotlabel);
+ instr.setcondition(cond);
+ list.concat(instr);
+ a_label(list,current_procinfo.gotlabel);
+ list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR));
+ list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0));
+ end;
+ else
+ begin
+ a_reg_alloc(list,NR_R31);
+ { place GOT ptr in r31 }
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R31,NR_LR));
+ end;
+ end;
+*)
+ { save the CR if necessary ( !!! always done currently ) }
+ { still need to find out where this has to be done for SystemV
+ a_reg_alloc(list,R_0);
+ list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
+ list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
+ new_reference(STACK_POINTER_REG,LA_CR)));
+ a_reg_dealloc(list,R_0); }
+ { now comes the AltiVec context save, not yet implemented !!! }
+
+ end;
+
+ procedure tcgppc.g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean);
+ { This procedure may be called before, as well as after g_stackframe_entry }
+ { is called. NOTE registers are not to be allocated through the register }
+ { allocator here, because the register colouring has already occured !! }
+
+ var
+ regcounter,firstregfpu,firstreggpr: TsuperRegister;
+ href : treference;
+ usesfpr,usesgpr,genret : boolean;
+ regcounter2, firstfpureg:Tsuperregister;
+ localsize: aint;
+ begin
+ { AltiVec context restore, not yet implemented !!! }
+
+ usesfpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
+ case target_info.abi of
+ abi_powerpc_aix:
+ firstfpureg := RS_F14;
+ abi_powerpc_sysv:
+ firstfpureg := RS_F14;
+ else
+ internalerror(2003122903);
+ end;
+ for regcounter:=firstfpureg to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ usesfpr:=true;
+ firstregfpu:=regcounter;
+ break;
+ end;
+ end;
+ end;
+
+ usesgpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for regcounter2:=RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr:=true;
+ firstreggpr:=regcounter2;
+ break;
+ end;
+ end;
+
+ localsize:= tppcprocinfo(current_procinfo).calc_stackframe_size;
+
+ { no return (blr) generated yet }
+ genret:=true;
+ if usesgpr or usesfpr then
+ begin
+ { address of gpr save area to r11 }
+ { (register allocator is no longer valid at this time and an add of 0 }
+ { is translated into a move, which is then registered with the register }
+ { allocator, causing a crash }
+ if (localsize <> 0) then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,localsize,NR_STACK_POINTER_REG,NR_R12)
+ else
+ list.concat(taicpu.op_reg_reg(A_MR,NR_R12,NR_STACK_POINTER_REG));
+ if usesfpr then
+ begin
+ reference_reset_base(href,NR_R12,-8);
+ for regcounter := firstregfpu to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ a_loadfpu_ref_reg(list,OS_F64,href,newreg(R_FPUREGISTER,regcounter,R_SUBNONE));
+ dec(href.offset,8);
+ end;
+ end;
+ inc(href.offset,4);
+ end
+ else
+ reference_reset_base(href,NR_R12,-4);
+
+ for regcounter2:=RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr:=true;
+ a_load_ref_reg(list,OS_INT,OS_INT,href,newreg(R_INTREGISTER,regcounter2,R_SUBNONE));
+ dec(href.offset,4);
+ end;
+ end;
+
+(*
+ reference_reset_base(href,r2,-((NR_R31-ord(firstreggpr)) shr 8+1)*4);
+ list.concat(taicpu.op_reg_ref(A_LMW,firstreggpr,href));
+*)
+ end;
+
+(*
+ { restore fprs and return }
+ if usesfpr then
+ begin
+ { address of fpr save area to r11 }
+ r:=NR_R12;
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,r,r,(ord(R_F31)-ord(firstregfpu.enum)+1)*8));
+ {
+ if (pi_do_call in current_procinfo.flags) then
+ a_call_name(objectlibrary.newasmsymbol('_restfpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+
+ '_x',AB_EXTERNAL,AT_FUNCTION))
+ else
+ { leaf node => lr haven't to be restored }
+ a_call_name('_restfpr_'+tostr(ord(firstregfpu.enum)-ord(R_F14)+14)+
+ '_l');
+ genret:=false;
+ }
+ end;
+*)
+
+
+ { if we didn't generate the return code, we've to do it now }
+ if genret then
+ begin
+ { adjust r1 }
+ { (register allocator is no longer valid at this time and an add of 0 }
+ { is translated into a move, which is then registered with the register }
+ { allocator, causing a crash }
+ if (not nostackframe) and
+ (localsize <> 0) then
+ a_op_const_reg(list,OP_ADD,OS_ADDR,localsize,NR_R1);
+ { load link register? }
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ if (pi_do_call in current_procinfo.flags) then
+ begin
+ case target_info.abi of
+ abi_powerpc_aix:
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_AIX);
+ abi_powerpc_sysv:
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_SYSV);
+ end;
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
+ list.concat(taicpu.op_reg(A_MTLR,NR_R0));
+ end;
+
+ { restore the CR if necessary from callers frame}
+ if target_info.abi = abi_powerpc_aix then
+ if false then { Not needed at the moment. }
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
+ list.concat(taicpu.op_reg_reg(A_MTSPR,NR_R0,NR_CR));
+ a_reg_dealloc(list,NR_R0);
+ end;
+ end;
+
+ list.concat(taicpu.op_none(A_BLR));
+ end;
+ end;
+
+ function tcgppc.save_regs(list : taasmoutput):longint;
+ {Generates code which saves used non-volatile registers in
+ the save area right below the address the stackpointer point to.
+ Returns the actual used save area size.}
+
+ var regcounter,firstregfpu,firstreggpr: TSuperRegister;
+ usesfpr,usesgpr: boolean;
+ href : treference;
+ offset: aint;
+ regcounter2, firstfpureg: Tsuperregister;
+ begin
+ usesfpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
+ case target_info.abi of
+ abi_powerpc_aix:
+ firstfpureg := RS_F14;
+ abi_powerpc_sysv:
+ firstfpureg := RS_F9;
+ else
+ internalerror(2003122903);
+ end;
+ for regcounter:=firstfpureg to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ usesfpr:=true;
+ firstregfpu:=regcounter;
+ break;
+ end;
+ end;
+ end;
+ usesgpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for regcounter2:=RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr:=true;
+ firstreggpr:=regcounter2;
+ break;
+ end;
+ end;
+ offset:= 0;
+
+ { save floating-point registers }
+ if usesfpr then
+ for regcounter := firstregfpu to RS_F31 do
+ begin
+ offset:= offset - 8;
+ reference_reset_base(href, NR_STACK_POINTER_REG, offset);
+ list.concat(taicpu.op_reg_ref(A_STFD, tregister(regcounter), href));
+ end;
+ (* Optimiztion in the future: a_call_name(list,'_savefXX'); *)
+
+ { save gprs in gpr save area }
+ if usesgpr then
+ if firstreggpr < RS_R30 then
+ begin
+ offset:= offset - 4 * (RS_R31 - firstreggpr + 1);
+ reference_reset_base(href,NR_STACK_POINTER_REG,offset);
+ list.concat(taicpu.op_reg_ref(A_STMW,tregister(firstreggpr),href));
+ {STMW stores multiple registers}
+ end
+ else
+ begin
+ for regcounter := firstreggpr to RS_R31 do
+ begin
+ offset:= offset - 4;
+ reference_reset_base(href, NR_STACK_POINTER_REG, offset);
+ list.concat(taicpu.op_reg_ref(A_STW, newreg(R_INTREGISTER,regcounter,R_SUBWHOLE), href));
+ end;
+ end;
+
+ { now comes the AltiVec context save, not yet implemented !!! }
+
+ save_regs:= -offset;
+ end;
+
+ procedure tcgppc.restore_regs(list : taasmoutput);
+ {Generates code which restores used non-volatile registers from
+ the save area right below the address the stackpointer point to.}
+
+ var regcounter,firstregfpu,firstreggpr: TSuperRegister;
+ usesfpr,usesgpr: boolean;
+ href : treference;
+ offset: integer;
+ regcounter2, firstfpureg: Tsuperregister;
+
+ begin
+ usesfpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
+ case target_info.abi of
+ abi_powerpc_aix:
+ firstfpureg := RS_F14;
+ abi_powerpc_sysv:
+ firstfpureg := RS_F9;
+ else
+ internalerror(2003122903);
+ end;
+ for regcounter:=firstfpureg to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ usesfpr:=true;
+ firstregfpu:=regcounter;
+ break;
+ end;
+ end;
+ end;
+
+ usesgpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for regcounter2:=RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr:=true;
+ firstreggpr:=regcounter2;
+ break;
+ end;
+ end;
+
+ offset:= 0;
+
+ { restore fp registers }
+ if usesfpr then
+ for regcounter := firstregfpu to RS_F31 do
+ begin
+ offset:= offset - 8;
+ reference_reset_base(href, NR_STACK_POINTER_REG, offset);
+ list.concat(taicpu.op_reg_ref(A_LFD, newreg(R_FPUREGISTER,regcounter,R_SUBWHOLE), href));
+ end;
+ (* Optimiztion in the future: a_call_name(list,'_restfXX'); *)
+
+ { restore gprs }
+ if usesgpr then
+ if firstreggpr < RS_R30 then
+ begin
+ offset:= offset - 4 * (RS_R31 - firstreggpr + 1);
+ reference_reset_base(href,NR_STACK_POINTER_REG,offset); //-220
+ list.concat(taicpu.op_reg_ref(A_LMW,tregister(firstreggpr),href));
+ {LMW loads multiple registers}
+ end
+ else
+ begin
+ for regcounter := firstreggpr to RS_R31 do
+ begin
+ offset:= offset - 4;
+ reference_reset_base(href, NR_STACK_POINTER_REG, offset);
+ list.concat(taicpu.op_reg_ref(A_LWZ, newreg(R_INTREGISTER,regcounter,R_SUBWHOLE), href));
+ end;
+ end;
+
+ { now comes the AltiVec context restore, not yet implemented !!! }
+ end;
+
+
+ procedure tcgppc.g_stackframe_entry_mac(list : taasmoutput;localsize : longint);
+ (* NOT IN USE *)
+
+ { generated the entry code of a procedure/function. Note: localsize is the }
+ { sum of the size necessary for local variables and the maximum possible }
+ { combined size of ALL the parameters of a procedure called by the current }
+ { one }
+
+ const
+ macosLinkageAreaSize = 24;
+
+ var
+ href : treference;
+ registerSaveAreaSize : longint;
+
+ begin
+ if (localsize mod 8) <> 0 then
+ internalerror(58991);
+ { CR and LR only have to be saved in case they are modified by the current }
+ { procedure, but currently this isn't checked, so save them always }
+ { following is the entry code as described in "Altivec Programming }
+ { Interface Manual", bar the saving of AltiVec registers }
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+ a_reg_alloc(list,NR_R0);
+
+ { save return address in callers frame}
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_LR));
+ { ... in caller's frame }
+ reference_reset_base(href,NR_STACK_POINTER_REG,8);
+ list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
+ a_reg_dealloc(list,NR_R0);
+
+ { save non-volatile registers in callers frame}
+ registerSaveAreaSize:= save_regs(list);
+
+ { save the CR if necessary in callers frame ( !!! always done currently ) }
+ a_reg_alloc(list,NR_R0);
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_CR));
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
+ list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
+ a_reg_dealloc(list,NR_R0);
+
+ (*
+ { save pointer to incoming arguments }
+ list.concat(taicpu.op_reg_reg_const(A_ORI,R_31,STACK_POINTER_REG,0));
+ *)
+
+ (*
+ a_reg_alloc(list,R_12);
+
+ { 0 or 8 based on SP alignment }
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,
+ R_12,STACK_POINTER_REG,0,28,28));
+ { add in stack length }
+ list.concat(taicpu.op_reg_reg_const(A_SUBFIC,R_12,R_12,
+ -localsize));
+ { establish new alignment }
+ list.concat(taicpu.op_reg_reg_reg(A_STWUX,STACK_POINTER_REG,STACK_POINTER_REG,R_12));
+
+ a_reg_dealloc(list,R_12);
+ *)
+
+ { allocate stack frame }
+ localsize:= align(localsize + macosLinkageAreaSize + registerSaveAreaSize, 16);
+ inc(localsize,tg.lasttemp);
+ localsize:=align(localsize,16);
+ //tppcprocinfo(current_procinfo).localsize:=localsize;
+
+ if (localsize <> 0) then
+ begin
+ if (localsize <= high(smallint)) then
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,-localsize);
+ a_load_store(list,A_STWU,NR_STACK_POINTER_REG,href);
+ end
+ else
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,0);
+ href.index := NR_R11;
+ a_reg_alloc(list,href.index);
+ a_load_const_reg(list,OS_S32,-localsize,href.index);
+ a_load_store(list,A_STWUX,NR_STACK_POINTER_REG,href);
+ a_reg_dealloc(list,href.index);
+ end;
+ end;
+ end;
+
+ procedure tcgppc.g_return_from_proc_mac(list : taasmoutput;parasize : aint);
+ (* NOT IN USE *)
+
+ var
+ href : treference;
+ begin
+ a_reg_alloc(list,NR_R0);
+
+ { restore stack pointer }
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_SP);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_STACK_POINTER_REG,href));
+ (*
+ list.concat(taicpu.op_reg_reg_const(A_ORI,NR_STACK_POINTER_REG,R_31,0));
+ *)
+
+ { restore the CR if necessary from callers frame
+ ( !!! always done currently ) }
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
+ list.concat(taicpu.op_reg_reg(A_MTSPR,NR_R0,NR_CR));
+ a_reg_dealloc(list,NR_R0);
+
+ (*
+ { restore return address from callers frame }
+ reference_reset_base(href,STACK_POINTER_REG,8);
+ list.concat(taicpu.op_reg_ref(A_LWZ,R_0,href));
+ *)
+
+ { restore non-volatile registers from callers frame }
+ restore_regs(list);
+
+ (*
+ { return to caller }
+ list.concat(taicpu.op_reg_reg(A_MTSPR,R_0,R_LR));
+ list.concat(taicpu.op_none(A_BLR));
+ *)
+
+ { restore return address from callers frame }
+ reference_reset_base(href,NR_STACK_POINTER_REG,8);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
+
+ { return to caller }
+ list.concat(taicpu.op_reg_reg(A_MTSPR,NR_R0,NR_LR));
+ list.concat(taicpu.op_none(A_BLR));
+ end;
+
+
+ procedure tcgppc.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
+
+ var
+ ref2, tmpref: treference;
+
+ begin
+ ref2 := ref;
+ fixref(list,ref2);
+ if assigned(ref2.symbol) then
+ begin
+ if target_info.system = system_powerpc_macos then
+ begin
+ if macos_direct_globals then
+ begin
+ reference_reset(tmpref);
+ tmpref.offset := ref2.offset;
+ tmpref.symbol := ref2.symbol;
+ tmpref.base := NR_NO;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,NR_RTOC,tmpref));
+ end
+ else
+ begin
+ reference_reset(tmpref);
+ tmpref.symbol := ref2.symbol;
+ tmpref.offset := 0;
+ tmpref.base := NR_RTOC;
+ list.concat(taicpu.op_reg_ref(A_LWZ,r,tmpref));
+
+ if ref2.offset <> 0 then
+ begin
+ reference_reset(tmpref);
+ tmpref.offset := ref2.offset;
+ tmpref.base:= r;
+ list.concat(taicpu.op_reg_ref(A_LA,r,tmpref));
+ end;
+ end;
+
+ if ref2.base <> NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,ref2.base));
+
+ //list.concat(tai_comment.create(strpnew('*** a_loadaddr_ref_reg')));
+ end
+ else
+ begin
+
+ { add the symbol's value to the base of the reference, and if the }
+ { reference doesn't have a base, create one }
+ reference_reset(tmpref);
+ tmpref.offset := ref2.offset;
+ tmpref.symbol := ref2.symbol;
+ tmpref.relsymbol := ref2.relsymbol;
+ tmpref.refaddr := addr_hi;
+ if ref2.base<> NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIS,r,
+ ref2.base,tmpref));
+ end
+ else
+ list.concat(taicpu.op_reg_ref(A_LIS,r,tmpref));
+ tmpref.base := NR_NO;
+ tmpref.refaddr := addr_lo;
+ { can be folded with one of the next instructions by the }
+ { optimizer probably }
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r,tmpref));
+ end
+ end
+ else if ref2.offset <> 0 Then
+ if ref2.base <> NR_NO then
+ a_op_const_reg_reg(list,OP_ADD,OS_32,ref2.offset,ref2.base,r)
+ { FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never}
+ { occurs, so now only ref.offset has to be loaded }
+ else
+ a_load_const_reg(list,OS_32,ref2.offset,r)
+ else if ref.index <> NR_NO Then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref2.base,ref2.index))
+ else if (ref2.base <> NR_NO) and
+ (r <> ref2.base) then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref2.base,r)
+ else
+ list.concat(taicpu.op_reg_const(A_LI,r,0));
+ end;
+
+{ ************* concatcopy ************ }
+
+{$ifndef ppc603}
+ const
+ maxmoveunit = 8;
+{$else ppc603}
+ const
+ maxmoveunit = 4;
+{$endif ppc603}
+
+ procedure tcgppc.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);
+
+ var
+ countreg: TRegister;
+ src, dst: TReference;
+ lab: tasmlabel;
+ count, count2: aint;
+ size: tcgsize;
+
+ begin
+{$ifdef extdebug}
+ if len > high(longint) then
+ internalerror(2002072704);
+{$endif extdebug}
+
+ { make sure short loads are handled as optimally as possible }
+ if (len <= maxmoveunit) and
+ (byte(len) in [1,2,4,8]) then
+ begin
+ if len < 8 then
+ begin
+ size := int_cgsize(len);
+ a_load_ref_ref(list,size,size,source,dest);
+ end
+ else
+ begin
+ a_reg_alloc(list,NR_F0);
+ a_loadfpu_ref_reg(list,OS_F64,source,NR_F0);
+ a_loadfpu_reg_ref(list,OS_F64,NR_F0,dest);
+ a_reg_dealloc(list,NR_F0);
+ end;
+ exit;
+ end;
+
+ count := len div maxmoveunit;
+
+ reference_reset(src);
+ reference_reset(dst);
+ { load the address of source into src.base }
+ if (count > 4) or
+ not issimpleref(source) or
+ ((source.index <> NR_NO) and
+ ((source.offset + longint(len)) > high(smallint))) then
+ begin
+ src.base := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_loadaddr_ref_reg(list,source,src.base);
+ end
+ else
+ begin
+ src := source;
+ end;
+ { load the address of dest into dst.base }
+ if (count > 4) or
+ not issimpleref(dest) or
+ ((dest.index <> NR_NO) and
+ ((dest.offset + longint(len)) > high(smallint))) then
+ begin
+ dst.base := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_loadaddr_ref_reg(list,dest,dst.base);
+ end
+ else
+ begin
+ dst := dest;
+ end;
+
+{$ifndef ppc603}
+ if count > 4 then
+ { generate a loop }
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ inc(dst.offset,8);
+ inc(src.offset,8);
+ list.concat(taicpu.op_reg_reg_const(A_SUBI,src.base,src.base,8));
+ list.concat(taicpu.op_reg_reg_const(A_SUBI,dst.base,dst.base,8));
+ countreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,count,countreg);
+ { explicitely allocate R_0 since it can be used safely here }
+ { (for holding date that's being copied) }
+ a_reg_alloc(list,NR_F0);
+ objectlibrary.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_reg_const(A_SUBIC_,countreg,countreg,1));
+ list.concat(taicpu.op_reg_ref(A_LFDU,NR_F0,src));
+ list.concat(taicpu.op_reg_ref(A_STFDU,NR_F0,dst));
+ a_jmp(list,A_BC,C_NE,0,lab);
+ a_reg_dealloc(list,NR_F0);
+ len := len mod 8;
+ end;
+
+ count := len div 8;
+ if count > 0 then
+ { unrolled loop }
+ begin
+ a_reg_alloc(list,NR_F0);
+ for count2 := 1 to count do
+ begin
+ a_loadfpu_ref_reg(list,OS_F64,src,NR_F0);
+ a_loadfpu_reg_ref(list,OS_F64,NR_F0,dst);
+ inc(src.offset,8);
+ inc(dst.offset,8);
+ end;
+ a_reg_dealloc(list,NR_F0);
+ len := len mod 8;
+ end;
+
+ if (len and 4) <> 0 then
+ begin
+ a_reg_alloc(list,NR_R0);
+ a_load_ref_reg(list,OS_32,OS_32,src,NR_R0);
+ a_load_reg_ref(list,OS_32,OS_32,NR_R0,dst);
+ inc(src.offset,4);
+ inc(dst.offset,4);
+ a_reg_dealloc(list,NR_R0);
+ end;
+{$else not ppc603}
+ if count > 4 then
+ { generate a loop }
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 4. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ inc(dst.offset,4);
+ inc(src.offset,4);
+ list.concat(taicpu.op_reg_reg_const(A_SUBI,src.base,src.base,4));
+ list.concat(taicpu.op_reg_reg_const(A_SUBI,dst.base,dst.base,4));
+ countreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,count,countreg);
+ { explicitely allocate R_0 since it can be used safely here }
+ { (for holding date that's being copied) }
+ a_reg_alloc(list,NR_R0);
+ objectlibrary.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_reg_const(A_SUBIC_,countreg,countreg,1));
+ list.concat(taicpu.op_reg_ref(A_LWZU,NR_R0,src));
+ list.concat(taicpu.op_reg_ref(A_STWU,NR_R0,dst));
+ a_jmp(list,A_BC,C_NE,0,lab);
+ a_reg_dealloc(list,NR_R0);
+ len := len mod 4;
+ end;
+
+ count := len div 4;
+ if count > 0 then
+ { unrolled loop }
+ begin
+ a_reg_alloc(list,NR_R0);
+ for count2 := 1 to count do
+ begin
+ a_load_ref_reg(list,OS_32,OS_32,src,NR_R0);
+ a_load_reg_ref(list,OS_32,OS_32,NR_R0,dst);
+ inc(src.offset,4);
+ inc(dst.offset,4);
+ end;
+ a_reg_dealloc(list,NR_R0);
+ len := len mod 4;
+ end;
+{$endif not ppc603}
+ { copy the leftovers }
+ if (len and 2) <> 0 then
+ begin
+ a_reg_alloc(list,NR_R0);
+ a_load_ref_reg(list,OS_16,OS_16,src,NR_R0);
+ a_load_reg_ref(list,OS_16,OS_16,NR_R0,dst);
+ inc(src.offset,2);
+ inc(dst.offset,2);
+ a_reg_dealloc(list,NR_R0);
+ end;
+ if (len and 1) <> 0 then
+ begin
+ a_reg_alloc(list,NR_R0);
+ a_load_ref_reg(list,OS_8,OS_8,src,NR_R0);
+ a_load_reg_ref(list,OS_8,OS_8,NR_R0,dst);
+ a_reg_dealloc(list,NR_R0);
+ end;
+ end;
+
+
+ procedure tcgppc.g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef);
+ var
+ hl : tasmlabel;
+ begin
+ if not(cs_check_overflow in aktlocalswitches) then
+ exit;
+ objectlibrary.getjumplabel(hl);
+ if not ((def.deftype=pointerdef) or
+ ((def.deftype=orddef) and
+ (torddef(def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
+ bool8bit,bool16bit,bool32bit]))) then
+ begin
+ list.concat(taicpu.op_reg(A_MCRXR,NR_CR7));
+ a_jmp(list,A_BC,C_NO,7,hl)
+ end
+ else
+ a_jmp_cond(list,OC_AE,hl);
+ a_call_name(list,'FPC_OVERFLOW');
+ a_label(list,hl);
+ end;
+
+
+ procedure tcgppc.g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);
+
+ procedure loadvmttor11;
+ var
+ href : treference;
+ begin
+ reference_reset_base(href,NR_R3,0);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
+ end;
+
+ procedure op_onr11methodaddr;
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_R11,procdef._class.vmtmethodoffset(procdef.extnumber));
+ if not((longint(href.offset) >= low(smallint)) and
+ (longint(href.offset) <= high(smallint))) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS,NR_R11,NR_R11,
+ smallint((href.offset shr 16)+ord(smallint(href.offset and $ffff) < 0))));
+ href.offset := smallint(href.offset and $ffff);
+ end;
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R11,href));
+ list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
+ list.concat(taicpu.op_none(A_BCTR));
+ end;
+
+ var
+ make_global : boolean;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef._class) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>objectsymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ (cs_create_smart in aktmoduleswitches) or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ { case 4 }
+ if po_virtualmethod in procdef.procoptions then
+ begin
+ loadvmttor11;
+ op_onr11methodaddr;
+ end
+ { case 0 }
+ else
+ list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+
+{***************** This is private property, keep out! :) *****************}
+
+ function tcgppc.issimpleref(const ref: treference): boolean;
+
+ begin
+ if (ref.base = NR_NO) and
+ (ref.index <> NR_NO) then
+ internalerror(200208101);
+ result :=
+ not(assigned(ref.symbol)) and
+ (((ref.index = NR_NO) and
+ (ref.offset >= low(smallint)) and
+ (ref.offset <= high(smallint))) or
+ ((ref.index <> NR_NO) and
+ (ref.offset = 0)));
+ end;
+
+
+ function tcgppc.fixref(list: taasmoutput; var ref: treference): boolean;
+
+ var
+ tmpreg: tregister;
+ begin
+ result := false;
+ if (ref.base = NR_NO) then
+ begin
+ ref.base := ref.index;
+ ref.index := NR_NO;
+ end;
+ if (ref.base <> NR_NO) then
+ begin
+ if (ref.index <> NR_NO) and
+ ((ref.offset <> 0) or assigned(ref.symbol)) then
+ begin
+ result := true;
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ list.concat(taicpu.op_reg_reg_reg(
+ A_ADD,tmpreg,ref.base,ref.index));
+ ref.index := NR_NO;
+ ref.base := tmpreg;
+ end
+ end
+ else
+ if ref.index <> NR_NO then
+ internalerror(200208102);
+ end;
+
+
+ { find out whether a is of the form 11..00..11b or 00..11...00. If }
+ { that's the case, we can use rlwinm to do an AND operation }
+ function tcgppc.get_rlwi_const(a: aint; var l1, l2: longint): boolean;
+
+ var
+ temp : longint;
+ testbit : aint;
+ compare: boolean;
+
+ begin
+ get_rlwi_const := false;
+ if (a = 0) or (a = -1) then
+ exit;
+ { start with the lowest bit }
+ testbit := 1;
+ { check its value }
+ compare := boolean(a and testbit);
+ { find out how long the run of bits with this value is }
+ { (it's impossible that all bits are 1 or 0, because in that case }
+ { this function wouldn't have been called) }
+ l1 := 31;
+ while (((a and testbit) <> 0) = compare) do
+ begin
+ testbit := testbit shl 1;
+ dec(l1);
+ end;
+
+ { check the length of the run of bits that comes next }
+ compare := not compare;
+ l2 := l1;
+ while (((a and testbit) <> 0) = compare) and
+ (l2 >= 0) do
+ begin
+ testbit := testbit shl 1;
+ dec(l2);
+ end;
+
+ { and finally the check whether the rest of the bits all have the }
+ { same value }
+ compare := not compare;
+ temp := l2;
+ if temp >= 0 then
+ if (a shr (31-temp)) <> ((-ord(compare)) shr (31-temp)) then
+ exit;
+
+ { we have done "not(not(compare))", so compare is back to its }
+ { initial value. If the lowest bit was 0, a is of the form }
+ { 00..11..00 and we need "rlwinm reg,reg,0,l2+1,l1", (+1 }
+ { because l2 now contains the position of the last zero of the }
+ { first run instead of that of the first 1) so switch l1 and l2 }
+ { in that case (we will generate "rlwinm reg,reg,0,l1,l2") }
+ if not compare then
+ begin
+ temp := l1;
+ l1 := l2+1;
+ l2 := temp;
+ end
+ else
+ { otherwise, l1 currently contains the position of the last }
+ { zero instead of that of the first 1 of the second run -> +1 }
+ inc(l1);
+ { the following is the same as "if l1 = -1 then l1 := 31;" }
+ l1 := l1 and 31;
+ l2 := l2 and 31;
+ get_rlwi_const := true;
+ end;
+
+
+ procedure tcgppc.a_load_store(list:taasmoutput;op: tasmop;reg:tregister;
+ ref: treference);
+
+ var
+ tmpreg: tregister;
+ tmpref: treference;
+ largeOffset: Boolean;
+
+ begin
+ tmpreg := NR_NO;
+
+ if target_info.system = system_powerpc_macos then
+ begin
+ largeOffset:= (cardinal(ref.offset-low(smallint)) >
+ high(smallint)-low(smallint));
+
+ if assigned(ref.symbol) then
+ begin {Load symbol's value}
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+
+ reference_reset(tmpref);
+ tmpref.symbol := ref.symbol;
+ tmpref.base := NR_RTOC;
+
+ if macos_direct_globals then
+ list.concat(taicpu.op_reg_ref(A_LA,tmpreg,tmpref))
+ else
+ list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
+ end;
+
+ if largeOffset then
+ begin {Add hi part of offset}
+ reference_reset(tmpref);
+
+ if Smallint(Lo(ref.offset)) < 0 then
+ tmpref.offset := Hi(ref.offset) + 1 {Compensate when lo part is negative}
+ else
+ tmpref.offset := Hi(ref.offset);
+
+ if (tmpreg <> NR_NO) then
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg, tmpreg,tmpref))
+ else
+ begin
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
+ end;
+ end;
+
+ if (tmpreg <> NR_NO) then
+ begin
+ {Add content of base register}
+ if ref.base <> NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,
+ ref.base,tmpreg));
+
+ {Make ref ready to be used by op}
+ ref.symbol:= nil;
+ ref.base:= tmpreg;
+ if largeOffset then
+ ref.offset := Smallint(Lo(ref.offset));
+
+ list.concat(taicpu.op_reg_ref(op,reg,ref));
+ //list.concat(tai_comment.create(strpnew('*** a_load_store indirect global')));
+ end
+ else
+ list.concat(taicpu.op_reg_ref(op,reg,ref));
+ end
+ else {if target_info.system <> system_powerpc_macos}
+ begin
+ if assigned(ref.symbol) or
+ (cardinal(ref.offset-low(smallint)) >
+ high(smallint)-low(smallint)) then
+ begin
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ reference_reset(tmpref);
+ tmpref.symbol := ref.symbol;
+ tmpref.relsymbol := ref.relsymbol;
+ tmpref.offset := ref.offset;
+ tmpref.refaddr := addr_hi;
+ if ref.base <> NR_NO then
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
+ ref.base,tmpref))
+ else
+ list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
+ ref.base := tmpreg;
+ ref.refaddr := addr_lo;
+ list.concat(taicpu.op_reg_ref(op,reg,ref));
+ end
+ else
+ list.concat(taicpu.op_reg_ref(op,reg,ref));
+ end;
+ end;
+
+
+ procedure tcgppc.a_jmp(list: taasmoutput; op: tasmop; c: tasmcondflag;
+ crval: longint; l: tasmlabel);
+ var
+ p: taicpu;
+
+ begin
+ p := taicpu.op_sym(op,l);
+ if op <> A_B then
+ create_cond_norm(c,crval,p.condition);
+ p.is_jmp := true;
+ list.concat(p)
+ end;
+
+
+ procedure tcg64fppc.a_op64_reg_reg(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+ begin
+ a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
+ end;
+
+
+ procedure tcg64fppc.a_op64_const_reg(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
+ begin
+ a_op64_const_reg_reg(list,op,size,value,reg,reg);
+ end;
+
+
+ procedure tcg64fppc.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
+ end;
+ OP_ADD:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDC,regdst.reglo,regsrc1.reglo,regsrc2.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDE,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
+ end;
+ OP_SUB:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUBC,regdst.reglo,regsrc2.reglo,regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBFE,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
+ end;
+ else
+ internalerror(2002072801);
+ end;
+ end;
+
+
+ procedure tcg64fppc.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
+
+ const
+ ops: array[boolean,1..3] of tasmop = ((A_ADDIC,A_ADDC,A_ADDZE),
+ (A_SUBIC,A_SUBC,A_ADDME));
+ var
+ tmpreg: tregister;
+ tmpreg64: tregister64;
+ issub: boolean;
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(value),regsrc.reglo,regdst.reglo);
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(value shr 32),regsrc.reghi,
+ regdst.reghi);
+ end;
+ OP_ADD, OP_SUB:
+ begin
+ if (value < 0) then
+ begin
+ if op = OP_ADD then
+ op := OP_SUB
+ else
+ op := OP_ADD;
+ value := -value;
+ end;
+ if (longint(value) <> 0) then
+ begin
+ issub := op = OP_SUB;
+ if (value > 0) and
+ (value-ord(issub) <= 32767) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(ops[issub,1],
+ regdst.reglo,regsrc.reglo,longint(value)));
+ list.concat(taicpu.op_reg_reg(ops[issub,3],
+ regdst.reghi,regsrc.reghi));
+ end
+ else if ((value shr 32) = 0) then
+ begin
+ tmpreg := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ cg.a_load_const_reg(list,OS_32,cardinal(value),tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(ops[issub,2],
+ regdst.reglo,regsrc.reglo,tmpreg));
+ list.concat(taicpu.op_reg_reg(ops[issub,3],
+ regdst.reghi,regsrc.reghi));
+ end
+ else
+ begin
+ tmpreg64.reglo := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ tmpreg64.reghi := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load64_const_reg(list,value,tmpreg64);
+ a_op64_reg_reg_reg(list,op,size,tmpreg64,regsrc,regdst);
+ end
+ end
+ else
+ begin
+ cg.a_load_reg_reg(list,OS_INT,OS_INT,regsrc.reglo,regdst.reglo);
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(value shr 32),regsrc.reghi,
+ regdst.reghi);
+ end;
+ end;
+ else
+ internalerror(2002072802);
+ end;
+ end;
+
+
+begin
+ cg := tcgppc.create;
+ cg64 :=tcg64fppc.create;
+end.
diff --git a/compiler/powerpc/cpubase.pas b/compiler/powerpc/cpubase.pas
new file mode 100644
index 0000000000..dd94e6271c
--- /dev/null
+++ b/compiler/powerpc/cpubase.pas
@@ -0,0 +1,558 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the PowerPC
+
+ 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 contains the base types for the PowerPC
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ strings,globtype,
+ cutils,cclasses,aasmbase,cpuinfo,cgbase;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp=(A_None,
+ { normal opcodes }
+ a_add, a_add_, a_addo, a_addo_, a_addc, a_addc_, a_addco, a_addco_,
+ a_adde, a_adde_, a_addeo, a_addeo_, a_addi, a_addic, a_addic_, a_addis,
+ a_addme, a_addme_, a_addmeo, a_addmeo_, a_addze, a_addze_, a_addzeo,
+ a_addzeo_, a_and, a_and_, a_andc, a_andc_, a_andi_, a_andis_, a_b,
+ a_ba, a_bl, a_bla, a_bc, a_bca, a_bcl, a_bcla, a_bcctr, a_bcctrl, a_bclr,
+ a_bclrl, a_cmp, a_cmpi, a_cmpl, a_cmpli, a_cntlzw, a_cntlzw_, a_crand,
+ a_crandc, a_creqv, a_crnand, a_crnor, a_cror, a_crorc, a_crxor, a_dcba,
+ a_dcbf, a_dcbi, a_dcbst, a_dcbt, a_dcbtst, a_dcbz, a_divw, a_divw_, a_divwo, a_divwo_,
+ a_divwu, a_divwu_, a_divwuo, a_divwuo_, a_eciwx, a_ecowx, a_eieio, a_eqv,
+ a_eqv_, a_extsb, a_extsb_, a_extsh, a_extsh_, a_fabs, a_fabs_, a_fadd,
+ a_fadd_, a_fadds, a_fadds_, a_fcmpo, a_fcmpu, a_fctiw, a_fctw_, a_fctwz,
+ a_fctwz_, a_fdiv, a_fdiv_, a_fdivs, a_fdivs_, a_fmadd, a_fmadd_, a_fmadds,
+ a_fmadds_, a_fmr, a_fmsub, a_fmsub_, a_fmsubs, a_fmsubs_, a_fmul, a_fmul_,
+ a_fmuls, a_fmuls_, a_fnabs, a_fnabs_, a_fneg, a_fneg_, a_fnmadd,
+ a_fnmadd_, a_fnmadds, a_fnmadds_, a_fnmsub, a_fnmsub_, a_fnmsubs,
+ a_fnmsubs_, a_fres, a_fres_, a_frsp, a_frsp_, a_frsqrte, a_frsqrte_,
+ a_fsel, a_fsel_, a_fsqrt, a_fsqrt_, a_fsqrts, a_fsqrts_, a_fsub, a_fsub_,
+ a_fsubs, a_fsubs_, a_icbi, a_isync, a_lbz, a_lbzu, a_lbzux, a_lbzx,
+ a_lfd, a_lfdu, a_lfdux, a_lfdx, a_lfs, a_lfsu, a_lfsux, a_lfsx, a_lha,
+ a_lhau, a_lhaux, a_lhax, a_hbrx, a_lhz, a_lhzu, a_lhzux, a_lhzx, a_lmw,
+ a_lswi, a_lswx, a_lwarx, a_lwbrx, a_lwz, a_lwzu, a_lwzux, a_lwzx, a_mcrf,
+ a_mcrfs, a_mcrxr, a_mfcr, a_mffs, a_mffs_, a_mfmsr, a_mfspr, a_mfsr,
+ a_mfsrin, a_mftb, a_mtcrf, a_mtfsb0, a_mtfsb1, a_mtfsf, a_mtfsf_,
+ a_mtfsfi, a_mtfsfi_, a_mtmsr, a_mtspr, a_mtsr, a_mtsrin, a_mulhw,
+ a_mulhw_, a_mulhwu, a_mulhwu_, a_mulli, a_mullw, a_mullw_, a_mullwo,
+ a_mullwo_, a_nand, a_nand_, a_neg, a_neg_, a_nego, a_nego_, a_nor, a_nor_,
+ a_or, a_or_, a_orc, a_orc_, a_ori, a_oris, a_rfi, a_rlwimi, a_rlwimi_,
+ a_rlwinm, a_rlwinm_, a_rlwnm, a_rlwnm_, a_sc, a_slw, a_slw_, a_sraw, a_sraw_,
+ a_srawi, a_srawi_,a_srw, a_srw_, a_stb, a_stbu, a_stbux, a_stbx, a_stfd,
+ a_stfdu, a_stfdux, a_stfdx, a_stfiwx, a_stfs, a_stfsu, a_stfsux, a_stfsx,
+ a_sth, a_sthbrx, a_sthu, a_sthux, a_sthx, a_stmw, a_stswi, a_stswx, a_stw,
+ a_stwbrx, a_stwcx_, a_stwu, a_stwux, a_stwx, a_subf, a_subf_, a_subfo,
+ a_subfo_, a_subfc, a_subfc_, a_subfco, a_subfco_, a_subfe, a_subfe_,
+ a_subfeo, a_subfeo_, a_subfic, a_subfme, a_subfme_, a_subfmeo, a_subfmeo_,
+ a_subfze, a_subfze_, a_subfzeo, a_subfzeo_, a_sync, a_tlbia, a_tlbie,
+ a_tlbsync, a_tw, a_twi, a_xor, a_xor_, a_xori, a_xoris,
+ { simplified mnemonics }
+ a_subi, a_subis, a_subic, a_subic_, a_sub, a_sub_, a_subo, a_subo_,
+ a_subc, a_subc_, a_subco, a_subco_, a_cmpwi, a_cmpw, a_cmplwi, a_cmplw,
+ a_extlwi, a_extlwi_, a_extrwi, a_extrwi_, a_inslwi, a_inslwi_, a_insrwi,
+ a_insrwi_, a_rotlwi, a_rotlwi_, a_rotlw, a_rotlw_, a_slwi, a_slwi_,
+ a_srwi, a_srwi_, a_clrlwi, a_clrlwi_, a_clrrwi, a_clrrwi_, a_clrslwi,
+ a_clrslwi_, a_blr, a_bctr, a_blrl, a_bctrl, a_crset, a_crclr, a_crmove,
+ a_crnot, a_mt {move to special prupose reg}, a_mf {move from special purpose reg},
+ a_nop, a_li, a_lis, a_la, a_mr, a_mr_, a_not, a_not_, a_mtcr, a_mtlr, a_mflr,
+ a_mtctr, a_mfctr);
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[8];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rppcnor.inc}-1;
+ totherregisterset = set of tregisterindex;
+
+ const
+ maxvarregs = 32-6; { 32 int registers - r0 - stackpointer - r2 - 3 scratch registers }
+ maxfpuvarregs = 28; { 32 fpuregisters - some scratch registers (minimally 2) }
+ { Available Superregisters }
+ {$i rppcsup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE=R_SUBNONE;
+
+ { Available Registers }
+ {$i rppccon.inc}
+
+ { Integer Super registers first and last }
+ first_int_imreg = $20;
+
+ { Float Super register first and last }
+ first_fpu_imreg = $20;
+
+ { MM Super register first and last }
+ first_mm_imreg = $20;
+
+{$warning TODO Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rppcnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i rppcstab.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i rppcdwrf.inc}
+ );
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCondFlag = (C_None { unconditional jumps },
+ { conditions when not using ctr decrement etc }
+ C_LT,C_LE,C_EQ,C_GE,C_GT,C_NL,C_NE,C_NG,C_SO,C_NS,C_UN,C_NU,
+ { conditions when using ctr decrement etc }
+ C_T,C_F,C_DNZ,C_DNZT,C_DNZF,C_DZ,C_DZT,C_DZF);
+
+ TDirHint = (DH_None,DH_Minus,DH_Plus);
+
+ const
+ { these are in the XER, but when moved to CR_x they correspond with the }
+ { bits below }
+ C_OV = C_GT;
+ C_CA = C_EQ;
+ C_NO = C_NG;
+ C_NC = C_NE;
+
+ type
+ TAsmCond = packed record
+ dirhint : tdirhint;
+ case simple: boolean of
+ false: (BO, BI: byte);
+ true: (
+ cond: TAsmCondFlag;
+ case byte of
+ 0: ();
+ { specifies in which part of the cr the bit has to be }
+ { tested for blt,bgt,beq,..,bnu }
+ 1: (cr: RS_CR0..RS_CR7);
+ { specifies the bit to test for bt,bf,bdz,..,bdzf }
+ 2: (crbit: byte)
+ );
+ end;
+
+ const
+ AsmCondFlag2BO: Array[C_T..C_DZF] of Byte =
+ (12,4,16,8,0,18,10,2);
+
+ AsmCondFlag2BOLT_NU: Array[C_LT..C_NU] of Byte =
+ (12,4,12,4,12,4,4,4,12,4,12,4);
+
+ AsmCondFlag2BI: Array[C_LT..C_NU] of Byte =
+ (0,1,2,0,1,0,2,1,3,3,3,3);
+
+ AsmCondFlagTF: Array[TAsmCondFlag] of Boolean =
+ (false,true,false,true,false,true,false,false,false,true,false,true,false,
+ true,false,false,true,false,false,true,false);
+
+ AsmCondFlag2Str: Array[TAsmCondFlag] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'lt','le','eq','ge','gt','nl','ne','ng','so','ns','un','nu',
+ 't','f','dnz','dnzt','dnzf','dz','dzt','dzf');
+
+ UpperAsmCondFlag2Str: Array[TAsmCondFlag] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'LT','LE','EQ','GE','GT','NL','NE','NG','SO','NS','UN','NU',
+ 'T','F','DNZ','DNZT','DNZF','DZ','DZT','DZF');
+
+
+ const
+ CondAsmOps=3;
+ CondAsmOp:array[0..CondAsmOps-1] of TasmOp=(
+ A_BC, A_TW, A_TWI
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlagsEnum = (F_EQ,F_NE,F_LT,F_LE,F_GT,F_GE,F_SO,F_FX,F_FEX,F_VX,F_OX);
+ TResFlags = record
+ cr: RS_CR0..RS_CR7;
+ flag: TResFlagsEnum;
+ end;
+
+ (*
+ const
+ { arrays for boolean location conversions }
+
+ flag_2_cond : array[TResFlags] of TAsmCond =
+ (C_E,C_NE,C_LT,C_LE,C_GT,C_GE,???????????????);
+ *)
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+ const
+ symaddr2str: array[trefaddr] of string[3] = ('','','@ha','@l','');
+
+ const
+ { MacOS only. Whether the direct data area (TOC) directly contain
+ global variables. Otherwise it contains pointers to global variables. }
+ macos_direct_globals = false;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 5;
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from rs6000.h (DBX_REGISTER_NUMBER)
+ from GCC 3.x source code. PowerPC has 1:1 mapping
+ according to the order of the registers defined
+ in GCC
+
+ }
+
+ stab_regindex : array[tregisterindex] of shortint = (
+ {$i rppcstab.inc}
+ );
+
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_R1;
+ RS_STACK_POINTER_REG = RS_R1;
+ {# Frame pointer register }
+ NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG;
+ RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+
+ Taken from GCC rs6000.h
+ }
+{$warning As indicated in rs6000.h, but can't find it anywhere else!}
+ NR_PIC_OFFSET_REG = NR_R30;
+ { Return address of a function }
+ NR_RETURN_ADDRESS_REG = NR_R0;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R3;
+ RS_FUNCTION_RETURN_REG = RS_R3;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_R4;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_R4;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_R3;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_R3;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ NR_FPU_RESULT_REG = NR_F1;
+ NR_MM_RESULT_REG = NR_M0;
+
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..18] of tsuperregister = (
+ RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
+ RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,RS_R26,RS_R27,RS_R28,RS_R29,
+ RS_R30,RS_R31
+ );
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ LinkageAreaSizeAIX = 24;
+ LinkageAreaSizeSYSV = 8;
+ { offset in the linkage area for the saved stack pointer }
+ LA_SP = 0;
+ { offset in the linkage area for the saved conditional register}
+ LA_CR_AIX = 4;
+ { offset in the linkage area for the saved link register}
+ LA_LR_AIX = 8;
+ LA_LR_SYSV = 4;
+ { offset in the linkage area for the saved RTOC register}
+ LA_RTOC_AIX = 20;
+
+ PARENT_FRAMEPOINTER_OFFSET = 12;
+
+ NR_RTOC = NR_R2;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+
+ procedure inverse_flags(var r : TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ procedure create_cond_imm(BO,BI:byte;var r : TAsmCond);
+ procedure create_cond_norm(cond: TAsmCondFlag; cr: byte;var r : TasmCond);
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+ function is_condreg(r : tregister):boolean;
+
+ function inverse_cond(const c: TAsmCond): Tasmcond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function conditions_equal(const c1, c2: TAsmCond): boolean;
+
+implementation
+
+ uses
+ rgbase,verbose;
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i rppcstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i rppcrni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rppcsri.inc}
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ is_calljmp:=false;
+ case o of
+ A_B,A_BA,A_BL,A_BLA,A_BC,A_BCA,A_BCL,A_BCLA,A_BCCTR,A_BCCTRL,A_BCLR,
+ A_BCLRL,A_TW,A_TWI: is_calljmp:=true;
+ end;
+ end;
+
+
+ procedure inverse_flags(var r: TResFlags);
+ const
+ inv_flags: array[F_EQ..F_GE] of TResFlagsEnum =
+ (F_NE,F_EQ,F_GE,F_GE,F_LE,F_LT);
+ begin
+ r.flag := inv_flags[r.flag];
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): Tasmcond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inv_condflags:array[TAsmCondFlag] of TAsmCondFlag=(C_None,
+ C_GE,C_GT,C_NE,C_LT,C_LE,C_LT,C_EQ,C_GT,C_NS,C_SO,C_NU,C_UN,
+ C_F,C_T,C_DNZ,C_DNZF,C_DNZT,C_DZ,C_DZF,C_DZT);
+ begin
+ if (c.cond in [C_DNZ,C_DZ]) then
+ internalerror(2005022501);
+ result := c;
+ result.cond := inv_condflags[c.cond];
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean;
+ begin
+ result :=
+ (c1.simple and c2.simple) and
+ (c1.cond = c2.cond) and
+ ((not(c1.cond in [C_T..C_DZF]) and
+ (c1.cr = c2.cr)) or
+ (c1.crbit = c2.crbit));
+ end;
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const
+ flag_2_cond: array[F_EQ..F_SO] of TAsmCondFlag =
+ (C_EQ,C_NE,C_LT,C_LE,C_GT,C_GE,C_SO);
+ begin
+ if f.flag > high(flag_2_cond) then
+ internalerror(200112301);
+ result.simple := true;
+ result.cr := f.cr;
+ result.cond := flag_2_cond[f.flag];
+ end;
+
+
+ procedure create_cond_imm(BO,BI:byte;var r : TAsmCond);
+ begin
+ r.simple := false;
+ r.bo := bo;
+ r.bi := bi;
+ end;
+
+
+ procedure create_cond_norm(cond: TAsmCondFlag; cr: byte;var r : TasmCond);
+ begin
+ r.simple := true;
+ r.cond := cond;
+ case cond of
+ C_NONE:;
+ C_T..C_DZF: r.crbit := cr
+ else r.cr := RS_CR0+cr;
+ end;
+ end;
+
+
+ function is_condreg(r : tregister):boolean;
+ var
+ supreg: tsuperregister;
+ begin
+ result := false;
+ if (getregtype(r) = R_SPECIALREGISTER) then
+ begin
+ supreg := getsupreg(r);
+ result := (supreg >= RS_CR0) and (supreg <= RS_CR7);
+ end;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_MMREGISTER,
+ R_FPUREGISTER,
+ R_INTREGISTER :
+ result:=OS_32;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ begin
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+end.
diff --git a/compiler/powerpc/cpuinfo.pas b/compiler/powerpc/cpuinfo.pas
new file mode 100644
index 0000000000..75332583b4
--- /dev/null
+++ b/compiler/powerpc/cpuinfo.pas
@@ -0,0 +1,71 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the PowerPC
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors =
+ (no_processor,
+ ppc601,
+ ppc604
+ );
+
+ tfputype =
+ (no_fpuprocessor,
+ fpu_soft,
+ fpu_standard
+ );
+
+
+Const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { the difference to stdcall is only the name mangling }
+ pocall_cdecl,
+ { the difference to stdcall is only the name mangling }
+ pocall_cppdecl,
+ { pass all const records by reference }
+ pocall_mwpascal
+ ];
+
+ processorsstr : array[tprocessors] of string[10] = ('',
+ '603',
+ '604'
+ );
+
+ fputypestr : array[tfputype] of string[8] = ('',
+ 'SOFT',
+ 'STANDARD'
+ );
+
+Implementation
+
+end.
diff --git a/compiler/powerpc/cpunode.pas b/compiler/powerpc/cpunode.pas
new file mode 100644
index 0000000000..0b9015cd13
--- /dev/null
+++ b/compiler/powerpc/cpunode.pas
@@ -0,0 +1,50 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the PowerPC 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
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ nppcadd,
+ nppccal,
+// nppccon,
+// nppcflw,
+// nppcmem,
+ nppcset,
+ nppcinl,
+// nppcopt,
+ nppcmat,
+ nppccnv,
+ nppcld
+ ;
+
+end.
diff --git a/compiler/powerpc/cpupara.pas b/compiler/powerpc/cpupara.pas
new file mode 100644
index 0000000000..6d8f029620
--- /dev/null
+++ b/compiler/powerpc/cpupara.pas
@@ -0,0 +1,634 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ PowerPC specific calling conventions
+
+ 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 cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ aasmtai,
+ cpubase,
+ symconst,symtype,symdef,symsym,
+ paramgr,parabase,cgbase;
+
+ type
+ tppcparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+ function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,systems,
+ defutil,
+ cgutils;
+
+
+ function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ if (target_info.system = system_powerpc_darwin) then
+ result := [RS_R2..RS_R12]
+ else
+ result := [RS_R3..RS_R12];
+ end;
+
+
+ function tppcparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ case target_info.abi of
+ abi_powerpc_aix,
+ abi_powerpc_sysv:
+ result := [RS_F0..RS_F13];
+ else
+ internalerror(2003091401);
+ end;
+ end;
+
+
+ procedure tppcparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.intsize:=tcgsize2size[OS_INT];
+ cgpara.alignment:=get_para_align(calloption);
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ if (nr<=8) then
+ begin
+ if nr=0 then
+ internalerror(200309271);
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,RS_R2+nr,R_SUBWHOLE);
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ if (target_info.abi <> abi_powerpc_aix) then
+ reference.offset:=sizeof(aint)*(nr-8)
+ else
+ reference.offset:=sizeof(aint)*(nr);
+ end;
+ end;
+ end;
+
+
+
+ function getparaloc(p : tdef) : tcgloc;
+
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.deftype of
+ orddef:
+ result:=LOC_REGISTER;
+ floatdef:
+ result:=LOC_FPUREGISTER;
+ enumdef:
+ result:=LOC_REGISTER;
+ pointerdef:
+ result:=LOC_REGISTER;
+ formaldef:
+ result:=LOC_REGISTER;
+ classrefdef:
+ result:=LOC_REGISTER;
+ recorddef:
+ if (target_info.abi<>abi_powerpc_aix) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ objectdef:
+ if is_object(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ procvardef:
+ if (po_methodpointer in tprocvardef(p).procoptions) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ filedef:
+ result:=LOC_REGISTER;
+ arraydef:
+ result:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ result:=LOC_REGISTER
+ else
+ result:=LOC_REFERENCE;
+ variantdef:
+ result:=LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ result:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+
+ function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out always require address }
+ if varspez in [vs_var,vs_out] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.deftype of
+ variantdef,
+ formaldef :
+ result:=true;
+ recorddef:
+ result :=
+ (target_info.abi<>abi_powerpc_aix) or
+ ((varspez = vs_const) and
+ ((calloption = pocall_mwpascal) or
+ (not (calloption in [pocall_cdecl,pocall_cppdecl]) and
+ (def.size > 8)
+ )
+ )
+ );
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef :
+ result:=is_object(def);
+ setdef :
+ result:=(tsetdef(def).settype<>smallset);
+ stringdef :
+ result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
+ procvardef :
+ result:=po_methodpointer in tprocvardef(def).procoptions;
+ end;
+ end;
+
+
+ procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ case target_info.abi of
+ abi_powerpc_aix:
+ cur_stack_offset:=24;
+ abi_powerpc_sysv:
+ cur_stack_offset:=8;
+ else
+ internalerror(2003051901);
+ end;
+ curintreg:=RS_R3;
+ curfloatreg:=RS_F1;
+ curmmreg:=RS_M1;
+ end;
+
+
+ procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ var
+ retcgsize : tcgsize;
+ begin
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ retcgsize:=OS_ADDR
+ else
+ retcgsize:=def_cgsize(p.rettype.def);
+
+ location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
+ p.funcretloc[side].size:=retcgsize;
+ { void has no location }
+ if is_void(p.rettype.def) then
+ begin
+ p.funcretloc[side].loc:=LOC_VOID;
+ exit;
+ end;
+
+ { Return in FPU register? }
+ if p.rettype.def.deftype=floatdef then
+ begin
+ p.funcretloc[side].loc:=LOC_FPUREGISTER;
+ p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+ p.funcretloc[side].size:=retcgsize;
+ end
+ else
+ { Return in register? }
+ if not ret_in_param(p.rettype.def,p.proccalloption) then
+ begin
+{$ifndef cpu64bit}
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { low 32bits }
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ if side=callerside then
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+ { high 32bits }
+ if side=callerside then
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+ end
+ else
+{$endif cpu64bit}
+ begin
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].size:=retcgsize;
+ if side=callerside then
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+ else
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+ end;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REFERENCE;
+ p.funcretloc[side].size:=retcgsize;
+ end;
+ end;
+
+
+ function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ create_funcretloc_info(p,side);
+ end;
+
+
+
+ function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+ var
+ stack_offset: longint;
+ paralen: aint;
+ nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
+ paradef : tdef;
+ paraloc : pcgparalocation;
+ i : integer;
+ hp : tparavarsym;
+ loc : tcgloc;
+ paracgsize: tcgsize;
+
+ begin
+{$ifdef extdebug}
+ if po_explicitparaloc in p.procoptions then
+ internalerror(200411141);
+{$endif extdebug}
+
+ result:=0;
+ nextintreg := curintreg;
+ nextfloatreg := curfloatreg;
+ nextmmreg := curmmreg;
+ stack_offset := cur_stack_offset;
+ case target_info.abi of
+ abi_powerpc_aix:
+ maxfpureg := RS_F13;
+ abi_powerpc_sysv:
+ maxfpureg := RS_F8;
+ else internalerror(2004070912);
+ end;
+
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paradef := hp.vartype.def;
+ { Syscall for Morphos can have already a paraloc set }
+ if (vo_has_explicit_paraloc in hp.varoptions) then
+ begin
+ if not(vo_is_syscall_lib in hp.varoptions) then
+ internalerror(200412153);
+ continue;
+ end;
+ hp.paraloc[side].reset;
+ { currently only support C-style array of const }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(paradef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc := LOC_REGISTER;
+ paraloc^.register := NR_R0;
+ paraloc^.size := OS_ADDR;
+ break;
+ end;
+
+ if (hp.varspez in [vs_var,vs_out]) or
+ push_addr_param(hp.varspez,paradef,p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then
+ begin
+ paradef:=voidpointertype.def;
+ loc:=LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end
+ else
+ begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+ if (target_info.abi = abi_powerpc_aix) and
+ (paradef.deftype = recorddef) and
+ (hp.varspez in [vs_value,vs_const]) then
+ begin
+ { if a record has only one field and that field is }
+ { non-composite (not array or record), it must be }
+ { passed according to the rules of that type. }
+ if (trecorddef(hp.vartype.def).symtable.symindex.count = 1) and
+ (not trecorddef(hp.vartype.def).isunion) and
+ ((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
+ ((target_info.system = system_powerpc_darwin) and
+ (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
+ begin
+ paradef :=
+ tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
+ loc := getparaloc(paradef);
+ paracgsize:=def_cgsize(paradef);
+ end
+ else
+ begin
+ loc := LOC_REGISTER;
+ paracgsize := int_cgsize(paralen);
+ end;
+ end
+ else
+ begin
+ loc:=getparaloc(paradef);
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end
+ end;
+ hp.paraloc[side].alignment:=std_param_align;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ if (target_info.abi = abi_powerpc_aix) and
+ (paradef.deftype = recorddef) then
+ hp.paraloc[side].composite:=true;
+{$ifndef cpu64bit}
+ if (target_info.abi=abi_powerpc_sysv) and
+ is_64bit(paradef) and
+ odd(nextintreg-RS_R3) then
+ inc(nextintreg);
+{$endif not cpu64bit}
+ if (paralen = 0) then
+ if (paradef.deftype = recorddef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc := LOC_VOID;
+ end
+ else
+ internalerror(2005011310);
+ { can become < 0 for e.g. 3-byte records }
+ while (paralen > 0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ if (loc = LOC_REGISTER) and
+ (nextintreg <= RS_R10) then
+ begin
+ paraloc^.loc := loc;
+ { make sure we don't lose whether or not the type is signed }
+ if (paradef.deftype <> orddef) then
+ paracgsize := int_cgsize(paralen);
+ if (paracgsize in [OS_NO,OS_64,OS_S64]) then
+ paraloc^.size := OS_INT
+ else
+ paraloc^.size := paracgsize;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
+ inc(nextintreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ if target_info.abi=abi_powerpc_aix then
+ inc(stack_offset,tcgsize2size[paraloc^.size]);
+ end
+ else if (loc = LOC_FPUREGISTER) and
+ (nextfloatreg <= maxfpureg) then
+ begin
+ paraloc^.loc:=loc;
+ paraloc^.size := paracgsize;
+ paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
+ inc(nextfloatreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ { if nextfpureg > maxfpureg, all intregs are already used, since there }
+ { are less of those available for parameter passing in the AIX abi }
+ if target_info.abi=abi_powerpc_aix then
+{$ifndef cpu64bit}
+ if (paracgsize = OS_F32) then
+ begin
+ inc(stack_offset,4);
+ if (nextintreg < RS_R11) then
+ inc(nextintreg);
+ end
+ else
+ begin
+ inc(stack_offset,8);
+ if (nextintreg < RS_R10) then
+ inc(nextintreg,2)
+ else
+ nextintreg := RS_R11;
+ end;
+{$else not cpu64bit}
+ begin
+ inc(stack_offset,tcgsize2size[paracgsize]);
+ if (nextintreg < RS_R11) then
+ inc(nextintreg);
+ end;
+{$endif not cpu64bit}
+ end
+ else { LOC_REFERENCE }
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=int_cgsize(paralen);
+ if (side = callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_R12;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen := 0;
+ end;
+ end;
+ end;
+ curintreg:=nextintreg;
+ curfloatreg:=nextfloatreg;
+ curmmreg:=nextmmreg;
+ cur_stack_offset:=stack_offset;
+ result:=stack_offset;
+ end;
+
+
+ function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ cur_stack_offset: aword;
+ parasize, l: longint;
+ curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
+ i : integer;
+ hp: tparavarsym;
+ paraloc: pcgparalocation;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+ firstfloatreg:=curfloatreg;
+
+ result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ { just continue loading the parameters in the registers }
+ begin
+ result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+ { varargs routines have to reserve at least 32 bytes for the AIX abi }
+ if (target_info.abi = abi_powerpc_aix) and
+ (result < 32) then
+ result := 32;
+ end
+ else
+ begin
+ parasize:=cur_stack_offset;
+ for i:=0 to varargspara.count-1 do
+ begin
+ hp:=tparavarsym(varargspara[i]);
+ hp.paraloc[callerside].alignment:=4;
+ paraloc:=hp.paraloc[callerside].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=def_cgsize(hp.vartype.def);
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
+ paraloc^.reference.offset:=parasize;
+ parasize:=parasize+l;
+ end;
+ result:=parasize;
+ end;
+ if curfloatreg<>firstfloatreg then
+ include(varargspara.varargsinfo,va_uses_float_reg);
+ end;
+
+
+ function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
+ var
+ paraloc : pcgparalocation;
+ paracgsize : tcgsize;
+ begin
+ result:=false;
+ case target_info.system of
+ system_powerpc_morphos:
+ begin
+ paracgsize:=def_cgsize(p.vartype.def);
+ p.paraloc[callerside].alignment:=4;
+ p.paraloc[callerside].size:=paracgsize;
+ p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
+ paraloc:=p.paraloc[callerside].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=paracgsize;
+ paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
+ { pattern is always uppercase'd }
+ if s='D0' then
+ paraloc^.reference.offset:=0
+ else if s='D1' then
+ paraloc^.reference.offset:=4
+ else if s='D2' then
+ paraloc^.reference.offset:=8
+ else if s='D3' then
+ paraloc^.reference.offset:=12
+ else if s='D4' then
+ paraloc^.reference.offset:=16
+ else if s='D5' then
+ paraloc^.reference.offset:=20
+ else if s='D6' then
+ paraloc^.reference.offset:=24
+ else if s='D7' then
+ paraloc^.reference.offset:=28
+ else if s='A0' then
+ paraloc^.reference.offset:=32
+ else if s='A1' then
+ paraloc^.reference.offset:=36
+ else if s='A2' then
+ paraloc^.reference.offset:=40
+ else if s='A3' then
+ paraloc^.reference.offset:=44
+ else if s='A4' then
+ paraloc^.reference.offset:=48
+ else if s='A5' then
+ paraloc^.reference.offset:=52
+ { 'A6' (offset 56) is used by mossyscall as libbase, so API
+ never passes parameters in it,
+ Indeed, but this allows to declare libbase either explicitly
+ or let the compiler insert it }
+ else if s='A6' then
+ paraloc^.reference.offset:=56
+ { 'A7' is the stack pointer on 68k, can't be overwritten
+ by API calls, so it has no offset }
+ { 'R12' is special, used internally to support r12base sysv
+ calling convention }
+ else if s='R12' then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=OS_ADDR;
+ paraloc^.register:=NR_R12;
+ end
+ else
+ exit;
+
+ { copy to callee side }
+ p.paraloc[calleeside].add_location^:=paraloc^;
+ end;
+ else
+ internalerror(200404182);
+ end;
+ result:=true;
+ end;
+
+
+begin
+ paramanager:=tppcparamanager.create;
+end.
diff --git a/compiler/powerpc/cpupi.pas b/compiler/powerpc/cpupi.pas
new file mode 100644
index 0000000000..448a3f3d64
--- /dev/null
+++ b/compiler/powerpc/cpupi.pas
@@ -0,0 +1,144 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ 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 contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,
+ procinfo,cpuinfo,psub;
+
+ type
+ tppcprocinfo = class(tcgprocinfo)
+ { offset where the frame pointer from the outer procedure is stored. }
+ parent_framepointer_offset : longint;
+ constructor create(aparent:tprocinfo);override;
+ procedure set_first_temp_offset;override;
+ procedure allocate_push_parasize(size: longint);override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+
+ implementation
+
+ uses
+ globtype,globals,systems,
+ cpubase,
+ aasmtai,
+ tgobj,
+ symconst,symsym,paramgr,symutil,
+ verbose;
+
+ constructor tppcprocinfo.create(aparent:tprocinfo);
+
+ begin
+ inherited create(aparent);
+ maxpushedparasize:=0;
+ end;
+
+
+ procedure tppcprocinfo.set_first_temp_offset;
+ var
+ ofs : aword;
+ locals: longint;
+ begin
+ if not(po_assembler in procdef.procoptions) then
+ begin
+ case target_info.abi of
+ abi_powerpc_aix:
+ ofs:=align(maxpushedparasize+LinkageAreaSizeAIX,16);
+ abi_powerpc_sysv:
+ ofs:=align(maxpushedparasize+LinkageAreaSizeSYSV,16);
+ else
+ internalerror(200402191);
+ end;
+ tg.setfirsttemp(ofs);
+ end
+ else
+ begin
+ locals := 0;
+ current_procinfo.procdef.localst.foreach_static(@count_locals,@locals);
+ if locals <> 0 then
+ { at 0(r1), the previous value of r1 will be stored }
+ tg.setfirsttemp(4);
+ end;
+ end;
+
+
+(*
+ procedure tppcprocinfo.after_pass1;
+ begin
+ if not(po_assembler in procdef.procoptions) then
+ begin
+ if cs_asm_source in aktglobalswitches then
+ aktproccode.insert(Tai_comment.Create(strpnew('Parameter copies start at: r1+'+tostr(procdef.parast.address_fixup))));
+
+ if cs_asm_source in aktglobalswitches then
+ aktproccode.insert(Tai_comment.Create(strpnew('Locals start at: r1+'+tostr(procdef.localst.address_fixup))));
+ firsttemp_offset:=align(procdef.localst.address_fixup+procdef.localst.datasize,16);
+ if cs_asm_source in aktglobalswitches then
+ aktproccode.insert(Tai_comment.Create(strpnew('Temp. space start: r1+'+tostr(firsttemp_offset))));
+
+ //!!!! tg.setfirsttemp(firsttemp_offset);
+ tg.firsttemp:=firsttemp_offset;
+ tg.lasttemp:=firsttemp_offset;
+ inherited after_pass1;
+ end;
+ end;
+*)
+
+
+ procedure tppcprocinfo.allocate_push_parasize(size:longint);
+ begin
+ if size>maxpushedparasize then
+ maxpushedparasize:=size;
+ end;
+
+
+ function tppcprocinfo.calc_stackframe_size:longint;
+ var
+ first_save_fpu_register: longint;
+ begin
+ { more or less copied from cgcpu.pas/g_stackframe_entry }
+ { FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
+ case target_info.abi of
+ abi_powerpc_aix:
+ first_save_fpu_register := 14;
+ abi_powerpc_sysv:
+ first_save_fpu_register := 9;
+ else
+ internalerror(2003122903);
+ end;
+ if not (po_assembler in procdef.procoptions) then
+ result := align(align((31-13+1)*4+(31-first_save_fpu_register+1)*8,16)+tg.lasttemp,16)
+ else
+ result := align(tg.lasttemp,16);
+ end;
+
+
+begin
+ cprocinfo:=tppcprocinfo;
+end.
diff --git a/compiler/powerpc/cpuswtch.pas b/compiler/powerpc/cpuswtch.pas
new file mode 100644
index 0000000000..91fa89bbb2
--- /dev/null
+++ b/compiler/powerpc/cpuswtch.pas
@@ -0,0 +1,118 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ interprets the commandline options which are powerpc specific
+
+ 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 cpuswtch;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ options;
+
+type
+ toptionpowerpc=class(toption)
+ procedure interpret_proc_specific_options(const opt:string);override;
+ end;
+
+implementation
+
+uses
+ cutils,globtype,systems,globals;
+
+procedure toptionpowerpc.interpret_proc_specific_options(const opt:string);
+var
+ more: string;
+ j: longint;
+begin
+ More:=Upper(copy(opt,3,length(opt)-2));
+ case opt[2] of
+ 'O' : Begin
+ j := 3;
+ While (j <= Length(Opt)) Do
+ Begin
+ case opt[j] of
+ '-' :
+ begin
+ initglobalswitches:=initglobalswitches-[cs_optimize,cs_fastoptimize,cs_slowoptimize,cs_littlesize,
+ cs_regvars,cs_uncertainopts];
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+ end;
+ 'a' :
+ begin
+ UpdateAlignmentStr(Copy(Opt,j+1,255),ParaAlignment);
+ j:=length(Opt);
+ end;
+ 'g' : initglobalswitches:=initglobalswitches+[cs_littlesize];
+ 'G' : initglobalswitches:=initglobalswitches-[cs_littlesize];
+ 'r' :
+ begin
+ initglobalswitches:=initglobalswitches+[cs_regvars];
+ Simplify_ppu:=false;
+ end;
+ 'u' : initglobalswitches:=initglobalswitches+[cs_uncertainopts];
+ '1' : initglobalswitches:=initglobalswitches-[cs_fastoptimize,cs_slowoptimize]+[cs_optimize];
+ '2' : initglobalswitches:=initglobalswitches-[cs_slowoptimize]+[cs_optimize,cs_fastoptimize];
+ '3' : initglobalswitches:=initglobalswitches+[cs_optimize,cs_fastoptimize,cs_slowoptimize];
+{$ifdef dummy}
+ 'p' :
+ Begin
+ If j < Length(Opt) Then
+ Begin
+ Case opt[j+1] Of
+ '1': initoptprocessor := Class386;
+ '2': initoptprocessor := ClassP5;
+ '3': initoptprocessor := ClassP6
+ Else IllegalPara(Opt)
+ End;
+ Inc(j);
+ End
+ Else IllegalPara(opt)
+ End;
+{$endif dummy}
+ else IllegalPara(opt);
+ End;
+ Inc(j)
+ end;
+ end;
+{$ifdef dummy}
+ 'R' : begin
+ if More='GAS' then
+ initasmmode:=asmmode_ppc_gas
+ else
+ if More='MOTOROLA' then
+ initasmmode:=asmmode_ppc_motorola
+ else
+ if More='DIRECT' then
+ initasmmode:=asmmode_direct
+ else
+ IllegalPara(opt);
+ end;
+{$endif dummy}
+ else
+ IllegalPara(opt);
+ end;
+end;
+
+
+initialization
+ coption:=toptionpowerpc;
+end.
diff --git a/compiler/powerpc/cputarg.pas b/compiler/powerpc/cputarg.pas
new file mode 100644
index 0000000000..f3bc579da7
--- /dev/null
+++ b/compiler/powerpc/cputarg.pas
@@ -0,0 +1,90 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the powerpc dependent target units
+
+ 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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETMACOS}
+ ,t_macos
+ {$endif}
+ {$ifndef NOTARGETDARWIN}
+ ,t_bsd
+ {$endif}
+ {$ifndef NOTARGETMORPHOS}
+ ,t_morph
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGPPCGAS}
+ ,agppcgas
+ {$endif}
+ {$ifndef NOAGPPPCMPW}
+ ,agppcmpw
+ {$endif}
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaPPCGas}
+ ,rappcgas
+ {$endif NoRaPPCGas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+{**************************************
+ Optimizer
+**************************************}
+
+ {$ifndef NOOPT}
+ , aoptcpu
+ {$endif NOOPT}
+ ;
+
+end.
diff --git a/compiler/powerpc/itcpugas.pas b/compiler/powerpc/itcpugas.pas
new file mode 100644
index 0000000000..98364680b7
--- /dev/null
+++ b/compiler/powerpc/itcpugas.pas
@@ -0,0 +1,143 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the PowerPC GAS instruction tables
+
+ 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 itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+ const
+ gas_op2str : array[tasmop] of string[14] = ('<none>',
+ 'add','add.','addo','addo.','addc','addc.','addco','addco.',
+ 'adde','adde.','addeo','addeo.','addi','addic','addic.','addis',
+ 'addme','addme.','addmeo','addmeo.','addze','addze.','addzeo',
+ 'addzeo.','and','and.','andc','andc.','andi.','andis.','b',
+ 'ba','bl','bla','bc','bca','bcl','bcla','bcctr','bcctrl','bclr',
+ 'bclrl','cmp','cmpi','cmpl','cmpli','cntlzw','cntlzw.','crand',
+ 'crandc','creqv','crnand','crnor','cror','crorc','crxor','dcba',
+ 'dcbf','dcbi','dcbst','dcbt','dcbtst','dcbz','divw','divw.','divwo','divwo.',
+ 'divwu','divwu.','divwuo','divwuo.','eciwx','ecowx','eieio','eqv',
+ 'eqv.','extsb','extsb.','extsh','extsh.','fabs','fabs.','fadd',
+ 'fadd.','fadds','fadds.','fcmpo','fcmpu','fctiw','fctiw.','fctiwz',
+ 'fctiwz.','fdiv','fdiv.','fdivs','fdivs.','fmadd','fmadd.','fmadds',
+ 'fmadds.','fmr','fmsub','fmsub.','fmsubs','fmsubs.','fmul','fmul.',
+ 'fmuls','fmuls.','fnabs','fnabs.','fneg','fneg.','fnmadd',
+ 'fnmadd.','fnmadds','fnmadds.','fnmsub','fnmsub.','fnmsubs',
+ 'fnmsubs.','fres','fres.','frsp','frsp.','frsqrte','frsqrte.',
+ 'fsel','fsel.','fsqrt','fsqrt.','fsqrts','fsqrts.','fsub','fsub.',
+ 'fsubs','fsubs.','icbi','isync','lbz','lbzu','lbzux','lbzx',
+ 'lfd','lfdu','lfdux','lfdx','lfs','lfsu','lfsux','lfsx','lha',
+ 'lhau','lhaux','lhax','hbrx','lhz','lhzu','lhzux','lhzx','lmw',
+ 'lswi','lswx','lwarx','lwbrx','lwz','lwzu','lwzux','lwzx','mcrf',
+ 'mcrfs','mcrxr','mfcr','mffs','mffs.','mfmsr','mfspr','mfsr',
+ 'mfsrin','mftb','mtcrf','mtfsb0','mtfsb1','mtfsf','mtfsf.',
+ 'mtfsfi','mtfsfi.','mtmsr','mtspr','mtsr','mtsrin','mulhw',
+ 'mulhw.','mulhwu','mulhwu.','mulli','mullw','mullw.','mullwo',
+ 'mullwo.','nand','nand.','neg','neg.','nego','nego.','nor','nor.',
+ 'or','or.','orc','orc.','ori','oris', 'rfi', 'rlwimi', 'rlwimi.',
+ 'rlwinm', 'rlwinm.','rlwnm','rlwnm_','sc','slw', 'slw.', 'sraw', 'sraw.',
+ 'srawi', 'srawi.','srw', 'srw.', 'stb', 'stbu', 'stbux','stbx','stfd',
+ 'stfdu', 'stfdux', 'stfdx', 'stfiwx', 'stfs', 'stfsu', 'stfsux', 'stfsx',
+ 'sth', 'sthbrx', 'sthu', 'sthux', 'sthx', 'stmw', 'stswi', 'stswx', 'stw',
+ 'stwbrx', 'stwcx.', 'stwu', 'stwux', 'stwx', 'subf', 'subf.', 'subfo',
+ 'subfo.', 'subfc', 'subc.', 'subfco', 'subfco.', 'subfe', 'subfe.',
+ 'subfeo', 'subfeo.', 'subfic', 'subfme', 'subfme.', 'subfmeo', 'subfmeo.',
+ 'subfze', 'subfze.', 'subfzeo', 'subfzeo.', 'sync', 'tlbia', 'tlbie',
+ 'tlbsync', 'tw', 'twi', 'xor', 'xor.', 'xori', 'xoris',
+ { some simplified mnemonics }
+ 'subi', 'subis', 'subic', 'subic.', 'sub', 'sub.', 'subo', 'subo.',
+ 'subc', 'subc.', 'subco', 'subco.', 'cmpwi', 'cmpw', 'cmplwi', 'cmplw',
+ 'extlwi', 'extlwi.', 'extrwi', 'extrwi.', 'inslwi', 'inslwi.', 'insrwi',
+ 'insrwi.', 'rotlwi', 'rotlwi.', 'rotlw', 'rotlw.', 'slwi', 'slwi.',
+ 'srwi', 'srwi.', 'clrlwi', 'clrlwi.', 'clrrwi', 'clrrwi.', 'clrslwi',
+ 'clrslwi.', 'blr', 'bctr', 'blrl', 'bctrl', 'crset', 'crclr', 'crmove',
+ 'crnot', 'mt', 'mf','nop', 'li', 'lis', 'la', 'mr','mr.','not', 'not.',
+ 'mtcr', 'mtlr', 'mflr','mtctr', 'mfctr');
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ globtype,globals,
+ cutils,verbose, systems;
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {$i rppcgas.inc}
+ );
+
+ gas_regname_short_table : array[tregisterindex] of string[7] = (
+ {$i rppcgss.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rppcgri.inc}
+ );
+
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : longint;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ if (cs_create_smart in aktmoduleswitches) and
+ (target_info.system <> system_powerpc_darwin) then
+ result:=gas_regname_short_table[p]
+ else
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/compiler/powerpc/nppcadd.pas b/compiler/powerpc/nppcadd.pas
new file mode 100644
index 0000000000..754404f99b
--- /dev/null
+++ b/compiler/powerpc/nppcadd.pas
@@ -0,0 +1,1462 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the PowerPC
+
+ 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 nppcadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,ncgadd,cpubase;
+
+ type
+ tppcaddnode = class(tcgaddnode)
+ function pass_1: tnode; override;
+ procedure pass_2;override;
+ private
+ procedure pass_left_and_right;
+ procedure load_left_right(cmpop, load_constants: boolean);
+ function getresflags : tresflags;
+ procedure emit_compare(unsigned : boolean);
+ procedure second_addfloat;override;
+ procedure second_addboolean;override;
+ procedure second_addsmallset;override;
+{$ifdef SUPPORT_MMX}
+ procedure second_addmmx;override;
+{$endif SUPPORT_MMX}
+ procedure second_add64bit;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmcpu,defutil,htypechk,
+ cgbase,cpuinfo,pass_1,pass_2,regvars,
+ cpupara,cgcpu,cgutils,
+ ncon,nset,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+
+
+{*****************************************************************************
+ Pass 1
+*****************************************************************************}
+
+ function tppcaddnode.pass_1: tnode;
+ begin
+ resulttypepass(left);
+ if (nodetype in [equaln,unequaln]) and
+ (left.resulttype.def.deftype = orddef) and
+ is_64bit(left.resulttype.def) then
+ begin
+ result := nil;
+ firstpass(left);
+ firstpass(right);
+ expectloc := LOC_FLAGS;
+ calcregisters(self,2,0,0);
+ exit;
+ end;
+ result := inherited pass_1;
+ end;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure tppcaddnode.pass_left_and_right;
+ begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ { in case of constant put it to the left }
+ if (left.nodetype=ordconstn) then
+ swapleftright;
+
+ secondpass(left);
+ secondpass(right);
+ end;
+
+
+ procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean);
+
+ procedure load_node(var n: tnode);
+ begin
+ case n.location.loc of
+ LOC_REGISTER:
+ if not cmpop then
+ begin
+ location.register := n.location.register;
+ if is_64bit(n.resulttype.def) then
+ location.register64.reghi := n.location.register64.reghi;
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
+ if not cmpop then
+ begin
+ location.register := n.location.register;
+ if is_64bit(n.resulttype.def) then
+ location.register64.reghi := n.location.register64.reghi;
+ end;
+ end;
+ LOC_CONSTANT:
+ begin
+ if load_constants then
+ begin
+ location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
+ if not cmpop then
+ location.register := n.location.register;
+ if is_64bit(n.resulttype.def) then
+ location.register64.reghi := n.location.register64.reghi;
+ end;
+ end;
+ end;
+ end;
+
+ begin
+ load_node(left);
+ load_node(right);
+ if not(cmpop) and
+ (location.register = NR_NO) then
+ begin
+ location.register := cg.getintregister(exprasmlist,OS_INT);
+ if is_64bit(resulttype.def) then
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ end;
+ end;
+
+
+ function tppcaddnode.getresflags : tresflags;
+ begin
+ if (left.resulttype.def.deftype <> floatdef) then
+ result.cr := RS_CR0
+ else
+ result.cr := RS_CR1;
+ case nodetype of
+ equaln : result.flag:=F_EQ;
+ unequaln : result.flag:=F_NE;
+ else
+ if nf_swaped in flags then
+ case nodetype of
+ ltn : result.flag:=F_GT;
+ lten : result.flag:=F_GE;
+ gtn : result.flag:=F_LT;
+ gten : result.flag:=F_LE;
+ end
+ else
+ case nodetype of
+ ltn : result.flag:=F_LT;
+ lten : result.flag:=F_LE;
+ gtn : result.flag:=F_GT;
+ gten : result.flag:=F_GE;
+ end;
+ end
+ end;
+
+
+ procedure tppcaddnode.emit_compare(unsigned: boolean);
+ var
+ op : tasmop;
+ tmpreg : tregister;
+ useconst : boolean;
+ begin
+ // get the constant on the right if there is one
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ // can we use an immediate, or do we have to load the
+ // constant in a register first?
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+{$ifdef dummy}
+ if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.value64)<>0) and ((hi(right.location.value64)<>$ffffffff) or unsigned) then
+ internalerror(2002080301);
+{$endif extdebug}
+ if (nodetype in [equaln,unequaln]) then
+ if (unsigned and
+ (aword(right.location.value) > high(word))) or
+ (not unsigned and
+ (aint(right.location.value) < low(smallint)) or
+ (aint(right.location.value) > high(smallint))) then
+ { we can then maybe use a constant in the 'othersigned' case
+ (the sign doesn't matter for // equal/unequal)}
+ unsigned := not unsigned;
+
+ if (unsigned and
+ (aword(right.location.value) <= high(word))) or
+ (not(unsigned) and
+ (aint(right.location.value) >= low(smallint)) and
+ (aint(right.location.value) <= high(smallint))) then
+ useconst := true
+ else
+ begin
+ useconst := false;
+ tmpreg := cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_const_reg(exprasmlist,OS_INT,
+ right.location.value,tmpreg);
+ end
+ end
+ else
+ useconst := false;
+ location.loc := LOC_FLAGS;
+ location.resflags := getresflags;
+ if not unsigned then
+ if useconst then
+ op := A_CMPWI
+ else
+ op := A_CMPW
+ else
+ if useconst then
+ op := A_CMPLWI
+ else
+ op := A_CMPLW;
+
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if useconst then
+ exprasmlist.concat(taicpu.op_reg_const(op,left.location.register,longint(right.location.value)))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(op,left.location.register,tmpreg));
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(op,
+ left.location.register,right.location.register));
+ end;
+
+
+{*****************************************************************************
+ AddBoolean
+*****************************************************************************}
+
+ procedure tppcaddnode.second_addboolean;
+ var
+ cgop : TOpCg;
+ cgsize : TCgSize;
+ cmpop,
+ isjump : boolean;
+ otl,ofl : tasmlabel;
+ begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ cmpop:=false;
+ if (torddef(left.resulttype.def).typ=bool8bit) or
+ (torddef(right.resulttype.def).typ=bool8bit) then
+ cgsize:=OS_8
+ else
+ if (torddef(left.resulttype.def).typ=bool16bit) or
+ (torddef(right.resulttype.def).typ=bool16bit) then
+ cgsize:=OS_16
+ else
+ cgsize:=OS_32;
+
+ if (cs_full_boolean_eval in aktlocalswitches) or
+ (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ swapleftright;
+
+ isjump:=(left.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(left);
+ if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(exprasmlist,left.location,cgsize,false);
+ if isjump then
+ begin
+ truelabel:=otl;
+ falselabel:=ofl;
+ end
+ else if left.location.loc=LOC_JUMP then
+ internalerror(2003122901);
+
+ isjump:=(right.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(right);
+ if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(exprasmlist,right.location,cgsize,false);
+ if isjump then
+ begin
+ truelabel:=otl;
+ falselabel:=ofl;
+ end
+ else if right.location.loc=LOC_JUMP then
+ internalerror(200312292);
+
+ cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
+
+ { set result location }
+ if not cmpop then
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
+ else
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ load_left_right(cmpop,false);
+
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+
+ { compare the }
+ case nodetype of
+ ltn,lten,gtn,gten,
+ equaln,unequaln :
+ begin
+ if (right.location.loc <> LOC_CONSTANT) then
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
+ left.location.register,right.location.register))
+ else
+ exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
+ left.location.register,longint(right.location.value)));
+ location.resflags := getresflags;
+ end;
+ else
+ begin
+ case nodetype of
+ xorn :
+ cgop:=OP_XOR;
+ orn :
+ cgop:=OP_OR;
+ andn :
+ cgop:=OP_AND;
+ else
+ internalerror(200203247);
+ end;
+
+ if right.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
+ left.location.register,right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
+ right.location.value,left.location.register,
+ location.register);
+ end;
+ end;
+ end
+ else
+ begin
+ // just to make sure we free the right registers
+ cmpop := true;
+ case nodetype of
+ andn,
+ orn :
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ case nodetype of
+ andn :
+ begin
+ otl:=truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ cg.a_label(exprasmlist,truelabel);
+ truelabel:=otl;
+ end;
+ orn :
+ begin
+ ofl:=falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ cg.a_label(exprasmlist,falselabel);
+ falselabel:=ofl;
+ end;
+ else
+ internalerror(200403181);
+ end;
+ secondpass(right);
+ maketojumpbool(exprasmlist,right,lr_load_regvars);
+ end;
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ AddFloat
+*****************************************************************************}
+
+ procedure tppcaddnode.second_addfloat;
+ var
+ op : TAsmOp;
+ cmpop : boolean;
+ begin
+ pass_left_and_right;
+
+ cmpop:=false;
+ case nodetype of
+ addn :
+ op:=A_FADD;
+ muln :
+ op:=A_FMUL;
+ subn :
+ op:=A_FSUB;
+ slashn :
+ op:=A_FDIV;
+ ltn,lten,gtn,gten,
+ equaln,unequaln :
+ begin
+ op:=A_FCMPO;
+ cmpop:=true;
+ end;
+ else
+ internalerror(200403182);
+ end;
+
+ // get the operands in the correct order, there are no special cases
+ // here, everything is register-based
+ if nf_swaped in flags then
+ swapleftright;
+
+ // put both operands in a register
+ location_force_fpureg(exprasmlist,right.location,true);
+ location_force_fpureg(exprasmlist,left.location,true);
+
+ // initialize de result
+ if not cmpop then
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ if left.location.loc = LOC_FPUREGISTER then
+ location.register := left.location.register
+ else if right.location.loc = LOC_FPUREGISTER then
+ location.register := right.location.register
+ else
+ location.register := cg.getfpuregister(exprasmlist,location.size);
+ end
+ else
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags := getresflags;
+ end;
+
+ // emit the actual operation
+ if not cmpop then
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op,
+ location.register,left.location.register,
+ right.location.register))
+ end
+ else
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op,
+ newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register))
+ end;
+ end;
+
+{*****************************************************************************
+ AddSmallSet
+*****************************************************************************}
+
+ procedure tppcaddnode.second_addsmallset;
+ var
+ cgop : TOpCg;
+ tmpreg : tregister;
+ opdone,
+ cmpop : boolean;
+ begin
+ pass_left_and_right;
+
+ { when a setdef is passed, it has to be a smallset }
+ if ((left.resulttype.def.deftype=setdef) and
+ (tsetdef(left.resulttype.def).settype<>smallset)) or
+ ((right.resulttype.def.deftype=setdef) and
+ (tsetdef(right.resulttype.def).settype<>smallset)) then
+ internalerror(200203301);
+
+ opdone := false;
+ cmpop:=nodetype in [equaln,unequaln,lten,gten];
+
+ { set result location }
+ if not cmpop then
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
+ else
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ load_left_right(cmpop,false);
+
+ if not(cmpop) and
+ (location.register = NR_NO) then
+ location.register := cg.getintregister(exprasmlist,OS_INT);
+
+ case nodetype of
+ addn :
+ begin
+ if (nf_swaped in flags) and (left.nodetype=setelementn) then
+ swapleftright;
+ { are we adding set elements ? }
+ if right.nodetype=setelementn then
+ begin
+ { no range support for smallsets! }
+ if assigned(tsetelementnode(right).right) then
+ internalerror(43244);
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
+ aint(aword(1) shl aword(right.location.value)),
+ left.location.register,location.register)
+ else
+ begin
+ tmpreg := cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
+ cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
+ right.location.register,tmpreg);
+ if left.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
+ left.location.register,location.register)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
+ left.location.value,tmpreg,location.register);
+ end;
+ opdone := true;
+ end
+ else
+ cgop := OP_OR;
+ end;
+ symdifn :
+ cgop:=OP_XOR;
+ muln :
+ cgop:=OP_AND;
+ subn :
+ begin
+ cgop:=OP_AND;
+ if (not(nf_swaped in flags)) then
+ if (right.location.loc=LOC_CONSTANT) then
+ right.location.value := not(right.location.value)
+ else
+ opdone := true
+ else if (left.location.loc=LOC_CONSTANT) then
+ left.location.value := not(left.location.value)
+ else
+ begin
+ swapleftright;
+ opdone := true;
+ end;
+ if opdone then
+ begin
+ if left.location.loc = LOC_CONSTANT then
+ begin
+ tmpreg := cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_const_reg(exprasmlist,OS_INT,
+ left.location.value,tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
+ location.register,tmpreg,right.location.register));
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
+ location.register,left.location.register,
+ right.location.register));
+ end;
+ end;
+ equaln,
+ unequaln :
+ begin
+ emit_compare(true);
+ opdone := true;
+ end;
+ lten,gten:
+ begin
+ If (not(nf_swaped in flags) and
+ (nodetype = lten)) or
+ ((nf_swaped in flags) and
+ (nodetype = gten)) then
+ swapleftright;
+ // now we have to check whether left >= right
+ tmpreg := cg.getintregister(exprasmlist,OS_INT);
+ if left.location.loc = LOC_CONSTANT then
+ begin
+ cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
+ not(left.location.value),right.location.register,tmpreg);
+ exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
+ // the two instructions above should be folded together by
+ // the peepholeoptimizer
+ end
+ else
+ begin
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ cg.a_load_const_reg(exprasmlist,OS_INT,
+ right.location.value,tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
+ tmpreg,left.location.register));
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
+ right.location.register,left.location.register));
+ end;
+ location.resflags.cr := RS_CR0;
+ location.resflags.flag := F_EQ;
+ opdone := true;
+ end;
+ else
+ internalerror(2002072701);
+ end;
+
+ if not opdone then
+ begin
+ // these are all commutative operations
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
+ right.location.value,left.location.register,
+ location.register)
+ else
+ cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
+ right.location.register,left.location.register,
+ location.register);
+ end;
+ end;
+
+{*****************************************************************************
+ Add64bit
+*****************************************************************************}
+
+ procedure tppcaddnode.second_add64bit;
+ var
+ op : TOpCG;
+ op1,op2 : TAsmOp;
+ cmpop,
+ unsigned : boolean;
+
+
+ procedure emit_cmp64_hi;
+
+ var
+ oldleft, oldright: tlocation;
+ begin
+ // put the high part of the location in the low part
+ location_copy(oldleft,left.location);
+ location_copy(oldright,right.location);
+ if left.location.loc = LOC_CONSTANT then
+ left.location.value64 := left.location.value64 shr 32
+ else
+ left.location.register64.reglo := left.location.register64.reghi;
+ if right.location.loc = LOC_CONSTANT then
+ right.location.value64 := right.location.value64 shr 32
+ else
+ right.location.register64.reglo := right.location.register64.reghi;
+
+ // and call the normal emit_compare
+ emit_compare(unsigned);
+ location_copy(left.location,oldleft);
+ location_copy(right.location,oldright);
+ end;
+
+
+ procedure emit_cmp64_lo;
+
+ begin
+ emit_compare(true);
+ end;
+
+
+ procedure firstjmp64bitcmp;
+
+ var
+ oldnodetype: tnodetype;
+ begin
+{$ifdef OLDREGVARS}
+ load_all_regvars(exprasmlist);
+{$endif OLDREGVARS}
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn:
+ begin
+ cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
+ { cheat a little bit for the negative test }
+ toggleflag(nf_swaped);
+ cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
+ toggleflag(nf_swaped);
+ end;
+ lten,gten:
+ begin
+ oldnodetype:=nodetype;
+ if nodetype=lten then
+ nodetype:=ltn
+ else
+ nodetype:=gtn;
+ cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
+ { cheat for the negative test }
+ if nodetype=ltn then
+ nodetype:=gtn
+ else
+ nodetype:=ltn;
+ cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
+ nodetype:=oldnodetype;
+ end;
+ equaln:
+ begin
+ nodetype := unequaln;
+ cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
+ nodetype := equaln;
+ end;
+ unequaln:
+ begin
+ cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
+ end;
+ end;
+ end;
+
+
+ procedure secondjmp64bitcmp;
+
+ begin
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn,lten,gten:
+ begin
+ { the comparison of the low dword always has }
+ { to be always unsigned! }
+ cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
+ cg.a_jmp_always(exprasmlist,falselabel);
+ end;
+ equaln:
+ begin
+ nodetype := unequaln;
+ cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
+ cg.a_jmp_always(exprasmlist,truelabel);
+ nodetype := equaln;
+ end;
+ unequaln:
+ begin
+ cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
+ cg.a_jmp_always(exprasmlist,falselabel);
+ end;
+ end;
+ end;
+
+
+ var
+ tempreg64: tregister64;
+
+ begin
+ firstcomplex(self);
+
+ pass_left_and_right;
+
+ cmpop:=false;
+ unsigned:=((left.resulttype.def.deftype=orddef) and
+ (torddef(left.resulttype.def).typ=u64bit)) or
+ ((right.resulttype.def.deftype=orddef) and
+ (torddef(right.resulttype.def).typ=u64bit));
+ case nodetype of
+ addn :
+ begin
+ op:=OP_ADD;
+ end;
+ subn :
+ begin
+ op:=OP_SUB;
+ if (nf_swaped in flags) then
+ swapleftright;
+ end;
+ ltn,lten,
+ gtn,gten,
+ equaln,unequaln:
+ begin
+ op:=OP_NONE;
+ cmpop:=true;
+ end;
+ xorn:
+ op:=OP_XOR;
+ orn:
+ op:=OP_OR;
+ andn:
+ op:=OP_AND;
+ muln:
+ begin
+ { should be handled in pass_1 (JM) }
+ internalerror(200109051);
+ end;
+ else
+ internalerror(2002072705);
+ end;
+
+ if not cmpop then
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
+
+ load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
+ (nodetype in [addn,subn]));
+
+ if not(cs_check_overflow in aktlocalswitches) or
+ not(nodetype in [addn,subn]) then
+ begin
+ case nodetype of
+ ltn,lten,
+ gtn,gten:
+ begin
+ emit_cmp64_hi;
+ firstjmp64bitcmp;
+ emit_cmp64_lo;
+ secondjmp64bitcmp;
+ end;
+ equaln,unequaln:
+ begin
+ // instead of doing a complicated compare, do
+ // (left.hi xor right.hi) or (left.lo xor right.lo)
+ // (somewhate optimized so that no superfluous 'mr's are
+ // generated)
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if left.location.loc = LOC_REGISTER then
+ begin
+ tempreg64.reglo := left.location.register64.reglo;
+ tempreg64.reghi := left.location.register64.reghi;
+ end
+ else
+ begin
+ if (aint(right.location.value64) <> 0) then
+ tempreg64.reglo := cg.getintregister(exprasmlist,OS_32)
+ else
+ tempreg64.reglo := left.location.register64.reglo;
+ if ((right.location.value64 shr 32) <> 0) then
+ tempreg64.reghi := cg.getintregister(exprasmlist,OS_32)
+ else
+ tempreg64.reghi := left.location.register64.reghi;
+ end;
+
+ if (aint(right.location.value64) <> 0) then
+ { negative values can be handled using SUB, }
+ { positive values < 65535 using XOR. }
+ if (longint(right.location.value64) >= -32767) and
+ (longint(right.location.value64) < 0) then
+ cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
+ aint(right.location.value64),
+ left.location.register64.reglo,tempreg64.reglo)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
+ aint(right.location.value64),
+ left.location.register64.reglo,tempreg64.reglo);
+
+ if ((right.location.value64 shr 32) <> 0) then
+ if (longint(right.location.value64 shr 32) >= -32767) and
+ (longint(right.location.value64 shr 32) < 0) then
+ cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
+ aint(right.location.value64 shr 32),
+ left.location.register64.reghi,tempreg64.reghi)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
+ aint(right.location.value64 shr 32),
+ left.location.register64.reghi,tempreg64.reghi);
+ end
+ else
+ begin
+ tempreg64.reglo := cg.getintregister(exprasmlist,OS_INT);
+ tempreg64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,location.size,
+ left.location.register64,right.location.register64,
+ tempreg64);
+ end;
+
+ cg.a_reg_alloc(exprasmlist,NR_R0);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
+ tempreg64.reglo,tempreg64.reghi));
+ cg.a_reg_dealloc(exprasmlist,NR_R0);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags := getresflags;
+ end;
+ xorn,orn,andn,addn:
+ begin
+ if (location.register64.reglo = NR_NO) then
+ begin
+ location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ end;
+
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ cg64.a_op64_const_reg_reg(exprasmlist,op,location.size,right.location.value64,
+ left.location.register64,location.register64)
+ else
+ cg64.a_op64_reg_reg_reg(exprasmlist,op,location.size,right.location.register64,
+ left.location.register64,location.register64);
+ end;
+ subn:
+ begin
+ if left.location.loc <> LOC_CONSTANT then
+ begin
+ if (location.register64.reglo = NR_NO) then
+ begin
+ location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ end;
+ if right.location.loc <> LOC_CONSTANT then
+ // reg64 - reg64
+ cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,location.size,
+ right.location.register64,left.location.register64,
+ location.register64)
+ else
+ // reg64 - const64
+ cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,location.size,
+ right.location.value64,left.location.register64,
+ location.register64)
+ end
+ else if ((left.location.value64 shr 32) = 0) then
+ begin
+ if (location.register64.reglo = NR_NO) then
+ begin
+ location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ end;
+ if (int64(left.location.value64) >= low(smallint)) and
+ (int64(left.location.value64) <= high(smallint)) then
+ begin
+ // consts16 - reg64
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ location.register64.reglo,right.location.register64.reglo,
+ left.location.value));
+ end
+ else
+ begin
+ // const32 - reg64
+ location_force_reg(exprasmlist,left.location,
+ OS_32,true);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBC,
+ location.register64.reglo,left.location.register64.reglo,
+ right.location.register64.reglo));
+ end;
+ exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
+ location.register64.reghi,right.location.register64.reghi));
+ end
+ else if (aint(left.location.value64) = 0) then
+ begin
+ // (const32 shl 32) - reg64
+ if (location.register64.reglo = NR_NO) then
+ begin
+ location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ end;
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ location.register64.reglo,right.location.register64.reglo,0));
+ left.location.value64 := left.location.value64 shr 32;
+ location_force_reg(exprasmlist,left.location,OS_32,true);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,
+ location.register64.reghi,right.location.register64.reghi,
+ left.location.register));
+ end
+ else
+ begin
+ // const64 - reg64
+ location_force_reg(exprasmlist,left.location,
+ def_cgsize(left.resulttype.def),false);
+ if (left.location.loc = LOC_REGISTER) then
+ location.register64 := left.location.register64
+ else if (location.register64.reglo = NR_NO) then
+ begin
+ location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ end;
+ cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,location.size,
+ right.location.register64,left.location.register64,
+ location.register64);
+ end;
+ end;
+ else
+ internalerror(2002072803);
+ end;
+ end
+ else
+ begin
+ if is_signed(resulttype.def) then
+ begin
+ case nodetype of
+ addn:
+ begin
+ op1 := A_ADDC;
+ op2 := A_ADDEO;
+ end;
+ subn:
+ begin
+ op1 := A_SUBC;
+ op2 := A_SUBFEO;
+ end;
+ else
+ internalerror(2002072806);
+ end
+ end
+ else
+ begin
+ case nodetype of
+ addn:
+ begin
+ op1 := A_ADDC;
+ op2 := A_ADDE;
+ end;
+ subn:
+ begin
+ op1 := A_SUBC;
+ op2 := A_SUBFE;
+ end;
+ end;
+ end;
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.register64.reglo,
+ left.location.register64.reglo,right.location.register64.reglo));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.register64.reghi,
+ right.location.register64.reghi,left.location.register64.reghi));
+ if not(is_signed(resulttype.def)) then
+ if nodetype = addn then
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register64.reghi,left.location.register64.reghi))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register64.reghi,location.register64.reghi));
+ cg.g_overflowcheck(exprasmlist,location,resulttype.def);
+ end;
+
+ { set result location }
+ { (emit_compare sets it to LOC_FLAGS for compares, so set the }
+ { real location only now) (JM) }
+ if cmpop and
+ not(nodetype in [equaln,unequaln]) then
+ location_reset(location,LOC_JUMP,OS_NO);
+ end;
+
+
+{*****************************************************************************
+ AddMMX
+*****************************************************************************}
+
+{$ifdef SUPPORT_MMX}
+ procedure ti386addnode.second_addmmx;
+ var
+ op : TAsmOp;
+ cmpop : boolean;
+ mmxbase : tmmxtype;
+ hregister : tregister;
+ begin
+ pass_left_and_right;
+
+ cmpop:=false;
+ mmxbase:=mmx_type(left.resulttype.def);
+ case nodetype of
+ addn :
+ begin
+ if (cs_mmx_saturation in aktlocalswitches) then
+ begin
+ case mmxbase of
+ mmxs8bit:
+ op:=A_PADDSB;
+ mmxu8bit:
+ op:=A_PADDUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PADDSB;
+ mmxu16bit:
+ op:=A_PADDUSW;
+ end;
+ end
+ else
+ begin
+ case mmxbase of
+ mmxs8bit,mmxu8bit:
+ op:=A_PADDB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PADDW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PADDD;
+ end;
+ end;
+ end;
+ muln :
+ begin
+ case mmxbase of
+ mmxs16bit,mmxu16bit:
+ op:=A_PMULLW;
+ mmxfixed16:
+ op:=A_PMULHW;
+ end;
+ end;
+ subn :
+ begin
+ if (cs_mmx_saturation in aktlocalswitches) then
+ begin
+ case mmxbase of
+ mmxs8bit:
+ op:=A_PSUBSB;
+ mmxu8bit:
+ op:=A_PSUBUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PSUBSB;
+ mmxu16bit:
+ op:=A_PSUBUSW;
+ end;
+ end
+ else
+ begin
+ case mmxbase of
+ mmxs8bit,mmxu8bit:
+ op:=A_PSUBB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PSUBW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PSUBD;
+ end;
+ end;
+ end;
+ xorn:
+ op:=A_PXOR;
+ orn:
+ op:=A_POR;
+ andn:
+ op:=A_PAND;
+ else
+ internalerror(200403183);
+ end;
+
+ { left and right no register? }
+ { then one must be demanded }
+ if (left.location.loc<>LOC_MMXREGISTER) then
+ begin
+ if (right.location.loc=LOC_MMXREGISTER) then
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end
+ else
+ begin
+ { register variable ? }
+ if (left.location.loc=LOC_CMMXREGISTER) then
+ begin
+ hregister:=rg.getregistermm(exprasmlist);
+ emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
+ end
+ else
+ begin
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203245);
+
+ location_release(exprasmlist,left.location);
+
+ hregister:=rg.getregistermm(exprasmlist);
+ emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
+ end;
+
+ location_reset(left.location,LOC_MMXREGISTER,OS_NO);
+ left.location.register:=hregister;
+ end;
+ end;
+
+ { at this point, left.location.loc should be LOC_MMXREGISTER }
+ if right.location.loc<>LOC_MMXREGISTER then
+ begin
+ if (nodetype=subn) and (nf_swaped in flags) then
+ begin
+ if right.location.loc=LOC_CMMXREGISTER then
+ begin
+ emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
+ emit_reg_reg(op,S_NO,left.location.register,R_MM7);
+ emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
+ end
+ else
+ begin
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203247);
+ emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
+ emit_reg_reg(op,S_NO,left.location.register,R_MM7);
+ emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
+ location_release(exprasmlist,right.location);
+ end;
+ end
+ else
+ begin
+ if (right.location.loc=LOC_CMMXREGISTER) then
+ begin
+ emit_reg_reg(op,S_NO,right.location.register,left.location.register);
+ end
+ else
+ begin
+ if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203246);
+ emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
+ location_release(exprasmlist,right.location);
+ end;
+ end;
+ end
+ else
+ begin
+ { right.location=LOC_MMXREGISTER }
+ if (nodetype=subn) and (nf_swaped in flags) then
+ begin
+ emit_reg_reg(op,S_NO,left.location.register,right.location.register);
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end
+ else
+ begin
+ emit_reg_reg(op,S_NO,right.location.register,left.location.register);
+ end;
+ end;
+
+ location_freetemp(exprasmlist,right.location);
+ location_release(exprasmlist,right.location);
+ if cmpop then
+ begin
+ location_freetemp(exprasmlist,left.location);
+ location_release(exprasmlist,left.location);
+ end;
+ set_result_location(cmpop,true);
+ end;
+{$endif SUPPORT_MMX}
+
+
+{*****************************************************************************
+ pass_2
+*****************************************************************************}
+
+ procedure tppcaddnode.pass_2;
+ { is also being used for xor, and "mul", "sub, or and comparative }
+ { operators }
+ var
+ cgop : topcg;
+ op : tasmop;
+ tmpreg : tregister;
+ hl : tasmlabel;
+ cmpop : boolean;
+
+ { true, if unsigned types are compared }
+ unsigned : boolean;
+
+ begin
+ { to make it more readable, string and set (not smallset!) have their
+ own procedures }
+ case left.resulttype.def.deftype of
+ orddef :
+ begin
+ { handling boolean expressions }
+ if is_boolean(left.resulttype.def) and
+ is_boolean(right.resulttype.def) then
+ begin
+ second_addboolean;
+ exit;
+ end
+ { 64bit operations }
+ else if is_64bit(left.resulttype.def) then
+ begin
+ second_add64bit;
+ exit;
+ end;
+ end;
+ stringdef :
+ begin
+ internalerror(2002072402);
+ exit;
+ end;
+ setdef :
+ begin
+ { normalsets are already handled in pass1 }
+ if (tsetdef(left.resulttype.def).settype<>smallset) then
+ internalerror(200109041);
+ second_addsmallset;
+ exit;
+ end;
+ arraydef :
+ begin
+{$ifdef SUPPORT_MMX}
+ if is_mmx_able_array(left.resulttype.def) then
+ begin
+ second_addmmx;
+ exit;
+ end;
+{$endif SUPPORT_MMX}
+ end;
+ floatdef :
+ begin
+ second_addfloat;
+ exit;
+ end;
+ end;
+
+ { defaults }
+ cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+
+ pass_left_and_right;
+
+ { Convert flags to register first }
+ { can any of these things be in the flags actually?? (JM) }
+
+ if (left.location.loc = LOC_FLAGS) or
+ (right.location.loc = LOC_FLAGS) then
+ internalerror(2002072602);
+
+ { set result location }
+ if not cmpop then
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
+ else
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
+ (nodetype in [addn,subn,muln]));
+
+ if (location.register = NR_NO) and
+ not(cmpop) then
+ location.register := cg.getintregister(exprasmlist,OS_INT);
+
+ if not(cs_check_overflow in aktlocalswitches) or
+ (cmpop) or
+ (nodetype in [orn,andn,xorn]) then
+ begin
+ case nodetype of
+ addn, muln, xorn, orn, andn:
+ begin
+ case nodetype of
+ addn:
+ cgop := OP_ADD;
+ muln:
+ if unsigned then
+ cgop := OP_MUL
+ else
+ cgop := OP_IMUL;
+ xorn:
+ cgop := OP_XOR;
+ orn:
+ cgop := OP_OR;
+ andn:
+ cgop := OP_AND;
+ end;
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc <> LOC_CONSTANT) then
+ cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
+ left.location.register,right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
+ right.location.value,left.location.register,
+ location.register);
+ end;
+ subn:
+ begin
+ if (nf_swaped in flags) then
+ swapleftright;
+ if left.location.loc <> LOC_CONSTANT then
+ if right.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
+ right.location.register,left.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
+ right.location.value,left.location.register,
+ location.register)
+ else
+ if (longint(left.location.value) >= low(smallint)) and
+ (longint(left.location.value) <= high(smallint)) then
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ location.register,right.location.register,
+ longint(left.location.value)));
+ end
+ else
+ begin
+ tmpreg := cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_const_reg(exprasmlist,OS_INT,
+ left.location.value,tmpreg);
+ cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
+ right.location.register,tmpreg,location.register);
+ end;
+ end;
+ ltn,lten,gtn,gten,equaln,unequaln :
+ begin
+ emit_compare(unsigned);
+ end;
+ end;
+ end
+ else
+ // overflow checking is on and we have an addn, subn or muln
+ begin
+ if is_signed(resulttype.def) then
+ begin
+ case nodetype of
+ addn:
+ op := A_ADDO;
+ subn:
+ begin
+ op := A_SUBO;
+ if (nf_swaped in flags) then
+ swapleftright;
+ end;
+ muln:
+ op := A_MULLWO;
+ else
+ internalerror(2002072601);
+ end;
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
+ left.location.register,right.location.register));
+ cg.g_overflowcheck(exprasmlist,location,resulttype.def);
+ end
+ else
+ begin
+ case nodetype of
+ addn:
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
+ left.location.register,right.location.register));
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
+ cg.g_overflowcheck(exprasmlist,location,resulttype.def);
+ end;
+ subn:
+ begin
+ if nf_swaped in flags then
+ swapleftright;
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
+ left.location.register,right.location.register));
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
+ cg.g_overflowcheck(exprasmlist,location,resulttype.def);
+ end;
+ muln:
+ begin
+ { calculate the upper 32 bits of the product, = 0 if no overflow }
+ cg.a_reg_alloc(exprasmlist,NR_R0);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU_,NR_R0,
+ left.location.register,right.location.register));
+ cg.a_reg_dealloc(exprasmlist,NR_R0);
+ { calculate the real result }
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
+ left.location.register,right.location.register));
+ { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
+ objectlibrary.getjumplabel(hl);
+ tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,hl);
+ cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
+ cg.a_label(exprasmlist,hl);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+begin
+ caddnode:=tppcaddnode;
+end.
diff --git a/compiler/powerpc/nppccal.pas b/compiler/powerpc/nppccal.pas
new file mode 100644
index 0000000000..264896f900
--- /dev/null
+++ b/compiler/powerpc/nppccal.pas
@@ -0,0 +1,142 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the PowerPC specific part of call 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 bymethodpointer
+ 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 nppccal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symdef,node,ncal,ncgcal;
+
+ type
+ tppccallnode = class(tcgcallnode)
+ procedure extra_call_code;override;
+ procedure do_syscall;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symbase,symsym,symtable,defutil,paramgr,parabase,
+ cgbase,pass_2,
+ cpuinfo,cpubase,aasmbase,aasmtai,aasmcpu,
+ nmem,nld,ncnv,
+ ncgutil,cgutils,cgobj,tgobj,regvars,rgobj,rgcpu,
+ cg64f32,cgcpu,cpupi,procinfo;
+
+
+ procedure tppccallnode.extra_call_code;
+ begin
+ if assigned(varargsparas) then
+ begin
+ if (target_info.abi = abi_powerpc_sysv) then
+ begin
+ if va_uses_float_reg in varargsparas.varargsinfo then
+ exprasmlist.concat(taicpu.op_const_const_const(A_CREQV,6,6,6))
+ else
+ exprasmlist.concat(taicpu.op_const_const_const(A_CRXOR,6,6,6));
+ end;
+ end;
+ end;
+
+
+ procedure tppccallnode.do_syscall;
+ var
+ tmpref: treference;
+ begin
+ case target_info.system of
+ system_powerpc_morphos:
+ begin
+ if (po_syscall_sysv in tprocdef(procdefinition).procoptions) or
+ (po_syscall_sysvbase in tprocdef(procdefinition).procoptions) then
+ begin
+ cg.getcpuregister(exprasmlist,NR_R0);
+ cg.getcpuregister(exprasmlist,NR_R31);
+
+ reference_reset(tmpref);
+ tmpref.symbol:=objectlibrary.newasmsymbol(tglobalvarsym(tprocdef(procdefinition).libsym).mangledname,AB_EXTERNAL,AT_DATA);
+ tmpref.refaddr:=addr_hi;
+ exprasmlist.concat(taicpu.op_reg_ref(A_LIS,NR_R31,tmpref));
+ tmpref.base:=NR_R31;
+ tmpref.refaddr:=addr_lo;
+ exprasmlist.concat(taicpu.op_reg_ref(A_LWZ,NR_R31,tmpref));
+
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_ADDI,NR_R31,NR_R31,-tprocdef(procdefinition).extnumber));
+ reference_reset_base(tmpref,NR_R31,0);
+ exprasmlist.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
+ exprasmlist.concat(taicpu.op_reg(A_MTCTR,NR_R0));
+ exprasmlist.concat(taicpu.op_none(A_BCTRL));
+
+ cg.ungetcpuregister(exprasmlist,NR_R31);
+ cg.ungetcpuregister(exprasmlist,NR_R0);
+ end
+ else if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) or
+ (po_syscall_r12base in tprocdef(procdefinition).procoptions) then
+ begin
+ cg.getcpuregister(exprasmlist,NR_R0);
+ cg.getcpuregister(exprasmlist,NR_R31);
+
+ if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) then
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_ADDI,NR_R31,NR_R3,-tprocdef(procdefinition).extnumber))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_ADDI,NR_R31,NR_R12,-tprocdef(procdefinition).extnumber));
+ reference_reset_base(tmpref,NR_R31,0);
+ exprasmlist.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
+ exprasmlist.concat(taicpu.op_reg(A_MTCTR,NR_R0));
+ exprasmlist.concat(taicpu.op_none(A_BCTRL));
+
+ cg.ungetcpuregister(exprasmlist,NR_R31);
+ cg.ungetcpuregister(exprasmlist,NR_R0);
+ end
+ else if po_syscall_legacy in tprocdef(procdefinition).procoptions then
+ begin
+ cg.getcpuregister(exprasmlist,NR_R0);
+ cg.getcpuregister(exprasmlist,NR_R3);
+
+ { store call offset into R3 }
+ exprasmlist.concat(taicpu.op_reg_const(A_LI,NR_R3,-tprocdef(procdefinition).extnumber));
+
+ { prepare LR, and call function }
+ reference_reset_base(tmpref,NR_R2,100); { 100 ($64) is EmulDirectCallOS offset }
+ exprasmlist.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
+ exprasmlist.concat(taicpu.op_reg(A_MTLR,NR_R0));
+ exprasmlist.concat(taicpu.op_none(A_BLRL));
+
+ cg.ungetcpuregister(exprasmlist,NR_R0);
+ cg.ungetcpuregister(exprasmlist,NR_R3);
+ end
+ else
+ internalerror(2005010403);
+ end;
+ else
+ internalerror(2004042901);
+ end;
+ end;
+
+
+begin
+ ccallnode:=tppccallnode;
+end.
diff --git a/compiler/powerpc/nppccnv.pas b/compiler/powerpc/nppccnv.pas
new file mode 100644
index 0000000000..4dca8d53d3
--- /dev/null
+++ b/compiler/powerpc/nppccnv.pas
@@ -0,0 +1,334 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for type converting 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 nppccnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,defcmp;
+
+ type
+ tppctypeconvnode = class(tcgtypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real;override;
+ procedure second_real_to_real;override;
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+ uses
+ verbose,globtype,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,
+ defutil,
+ cgbase,cgutils,pass_1,pass_2,
+ ncon,ncal,
+ ncgutil,
+ cpubase,aasmcpu,
+ rgobj,tgobj,cgobj;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function tppctypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[19];
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resulttype.def) or
+ is_currency(left.resulttype.def) then
+ begin
+ { hack to avoid double division by 10000, as it's }
+ { already done by resulttypepass.resulttype_int_to_real }
+ if is_currency(left.resulttype.def) then
+ left.resulttype := s64inttype;
+ if is_signed(left.resulttype.def) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resulttype.def) then
+ inserttypeconv(left,s32inttype)
+ else
+ inserttypeconv(left,u32inttype);
+ firstpass(left);
+ end;
+ result := nil;
+ if registersfpu<1 then
+ registersfpu:=1;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+ procedure tppctypeconvnode.second_int_to_real;
+
+ type
+ tdummyarray = packed array[0..7] of byte;
+
+ const
+ dummy1: int64 = $4330000080000000;
+ dummy2: int64 = $4330000000000000;
+
+ var
+ tempconst: trealconstnode;
+ ref: treference;
+ valuereg, tempreg, leftreg, tmpfpureg: tregister;
+ size: tcgsize;
+ signed : boolean;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+
+ { the code here comes from the PowerPC Compiler Writer's Guide }
+
+ { * longint to double }
+ { addis R0,R0,0x4330 # R0 = 0x43300000 }
+ { stw R0,disp(R1) # store upper half }
+ { xoris R3,R3,0x8000 # flip sign bit }
+ { stw R3,disp+4(R1) # store lower half }
+ { lfd FR1,disp(R1) # float load double of value }
+ { fsub FR1,FR1,FR2 # subtract 0x4330000080000000 }
+
+ { * cardinal to double }
+ { addis R0,R0,0x4330 # R0 = 0x43300000 }
+ { stw R0,disp(R1) # store upper half }
+ { stw R3,disp+4(R1) # store lower half }
+ { lfd FR1,disp(R1) # float load double of value }
+ { fsub FR1,FR1,FR2 # subtract 0x4330000000000000 }
+ tg.Gettemp(exprasmlist,8,tt_normal,ref);
+
+ signed := is_signed(left.resulttype.def);
+
+ { we need a certain constant for the conversion, so create it here }
+ if signed then
+ tempconst :=
+ crealconstnode.create(double(tdummyarray(dummy1)),
+ pbestrealtype^)
+ else
+ tempconst :=
+ crealconstnode.create(double(tdummyarray(dummy2)),
+ pbestrealtype^);
+
+ resulttypepass(tempconst);
+ firstpass(tempconst);
+ secondpass(tempconst);
+ if (tempconst.location.loc <> LOC_CREFERENCE) or
+ { has to be handled by a helper }
+ is_64bitint(left.resulttype.def) then
+ internalerror(200110011);
+
+ case left.location.loc of
+ LOC_REGISTER:
+ begin
+ leftreg := left.location.register;
+ valuereg := leftreg;
+ end;
+ LOC_CREGISTER:
+ begin
+ leftreg := left.location.register;
+ if signed then
+ valuereg := cg.getintregister(exprasmlist,OS_INT)
+ else
+ valuereg := leftreg;
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ leftreg := cg.getintregister(exprasmlist,OS_INT);
+ valuereg := leftreg;
+ if signed then
+ size := OS_S32
+ else
+ size := OS_32;
+ cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),
+ size,left.location.reference,leftreg);
+ end
+ else
+ internalerror(200110012);
+ end;
+ tempreg := cg.getintregister(exprasmlist,OS_INT);
+ exprasmlist.concat(taicpu.op_reg_const(A_LIS,tempreg,$4330));
+ cg.a_load_reg_ref(exprasmlist,OS_32,OS_32,tempreg,ref);
+ if signed then
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_XORIS,valuereg,
+ { xoris expects a unsigned 16 bit int (FK) }
+ leftreg,$8000));
+ inc(ref.offset,4);
+ cg.a_load_reg_ref(exprasmlist,OS_32,OS_32,valuereg,ref);
+ dec(ref.offset,4);
+
+ tmpfpureg := cg.getfpuregister(exprasmlist,OS_F64);
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F64,tempconst.location.reference,
+ tmpfpureg);
+ tempconst.free;
+
+ location.register := cg.getfpuregister(exprasmlist,OS_F64);
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F64,ref,location.register);
+
+ tg.ungetiftemp(exprasmlist,ref);
+
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_FSUB,location.register,
+ location.register,tmpfpureg));
+
+ { work around bug in some PowerPC processors }
+ if (tfloatdef(resulttype.def).typ = s32real) then
+ exprasmlist.concat(taicpu.op_reg_reg(A_FRSP,location.register,
+ location.register));
+ end;
+
+
+ procedure tppctypeconvnode.second_real_to_real;
+ begin
+ inherited second_real_to_real;
+ { work around bug in some powerpc processors where doubles aren't }
+ { properly converted to singles }
+ if (tfloatdef(left.resulttype.def).typ = s64real) and
+ (tfloatdef(resulttype.def).typ = s32real) then
+ exprasmlist.concat(taicpu.op_reg_reg(A_FRSP,location.register,
+ location.register));
+ end;
+
+
+
+ procedure tppctypeconvnode.second_int_to_bool;
+ var
+ hreg1,
+ hreg2 : tregister;
+ href : treference;
+ resflags : tresflags;
+ opsize : tcgsize;
+ hlabel, oldtruelabel, oldfalselabel : tasmlabel;
+ begin
+ oldtruelabel:=truelabel;
+ oldfalselabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { byte(boolean) or word(wordbool) or longint(longbool) must }
+ { be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resulttype.def.size=resulttype.def.size) and
+ (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ begin
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ location_copy(location,left.location);
+ exit;
+ end;
+
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
+ opsize := def_cgsize(left.resulttype.def);
+ case left.location.loc of
+ LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER :
+ begin
+ if left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
+ begin
+ hreg1:=cg.getintregister(exprasmlist,OS_INT);
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ cg.a_load_ref_reg(exprasmlist,OS_INT,OS_INT,left.location.reference,hreg1);
+ hreg2:=cg.getintregister(exprasmlist,OS_INT);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ cg.a_load_ref_reg(exprasmlist,OS_INT,OS_INT,href,hreg2);
+ cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_32,hreg1,hreg2,hreg1);
+ end
+ else
+ cg.a_load_ref_reg(exprasmlist,opsize,opsize,left.location.reference,hreg1);
+ end
+ else
+ begin
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hreg1:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_32,left.location.register64.reghi,left.location.register64.reglo,hreg1);
+ end
+ else
+ hreg1 := left.location.register;
+ end;
+ hreg2 := cg.getintregister(exprasmlist,OS_INT);
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBIC,hreg2,hreg1,1));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,hreg1,hreg2,hreg1));
+ end;
+ LOC_FLAGS :
+ begin
+ hreg1:=cg.getintregister(exprasmlist,OS_INT);
+ resflags:=left.location.resflags;
+ cg.g_flags2reg(exprasmlist,location.size,resflags,hreg1);
+ end;
+ LOC_JUMP :
+ begin
+ hreg1:=cg.getintregister(exprasmlist,OS_INT);
+ objectlibrary.getjumplabel(hlabel);
+ cg.a_label(exprasmlist,truelabel);
+ cg.a_load_const_reg(exprasmlist,OS_INT,1,hreg1);
+ cg.a_jmp_always(exprasmlist,hlabel);
+ cg.a_label(exprasmlist,falselabel);
+ cg.a_load_const_reg(exprasmlist,OS_INT,0,hreg1);
+ cg.a_label(exprasmlist,hlabel);
+ end;
+ else
+ internalerror(10062);
+ end;
+ location.register := hreg1;
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ end;
+
+
+begin
+ ctypeconvnode:=tppctypeconvnode;
+end.
diff --git a/compiler/powerpc/nppcinl.pas b/compiler/powerpc/nppcinl.pas
new file mode 100644
index 0000000000..4d0b3b4720
--- /dev/null
+++ b/compiler/powerpc/nppcinl.pas
@@ -0,0 +1,146 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 inline 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 nppcinl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl,ncginl;
+
+ type
+ tppcinlinenode = class(tcginlinenode)
+ { first pass override
+ so that the code generator will actually generate
+ these nodes.
+ }
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_prefetch;override;
+ private
+ procedure load_fpu_location;
+ end;
+
+implementation
+
+ uses
+ cutils,globals,verbose,
+ aasmtai,aasmcpu,
+ symconst,symdef,
+ defutil,
+ cgbase,pass_2,
+ cpubase,ncgutil,
+ cgutils,cgobj,rgobj;
+
+
+{*****************************************************************************
+ TPPCINLINENODE
+*****************************************************************************}
+
+ function tppcinlinenode.first_abs_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_abs_real := nil;
+ end;
+
+ function tppcinlinenode.first_sqr_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_sqr_real := nil;
+ end;
+
+ { load the FPU into the an fpu register }
+ procedure tppcinlinenode.load_fpu_location;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ secondpass(left);
+ location_force_fpureg(exprasmlist,left.location,true);
+ location_copy(location,left.location);
+ if (location.loc = LOC_CFPUREGISTER) then
+ begin
+ location.loc := LOC_FPUREGISTER;
+ location.register := cg.getfpuregister(exprasmlist,OS_F64);
+ end;
+ end;
+
+ procedure tppcinlinenode.second_abs_real;
+ begin
+ location.loc:=LOC_FPUREGISTER;
+ load_fpu_location;
+ exprasmlist.concat(taicpu.op_reg_reg(A_FABS,location.register,
+ left.location.register));
+ end;
+
+ procedure tppcinlinenode.second_sqr_real;
+ begin
+ location.loc:=LOC_FPUREGISTER;
+ load_fpu_location;
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_FMUL,location.register,
+ left.location.register,left.location.register));
+ end;
+
+
+ procedure tppcinlinenode.second_prefetch;
+ var
+ r: tregister;
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ r:=cg.getintregister(exprasmlist,OS_ADDR);
+ if (left.location.reference.offset = 0) and
+ not assigned(left.location.reference.symbol) then
+ begin
+ if (left.location.reference.index = NR_NO) then
+ exprasmlist.concat(taicpu.op_const_reg(A_DCBT,0,left.location.reference.base))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(A_DCBT,left.location.reference.base,left.location.reference.index));
+ end
+ else
+ begin
+ cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,r);
+ exprasmlist.concat(taicpu.op_const_reg(A_DCBT,0,r));
+ end;
+ end;
+ else
+ internalerror(200402021);
+ end;
+ end;
+
+begin
+ cinlinenode:=tppcinlinenode;
+end.
diff --git a/compiler/powerpc/nppcld.pas b/compiler/powerpc/nppcld.pas
new file mode 100644
index 0000000000..a847b6fc7f
--- /dev/null
+++ b/compiler/powerpc/nppcld.pas
@@ -0,0 +1,126 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate ppc assembler for nodes that handle loads and assignments
+
+ 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 nppcld;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ node,ncgld;
+
+ type
+ tppcloadnode = class(tcgloadnode)
+ procedure pass_2; override;
+ procedure generate_picvaraccess;override;
+ end;
+
+
+ implementation
+
+ uses
+ verbose,
+ systems,
+ globtype,globals,
+ cpubase,
+ cgutils,cgobj,
+ aasmbase,aasmtai,
+ symconst,symsym,
+ procinfo,
+ nld;
+
+
+ procedure tppcloadnode.pass_2;
+ var
+ l : tasmsymbol;
+ ref : treference;
+ begin
+ case target_info.system of
+ system_powerpc_darwin:
+ begin
+ if (symtableentry.typ = procsym) and
+ (tprocsym(symtableentry).owner.symtabletype in [staticsymtable,globalsymtable]) and
+ (
+ (not tprocsym(symtableentry).owner.iscurrentunit) or
+ (po_external in tprocsym(symtableentry).procdef[1].procoptions)
+ ) then
+ begin
+ l:=objectlibrary.getasmsymbol('L'+tprocsym(symtableentry).procdef[1].mangledname+'$non_lazy_ptr');
+ if not(assigned(l)) then
+ begin
+ l:=objectlibrary.newasmsymbol('L'+tprocsym(symtableentry).procdef[1].mangledname+'$non_lazy_ptr',AB_COMMON,AT_DATA);
+ asmlist[al_picdata].concat(tai_symbol.create(l,0));
+ asmlist[al_picdata].concat(tai_const.create_indirect_sym(objectlibrary.newasmsymbol(tprocsym(symtableentry).procdef[1].mangledname,AB_EXTERNAL,AT_DATA)));
+ asmlist[al_picdata].concat(tai_const.create_32bit(0));
+ end;
+ reference_reset_symbol(ref,l,0);
+ reference_reset_base(location.reference,cg.getaddressregister(exprasmlist),0);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,ref,location.reference.base);
+ end
+ else
+ inherited pass_2;
+ end;
+ else
+ inherited pass_2;
+ end;
+ end;
+
+ procedure tppcloadnode.generate_picvaraccess;
+ var
+ l : tasmsymbol;
+ ref : treference;
+ begin
+ case target_info.system of
+ system_powerpc_darwin:
+ begin
+ if ([vo_is_dll_var,vo_is_external] * tglobalvarsym(symtableentry).varoptions <> []) or
+ ((tglobalvarsym(symtableentry).owner.symtabletype in [staticsymtable,globalsymtable]) and
+ (not(tglobalvarsym(symtableentry).owner.iscurrentunit) or
+ (cs_create_pic in aktmoduleswitches))) then
+ begin
+ l:=objectlibrary.getasmsymbol('L'+tglobalvarsym(symtableentry).mangledname+'$non_lazy_ptr');
+ if not(assigned(l)) then
+ begin
+ l:=objectlibrary.newasmsymbol('L'+tglobalvarsym(symtableentry).mangledname+'$non_lazy_ptr',AB_COMMON,AT_DATA);
+ asmlist[al_picdata].concat(tai_symbol.create(l,0));
+ asmlist[al_picdata].concat(tai_const.create_indirect_sym(objectlibrary.newasmsymbol(tglobalvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA)));
+ asmlist[al_picdata].concat(tai_const.create_32bit(0));
+ end;
+
+ reference_reset_symbol(ref,l,0);
+{ ref.base:=current_procinfo.got;
+ ref.relsymbol:=current_procinfo.gotlabel;}
+ reference_reset_base(location.reference,cg.getaddressregister(exprasmlist),0);
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,ref,location.reference.base);
+ end
+ else
+ internalerror(200403021);
+ end
+ else
+ internalerror(200402291);
+ end;
+ end;
+
+
+begin
+ cloadnode:=tppcloadnode;
+end.
diff --git a/compiler/powerpc/nppcmat.pas b/compiler/powerpc/nppcmat.pas
new file mode 100644
index 0000000000..247179a7c8
--- /dev/null
+++ b/compiler/powerpc/nppcmat.pas
@@ -0,0 +1,703 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for math 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 nppcmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat;
+
+ type
+ tppcmoddivnode = class(tmoddivnode)
+ function pass_1: tnode;override;
+ procedure pass_2;override;
+ end;
+
+ tppcshlshrnode = class(tshlshrnode)
+ procedure pass_2;override;
+ { everything will be handled in pass_2 }
+ function first_shlshr64bitint: tnode; override;
+ end;
+
+ tppcunaryminusnode = class(tunaryminusnode)
+ procedure pass_2;override;
+ end;
+
+ tppcnotnode = class(tnotnode)
+ procedure pass_2;override;
+ end;
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,
+ aasmbase,aasmcpu,aasmtai,
+ defutil,
+ cgbase,cgutils,cgobj,pass_2,
+ ncon,procinfo,
+ cpubase,
+ ncgutil,cgcpu;
+
+{ helper functions }
+procedure getmagic_unsigned32(d : dword; out magic_m : dword; out magic_add : boolean; out magic_shift : dword);
+var
+ p : longint;
+ nc, delta, q1, r1, q2, r2 : dword;
+
+begin
+ assert(d > 0);
+
+ magic_add := false;
+ nc := - 1 - (-d) mod d;
+ p := 31; { initialize p }
+ q1 := $80000000 div nc; { initialize q1 = 2p/nc }
+ r1 := $80000000 - q1*nc; { initialize r1 = rem(2p,nc) }
+ q2 := $7FFFFFFF div d; { initialize q2 = (2p-1)/d }
+ r2 := $7FFFFFFF - q2*d; { initialize r2 = rem((2p-1),d) }
+ repeat
+ inc(p);
+ if (r1 >= (nc - r1)) then begin
+ q1 := 2 * q1 + 1; { update q1 }
+ r1 := 2*r1 - nc; { update r1 }
+ end else begin
+ q1 := 2*q1; { update q1 }
+ r1 := 2*r1; { update r1 }
+ end;
+ if ((r2 + 1) >= (d - r2)) then begin
+ if (q2 >= $7FFFFFFF) then
+ magic_add := true;
+ q2 := 2*q2 + 1; { update q2 }
+ r2 := 2*r2 + 1 - d; { update r2 }
+ end else begin
+ if (q2 >= $80000000) then
+ magic_add := true;
+ q2 := 2*q2; { update q2 }
+ r2 := 2*r2 + 1; { update r2 }
+ end;
+ delta := d - 1 - r2;
+ until not ((p < 64) and ((q1 < delta) or ((q1 = delta) and (r1 = 0))));
+ magic_m := q2 + 1; { resulting magic number }
+ magic_shift := p - 32; { resulting shift }
+end;
+
+procedure getmagic_signed32(d : longint; out magic_m : longint; out magic_s : longint);
+const
+ two_31 : DWord = high(longint)+1;
+var
+ p : Longint;
+ ad, anc, delta, q1, r1, q2, r2, t : DWord;
+
+begin
+ assert((d < -1) or (d > 1));
+
+ ad := abs(d);
+ t := two_31 + (DWord(d) shr 31);
+ anc := t - 1 - t mod ad; { absolute value of nc }
+ p := 31; { initialize p }
+ q1 := two_31 div anc; { initialize q1 = 2p/abs(nc) }
+ r1 := two_31 - q1*anc; { initialize r1 = rem(2p,abs(nc)) }
+ q2 := two_31 div ad; { initialize q2 = 2p/abs(d) }
+ r2 := two_31 - q2*ad; { initialize r2 = rem(2p,abs(d)) }
+ repeat
+ inc(p);
+ q1 := 2*q1; { update q1 = 2p/abs(nc) }
+ r1 := 2*r1; { update r1 = rem(2p/abs(nc)) }
+ if (r1 >= anc) then begin { must be unsigned comparison }
+ inc(q1);
+ dec(r1, anc);
+ end;
+ q2 := 2*q2; { update q2 = 2p/abs(d) }
+ r2 := 2*r2; { update r2 = rem(2p/abs(d)) }
+ if (r2 >= ad) then begin { must be unsigned comparison }
+ inc(q2);
+ dec(r2, ad);
+ end;
+ delta := ad - r2;
+ until not ((q1 < delta) or ((q1 = delta) and (r1 = 0)));
+ magic_m := q2 + 1;
+ if (d < 0) then begin
+ magic_m := -magic_m; { resulting magic number }
+ end;
+ magic_s := p - 32; { resulting shift }
+end;
+
+{*****************************************************************************
+ TPPCMODDIVNODE
+*****************************************************************************}
+
+ function tppcmoddivnode.pass_1: tnode;
+ begin
+ result := inherited pass_1;
+ if not assigned(result) then
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tppcmoddivnode.pass_2;
+ const
+ { signed overflow }
+ divops: array[boolean, boolean] of tasmop =
+ ((A_DIVWU,A_DIVWU_),(A_DIVW,A_DIVWO_));
+ zerocond: tasmcond = (dirhint: DH_Plus; simple: true; cond:C_NE; cr: RS_CR1);
+ var
+ power : longint;
+ op : tasmop;
+ numerator,
+ divider,
+ resultreg : tregister;
+ size : Tcgsize;
+ hl : tasmlabel;
+ done: boolean;
+
+ procedure genOrdConstNodeDiv;
+ const
+ negops : array[boolean] of tasmop = (A_NEG, A_NEGO);
+ var
+ magic, shift : longint;
+ u_magic, u_shift : dword;
+ u_add : boolean;
+
+ divreg : tregister;
+ begin
+ if (tordconstnode(right).value = 0) then begin
+ internalerror(2005061701);
+ end else if (tordconstnode(right).value = 1) then begin
+ cg.a_load_reg_reg(exprasmlist, OS_INT, OS_INT, numerator, resultreg);
+ end else if (tordconstnode(right).value = -1) then begin
+ // note: only in the signed case possible..., may overflow
+ exprasmlist.concat(taicpu.op_reg_reg(negops[cs_check_overflow in aktlocalswitches], resultreg, numerator));
+ end else if (ispowerof2(tordconstnode(right).value, power)) then begin
+ if (is_signed(right.resulttype.def)) then begin
+ { From "The PowerPC Compiler Writer's Guide", pg. 52ff }
+ cg.a_op_const_reg_reg(exprasmlist, OP_SAR, OS_INT, power,
+ numerator, resultreg);
+ exprasmlist.concat(taicpu.op_reg_reg(A_ADDZE, resultreg, resultreg));
+ end else begin
+ cg.a_op_const_reg_reg(exprasmlist, OP_SHR, OS_INT, power, numerator, resultreg)
+ end;
+ end else begin
+ { replace division by multiplication, both implementations }
+ { from "The PowerPC Compiler Writer's Guide" pg. 53ff }
+ divreg := cg.getintregister(exprasmlist, OS_INT);
+ if (is_signed(right.resulttype.def)) then begin
+ getmagic_signed32(tordconstnode(right).value, magic, shift);
+ // load magic value
+ cg.a_load_const_reg(exprasmlist, OS_INT, magic, divreg);
+ // multiply
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHW, resultreg, numerator, divreg));
+ // add/subtract numerator
+ if (tordconstnode(right).value > 0) and (magic < 0) then begin
+ cg.a_op_reg_reg_reg(exprasmlist, OP_ADD, OS_INT, numerator, resultreg, resultreg);
+ end else if (tordconstnode(right).value < 0) and (magic > 0) then begin
+ cg.a_op_reg_reg_reg(exprasmlist, OP_SUB, OS_INT, numerator, resultreg, resultreg);
+ end;
+ // shift shift places to the right (arithmetic)
+ cg.a_op_const_reg_reg(exprasmlist, OP_SAR, OS_INT, shift, resultreg, resultreg);
+ // extract and add sign bit
+ if (tordconstnode(right).value >= 0) then begin
+ cg.a_op_const_reg_reg(exprasmlist, OP_SHR, OS_INT, 31, numerator, divreg);
+ end else begin
+ cg.a_op_const_reg_reg(exprasmlist, OP_SHR, OS_INT, 31, resultreg, divreg);
+ end;
+ cg.a_op_reg_reg_reg(exprasmlist, OP_ADD, OS_INT, resultreg, divreg, resultreg);
+ end else begin
+ getmagic_unsigned32(tordconstnode(right).value, u_magic, u_add, u_shift);
+ // load magic in divreg
+ cg.a_load_const_reg(exprasmlist, OS_INT, u_magic, divreg);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU, resultreg, numerator, divreg));
+ if (u_add) then begin
+ cg.a_op_reg_reg_reg(exprasmlist, OP_SUB, OS_INT, resultreg, numerator, divreg);
+ cg.a_op_const_reg_reg(exprasmlist, OP_SHR, OS_INT, 1, divreg, divreg);
+ cg.a_op_reg_reg_reg(exprasmlist, OP_ADD, OS_INT, divreg, resultreg, divreg);
+ cg.a_op_const_reg_reg(exprasmlist, OP_SHR, OS_INT, u_shift-1, divreg, resultreg);
+ end else begin
+ cg.a_op_const_reg_reg(exprasmlist, OP_SHR, OS_INT, u_shift, resultreg, resultreg);
+ end;
+ end;
+ end;
+ done := true;
+ end;
+
+ procedure genOrdConstNodeMod;
+ var
+ modreg, maskreg, tempreg : tregister;
+ begin
+ if (tordconstnode(right).value = 0) then begin
+ internalerror(2005061702);
+ end else if (abs(tordconstnode(right).value) = 1) then begin
+ // x mod +/-1 is always zero
+ cg.a_load_const_reg(exprasmlist, OS_INT, 0, resultreg);
+ end else if (ispowerof2(tordconstnode(right).value, power)) then begin
+ if (is_signed(right.resulttype.def)) then begin
+
+ tempreg := cg.getintregister(exprasmlist, OS_INT);
+ maskreg := cg.getintregister(exprasmlist, OS_INT);
+ modreg := cg.getintregister(exprasmlist, OS_INT);
+
+ cg.a_load_const_reg(exprasmlist, OS_INT, abs(tordconstnode(right).value)-1, modreg);
+ cg.a_op_const_reg_reg(exprasmlist, OP_SAR, OS_INT, 31, numerator, maskreg);
+ cg.a_op_reg_reg_reg(exprasmlist, OP_AND, OS_INT, numerator, modreg, tempreg);
+
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC, maskreg, maskreg, modreg));
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC, modreg, tempreg, 0));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE, modreg, modreg, modreg));
+ cg.a_op_reg_reg_reg(exprasmlist, OP_AND, OS_INT, modreg, maskreg, maskreg);
+ cg.a_op_reg_reg_reg(exprasmlist, OP_OR, OS_INT, maskreg, tempreg, resultreg);
+ end else begin
+ cg.a_op_const_reg_reg(exprasmlist, OP_AND, OS_INT, tordconstnode(right).value-1, numerator, resultreg);
+ end;
+ end else begin
+ genOrdConstNodeDiv();
+ cg.a_op_const_reg_reg(exprasmlist, OP_MUL, OS_INT, tordconstnode(right).value, resultreg, resultreg);
+ cg.a_op_reg_reg_reg(exprasmlist, OP_SUB, OS_INT, resultreg, numerator, resultreg);
+ end;
+ end;
+
+
+ begin
+ secondpass(left);
+ secondpass(right);
+ location_copy(location,left.location);
+
+ { put numerator in register }
+ size:=def_cgsize(left.resulttype.def);
+ location_force_reg(exprasmlist,left.location,
+ size,true);
+ location_copy(location,left.location);
+ numerator := location.register;
+ resultreg := location.register;
+ if (location.loc = LOC_CREGISTER) then begin
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(exprasmlist,size);
+ resultreg := location.register;
+ end else if (nodetype = modn) or (right.nodetype = ordconstn) then begin
+ // for a modulus op, and for const nodes we need the result register
+ // to be an extra register
+ resultreg := cg.getintregister(exprasmlist,size);
+ end;
+
+ done := false;
+ if (right.nodetype = ordconstn) then begin
+ if (nodetype = divn) then
+ genOrdConstNodeDiv
+ else
+ genOrdConstNodeMod;
+ done := true;
+ end;
+
+ if (not done) then begin
+ { load divider in a register if necessary }
+ location_force_reg(exprasmlist,right.location,
+ def_cgsize(right.resulttype.def),true);
+ if (right.nodetype <> ordconstn) then
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_CMPWI,NR_CR1,
+ right.location.register,0));
+ divider := right.location.register;
+
+ { needs overflow checking, (-maxlongint-1) div (-1) overflows! }
+ op := divops[is_signed(right.resulttype.def),
+ cs_check_overflow in aktlocalswitches];
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op,resultreg,numerator,
+ divider));
+
+ if (nodetype = modn) then
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,resultreg,
+ divider,resultreg));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
+ numerator,resultreg));
+ resultreg := location.register;
+ end;
+ end;
+ { set result location }
+ location.loc:=LOC_REGISTER;
+ location.register:=resultreg;
+ if right.nodetype <> ordconstn then
+ begin
+ objectlibrary.getjumplabel(hl);
+ exprasmlist.concat(taicpu.op_cond_sym(A_BC,zerocond,hl));
+ cg.a_call_name(exprasmlist,'FPC_DIVBYZERO');
+ cg.a_label(exprasmlist,hl);
+ end;
+ { unsigned division/module can only overflow in case of division by zero }
+ { (but checking this overflow flag is more convoluted than performing a }
+ { simple comparison with 0) }
+ if is_signed(right.resulttype.def) then
+ cg.g_overflowcheck(exprasmlist,location,resulttype.def);
+ end;
+
+
+{*****************************************************************************
+ TPPCSHLRSHRNODE
+*****************************************************************************}
+
+ function tppcshlshrnode.first_shlshr64bitint: tnode;
+ begin
+ result := nil;
+ end;
+
+ procedure tppcshlshrnode.pass_2;
+
+ var
+ resultreg, hregister1,hregister2,
+ hreg64hi,hreg64lo : tregister;
+ op : topcg;
+ asmop1, asmop2: tasmop;
+ shiftval: aint;
+
+ begin
+ secondpass(left);
+ secondpass(right);
+
+ if is_64bitint(left.resulttype.def) then
+ begin
+ location_force_reg(exprasmlist,left.location,
+ def_cgsize(left.resulttype.def),true);
+ location_copy(location,left.location);
+ hreg64hi := location.register64.reghi;
+ hreg64lo := location.register64.reglo;
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_32);
+ location.register64.reglo := cg.getintregister(exprasmlist,OS_32);
+ end;
+ if (right.nodetype = ordconstn) then
+ begin
+ shiftval := tordconstnode(right).value;
+ shiftval := shiftval and 63;
+{
+ I think the statements below is much more correct instead of the hack above,
+ but then we fail tshlshr.pp :/
+
+ if shiftval > 63 then
+ begin
+ cg.a_load_const_reg(exprasmlist,OS_32,0,location.register64.reglo);
+ cg.a_load_const_reg(exprasmlist,OS_32,0,location.register64.reglo);
+ end
+ else } if shiftval > 31 then
+ begin
+ if nodetype = shln then
+ begin
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHL,OS_32,
+ shiftval and 31,hreg64lo,location.register64.reghi);
+ cg.a_load_const_reg(exprasmlist,OS_32,0,location.register64.reglo);
+ end
+ else
+ begin
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHR,OS_32,
+ shiftval and 31,hreg64hi,location.register64.reglo);
+ cg.a_load_const_reg(exprasmlist,OS_32,0,location.register64.reghi);
+ end;
+ end
+ else
+ begin
+ if nodetype = shln then
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,location.register64.reghi,hreg64hi,shiftval,
+ 0,31-shiftval));
+ exprasmlist.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWIMI,location.register64.reghi,hreg64lo,shiftval,
+ 32-shiftval,31));
+ exprasmlist.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,location.register64.reglo,hreg64lo,shiftval,
+ 0,31-shiftval));
+ end
+ else
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,location.register64.reglo,hreg64lo,32-shiftval,
+ shiftval,31));
+ exprasmlist.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWIMI,location.register64.reglo,hreg64hi,32-shiftval,
+ 0,shiftval-1));
+ exprasmlist.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,location.register64.reghi,hreg64hi,32-shiftval,
+ shiftval,31));
+ end;
+ end;
+ end
+ else
+ { no constant shiftcount }
+ begin
+ location_force_reg(exprasmlist,right.location,OS_S32,true);
+ hregister1 := right.location.register;
+ if nodetype = shln then
+ begin
+ asmop1 := A_SLW;
+ asmop2 := A_SRW;
+ end
+ else
+ begin
+ asmop1 := A_SRW;
+ asmop2 := A_SLW;
+ resultreg := hreg64hi;
+ hreg64hi := hreg64lo;
+ hreg64lo := resultreg;
+ resultreg := location.register64.reghi;
+ location.register64.reghi := location.register64.reglo;
+ location.register64.reglo := resultreg;
+ end;
+
+ cg.getcpuregister(exprasmlist,NR_R0);
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ NR_R0,hregister1,32));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(asmop1,
+ location.register64.reghi,hreg64hi,hregister1));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(asmop2,
+ NR_R0,hreg64lo,NR_R0));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR,
+ location.register64.reghi,location.register64.reghi,NR_R0));
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBI,
+ NR_R0,hregister1,32));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(asmop1,
+ NR_R0,hreg64lo,NR_R0));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR,
+ location.register64.reghi,location.register64.reghi,NR_R0));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(asmop1,
+ location.register64.reglo,hreg64lo,hregister1));
+ cg.ungetcpuregister(exprasmlist,NR_R0);
+
+ if nodetype = shrn then
+ begin
+ resultreg := location.register64.reghi;
+ location.register64.reghi := location.register64.reglo;
+ location.register64.reglo := resultreg;
+ end;
+ end
+ end
+ else
+ begin
+ { load left operators in a register }
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),true);
+ location_copy(location,left.location);
+ resultreg := location.register;
+ hregister1 := location.register;
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ resultreg := cg.getintregister(exprasmlist,OS_32);
+ location.register := resultreg;
+ end;
+
+ { determine operator }
+ if nodetype=shln then
+ op:=OP_SHL
+ else
+ op:=OP_SHR;
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ cg.a_op_const_reg_reg(exprasmlist,op,OS_32,
+ tordconstnode(right).value and 31,hregister1,resultreg)
+ else
+ begin
+ { load shift count in a register if necessary }
+ location_force_reg(exprasmlist,right.location,def_cgsize(right.resulttype.def),true);
+ hregister2 := right.location.register;
+
+ cg.a_op_reg_reg_reg(exprasmlist,op,OS_32,hregister2,
+ hregister1,resultreg);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TPPCUNARYMINUSNODE
+*****************************************************************************}
+
+ procedure tppcunaryminusnode.pass_2;
+
+ var
+ src1: tregister;
+ op: tasmop;
+
+ begin
+ secondpass(left);
+ if is_64bitint(left.resulttype.def) then
+ begin
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),true);
+ location_copy(location,left.location);
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
+ location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
+ location.loc := LOC_REGISTER;
+ end;
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ location.register64.reglo,left.location.register64.reglo,0));
+ if not(cs_check_overflow in aktlocalswitches) then
+ exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
+ location.register64.reghi,left.location.register64.reghi))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZEO_,
+ location.register64.reghi,left.location.register64.reghi));
+ end
+ else
+ begin
+ location_copy(location,left.location);
+ location.loc:=LOC_REGISTER;
+ case left.location.loc of
+ LOC_FPUREGISTER, LOC_REGISTER:
+ begin
+ src1 := left.location.register;
+ location.register := src1;
+ end;
+ LOC_CFPUREGISTER, LOC_CREGISTER:
+ begin
+ src1 := left.location.register;
+ if left.location.loc = LOC_CREGISTER then
+ location.register := cg.getintregister(exprasmlist,OS_INT)
+ else
+ location.register := cg.getfpuregister(exprasmlist,location.size);
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ if (left.resulttype.def.deftype=floatdef) then
+ begin
+ src1 := cg.getfpuregister(exprasmlist,def_cgsize(left.resulttype.def));
+ location.register := src1;
+ cg.a_loadfpu_ref_reg(exprasmlist,
+ def_cgsize(left.resulttype.def),
+ left.location.reference,src1);
+ end
+ else
+ begin
+ src1 := cg.getintregister(exprasmlist,OS_32);
+ location.register:= src1;
+ cg.a_load_ref_reg(exprasmlist,OS_32,OS_32,
+ left.location.reference,src1);
+ end;
+ end;
+ end;
+ { choose appropriate operand }
+ if left.resulttype.def.deftype <> floatdef then
+ begin
+ if not(cs_check_overflow in aktlocalswitches) then
+ op := A_NEG
+ else
+ op := A_NEGO_;
+ location.loc := LOC_REGISTER;
+ end
+ else
+ begin
+ op := A_FNEG;
+ location.loc := LOC_FPUREGISTER;
+ end;
+ { emit operation }
+ exprasmlist.concat(taicpu.op_reg_reg(op,location.register,src1));
+ end;
+{ Here was a problem... }
+{ Operand to be negated always }
+{ seems to be converted to signed }
+{ 32-bit before doing neg!! }
+{ So this is useless... }
+{ that's not true: -2^31 gives an overflow error if it is negated (FK) }
+ cg.g_overflowcheck(exprasmlist,location,resulttype.def);
+ end;
+
+
+{*****************************************************************************
+ TPPCNOTNODE
+*****************************************************************************}
+
+ procedure tppcnotnode.pass_2;
+
+ var
+ hl : tasmlabel;
+
+ begin
+ if is_boolean(resulttype.def) then
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc=LOC_JUMP then
+ begin
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ location.loc:=LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER, LOC_CREGISTER, LOC_REFERENCE, LOC_CREFERENCE :
+ begin
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),true);
+ exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,left.location.register,0));
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags.cr:=RS_CR0;
+ location.resflags.flag:=F_EQ;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end
+ else if is_64bitint(left.resulttype.def) then
+ begin
+ secondpass(left);
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
+ location_copy(location,left.location);
+ { perform the NOT operation }
+ exprasmlist.concat(taicpu.op_reg_reg(A_NOT,location.register64.reghi,
+ location.register64.reghi));
+ exprasmlist.concat(taicpu.op_reg_reg(A_NOT,location.register64.reglo,
+ location.register64.reglo));
+ end
+ else
+ begin
+ secondpass(left);
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),true);
+ location_copy(location,left.location);
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(exprasmlist,OS_INT);
+ { perform the NOT operation }
+ cg.a_op_reg_reg(exprasmlist,OP_NOT,def_cgsize(resulttype.def),left.location.register,
+ location.register);
+ end;
+ end;
+
+begin
+ cmoddivnode:=tppcmoddivnode;
+ cshlshrnode:=tppcshlshrnode;
+ cunaryminusnode:=tppcunaryminusnode;
+ cnotnode:=tppcnotnode;
+end.
diff --git a/compiler/powerpc/nppcset.pas b/compiler/powerpc/nppcset.pas
new file mode 100644
index 0000000000..9bf937f1eb
--- /dev/null
+++ b/compiler/powerpc/nppcset.pas
@@ -0,0 +1,215 @@
+{
+ 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,cgbase,cgobj,aasmbase,aasmtai,globtype;
+
+ type
+ tppccasenode = class(tcgcasenode)
+ protected
+ function has_jumptable : boolean;override;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
+ procedure genlinearlist(hp : pcaselabel); override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,
+ symconst,symdef,defutil,
+ paramgr,
+ cpuinfo,
+ pass_2,cgcpu,
+ ncon,
+ tgobj,ncgutil,regvars,rgobj,aasmcpu,
+ procinfo,
+ cgutils;
+
+{*****************************************************************************
+ TCGCASENODE
+*****************************************************************************}
+
+
+ function tppccasenode.has_jumptable : boolean;
+ begin
+ has_jumptable:=true;
+ end;
+
+
+ procedure tppccasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ var
+ table : tasmlabel;
+ last : TConstExprInt;
+ indexreg : tregister;
+ href : treference;
+
+ procedure genitem(list:taasmoutput;t : pcaselabel);
+ var
+ i : aint;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ for i:=last+1 to t^._low-1 do
+ list.concat(Tai_const.Create_sym(elselabel));
+ for i:=t^._low to t^._high do
+ list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+ last:=t^._high;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+ begin
+ if not(jumptable_no_range) then
+ begin
+ { case expr less than min_ => goto elselabel }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_lt,aint(min_),hregister,elselabel);
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_gt,aint(max_),hregister,elselabel);
+ end;
+ objectlibrary.getjumplabel(table);
+ { make it a 32bit register }
+ // allocate base and index registers register
+ indexreg:= cg.makeregsize(exprasmlist, hregister, OS_INT);
+ { indexreg := hregister; }
+ cg.a_load_reg_reg(exprasmlist, opsize, OS_INT, hregister, indexreg);
+ { create reference, indexreg := indexreg * sizeof(OS_ADDR) }
+ cg.a_op_const_reg(exprasmlist, OP_MUL, OS_INT, tcgsize2size[OS_ADDR], indexreg);
+ reference_reset_symbol(href, table, (-aint(min_)) * tcgsize2size[OS_ADDR]);
+ href.index := indexreg;
+
+ cg.a_load_ref_reg(exprasmlist, OS_INT, OS_INT, href, indexreg);
+
+ exprasmlist.concat(taicpu.op_reg(A_MTCTR, indexreg));
+ exprasmlist.concat(taicpu.op_none(A_BCTR));
+
+ { generate jump table }
+ new_section(current_procinfo.aktlocaldata,sec_data,current_procinfo.procdef.mangledname,sizeof(aint));
+ current_procinfo.aktlocaldata.concat(Tai_label.Create(table));
+ last:=min_;
+ genitem(current_procinfo.aktlocaldata,hp);
+ end;
+
+
+ procedure tppccasenode.genlinearlist(hp : pcaselabel);
+
+ var
+ first, lastrange : boolean;
+ last : TConstExprInt;
+
+ procedure genitem(t : pcaselabel);
+
+ 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.getintregister(exprasmlist,OS_INT);
+ cg.a_load_const_reg(exprasmlist,OS_INT,value,tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD_,hregister,
+ hregister,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
+ if t^._low-last=0 then
+ cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ,0,hregister,blocklabel(t^.blockid))
+ else
+ gensub(longint(t^._low-last));
+ tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,blocklabel(t^.blockid));
+ last:=t^._low;
+ lastrange := false;
+ 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) or
+ (not lastrange) 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,blocklabel(t^.blockid));
+ last:=t^._high;
+ lastrange := true;
+ 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;
+ lastrange:=false;
+ first:=true;
+ genitem(hp);
+ cg.a_jmp_always(exprasmlist,elselabel);
+ end;
+ end;
+
+
+
+
+begin
+ ccasenode:=tppccasenode;
+end.
diff --git a/compiler/powerpc/ppcins.dat b/compiler/powerpc/ppcins.dat
new file mode 100644
index 0000000000..43ec86b907
--- /dev/null
+++ b/compiler/powerpc/ppcins.dat
@@ -0,0 +1,68 @@
+;****************************************************************************
+;
+; Copyright (c) 2002 by Florian Klaempfl
+;
+; Instruction template table for the PowerPC
+;
+; 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.
+;
+;****************************************************************************
+;
+add rD,rA,rB opcode=31,op22=266,oe=0,rc=0
+add_ rD,rA,rB opcode=31,op22=266,oe=0,rc=1
+addo rD,rA,rB opcode=31,op22=266,oe=1,rc=0
+addo_ rD,rA,rB opcode=31,op22=266,oe=1,rc=1
+addc rD,rA,rB opcode=31,op22=10,oe=0,rc=0
+addc_ rD,rA,rB opcode=31,op22=10,oe=0,rc=1
+addco rD,rA,rB opcode=31,op22=10,oe=1,rc=0
+addco_ rD,rA,rB opcode=31,op22=10,oe=1,rc=1
+adde rD,rA,rB opcode=31,op22=138,oe=0,rc=0
+adde_ rD,rA,rB opcode=31,op22=138,oe=0,rc=1
+addeo rD,rA,rB opcode=31,op22=138,oe=1,rc=0
+addeo_ rD,rA,rB opcode=31,op22=138,oe=1,rc=1
+addi rD,rA,SIMM opcode=14
+addic rD,rA,SIMM opcode=12
+addic_ rD,rA,SIMM opcode=13
+addis rD,rA,SIMM opcode=15
+addme rD,rA opcode=31,op22=234,oe=0,rc=0,reserved=$000f0000
+addme_ rD,rA opcode=31,op22=234,oe=0,rc=1,reserved=$000f0000
+addmeo rD,rA opcode=31,op22=234,oe=1,rc=0,reserved=$000f0000
+addmeo_ rD,rA opcode=31,op22=234,oe=1,rc=1,reserved=$000f0000
+addze rD,rA opcode=31,op22=202,oe=0,rc=0,reserved=$000f0000
+addze_ rD,rA opcode=31,op22=202,oe=0,rc=1,reserved=$000f0000
+addzeo rD,rA opcode=31,op22=202,oe=1,rc=0,reserved=$000f0000
+addzeo_ rD,rA opcode=31,op22=202,oe=1,rc=1,reserved=$000f0000
+and rA,rS,rB opcode=31,op21=28,rc=0
+and_ rA,rS,rB opcode=31,op21=28,rc=1
+andc rA,rS,rB opcode=31,op21=60,rc=0
+andc_ rA,rS,rB opcode=31,op21=60,rc=1
+andi_ rA,rS,UIMM opcode=28
+andis_ rA,rS,UIMM opcode=29
+b TA24 opcode=18,aa=0,lk=0
+ba TA24 opcode=18,aa=1,lk=0
+bl TA24 opcode=18,aa=0,lk=1
+bla TA24 opcode=18,aa=1,lk=1
+bc BO,BI,TA14 opcode=16,aa=0,lk=0
+bca BO,BI,TA14 opcode=16,aa=1,lk=0
+bcl BO,BI,TA14 opcode=16,aa=0,lk=1
+bcla BO,BI,TA14 opcode=16,aa=1,lk=1
+bcctr BO,BI opcode=19,op21=528,lk=0,reserved=$000f0000
+bcctrl BO,BI opcode=19,op21=528,lk=1,reserved=$000f0000
+bcltr BO,BI opcode=19,op21=16,lk=0,reserved=$000f0000
+bcltrl BO,BI opcode=19,op21=16,lk=1,reserved=$000f0000
+cmp crfD,L,rA,rB opcode=31,op21=0,reserved=$80000200
+cmpi crfD,L,rA,SIMM opcode=11,reserved=$00000200
+cmpl crfD,L,rA,rB opcode=31,op21=32,reserved=$80000200
+cmpli crfD,L,rA,UIMM opcode=10,reserved=$00000200
diff --git a/compiler/powerpc/ppcreg.dat b/compiler/powerpc/ppcreg.dat
new file mode 100644
index 0000000000..da311da4fa
--- /dev/null
+++ b/compiler/powerpc/ppcreg.dat
@@ -0,0 +1,120 @@
+;
+; PowerPC registers
+;
+; layout
+; <name>,<value>,<stdname>,<gasname>,<gasshortname>,<motname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,INVALID,INVALID,-1,-1
+
+R0,$01,$00,r0,r0,0,r0,0,0
+R1,$01,$01,r1,r1,1,r1,1,1
+R2,$01,$02,r2,r2,2,r2,2,2
+R3,$01,$03,r3,r3,3,r3,3,3
+R4,$01,$04,r4,r4,4,r4,4,4
+R5,$01,$05,r5,r5,5,r5,5,5
+R6,$01,$06,r6,r6,6,r6,6,6
+R7,$01,$07,r7,r7,7,r7,7,7
+R8,$01,$08,r8,r8,8,r8,8,8
+R9,$01,$09,r9,r9,9,r9,9,9
+R10,$01,$0a,r10,r10,10,r10,10,10
+R11,$01,$0b,r11,r11,11,r11,11,11
+R12,$01,$0c,r12,r12,12,r12,12,12
+R13,$01,$0d,r13,r13,13,r13,13,13
+R14,$01,$0e,r14,r14,14,r14,14,14
+R15,$01,$0f,r15,r15,15,r15,15,15
+R16,$01,$10,r16,r16,16,r16,16,16
+R17,$01,$11,r17,r17,17,r17,17,17
+R18,$01,$12,r18,r18,18,r18,18,18
+R19,$01,$13,r19,r19,19,r19,19,19
+R20,$01,$14,r20,r20,20,r20,20,20
+R21,$01,$15,r21,r21,21,r21,21,21
+R22,$01,$16,r22,r22,22,r22,22,22
+R23,$01,$17,r23,r23,23,r23,23,23
+R24,$01,$18,r24,r24,24,r24,24,24
+R25,$01,$19,r25,r25,25,r25,25,25
+R26,$01,$1a,r26,r26,26,r26,26,26
+R27,$01,$1b,r27,r27,27,r27,27,27
+R28,$01,$1c,r28,r28,28,r28,28,28
+R29,$01,$1d,r29,r29,29,r29,29,29
+R30,$01,$1e,r30,r30,30,r30,30,30
+R31,$01,$1f,r31,r31,31,r31,31,31
+
+F0,$02,$00,F0,f0,0,F0,32,32
+F1,$02,$01,F1,f1,1,F1,33,33
+F2,$02,$02,F2,f2,2,F2,34,34
+F3,$02,$03,F3,f3,3,F3,35,35
+F4,$02,$04,F4,f4,4,F4,36,36
+F5,$02,$05,F5,f5,5,F5,37,37
+F6,$02,$06,F6,f6,6,F6,38,38
+F7,$02,$07,F7,f7,7,F7,39,39
+F8,$02,$08,F8,f8,8,F8,40,40
+F9,$02,$09,F9,f9,9,F9,41,41
+F10,$02,$0a,F10,f10,10,F10,42,42
+F11,$02,$0b,F11,f11,11,F11,43,43
+F12,$02,$0c,F12,f12,12,F12,44,44
+F13,$02,$0d,F13,f13,13,F13,45,45
+F14,$02,$0e,F14,f14,14,F14,46,46
+F15,$02,$0f,F15,f15,15,F15,47,47
+F16,$02,$10,F16,f16,16,F16,48,48
+F17,$02,$11,F17,f17,17,F17,49,49
+F18,$02,$12,F18,f18,18,F18,50,50
+F19,$02,$13,F19,f19,19,F19,51,51
+F20,$02,$14,F20,f20,20,F20,52,52
+F21,$02,$15,F21,f21,21,F21,53,53
+F22,$02,$16,F22,f22,22,F22,54,54
+F23,$02,$17,F23,f23,23,F23,55,55
+F24,$02,$18,F24,f24,24,F24,56,56
+F25,$02,$19,F25,f25,25,F25,57,57
+F26,$02,$1a,F26,f26,26,F26,58,58
+F27,$02,$1b,F27,f27,27,F27,59,59
+F28,$02,$1c,F28,f28,28,F28,60,60
+F29,$02,$1d,F29,f29,29,F29,61,61
+F30,$02,$1e,F30,f30,30,F30,62,62
+F31,$02,$1f,F31,f31,31,F31,63,63
+
+M0,$03,$00,M0,v0,0,M0,-1,-1
+M1,$03,$01,M1,v1,1,M1,-1,-1
+M2,$03,$02,M2,v2,2,M2,-1,-1
+M3,$03,$03,M3,v3,3,M3,-1,-1
+M4,$03,$04,M4,v4,4,M4,-1,-1
+M5,$03,$05,M5,v5,5,M5,-1,-1
+M6,$03,$06,M6,v6,6,M6,-1,-1
+M7,$03,$07,M7,v7,7,M7,-1,-1
+M8,$03,$08,M8,v8,8,M8,-1,-1
+M9,$03,$09,M9,v9,9,M9,-1,-1
+M10,$03,$0a,M10,v10,10,M10,-1,-1
+M11,$03,$0b,M11,v11,11,M11,-1,-1
+M12,$03,$0c,M12,v12,12,M12,-1,-1
+M13,$03,$0d,M13,v13,13,M13,-1,-1
+M14,$03,$0e,M14,v14,14,M14,-1,-1
+M15,$03,$0f,M15,v15,15,M15,-1,-1
+M16,$03,$10,M16,v16,16,M16,-1,-1
+M17,$03,$11,M17,v17,17,M17,-1,-1
+M18,$03,$12,M18,v18,18,M18,-1,-1
+M19,$03,$13,M19,v19,19,M19,-1,-1
+M20,$03,$14,M20,v20,20,M20,-1,-1
+M21,$03,$15,M21,v21,21,M21,-1,-1
+M22,$03,$16,M22,v22,22,M22,-1,-1
+M23,$03,$17,M23,v23,23,M23,-1,-1
+M24,$03,$18,M24,v24,24,M24,-1,-1
+M25,$03,$19,M25,v25,25,M25,-1,-1
+M26,$03,$1a,M26,v26,26,M26,-1,-1
+M27,$03,$1b,M27,v27,27,M27,-1,-1
+M28,$03,$1c,M28,v28,28,M28,-1,-1
+M29,$03,$1d,M29,v29,29,M29,-1,-1
+M30,$03,$1e,M30,v30,30,M30,-1,-1
+M31,$03,$1f,M31,v31,31,M31,-1,-1
+
+CR,$05,$00,CR,cr,cr,CR,-1,-1
+CR0,$05,$01,CR0,cr0,cr0,CR0,68,68
+CR1,$05,$02,CR1,cr1,cr1,CR1,69,69
+CR2,$05,$03,CR2,cr2,cr2,CR2,70,70
+CR3,$05,$04,CR3,cr3,cr3,CR3,71,71
+CR4,$05,$05,CR4,cr4,cr4,CR4,72,72
+CR5,$05,$06,CR5,cr5,cr5,CR5,73,73
+CR6,$05,$07,CR6,cr6,cr5,CR6,74,74
+CR7,$05,$08,CR7,cr7,cr6,CR7,75,75
+XER,$05,$09,XER,xer,xer,XER,76,76
+LR,$05,$0a,LR,lr,lr,LR,65,65
+CTR,$05,$0b,CTR,ctr,ctr,CTR,66,66
+FPSCR,$05,$0c,FPSCR,fpscr,fpscr,FPSCR,-1,-1
diff --git a/compiler/powerpc/rappc.pas b/compiler/powerpc/rappc.pas
new file mode 100644
index 0000000000..633c9977ff
--- /dev/null
+++ b/compiler/powerpc/rappc.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common ppc assembler reader routines
+
+ 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 rappc;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,rautils,cclasses;
+
+ type
+ TPPCOperand=class(TOperand)
+ end;
+
+ TPPCInstruction=class(TInstruction)
+ end;
+
+ implementation
+
+end.
diff --git a/compiler/powerpc/rappcgas.pas b/compiler/powerpc/rappcgas.pas
new file mode 100644
index 0000000000..d143359f9c
--- /dev/null
+++ b/compiler/powerpc/rappcgas.pas
@@ -0,0 +1,733 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the PowerPC GNU AS styled inline assembler.
+
+ 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 rappcgas;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ raatt,rappc;
+
+ type
+ tppcattreader = class(tattreader)
+ function is_asmopcode(const s: string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tppcoperand);
+ procedure BuildOperand(oper : tppcoperand);
+ procedure BuildOpCode(instr : tppcinstruction);
+ procedure ReadAt(oper : tppcoperand);
+ procedure ReadSym(oper : tppcoperand);
+ procedure ConvertCalljmp(instr : tppcinstruction);
+ end;
+
+
+ Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmcpu,
+ { symtable }
+ symconst,symsym,
+ { parser }
+ procinfo,
+ rabase,rautils,
+ cgbase,cgobj
+ ;
+
+ procedure tppcattreader.ReadSym(oper : tppcoperand);
+ var
+ tempstr : string;
+ typesize,l,k : aint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ procedure tppcattreader.ReadAt(oper : tppcoperand);
+ begin
+ { check for ...@ }
+ if actasmtoken=AS_AT then
+ begin
+ if (oper.opr.ref.symbol=nil) and
+ (oper.opr.ref.offset = 0) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ if upper(actasmpattern)='L' then
+ oper.opr.ref.refaddr:=addr_lo
+ else if upper(actasmpattern)='HA' then
+ oper.opr.ref.refaddr:=addr_hi
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end;
+
+
+ Procedure tppcattreader.BuildReference(oper : tppcoperand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken <> AS_RPAREN then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+ var
+ l : aint;
+
+ begin
+ Consume(AS_LPAREN);
+ Case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { offset(offset) is invalid }
+ If oper.opr.Ref.Offset <> 0 Then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ End
+ Else
+ Begin
+ oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+ Consume(AS_RPAREN);
+ if actasmtoken=AS_AT then
+ ReadAt(oper);
+ end;
+ exit;
+ End;
+ AS_REGISTER: { (reg ... }
+ Begin
+ if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
+ ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
+ message(asmr_e_cannot_index_relative_var);
+ oper.opr.ref.base:=actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { (reg) }
+ if actasmtoken=AS_RPAREN then
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ { (reg,reg .. }
+ Consume(AS_COMMA);
+ if (actasmtoken=AS_REGISTER) and
+ (oper.opr.Ref.Offset = 0) then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ Consume_RParen;
+ end
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; {end case }
+ AS_ID:
+ Begin
+ ReadSym(oper);
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,true);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end;
+ Consume(AS_RPAREN);
+ if actasmtoken=AS_AT then
+ ReadAt(oper);
+ End;
+ AS_COMMA: { (, ... can either be scaling, or index }
+ Begin
+ Consume(AS_COMMA);
+ { Index }
+ if (actasmtoken=AS_REGISTER) then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ Consume_RParen;
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ end;
+
+
+ Procedure tppcattreader.BuildOperand(oper : tppcoperand);
+ var
+ expr : string;
+ typesize,l : aint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+
+ var
+ tempreg : tregister;
+ hl : tasmlabel;
+ ofs : aint;
+ Begin
+ expr:='';
+ case actasmtoken of
+ AS_LPAREN: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ begin
+ ofs:=oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val,ofs);
+ end
+ else
+ BuildReference(oper);
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr,false) then
+ ReadAt(oper)
+ else
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+ if is_condreg(tempreg) and
+ ((actopcode = A_BC) or
+ (actopcode = A_BCCTR) or
+ (actopcode = A_BCLR) or
+ (actopcode = A_TW) or
+ (actopcode = A_TWI)) then
+ begin
+ { it isn't a real operand, everything is stored in the condition }
+ oper.opr.typ:=OPR_NONE;
+ actcondition.cr := getsupreg(tempreg);
+ end
+ else
+ begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end
+ else if is_condreg(tempreg) then
+ begin
+ if not(actcondition.cond in [C_T..C_DZF]) then
+ Message(asmr_e_syn_operand);
+ if actasmtoken=AS_STAR then
+ begin
+ consume(AS_STAR);
+ if (actasmtoken=AS_INTNUM) then
+ begin
+ consume(AS_INTNUM);
+ if actasmtoken=AS_PLUS then
+ begin
+ consume(AS_PLUS);
+ if (actasmtoken=AS_ID) then
+ begin
+ oper.opr.typ:=OPR_NONE;
+ if actasmpattern='LT' then
+ actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4
+ else if actasmpattern='GT' then
+ actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+1
+ else if actasmpattern='EQ' then
+ actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+2
+ else if actasmpattern='SO' then
+ actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+3
+ else
+ Message(asmr_e_syn_operand);
+ consume(AS_ID);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+{*****************************************************************************
+ tppcattreader
+*****************************************************************************}
+
+ procedure tppcattreader.BuildOpCode(instr : tppcinstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ begin
+ { condition operands doesn't set the operand but write to the
+ condition field of the instruction
+ }
+ if instr.Operands[operandnum].opr.typ<>OPR_NONE then
+ Inc(operandnum);
+ end;
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tppcoperand);
+ end; { end case }
+ until false;
+ if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
+ dec(operandnum);
+ instr.Ops:=operandnum;
+ end;
+
+
+ function tppcattreader.is_asmopcode(const s: string):boolean;
+ var
+ str2opentry: tstr2opentry;
+ cond : tasmcondflag;
+ hs : string;
+
+ Begin
+ { making s a value parameter would break other assembler readers }
+ hs:=s;
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+ { clear condition }
+ fillchar(actcondition,sizeof(actcondition),0);
+
+ { check for direction hint }
+ if hs[length(s)]='-' then
+ begin
+ dec(ord(hs[0]));
+ actcondition.dirhint:=DH_Minus;
+ end
+ else if hs[length(s)]='+' then
+ begin
+ dec(ord(hs[0]));
+ actcondition.dirhint:=DH_Plus;
+ end;
+ str2opentry:=tstr2opentry(iasmops.search(hs));
+ if assigned(str2opentry) then
+ begin
+ if actcondition.dirhint<>DH_None then
+ message1(asmr_e_unknown_opcode,actasmpattern);
+ actopcode:=str2opentry.op;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ { not found, check branch instructions }
+ if hs[1]='B' then
+ begin
+ { we can search here without an extra table which is sorted by string length
+ because we take the whole remaining string without the leading B }
+ if copy(hs,length(s)-1,2)='LR' then
+ begin
+ actopcode := A_BCLR;
+ setlength(hs,length(hs)-2)
+ end
+ else if copy(hs,length(s)-2,3)='CTR' then
+ begin
+ actopcode := A_BCCTR;
+ setlength(hs,length(hs)-3)
+ end
+ else
+ actopcode := A_BC;
+ for cond:=low(TAsmCondFlag) to high(TAsmCondFlag) do
+ if copy(hs,2,length(s)-1)=UpperAsmCondFlag2Str[cond] then
+ begin
+ actcondition.simple:=true;
+ actcondition.cond:=cond;
+ if (cond in [C_LT,C_LE,C_EQ,C_GE,C_GT,C_NL,C_NE,C_NG,C_SO,C_NS,C_UN,C_NU]) then
+ actcondition.cr := RS_CR0;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ end;
+ end;
+
+ procedure tppcattreader.ConvertCalljmp(instr : tppcinstruction);
+ begin
+ if instr.Operands[1].opr.typ=OPR_REFERENCE then
+ begin
+ instr.Operands[1].opr.ref.refaddr:=addr_full;
+ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+ (instr.Operands[1].opr.ref.index<>NR_NO) then
+ Message(asmr_e_syn_operand);
+ end;
+ end;
+
+
+ procedure tppcattreader.handleopcode;
+ var
+ instr : tppcinstruction;
+ begin
+ instr:=TPPCInstruction.Create(TPPCOperand);
+ BuildOpcode(instr);
+ instr.condition := actcondition;
+ if is_calljmp(instr.opcode) then
+ ConvertCalljmp(instr);
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_ppc_att_info : tasmmodeinfo =
+ (
+ id : asmmode_ppc_gas;
+ idtxt : 'GAS';
+ casmreader : tppcattreader;
+ );
+
+ asmmode_ppc_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : tppcattreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_ppc_att_info);
+ RegisterAsmMode(asmmode_ppc_standard_info);
+end.
diff --git a/compiler/powerpc/rgcpu.pas b/compiler/powerpc/rgcpu.pas
new file mode 100644
index 0000000000..ccc09c9f03
--- /dev/null
+++ b/compiler/powerpc/rgcpu.pas
@@ -0,0 +1,130 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the powerpc specific class for the register
+ allocator
+
+ 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 rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+{
+ function getcpuregisterint(list: taasmoutput; reg: Tnewregister): tregister; override;
+ procedure ungetregisterint(list: taasmoutput; reg: tregister); override;
+ function getcpuregisterfpu(list : taasmoutput; r : Toldregister) : tregister;override;
+ procedure ungetregisterfpu(list: taasmoutput; r : tregister; size:TCGsize);override;
+ procedure cleartempgen; override;
+ private
+ usedpararegs: Tsupregset;
+ usedparafpuregs: tregisterset;
+}
+ end;
+
+ implementation
+
+ uses
+ cgobj, verbose, cutils;
+
+(*
+ function trgcpu.getcpuregisterint(list: taasmoutput; reg: Tnewregister): tregister;
+
+ begin
+ if ((reg shr 8) in [RS_R0]) and
+ not((reg shr 8) in is_reg_var_int) then
+ begin
+ if (reg shr 8) in usedpararegs then
+ internalerror(2003060701);
+{ comment(v_warning,'Double allocation of register '+tostr((reg shr 8)-1));}
+ include(usedpararegs,reg shr 8);
+ result.enum:=R_INTREGISTER;
+ result.number:=reg;
+ cg.a_reg_alloc(list,result);
+ end
+ else result := inherited getcpuregisterint(list,reg);
+ end;
+
+
+ procedure trgcpu.ungetregisterint(list: taasmoutput; reg: tregister);
+
+ begin
+ if ((reg.number shr 8) in [RS_R0]) and
+ not((reg.number shr 8) in is_reg_var_int) then
+ begin
+ if not((reg.number shr 8) in usedpararegs) then
+ internalerror(2003060702);
+{ comment(v_warning,'Double free of register '+tostr((reg.number shr 8)-1));}
+ exclude(usedpararegs,reg.number shr 8);
+ cg.a_reg_dealloc(list,reg);
+ end
+ else
+ inherited ungetregisterint(list,reg);
+ end;
+
+
+ function trgcpu.getcpuregisterfpu(list : taasmoutput; r : Toldregister) : tregister;
+ begin
+ if (r in [R_F1..R_F13]) and
+ not is_reg_var_other[r] then
+ begin
+ if r in usedparafpuregs then
+ internalerror(2003060902);
+ include(usedparafpuregs,r);
+ result.enum := r;
+ cg.a_reg_alloc(list,result);
+ end
+ else
+ result := inherited getcpuregisterfpu(list,r);
+ end;
+
+
+ procedure trgcpu.ungetregisterfpu(list: taasmoutput; r : tregister; size:TCGsize);
+ begin
+ if (r.enum in [R_F1..R_F13]) and
+ not is_reg_var_other[r.enum] then
+ begin
+ if not(r.enum in usedparafpuregs) then
+ internalerror(2003060903);
+ exclude(usedparafpuregs,r.enum);
+ cg.a_reg_dealloc(list,r);
+ end
+ else
+ inherited ungetregisterfpu(list,r,size);
+ end;
+
+
+ procedure trgcpu.cleartempgen;
+
+ begin
+ inherited cleartempgen;
+ usedpararegs := [];
+ usedparafpuregs := [];
+ end;
+*)
+
+end.
diff --git a/compiler/powerpc/rppccon.inc b/compiler/powerpc/rppccon.inc
new file mode 100644
index 0000000000..4ff6799228
--- /dev/null
+++ b/compiler/powerpc/rppccon.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_R16 = tregister($01000010);
+NR_R17 = tregister($01000011);
+NR_R18 = tregister($01000012);
+NR_R19 = tregister($01000013);
+NR_R20 = tregister($01000014);
+NR_R21 = tregister($01000015);
+NR_R22 = tregister($01000016);
+NR_R23 = tregister($01000017);
+NR_R24 = tregister($01000018);
+NR_R25 = tregister($01000019);
+NR_R26 = tregister($0100001a);
+NR_R27 = tregister($0100001b);
+NR_R28 = tregister($0100001c);
+NR_R29 = tregister($0100001d);
+NR_R30 = tregister($0100001e);
+NR_R31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_M0 = tregister($03000000);
+NR_M1 = tregister($03000001);
+NR_M2 = tregister($03000002);
+NR_M3 = tregister($03000003);
+NR_M4 = tregister($03000004);
+NR_M5 = tregister($03000005);
+NR_M6 = tregister($03000006);
+NR_M7 = tregister($03000007);
+NR_M8 = tregister($03000008);
+NR_M9 = tregister($03000009);
+NR_M10 = tregister($0300000a);
+NR_M11 = tregister($0300000b);
+NR_M12 = tregister($0300000c);
+NR_M13 = tregister($0300000d);
+NR_M14 = tregister($0300000e);
+NR_M15 = tregister($0300000f);
+NR_M16 = tregister($03000010);
+NR_M17 = tregister($03000011);
+NR_M18 = tregister($03000012);
+NR_M19 = tregister($03000013);
+NR_M20 = tregister($03000014);
+NR_M21 = tregister($03000015);
+NR_M22 = tregister($03000016);
+NR_M23 = tregister($03000017);
+NR_M24 = tregister($03000018);
+NR_M25 = tregister($03000019);
+NR_M26 = tregister($0300001a);
+NR_M27 = tregister($0300001b);
+NR_M28 = tregister($0300001c);
+NR_M29 = tregister($0300001d);
+NR_M30 = tregister($0300001e);
+NR_M31 = tregister($0300001f);
+NR_CR = tregister($05000000);
+NR_CR0 = tregister($05000001);
+NR_CR1 = tregister($05000002);
+NR_CR2 = tregister($05000003);
+NR_CR3 = tregister($05000004);
+NR_CR4 = tregister($05000005);
+NR_CR5 = tregister($05000006);
+NR_CR6 = tregister($05000007);
+NR_CR7 = tregister($05000008);
+NR_XER = tregister($05000009);
+NR_LR = tregister($0500000a);
+NR_CTR = tregister($0500000b);
+NR_FPSCR = tregister($0500000c);
diff --git a/compiler/powerpc/rppcdwrf.inc b/compiler/powerpc/rppcdwrf.inc
new file mode 100644
index 0000000000..2c9c9942a8
--- /dev/null
+++ b/compiler/powerpc/rppcdwrf.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+65,
+66,
+-1
diff --git a/compiler/powerpc/rppcgas.inc b/compiler/powerpc/rppcgas.inc
new file mode 100644
index 0000000000..3c68549ce1
--- /dev/null
+++ b/compiler/powerpc/rppcgas.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'v0',
+'v1',
+'v2',
+'v3',
+'v4',
+'v5',
+'v6',
+'v7',
+'v8',
+'v9',
+'v10',
+'v11',
+'v12',
+'v13',
+'v14',
+'v15',
+'v16',
+'v17',
+'v18',
+'v19',
+'v20',
+'v21',
+'v22',
+'v23',
+'v24',
+'v25',
+'v26',
+'v27',
+'v28',
+'v29',
+'v30',
+'v31',
+'cr',
+'cr0',
+'cr1',
+'cr2',
+'cr3',
+'cr4',
+'cr5',
+'cr6',
+'cr7',
+'xer',
+'lr',
+'ctr',
+'fpscr'
diff --git a/compiler/powerpc/rppcgri.inc b/compiler/powerpc/rppcgri.inc
new file mode 100644
index 0000000000..b26f900caa
--- /dev/null
+++ b/compiler/powerpc/rppcgri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+0,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+107,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106
diff --git a/compiler/powerpc/rppcgss.inc b/compiler/powerpc/rppcgss.inc
new file mode 100644
index 0000000000..df78c36d00
--- /dev/null
+++ b/compiler/powerpc/rppcgss.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'cr',
+'cr0',
+'cr1',
+'cr2',
+'cr3',
+'cr4',
+'cr5',
+'cr5',
+'cr6',
+'xer',
+'lr',
+'ctr',
+'fpscr'
diff --git a/compiler/powerpc/rppcmot.inc b/compiler/powerpc/rppcmot.inc
new file mode 100644
index 0000000000..4fc340afd7
--- /dev/null
+++ b/compiler/powerpc/rppcmot.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'M0',
+'M1',
+'M2',
+'M3',
+'M4',
+'M5',
+'M6',
+'M7',
+'M8',
+'M9',
+'M10',
+'M11',
+'M12',
+'M13',
+'M14',
+'M15',
+'M16',
+'M17',
+'M18',
+'M19',
+'M20',
+'M21',
+'M22',
+'M23',
+'M24',
+'M25',
+'M26',
+'M27',
+'M28',
+'M29',
+'M30',
+'M31',
+'CR',
+'CR0',
+'CR1',
+'CR2',
+'CR3',
+'CR4',
+'CR5',
+'CR6',
+'CR7',
+'XER',
+'LR',
+'CTR',
+'FPSCR'
diff --git a/compiler/powerpc/rppcmri.inc b/compiler/powerpc/rppcmri.inc
new file mode 100644
index 0000000000..9a59178c7d
--- /dev/null
+++ b/compiler/powerpc/rppcmri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+0,
+107,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/compiler/powerpc/rppcnor.inc b/compiler/powerpc/rppcnor.inc
new file mode 100644
index 0000000000..387be62acb
--- /dev/null
+++ b/compiler/powerpc/rppcnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from ppcreg.dat }
+110
diff --git a/compiler/powerpc/rppcnum.inc b/compiler/powerpc/rppcnum.inc
new file mode 100644
index 0000000000..d612e34d8a
--- /dev/null
+++ b/compiler/powerpc/rppcnum.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($03000008),
+tregister($03000009),
+tregister($0300000a),
+tregister($0300000b),
+tregister($0300000c),
+tregister($0300000d),
+tregister($0300000e),
+tregister($0300000f),
+tregister($03000010),
+tregister($03000011),
+tregister($03000012),
+tregister($03000013),
+tregister($03000014),
+tregister($03000015),
+tregister($03000016),
+tregister($03000017),
+tregister($03000018),
+tregister($03000019),
+tregister($0300001a),
+tregister($0300001b),
+tregister($0300001c),
+tregister($0300001d),
+tregister($0300001e),
+tregister($0300001f),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c)
diff --git a/compiler/powerpc/rppcrni.inc b/compiler/powerpc/rppcrni.inc
new file mode 100644
index 0000000000..1a49189c1d
--- /dev/null
+++ b/compiler/powerpc/rppcrni.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+109
diff --git a/compiler/powerpc/rppcsri.inc b/compiler/powerpc/rppcsri.inc
new file mode 100644
index 0000000000..9a59178c7d
--- /dev/null
+++ b/compiler/powerpc/rppcsri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+0,
+107,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/compiler/powerpc/rppcstab.inc b/compiler/powerpc/rppcstab.inc
new file mode 100644
index 0000000000..2c9c9942a8
--- /dev/null
+++ b/compiler/powerpc/rppcstab.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+65,
+66,
+-1
diff --git a/compiler/powerpc/rppcstd.inc b/compiler/powerpc/rppcstd.inc
new file mode 100644
index 0000000000..4fc340afd7
--- /dev/null
+++ b/compiler/powerpc/rppcstd.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'M0',
+'M1',
+'M2',
+'M3',
+'M4',
+'M5',
+'M6',
+'M7',
+'M8',
+'M9',
+'M10',
+'M11',
+'M12',
+'M13',
+'M14',
+'M15',
+'M16',
+'M17',
+'M18',
+'M19',
+'M20',
+'M21',
+'M22',
+'M23',
+'M24',
+'M25',
+'M26',
+'M27',
+'M28',
+'M29',
+'M30',
+'M31',
+'CR',
+'CR0',
+'CR1',
+'CR2',
+'CR3',
+'CR4',
+'CR5',
+'CR6',
+'CR7',
+'XER',
+'LR',
+'CTR',
+'FPSCR'
diff --git a/compiler/powerpc/rppcsup.inc b/compiler/powerpc/rppcsup.inc
new file mode 100644
index 0000000000..4e6f879355
--- /dev/null
+++ b/compiler/powerpc/rppcsup.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_R16 = $10;
+RS_R17 = $11;
+RS_R18 = $12;
+RS_R19 = $13;
+RS_R20 = $14;
+RS_R21 = $15;
+RS_R22 = $16;
+RS_R23 = $17;
+RS_R24 = $18;
+RS_R25 = $19;
+RS_R26 = $1a;
+RS_R27 = $1b;
+RS_R28 = $1c;
+RS_R29 = $1d;
+RS_R30 = $1e;
+RS_R31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_M0 = $00;
+RS_M1 = $01;
+RS_M2 = $02;
+RS_M3 = $03;
+RS_M4 = $04;
+RS_M5 = $05;
+RS_M6 = $06;
+RS_M7 = $07;
+RS_M8 = $08;
+RS_M9 = $09;
+RS_M10 = $0a;
+RS_M11 = $0b;
+RS_M12 = $0c;
+RS_M13 = $0d;
+RS_M14 = $0e;
+RS_M15 = $0f;
+RS_M16 = $10;
+RS_M17 = $11;
+RS_M18 = $12;
+RS_M19 = $13;
+RS_M20 = $14;
+RS_M21 = $15;
+RS_M22 = $16;
+RS_M23 = $17;
+RS_M24 = $18;
+RS_M25 = $19;
+RS_M26 = $1a;
+RS_M27 = $1b;
+RS_M28 = $1c;
+RS_M29 = $1d;
+RS_M30 = $1e;
+RS_M31 = $1f;
+RS_CR = $00;
+RS_CR0 = $01;
+RS_CR1 = $02;
+RS_CR2 = $03;
+RS_CR3 = $04;
+RS_CR4 = $05;
+RS_CR5 = $06;
+RS_CR6 = $07;
+RS_CR7 = $08;
+RS_XER = $09;
+RS_LR = $0a;
+RS_CTR = $0b;
+RS_FPSCR = $0c;
diff --git a/compiler/powerpc64/aasmcpu.pas b/compiler/powerpc64/aasmcpu.pas
new file mode 100644
index 0000000000..306060e1ac
--- /dev/null
+++ b/compiler/powerpc64/aasmcpu.pas
@@ -0,0 +1,537 @@
+{
+ Copyright (c) 1999-2002 by Jonas Maebe
+
+ Contains the assembler object for the PowerPC64. Heavily based on code
+ from the PowerPC platform
+
+ 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;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ globtype, verbose,
+ aasmbase, aasmtai,
+ cpubase, cgbase, cgutils;
+
+const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 1;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 0;
+
+type
+ taicpu = class(tai_cpu_abstract)
+ constructor op_none(op: tasmop);
+
+ constructor op_reg(op: tasmop; _op1: tregister);
+ constructor op_const(op: tasmop; _op1: 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: aint);
+ constructor op_const_reg(op: tasmop; _op1: aint; _op2: tregister);
+
+ constructor op_const_const(op: tasmop; _op1, _op2: aint);
+
+ constructor op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3,
+ _op4: aint);
+
+ 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: aint);
+ constructor op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3:
+ treference);
+ constructor op_const_reg_reg(op: tasmop; _op1: aint; _op2, _op3: tregister);
+ constructor op_const_reg_const(op: tasmop; _op1: aint; _op2: tregister;
+ _op3: aint);
+ constructor op_const_const_const(op: tasmop; _op1: aint; _op2: aint; _op3:
+ aint);
+
+ constructor op_reg_reg_reg_reg(op: tasmop; _op1, _op2, _op3, _op4:
+ tregister);
+ constructor op_reg_bool_reg_reg(op: tasmop; _op1: tregister; _op2: boolean;
+ _op3, _op4: tregister);
+ constructor op_reg_bool_reg_const(op: tasmop; _op1: tregister; _op2:
+ boolean; _op3: tregister; _op4: aint);
+
+ constructor op_reg_reg_reg_const_const(op: tasmop; _op1, _op2, _op3:
+ tregister; _op4, _op5: aint);
+ constructor op_reg_reg_const_const_const(op: tasmop; _op1, _op2: tregister;
+ _op3, _op4, _op5: aint);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op: tasmop; cond: TAsmCond; _op1: tasmsymbol);
+ constructor op_const_const_sym(op: tasmop; _op1, _op2: aint; _op3:
+ tasmsymbol);
+
+ constructor op_sym(op: tasmop; _op1: tasmsymbol);
+ constructor op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: aint);
+ constructor op_reg_sym_ofs(op: tasmop; _op1: tregister; _op2: tasmsymbol;
+ _op2ofs: aint);
+ constructor op_sym_ofs_ref(op: tasmop; _op1: tasmsymbol; _op1ofs: aint; const
+ _op2: treference);
+
+ procedure loadbool(opidx: aint; _b: boolean);
+
+ function is_same_reg_move(regtype: Tregistertype): boolean; override;
+
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+ function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+procedure InitAsm;
+procedure DoneAsm;
+
+function spilling_create_load(const ref: treference; r: tregister): tai;
+function spilling_create_store(r: tregister; const ref: treference): tai;
+
+procedure fixup_jmps(list: taasmoutput);
+
+implementation
+
+uses cutils, cclasses;
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+procedure taicpu.loadbool(opidx: aint; _b: boolean);
+begin
+ if opidx >= ops then
+ ops := opidx + 1;
+ with oper[opidx]^ do
+ begin
+ if typ = top_ref then
+ dispose(ref);
+ b := _b;
+ typ := top_bool;
+ end;
+end;
+
+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_const(op: tasmop; _op1: aint);
+begin
+ inherited create(op);
+ ops := 1;
+ loadconst(0, _op1);
+end;
+
+constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister;
+ _op3, _op4: aint);
+begin
+ inherited create(op);
+ ops := 4;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadconst(2, _op3);
+ loadconst(3, _op4);
+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: aint);
+begin
+ inherited create(op);
+ ops := 2;
+ loadreg(0, _op1);
+ loadconst(1, _op2);
+end;
+
+constructor taicpu.op_const_reg(op: tasmop; _op1: aint; _op2: tregister);
+begin
+ inherited create(op);
+ ops := 2;
+ loadconst(0, _op1);
+ loadreg(1, _op2);
+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_const_const(op: tasmop; _op1, _op2: aint);
+begin
+ inherited create(op);
+ ops := 2;
+ loadconst(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_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: aint);
+begin
+ inherited create(op);
+ ops := 3;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadsymbol(0, _op3, _op3ofs);
+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_const_reg_reg(op: tasmop; _op1: aint; _op2, _op3:
+ tregister);
+begin
+ inherited create(op);
+ ops := 3;
+ loadconst(0, _op1);
+ loadreg(1, _op2);
+ loadreg(2, _op3);
+end;
+
+constructor taicpu.op_const_reg_const(op: tasmop; _op1: aint; _op2: tregister;
+ _op3: aint);
+begin
+ inherited create(op);
+ ops := 3;
+ loadconst(0, _op1);
+ loadreg(1, _op2);
+ loadconst(2, _op3);
+end;
+
+constructor taicpu.op_const_const_const(op: tasmop; _op1: aint; _op2: aint;
+ _op3: aint);
+begin
+ inherited create(op);
+ ops := 3;
+ loadconst(0, _op1);
+ loadconst(1, _op2);
+ loadconst(2, _op3);
+end;
+
+constructor taicpu.op_reg_reg_reg_reg(op: tasmop; _op1, _op2, _op3, _op4:
+ tregister);
+begin
+ inherited create(op);
+ ops := 4;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadreg(2, _op3);
+ loadreg(3, _op4);
+end;
+
+constructor taicpu.op_reg_bool_reg_reg(op: tasmop; _op1: tregister; _op2:
+ boolean; _op3, _op4: tregister);
+begin
+ inherited create(op);
+ ops := 4;
+ loadreg(0, _op1);
+ loadbool(1, _op2);
+ loadreg(2, _op3);
+ loadreg(3, _op4);
+end;
+
+constructor taicpu.op_reg_bool_reg_const(op: tasmop; _op1: tregister; _op2:
+ boolean; _op3: tregister; _op4: aint);
+begin
+ inherited create(op);
+ ops := 4;
+ loadreg(0, _op1);
+ loadbool(0, _op2);
+ loadreg(0, _op3);
+ loadconst(0, cardinal(_op4));
+end;
+
+constructor taicpu.op_reg_reg_reg_const_const(op: tasmop; _op1, _op2, _op3:
+ tregister; _op4, _op5: aint);
+begin
+ inherited create(op);
+ ops := 5;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadreg(2, _op3);
+ loadconst(3, cardinal(_op4));
+ loadconst(4, cardinal(_op5));
+end;
+
+constructor taicpu.op_reg_reg_const_const_const(op: tasmop; _op1, _op2:
+ tregister; _op3, _op4, _op5: aint);
+begin
+ inherited create(op);
+ ops := 5;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadconst(2, _op3);
+ loadconst(3, _op4);
+ loadconst(4, _op5);
+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_const_const_sym(op: tasmop; _op1, _op2: aint; _op3:
+ tasmsymbol);
+begin
+ inherited create(op);
+ ops := 3;
+ loadconst(0, _op1);
+ loadconst(1, _op2);
+ loadsymbol(2, _op3, 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: aint);
+begin
+ inherited create(op);
+ ops := 1;
+ loadsymbol(0, _op1, _op1ofs);
+end;
+
+constructor taicpu.op_reg_sym_ofs(op: tasmop; _op1: tregister; _op2: tasmsymbol;
+ _op2ofs: aint);
+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: aint;
+ 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
+ result :=
+ (((opcode=A_MR) and
+ (regtype = R_INTREGISTER)) or
+ ((opcode = A_FMR) and
+ (regtype = R_FPUREGISTER))) and
+ { these opcodes can only have registers as operands }
+ (oper[0]^.reg=oper[1]^.reg);
+end;
+
+
+function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+begin
+ result := operand_read;
+ case opcode of
+ A_STMW,A_LMW:
+ internalerror(2005021805);
+
+ A_STBU, A_STBUX, A_STHU, A_STHUX,
+ A_STWU, A_STWUX, A_STDU, A_STDUX,
+ A_STFSU, A_STFSUX, A_STFDU, A_STFDUX,
+ A_STB, A_STBX, A_STH, A_STHX,
+ A_STW, A_STWX, A_STD, A_STDX,
+ A_STFS, A_STFSX, A_STFD, A_STFDX, A_STFIWX, A_STHBRX, A_STWBRX, A_STWCX_, A_STDCX_,
+ A_CMP, A_CMPI, A_CMPL, A_CMPLI, A_CMPD, A_CMPDI, A_CMPLD, A_CMPLDI,
+ A_DCBA, A_DCBI, A_DCBST, A_DCBT, A_DCBTST, A_DCBZ,
+ A_ECOWX, A_FCMPO, A_FCMPU, A_MTMSR, A_TLBIE, A_TW, A_TWI, A_MFXER,
+ A_CMPWI, A_CMPW, A_CMPLWI, A_CMPLW, A_MT, A_MTLR, A_MTCTR:;
+ else
+ if opnr = 0 then
+ result := operand_write;
+ end;
+end;
+
+function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
+begin
+ result := operand_read;
+ case opcode of
+ A_STBU, A_STBUX, A_STHU, A_STHUX, A_STWU, A_STWUX, A_STDU, A_STDUX,
+ A_STFSU, A_STFSUX, A_STFDU, A_STFDUX:
+ if (oper[opnr]^.ref^.base = reg) then
+ result := operand_readwrite;
+ end;
+end;
+
+
+function spilling_create_load(const ref: treference; r: tregister): tai;
+begin
+ result := taicpu.op_reg_ref(A_LD, r, ref);
+end;
+
+function spilling_create_store(r: tregister; const ref: treference): tai;
+begin
+ result := taicpu.op_reg_ref(A_STD, r, ref);
+end;
+
+procedure InitAsm;
+begin
+end;
+
+procedure DoneAsm;
+begin
+end;
+
+procedure fixup_jmps(list: taasmoutput);
+var
+ p: tai;
+ newjmp: taicpu;
+ labelpositions: tlist;
+ instrpos: ptrint;
+ l: tasmlabel;
+ inserted_something: boolean;
+begin
+ // if certainly not enough instructions to cause an overflow, don't bother
+ if (list.count <= (high(smallint) div 4)) then
+ exit;
+ labelpositions := tlist.create;
+ p := tai(list.first);
+ instrpos := 1;
+ // record label positions
+ while assigned(p) do
+ begin
+ if p.typ = ait_label then
+ begin
+ if (tai_label(p).l.labelnr > labelpositions.count) then
+ labelpositions.count := tai_label(p).l.labelnr * 2;
+ labelpositions[tai_label(p).l.labelnr] := pointer(instrpos);
+ end;
+ if p.typ = ait_instruction then
+ inc(instrpos);
+ p := tai(p.next);
+ end;
+
+ // check and fix distances
+ repeat
+ inserted_something := false;
+ p := tai(list.first);
+ instrpos := 1;
+ while assigned(p) do
+ begin
+ case p.typ of
+ ait_label:
+ // update labelposition in case it changed due to insertion
+ // of jumps
+ begin
+ // can happen because of newly inserted labels
+ if (tai_label(p).l.labelnr > labelpositions.count) then
+ labelpositions.count := tai_label(p).l.labelnr * 2;
+ labelpositions[tai_label(p).l.labelnr] := pointer(instrpos);
+ end;
+ ait_instruction:
+ begin
+ inc(instrpos);
+ case taicpu(p).opcode of
+ A_BC:
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ assigned(taicpu(p).oper[0]^.ref^.symbol) and
+ (taicpu(p).oper[0]^.ref^.symbol is tasmlabel) and
+ (labelpositions[tasmlabel(taicpu(p).oper[0]^.ref^.symbol).labelnr] <> NIL) and
+ (ptruint(abs(ptrint(labelpositions[tasmlabel(taicpu(p).oper[0]^.ref^.symbol).labelnr]-instrpos)) - (low(smallint) div 4)) > ptruint((high(smallint) - low(smallint)) div 4)) then
+ begin
+ // add a new label after this jump
+ objectlibrary.getjumplabel(l);
+ list.insertafter(tai_label.create(l),p);
+ // add a new unconditional jump between this jump and the label
+ newjmp := taicpu.op_sym(A_B,taicpu(p).oper[0]^.ref^.symbol);
+ newjmp.is_jmp := true;
+ newjmp.fileinfo := taicpu(p).fileinfo;
+ list.insertafter(newjmp,p);
+ inc(instrpos);
+ // change the conditional jump to point to the newly inserted label
+ tasmlabel(taicpu(p).oper[0]^.ref^.symbol).decrefs;
+ taicpu(p).oper[0]^.ref^.symbol := l;
+ l.increfs;
+ // and invert its condition code
+ taicpu(p).condition := inverse_cond(taicpu(p).condition);
+ // we inserted an instruction, so will have to check everything again
+ inserted_something := true;
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next);
+ end;
+ until not inserted_something;
+ labelpositions.free;
+end;
+
+begin
+ cai_align := tai_align;
+ cai_cpu := taicpu;
+end.
+
diff --git a/compiler/powerpc64/agppcgas.pas b/compiler/powerpc64/agppcgas.pas
new file mode 100644
index 0000000000..44dae97e39
--- /dev/null
+++ b/compiler/powerpc64/agppcgas.pas
@@ -0,0 +1,343 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asm for the PowerPC64. Heavily based on the one
+ from the PowerPC 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.
+
+ ****************************************************************************
+}
+{ This unit implements the GNU Assembler writer for the PowerPC
+}
+
+unit agppcgas;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ aasmtai,
+ aggas,
+ cpubase;
+
+type
+ PPPCGNUAssembler = ^TPPCGNUAssembler;
+ TPPCGNUAssembler = class(TGNUassembler)
+ public
+ procedure WriteExtraHeader; override;
+ procedure WriteInstruction(hp: tai); override;
+ end;
+
+implementation
+
+uses
+ cutils, globals, verbose,
+ cgbase, cgutils, systems,
+ assemble, globtype, fmodule,
+ itcpugas, finput,
+ aasmcpu;
+
+
+procedure TPPCGNUAssembler.WriteExtraHeader;
+var
+ i: longint;
+begin
+ for i := 0 to 31 do
+ AsmWriteln(#9'.set'#9'r' + tostr(i) + ',' + tostr(i));
+ for i := 0 to 31 do
+ AsmWriteln(#9'.set'#9'f' + tostr(i) + ',' + tostr(i));
+end;
+
+const
+ as_ppc_gas_info: tasminfo =
+ (
+ id: as_gas;
+
+ idtxt: 'AS';
+ asmbin: 'as';
+ asmcmd: '-a64 -o $OBJ $ASM';
+ supported_target: system_any;
+ flags: [af_allowdirect, af_needar, af_smartlink_sections];
+ labelprefix: '.L';
+ comment: '# ';
+ );
+
+ refaddr2str: array[trefaddr] of string[9] = ('', '', '', '@l', '@h', '@higher', '@highest', '@ha', '@highera', '@highesta');
+
+function getreferencestring(var ref: treference): string;
+var
+ s: string;
+begin
+ with ref do
+ begin
+ if ((offset < -32768) or (offset > 32767)) and
+ (refaddr = addr_no) then
+ ; //internalerror(19991);
+ if (refaddr = addr_no) then
+ s := ''
+ else
+ begin
+ s := '(';
+ if assigned(symbol) then
+ begin
+ s := s + symbol.name;
+ if assigned(relsymbol) then
+ s := s + '-' + relsymbol.name;
+ end;
+ end;
+ if offset < 0 then
+ s := s + tostr(offset)
+ else if (offset > 0) then
+ begin
+ if assigned(symbol) then
+ s := s + '+' + tostr(offset)
+ else
+ s := s + tostr(offset);
+ end;
+
+ if (refaddr in [addr_low, addr_high, addr_higher, addr_highest, addr_higha, addr_highera, addr_highesta]) then
+ begin
+ s := s + ')';
+ if (target_info.system <> system_powerpc_darwin) then
+ s := s + refaddr2str[refaddr];
+ end;
+
+ if (index = NR_NO) and (base <> NR_NO) then
+ begin
+ if offset = 0 then
+ begin
+ if assigned(symbol) then
+ begin
+ if target_info.system <> system_powerpc_darwin then
+ s := s + '+0'
+ end
+ else
+ s := s + '0';
+ end;
+ s := s + '(' + gas_regname(base) + ')';
+ end
+ else if (index <> NR_NO) and (base <> NR_NO) then
+ begin
+ if (offset = 0) then
+ s := s + gas_regname(base) + ',' + gas_regname(index)
+ else
+ internalerror(19992);
+ end;
+ end;
+ getreferencestring := s;
+end;
+
+function getopstr_jmp(const o: toper): string;
+var
+ hs: string;
+begin
+ case o.typ of
+ top_reg:
+ getopstr_jmp := gas_regname(o.reg);
+ { no top_ref jumping for powerpc }
+ top_const:
+ getopstr_jmp := tostr(o.val);
+ top_ref:
+ begin
+ if o.ref^.refaddr <> addr_full then
+ internalerror(200402262);
+ hs := o.ref^.symbol.name;
+ if o.ref^.offset > 0 then
+ hs := hs + '+' + tostr(o.ref^.offset)
+ else if o.ref^.offset < 0 then
+ hs := hs + tostr(o.ref^.offset);
+ getopstr_jmp := hs;
+ end;
+ top_none:
+ getopstr_jmp := '';
+ else
+ internalerror(2002070603);
+ end;
+end;
+
+function getopstr(const o: toper): string;
+var
+ hs: string;
+begin
+ case o.typ of
+ top_reg:
+ getopstr := gas_regname(o.reg);
+ top_const:
+ getopstr := tostr(longint(o.val));
+ top_ref:
+ if o.ref^.refaddr = addr_full then
+ begin
+ hs := o.ref^.symbol.name;
+ if o.ref^.offset > 0 then
+ hs := hs + '+' + tostr(o.ref^.offset)
+ else if o.ref^.offset < 0 then
+ hs := hs + tostr(o.ref^.offset);
+ getopstr := hs;
+ end
+ else
+ getopstr := getreferencestring(o.ref^);
+ else
+ internalerror(2002070604);
+ end;
+end;
+
+function branchmode(o: tasmop): string[4];
+var
+ tempstr: string[4];
+begin
+ tempstr := '';
+ case o of
+ A_BCCTR, A_BCCTRL: tempstr := 'ctr';
+ A_BCLR, A_BCLRL: tempstr := 'lr';
+ end;
+ case o of
+ A_BL, A_BLA, A_BCL, A_BCLA, A_BCCTRL, A_BCLRL: tempstr := tempstr + 'l';
+ end;
+ case o of
+ A_BA, A_BLA, A_BCA, A_BCLA: tempstr := tempstr + 'a';
+ end;
+ branchmode := tempstr;
+end;
+
+function cond2str(op: tasmop; c: tasmcond): string;
+{ note: no checking is performed whether the given combination of }
+{ conditions is valid }
+var
+ tempstr: string;
+begin
+ tempstr := #9;
+ case c.simple of
+ false:
+ begin
+ cond2str := tempstr + gas_op2str[op];
+ case c.dirhint of
+ DH_None: ;
+ DH_Minus:
+ cond2str := cond2str + '-';
+ DH_Plus:
+ cond2str := cond2str + '+';
+ else
+ internalerror(2003112901);
+ end;
+ cond2str := cond2str + #9 + tostr(c.bo) + ',' + tostr(c.bi);
+ end;
+ true:
+ if (op >= A_B) and (op <= A_BCLRL) then
+ case c.cond of
+ { unconditional branch }
+ C_NONE:
+ cond2str := tempstr + gas_op2str[op];
+ { bdnzt etc }
+ else
+ begin
+ tempstr := tempstr + 'b' + asmcondflag2str[c.cond] +
+ branchmode(op);
+ case c.dirhint of
+ DH_None:
+ tempstr := tempstr + #9;
+ DH_Minus:
+ tempstr := tempstr + ('-' + #9);
+ DH_Plus:
+ tempstr := tempstr + ('+' + #9);
+ else
+ internalerror(2003112901);
+ end;
+ case c.cond of
+ C_LT..C_NU:
+ cond2str := tempstr + gas_regname(newreg(R_SPECIALREGISTER,
+ c.cr, R_SUBWHOLE));
+ C_T, C_F, C_DNZT, C_DNZF, C_DZT, C_DZF:
+ cond2str := tempstr + tostr(c.crbit);
+ else
+ cond2str := tempstr;
+ end;
+ end;
+ end
+ { we have a trap instruction }
+ else
+ begin
+ internalerror(2002070601);
+ { not yet implemented !!!!!!!!!!!!!!!!!!!!! }
+ { case tempstr := 'tw';}
+ end;
+ end;
+end;
+
+procedure TPPCGNUAssembler.WriteInstruction(hp: tai);
+var
+ op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+begin
+ op := taicpu(hp).opcode;
+ if is_calljmp(op) then
+ begin
+ { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
+ case op of
+ A_BL :
+ s := #9 + gas_op2str[op] + #9;
+ A_B, A_BA, A_BLA:
+ s := #9 + gas_op2str[op] + #9;
+ A_BCTR, A_BCTRL, A_BLR, A_BLRL:
+ s := #9 + gas_op2str[op]
+ else
+ begin
+ s := cond2str(op, taicpu(hp).condition);
+ if (s[length(s)] <> #9) and
+ (taicpu(hp).ops > 0) then
+ s := s + ',';
+ end;
+ end;
+
+ if (taicpu(hp).ops > 0) and (taicpu(hp).oper[0]^.typ <> top_none) then
+ begin
+ { first write the current contents of s, because the symbol }
+ { may be 255 characters }
+ asmwrite(s);
+ s := getopstr_jmp(taicpu(hp).oper[0]^);
+ end;
+ end
+ else
+ { process operands }
+ begin
+ s := #9 + gas_op2str[op];
+ if taicpu(hp).ops <> 0 then
+ begin
+ {
+ if not is_calljmp(op) then
+ sep:=','
+ else
+ }
+ sep := #9;
+ for i := 0 to taicpu(hp).ops - 1 do
+ begin
+ // debug code
+ // writeln(s);
+ // writeln(taicpu(hp).fileinfo.line);
+ s := s + sep + getopstr(taicpu(hp).oper[i]^);
+ sep := ',';
+ end;
+ end;
+ end;
+ AsmWriteLn(s);
+end;
+
+
+begin
+ RegisterAssembler(as_ppc_gas_info, TPPCGNUAssembler);
+end.
diff --git a/compiler/powerpc64/aoptcpu.pas b/compiler/powerpc64/aoptcpu.pas
new file mode 100644
index 0000000000..bd96f25524
--- /dev/null
+++ b/compiler/powerpc64/aoptcpu.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the PowerPC optimizer object
+
+ 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;
+
+interface
+
+{$I fpcdefs.inc}
+
+uses cpubase, aoptobj, aoptcpub, aopt;
+
+type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ end;
+
+implementation
+
+begin
+ casmoptimizer := TCpuAsmOptimizer;
+end.
diff --git a/compiler/powerpc64/aoptcpub.pas b/compiler/powerpc64/aoptcpub.pas
new file mode 100644
index 0000000000..b2e82450c5
--- /dev/null
+++ b/compiler/powerpc64/aoptcpub.pas
@@ -0,0 +1,123 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the PowerPC64 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
+ aasmcpu, AOptBase, cpubase;
+
+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 = 5;
+
+ {Oper index of operand that contains the source (reference) with a load }
+ {instruction }
+
+ LoadSrc = 1;
+
+ {Oper index of operand that contains the destination (register) with a load }
+ {instruction }
+
+ LoadDst = 0;
+
+ {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_B;
+ aopt_condjmp = A_BC;
+
+implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+
+constructor TCondRegs.init;
+begin
+end;
+
+destructor TCondRegs.Done;
+{$IFDEF inl}inline;
+{$ENDIF inl}
+begin
+end;
+
+end.
+
diff --git a/compiler/powerpc64/aoptcpuc.pas b/compiler/powerpc64/aoptcpuc.pas
new file mode 100644
index 0000000000..e002fedb21
--- /dev/null
+++ b/compiler/powerpc64/aoptcpuc.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ 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 aoptcpuc;
+
+interface
+
+{$I fpcdefs.inc}
+
+uses
+ AOptCs;
+
+type
+ TRegInfoCpu = object(TRegInfo)
+ end;
+
+implementation
+
+end.
+
diff --git a/compiler/powerpc64/aoptcpud.pas b/compiler/powerpc64/aoptcpud.pas
new file mode 100644
index 0000000000..5e6e7fc308
--- /dev/null
+++ b/compiler/powerpc64/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ 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.
+
diff --git a/compiler/powerpc64/cgcpu.pas b/compiler/powerpc64/cgcpu.pas
new file mode 100644
index 0000000000..4bf6434d1a
--- /dev/null
+++ b/compiler/powerpc64/cgcpu.pas
@@ -0,0 +1,1668 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the PowerPC
+
+ 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 cgcpu;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ globtype, symtype, symdef,
+ cgbase, cgobj,
+ aasmbase, aasmcpu, aasmtai,
+ cpubase, cpuinfo, cgutils, rgcpu,
+ parabase;
+
+type
+ tcgppc = class(tcg)
+ procedure init_register_allocators; override;
+ procedure done_register_allocators; override;
+
+ { passing parameters, per default the parameter is pushed }
+ { nr gives the number of the parameter (enumerated from }
+ { left to right), this allows to move the parameter to }
+ { register, if the cpu supports register calling }
+ { conventions }
+ procedure a_param_const(list: taasmoutput; size: tcgsize; a: aint; const
+ paraloc: tcgpara); override;
+ procedure a_param_ref(list: taasmoutput; size: tcgsize; const r: treference;
+ const paraloc: tcgpara); override;
+ procedure a_paramaddr_ref(list: taasmoutput; const r: treference; const
+ paraloc: tcgpara); override;
+
+ procedure a_call_name(list: taasmoutput; const s: string); override;
+ procedure a_call_name_direct(list: taasmoutput; s: string; prependDot : boolean);
+
+ procedure a_call_reg(list: taasmoutput; reg: tregister); override;
+
+ procedure a_op_const_reg(list: taasmoutput; Op: TOpCG; size: TCGSize; a:
+ aint; reg: TRegister); override;
+ procedure a_op_reg_reg(list: taasmoutput; Op: TOpCG; size: TCGSize; src,
+ dst: TRegister); override;
+
+ procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister); override;
+
+ { move instructions }
+ procedure a_load_const_reg(list: taasmoutput; size: tcgsize; a: aint; reg:
+ tregister); override;
+ procedure a_load_reg_ref(list: taasmoutput; fromsize, tosize: tcgsize; reg:
+ tregister; const ref: treference); override;
+ procedure a_load_ref_reg(list: taasmoutput; fromsize, tosize: tcgsize; const
+ Ref: treference; reg: tregister); override;
+ procedure a_load_reg_reg(list: taasmoutput; fromsize, tosize: tcgsize; reg1,
+ reg2: tregister); override;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2:
+ tregister); override;
+ procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref:
+ treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg:
+ tregister; const ref: treference); override;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list: taasmoutput; size: tcgsize; cmp_op:
+ topcmp; a: aint; reg: tregister;
+ l: tasmlabel); override;
+ procedure a_cmp_reg_reg_label(list: taasmoutput; size: tcgsize; cmp_op:
+ topcmp; reg1, reg2: tregister; l: tasmlabel); override;
+
+ procedure a_jmp_name(list: taasmoutput; const s: string); override;
+ procedure a_jmp_always(list: taasmoutput; l: tasmlabel); override;
+ procedure a_jmp_flags(list: taasmoutput; const f: TResFlags; l: tasmlabel);
+ override;
+
+ procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags;
+ reg: TRegister); override;
+
+ procedure g_proc_entry(list: taasmoutput; localsize: longint; nostackframe:
+ boolean); override;
+ procedure g_proc_exit(list: taasmoutput; parasize: longint; nostackframe:
+ boolean); override;
+ procedure g_save_standard_registers(list: Taasmoutput); override;
+ procedure g_restore_standard_registers(list: Taasmoutput); override;
+
+ procedure a_loadaddr_ref_reg(list: taasmoutput; const ref: treference; r:
+ tregister); override;
+
+ procedure g_concatcopy(list: taasmoutput; const source, dest: treference;
+ len: aint); override;
+
+ procedure g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef);
+ override;
+ procedure a_jmp_cond(list: taasmoutput; cond: TOpCmp; l: tasmlabel);
+
+ procedure g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const
+ labelname: string; ioffset: longint); override;
+
+ private
+
+ { Make sure ref is a valid reference for the PowerPC and sets the }
+ { base to the value of the index if (base = R_NO). }
+ { Returns true if the reference contained a base, index and an }
+ { offset or symbol, in which case the base will have been changed }
+ { to a tempreg (which has to be freed by the caller) containing }
+ { the sum of part of the original reference }
+ function fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
+
+ { returns whether a reference can be used immediately in a powerpc }
+ { instruction }
+ function issimpleref(const ref: treference): boolean;
+
+ { contains the common code of a_load_reg_ref and a_load_ref_reg }
+ procedure a_load_store(list: taasmoutput; op: tasmop; reg: tregister;
+ ref: treference);
+
+ { creates the correct branch instruction for a given combination }
+ { of asmcondflags and destination addressing mode }
+ procedure a_jmp(list: taasmoutput; op: tasmop;
+ c: tasmcondflag; crval: longint; l: tasmlabel);
+
+ { returns the lowest numbered FP register in use, and the number of used FP registers
+ for the current procedure }
+ procedure calcFirstUsedFPR(out firstfpr : TSuperRegister; out fprcount : aint);
+ { returns the lowest numbered GP register in use, and the number of used GP registers
+ for the current procedure }
+ procedure calcFirstUsedGPR(out firstgpr : TSuperRegister; out gprcount : aint);
+
+ { returns true if the offset of the given reference can not be represented by a 16 bit
+ immediate as required by some PowerPC instructions }
+ function hasLargeOffset(const ref : TReference) : Boolean; inline;
+ end;
+
+const
+ TOpCG2AsmOpConstLo: array[topcg] of TAsmOp = (A_NONE, A_ADDI, A_ANDI_,
+ A_DIVWU,
+ A_DIVW, A_MULLW, A_MULLW, A_NONE, A_NONE, A_ORI,
+ A_SRAWI, A_SLWI, A_SRWI, A_SUBI, A_XORI);
+ TOpCG2AsmOpConstHi: array[topcg] of TAsmOp = (A_NONE, A_ADDIS, A_ANDIS_,
+ A_DIVWU, A_DIVW, A_MULLW, A_MULLW, A_NONE, A_NONE,
+ A_ORIS, A_NONE, A_NONE, A_NONE, A_SUBIS, A_XORIS);
+
+ TShiftOpCG2AsmOpConst32 : array[OP_SAR..OP_SHR] of TAsmOp = (A_SRAWI, A_SLWI, A_SRWI);
+ TShiftOpCG2AsmOpConst64 : array[OP_SAR..OP_SHR] of TAsmOp = (A_SRADI, A_SLDI, A_SRDI);
+
+ TOpCmp2AsmCond: array[topcmp] of TAsmCondFlag = (C_NONE, C_EQ, C_GT,
+ C_LT, C_GE, C_LE, C_NE, C_LE, C_LT, C_GE, C_GT);
+
+implementation
+
+uses
+ sysutils,
+ globals, verbose, systems, cutils,
+ symconst, symsym, fmodule,
+ rgobj, tgobj, cpupi, procinfo, paramgr;
+
+procedure tcgppc.init_register_allocators;
+begin
+ inherited init_register_allocators;
+ rg[R_INTREGISTER] := trgcpu.create(R_INTREGISTER, R_SUBWHOLE,
+ [RS_R3, RS_R4, RS_R5, RS_R6, RS_R7, RS_R8,
+ RS_R9, RS_R10, RS_R11, RS_R12, RS_R31, RS_R30, RS_R29,
+ RS_R28, RS_R27, RS_R26, RS_R25, RS_R24, RS_R23, RS_R22,
+ RS_R21, RS_R20, RS_R19, RS_R18, RS_R17, RS_R16, RS_R15,
+ RS_R14, RS_R13], first_int_imreg, []);
+ rg[R_FPUREGISTER] := trgcpu.create(R_FPUREGISTER, R_SUBNONE,
+ [RS_F0, RS_F1, RS_F2, RS_F3, RS_F4, RS_F5, RS_F6, RS_F7, RS_F8, RS_F9,
+ RS_F10, RS_F11, RS_F12, RS_F13, RS_F31, RS_F30, RS_F29, RS_F28, RS_F27,
+ RS_F26, RS_F25, RS_F24, RS_F23, RS_F22, RS_F21, RS_F20, RS_F19, RS_F18,
+ RS_F17, RS_F16, RS_F15, RS_F14], first_fpu_imreg, []);
+{$WARNING FIX ME}
+ rg[R_MMREGISTER] := trgcpu.create(R_MMREGISTER, R_SUBNONE,
+ [RS_M0, RS_M1, RS_M2], first_mm_imreg, []);
+end;
+
+procedure tcgppc.done_register_allocators;
+begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_MMREGISTER].free;
+ inherited done_register_allocators;
+end;
+
+procedure tcgppc.a_param_const(list: taasmoutput; size: tcgsize; a: aint; const
+ paraloc: tcgpara);
+var
+ ref: treference;
+begin
+ paraloc.check_simple_location;
+ case paraloc.location^.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_load_const_reg(list, size, a, paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ a_load_const_ref(list, size, a, ref);
+ end;
+ else
+ internalerror(2002081101);
+ end;
+end;
+
+procedure tcgppc.a_param_ref(list: taasmoutput; size: tcgsize; const r:
+ treference; const paraloc: tcgpara);
+
+var
+ tmpref, ref: treference;
+ location: pcgparalocation;
+ sizeleft: aint;
+
+begin
+ location := paraloc.location;
+ tmpref := r;
+ sizeleft := paraloc.intsize;
+ while assigned(location) do
+ begin
+ case location^.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ begin
+ a_load_ref_reg(list, location^.size, location^.size, tmpref,
+ location^.register);
+ end;
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(ref, location^.reference.index,
+ location^.reference.offset);
+ g_concatcopy(list, tmpref, ref, sizeleft);
+ if assigned(location^.next) then
+ internalerror(2005010710);
+ end;
+ LOC_FPUREGISTER, LOC_CFPUREGISTER:
+ case location^.size of
+ OS_F32, OS_F64:
+ a_loadfpu_ref_reg(list, location^.size, tmpref, location^.register);
+ else
+ internalerror(2002072801);
+ end;
+ LOC_VOID:
+ begin
+ // nothing to do
+ end;
+ else
+ internalerror(2002081103);
+ end;
+ inc(tmpref.offset, tcgsize2size[location^.size]);
+ dec(sizeleft, tcgsize2size[location^.size]);
+ location := location^.next;
+ end;
+end;
+
+procedure tcgppc.a_paramaddr_ref(list: taasmoutput; const r: treference; const
+ paraloc: tcgpara);
+var
+ ref: treference;
+ tmpreg: tregister;
+
+begin
+ paraloc.check_simple_location;
+ case paraloc.location^.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_loadaddr_ref_reg(list, r, paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_loadaddr_ref_reg(list, r, tmpreg);
+ a_load_reg_ref(list, OS_ADDR, OS_ADDR, tmpreg, ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+end;
+
+{ calling a procedure by name }
+
+procedure tcgppc.a_call_name(list: taasmoutput; const s: string);
+begin
+ a_call_name_direct(list, s, true);
+end;
+
+procedure tcgppc.a_call_name_direct(list: taasmoutput; s: string; prependDot : boolean);
+begin
+ if (prependDot) then begin
+ s := '.' + s;
+ end;
+ list.concat(taicpu.op_sym(A_BL, objectlibrary.newasmsymbol(s, AB_EXTERNAL,
+ AT_FUNCTION)));
+ list.concat(taicpu.op_none(A_NOP));
+ {
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+ }
+ include(current_procinfo.flags, pi_do_call);
+end;
+
+
+{ calling a procedure by address }
+
+procedure tcgppc.a_call_reg(list: taasmoutput; reg: tregister);
+
+var
+ tmpreg: tregister;
+ tmpref: treference;
+
+ gotref : treference;
+
+begin
+ tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+
+ reference_reset(tmpref);
+ tmpref.offset := 0;
+ tmpref.base := reg;
+ list.concat(taicpu.op_reg_ref(A_LD, tmpreg, tmpref));
+
+// TODO: GOT change
+
+// reference_reset(gotref);
+// tmpref.offset := 40;
+// tmpref.base := rg[R_INTREGISTER].getregister(list, NR_STACK_POINTER_REG);
+
+// taicpu.op_load_reg_ref(list, OS_INT, OS_INT,
+ list.concat(taicpu.op_reg(A_MTCTR, tmpreg));
+
+
+ list.concat(taicpu.op_none(A_BCTRL));
+ //if target_info.system=system_powerpc_macos then
+ // //NOP is not needed here.
+ // list.concat(taicpu.op_none(A_NOP));
+ include(current_procinfo.flags, pi_do_call);
+end;
+
+{********************** load instructions ********************}
+
+procedure tcgppc.a_load_const_reg(list: taasmoutput; size: TCGSize; a: aint;
+ reg: TRegister);
+
+ { loads a 32 bit constant into the given register, using an optimal instruction sequence.
+ This is either LIS, LI or LI+ADDIS.
+ Returns true if during these operations the upper 32 bits were filled with 1 bits (e.g.
+ sign extension was performed) }
+ function load32bitconstant(list : taasmoutput; size : TCGSize; a : longint;
+ reg : TRegister) : boolean;
+ var
+ is_half_signed : byte;
+ begin
+ { if the lower 16 bits are zero, do a single LIS }
+ if (smallint(a) = 0) and ((a shr 16) <> 0) then begin
+ list.concat(taicpu.op_reg_const(A_LIS, reg, smallint(hi(a))));
+ load32bitconstant := longint(a) < 0;
+ end else begin
+ is_half_signed := ord(smallint(lo(a)) < 0);
+ list.concat(taicpu.op_reg_const(A_LI, reg, smallint(a and $ffff)));
+ if smallint(hi(a) + is_half_signed) <> 0 then begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS, reg, reg, smallint(hi(a) + is_half_signed)));
+ end;
+ load32bitconstant := (smallint(a) < 0) or (a < 0);
+ end;
+ end;
+
+ { R0-safe version of the above (ADDIS doesn't work the same way with R0 as base), without
+ the return value }
+ procedure load32bitconstantR0(list : taasmoutput; size : TCGSize; a : longint;
+ reg : TRegister);
+ begin
+ // only 16 bit constant? (-2^15 <= a <= +2^15-1)
+ if (a >= low(smallint)) and (a <= high(smallint)) then begin
+ list.concat(taicpu.op_reg_const(A_LI, reg, smallint(a)));
+ end else begin
+ { check if we have to start with LI or LIS, load as 32 bit constant }
+ if ((a and $FFFF) <> 0) then begin
+ list.concat(taicpu.op_reg_const(A_LIS, reg, smallint(a shr 16)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, reg, reg, word(a)));
+ end else begin
+ list.concat(taicpu.op_reg_const(A_LIS, reg, smallint(a shr 16)));
+ end;
+ end;
+ end;
+
+var
+ extendssign : boolean;
+ {$IFDEF EXTDEBUG}
+ astring : string;
+ {$ENDIF EXTDEBUG}
+
+begin
+ {$IFDEF EXTDEBUG}
+ astring := 'a_load_const reg ' + inttostr(hi(a)) + ' ' + inttostr(lo(a)) + ' ' + inttostr(ord(size)) + ' ' + inttostr(tcgsize2size[size]);
+ list.concat(tai_comment.create(strpnew(astring)));
+ {$ENDIF EXTDEBUG}
+
+ if not (size in [OS_8, OS_S8, OS_16, OS_S16, OS_32, OS_S32, OS_64, OS_S64]) then
+ internalerror(2002090902);
+ if (lo(a) = 0) and (hi(a) <> 0) then begin
+ { load only upper 32 bits, and shift }
+ load32bitconstant(list, size, hi(a), reg);
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, reg, reg, 32));
+ end else begin
+ { load lower 32 bits }
+ extendssign := load32bitconstant(list, size, lo(a), reg);
+ if (extendssign) and (hi(a) = 0) then
+ { if upper 32 bits are zero, but loading the lower 32 bit resulted in automatic
+ sign extension, clear those bits }
+ a_load_reg_reg(list, OS_32, OS_64, reg, reg)
+ else if (not
+ ((extendssign and (longint(hi(a)) = -1)) or
+ ((not extendssign) and (hi(a)=0)))
+ ) then begin
+ { only load the upper 32 bits, if the automatic sign extension is not okay,
+ that is, _not_ if
+ - loading the lower 32 bits resulted in -1 in the upper 32 bits, and the upper
+ 32 bits should contain -1
+ - loading the lower 32 bits resulted in 0 in the upper 32 bits, and the upper
+ 32 bits should contain 0 }
+ load32bitconstantR0(list, size, hi(a), NR_R0);
+ { combine both registers }
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, reg, NR_R0, 32, 0));
+ end;
+ end;
+end;
+
+procedure tcgppc.a_load_reg_ref(list: taasmoutput; fromsize, tosize: TCGSize;
+ reg: tregister; const ref: treference);
+
+const
+ StoreInstr: array[OS_8..OS_64, boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_STB, A_STBU), (A_STBX, A_STBUX)),
+ ((A_STH, A_STHU), (A_STHX, A_STHUX)),
+ ((A_STW, A_STWU), (A_STWX, A_STWUX)),
+ ((A_STD, A_STDU), (A_STDX, A_STDUX))
+ );
+var
+ op: TAsmOp;
+ ref2: TReference;
+begin
+ ref2 := ref;
+ fixref(list, ref2, tosize);
+ if tosize in [OS_S8..OS_S64] then
+ { storing is the same for signed and unsigned values }
+ tosize := tcgsize(ord(tosize) - (ord(OS_S8) - ord(OS_8)));
+ op := storeinstr[tcgsize2unsigned[tosize], ref2.index <> NR_NO, false];
+ a_load_store(list, op, reg, ref2);
+end;
+
+procedure tcgppc.a_load_ref_reg(list: taasmoutput; fromsize, tosize: tcgsize;
+ const ref: treference; reg: tregister);
+
+const
+ LoadInstr: array[OS_8..OS_S64, boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_LBZ, A_LBZU), (A_LBZX, A_LBZUX)),
+ ((A_LHZ, A_LHZU), (A_LHZX, A_LHZUX)),
+ ((A_LWZ, A_LWZU), (A_LWZX, A_LWZUX)),
+ ((A_LD, A_LDU), (A_LDX, A_LDUX)),
+ { 128bit stuff too }
+ ((A_NONE, A_NONE), (A_NONE, A_NONE)),
+ { there's no load-byte-with-sign-extend :( }
+ ((A_LBZ, A_LBZU), (A_LBZX, A_LBZUX)),
+ ((A_LHA, A_LHAU), (A_LHAX, A_LHAUX)),
+ { there's no load-word-arithmetic-indexed with update, simulate it in code :( }
+ ((A_LWA, A_LWAU), (A_LWAX, A_LWAUX)),
+ ((A_LD, A_LDU), (A_LDX, A_LDUX))
+ );
+var
+ op: tasmop;
+ ref2: treference;
+
+begin
+ { TODO: optimize/take into consideration fromsize/tosize. Will }
+ { probably only matter for OS_S8 loads though }
+ if not (fromsize in [OS_8, OS_S8, OS_16, OS_S16, OS_32, OS_S32, OS_64, OS_S64]) then
+ internalerror(2002090902);
+ ref2 := ref;
+ fixref(list, ref2, tosize);
+ { the caller is expected to have adjusted the reference already }
+ { in this case }
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ op := loadinstr[fromsize, ref2.index <> NR_NO, false];
+ // there is no LWAU instruction, simulate using ADDI and LWA
+ if (op = A_LWAU) then begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, reg, reg, ref2.offset));
+ ref2.offset := 0;
+ op := A_LWA;
+ end;
+ a_load_store(list, op, reg, ref2);
+ // sign extend shortint if necessary, since there is no
+ // load instruction that does that automatically (JM)
+ if fromsize = OS_S8 then
+ list.concat(taicpu.op_reg_reg(A_EXTSB, reg, reg));
+end;
+
+procedure tcgppc.a_load_reg_reg(list: taasmoutput; fromsize, tosize: tcgsize;
+ reg1, reg2: tregister);
+
+const
+ movemap : array[OS_8..OS_S128, OS_8..OS_S128] of tasmop = (
+{ to -> OS_8 OS_16 OS_32 OS_64 OS_128 OS_S8 OS_S16 OS_S32 OS_S64 OS_S128 }
+{ from }
+{ OS_8 } (A_MR, A_RLDICL, A_RLDICL, A_RLDICL, A_NONE, A_RLDICL, A_RLDICL, A_RLDICL, A_RLDICL, A_NOP ),
+{ OS_16 } (A_RLDICL, A_MR, A_RLDICL, A_RLDICL, A_NONE, A_RLDICL, A_RLDICL, A_RLDICL, A_RLDICL, A_NOP ),
+{ OS_32 } (A_RLDICL, A_RLDICL, A_MR, A_RLDICL, A_NONE, A_RLDICL, A_RLDICL, A_RLDICL, A_RLDICL, A_NOP ),
+{ OS_64 } (A_RLDICL, A_RLDICL, A_RLDICL, A_MR, A_NONE, A_RLDICL, A_RLDICL, A_RLDICL, A_RLDICL, A_NOP ),
+{ OS_128 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NOP ),
+{ OS_S8 } (A_EXTSB, A_EXTSB, A_EXTSB, A_EXTSB, A_NONE, A_MR, A_EXTSB, A_EXTSB, A_EXTSB, A_NOP ),
+{ OS_S16 } (A_RLDICL, A_EXTSH, A_EXTSH, A_EXTSH, A_NONE, A_EXTSB, A_MR, A_EXTSH, A_EXTSH, A_NOP ),
+{ OS_S32 } (A_RLDICL, A_RLDICL, A_EXTSW, A_EXTSW, A_NONE, A_EXTSB, A_EXTSH, A_MR, A_EXTSW, A_NOP ),
+{ OS_S64 } (A_RLDICL, A_RLDICL, A_RLDICL, A_MR, A_NONE, A_EXTSB, A_EXTSH, A_EXTSW, A_MR, A_NOP ),
+{ OS_S128 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NOP )
+);
+
+var
+ instr: taicpu;
+ op : tasmop;
+begin
+ op := movemap[fromsize, tosize];
+ case op of
+ A_MR, A_EXTSB, A_EXTSH, A_EXTSW : instr := taicpu.op_reg_reg(op, reg2, reg1);
+ A_RLDICL : instr := taicpu.op_reg_reg_const_const(A_RLDICL, reg2, reg1, 0, (8-tcgsize2size[fromsize])*8);
+ else
+ internalerror(2002090901);
+ end;
+ list.concat(instr);
+ rg[R_INTREGISTER].add_move_instruction(instr);
+end;
+
+procedure tcgppc.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2:
+ tregister);
+var
+ instr: taicpu;
+begin
+ instr := taicpu.op_reg_reg(A_FMR, reg2, reg1);
+ list.concat(instr);
+ rg[R_FPUREGISTER].add_move_instruction(instr);
+end;
+
+procedure tcgppc.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref:
+ treference; reg: tregister);
+const
+ FpuLoadInstr: array[OS_F32..OS_F64, boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_LFS, A_LFSU), (A_LFSX, A_LFSUX)),
+ ((A_LFD, A_LFDU), (A_LFDX, A_LFDUX)));
+var
+ op: tasmop;
+ ref2: treference;
+
+begin
+ { several functions call this procedure with OS_32 or OS_64 }
+ { so this makes life easier (FK) }
+ case size of
+ OS_32, OS_F32:
+ size := OS_F32;
+ OS_64, OS_F64, OS_C64:
+ size := OS_F64;
+ else
+ internalerror(200201121);
+ end;
+ ref2 := ref;
+ fixref(list, ref2, size);
+ op := fpuloadinstr[size, ref2.index <> NR_NO, false];
+ a_load_store(list, op, reg, ref2);
+end;
+
+procedure tcgppc.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg:
+ tregister; const ref: treference);
+
+const
+ FpuStoreInstr: array[OS_F32..OS_F64, boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_STFS, A_STFSU), (A_STFSX, A_STFSUX)),
+ ((A_STFD, A_STFDU), (A_STFDX, A_STFDUX)));
+var
+ op: tasmop;
+ ref2: treference;
+
+begin
+ if not (size in [OS_F32, OS_F64]) then
+ internalerror(200201122);
+ ref2 := ref;
+ fixref(list, ref2, size);
+ op := fpustoreinstr[size, ref2.index <> NR_NO, false];
+ a_load_store(list, op, reg, ref2);
+end;
+
+procedure tcgppc.a_op_const_reg(list: taasmoutput; Op: TOpCG; size: TCGSize; a:
+ aint; reg: TRegister);
+begin
+ a_op_const_reg_reg(list, op, size, a, reg, reg);
+end;
+
+procedure tcgppc.a_op_reg_reg(list: taasmoutput; Op: TOpCG; size: TCGSize; src,
+ dst: TRegister);
+begin
+ a_op_reg_reg_reg(list, op, size, src, dst, dst);
+end;
+
+procedure tcgppc.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister);
+var
+ l1, l2: longint;
+ oplo, ophi: tasmop;
+ scratchreg: tregister;
+ useReg : boolean;
+ shiftmask : longint;
+
+ procedure do_lo_hi;
+ begin
+ usereg := false;
+ if (size in [OS_64, OS_S64]) then begin
+ // ts: use register method for 64 bit consts. Sloooooow
+ usereg := true;
+ end else if (size in [OS_32, OS_S32]) then begin
+ list.concat(taicpu.op_reg_reg_const(oplo, dst, src, word(a)));
+ list.concat(taicpu.op_reg_reg_const(ophi, dst, dst, word(a shr 16)));
+ end else begin
+ list.concat(taicpu.op_reg_reg_const(oplo, dst, src, word(a)));
+ end;
+ end;
+
+begin
+ if op = OP_SUB then begin
+ a_op_const_reg_reg(list, OP_ADD, size, -a, src, dst);
+ exit;
+ end;
+ ophi := TOpCG2AsmOpConstHi[op];
+ oplo := TOpCG2AsmOpConstLo[op];
+ // peephole optimizations for AND, OR, XOR - can't this be done at
+ // some higher level, independent of architecture?
+ if (op in [OP_AND, OP_OR, OP_XOR]) then begin
+ if (a = 0) then begin
+ if op = OP_AND then
+ list.concat(taicpu.op_reg_const(A_LI, dst, 0))
+ else
+ a_load_reg_reg(list, size, size, src, dst);
+ exit;
+ end else if (a = -1) then begin
+ case op of
+ OP_OR:
+ list.concat(taicpu.op_reg_const(A_LI, dst, -1));
+ OP_XOR:
+ list.concat(taicpu.op_reg_reg(A_NOT, dst, src));
+ OP_AND:
+ a_load_reg_reg(list, size, size, src, dst);
+ end;
+ exit;
+ end;
+ { optimization for add }
+ end else if (op = OP_ADD) then
+ if a = 0 then begin
+ a_load_reg_reg(list, size, size, src, dst);
+ exit;
+ end else if (a >= low(smallint)) and (a <= high(smallint)) then begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, dst, src, smallint(a)));
+ exit;
+ end;
+
+ { otherwise, the instructions we can generate depend on the }
+ { operation }
+ useReg := false;
+ case op of
+ OP_DIV, OP_IDIV:
+ if (a = 0) then
+ internalerror(200208103)
+ else if (a = 1) then begin
+ a_load_reg_reg(list, OS_INT, OS_INT, src, dst);
+ exit
+ end else if false {and ispowerof2(a, l1)} then begin
+ internalerror(200208103);
+ case op of
+ OP_DIV: begin
+ list.concat(taicpu.op_reg_reg_const(A_SRDI, dst, src, l1));
+ end;
+ OP_IDIV:
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_SRADI, dst, src, l1));
+ list.concat(taicpu.op_reg_reg(A_ADDZE, dst, dst));
+ end;
+ end;
+ exit;
+ end else
+ usereg := true;
+ OP_IMUL, OP_MUL:
+ if (a = 0) then begin
+ list.concat(taicpu.op_reg_const(A_LI, dst, 0));
+ exit
+ end else if (a = -1) then begin
+ list.concat(taicpu.op_reg_reg(A_NEG, dst, dst));
+ end else if (a = 1) then begin
+ a_load_reg_reg(list, OS_INT, OS_INT, src, dst);
+ exit
+ end else if ispowerof2(a, l1) then
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, dst, src, l1))
+ else if (a >= low(smallint)) and (a <= high(smallint)) then
+ list.concat(taicpu.op_reg_reg_const(A_MULLI, dst, src,
+ smallint(a)))
+ else
+ usereg := true;
+ OP_ADD:
+ {$todo ts:optimize}
+ useReg := true;
+ OP_OR:
+ do_lo_hi;
+ OP_AND:
+ useReg := true;
+ OP_XOR:
+ do_lo_hi;
+ OP_SHL, OP_SHR, OP_SAR:
+ begin
+ {$note ts: cleanup todo, fix remaining bugs}
+ if (size in [OS_64, OS_S64]) then begin
+ if (a and 63) <> 0 then
+ list.concat(taicpu.op_reg_reg_const(
+ TShiftOpCG2AsmOpConst64[Op], dst, src, a and 63))
+ else
+ a_load_reg_reg(list, size, size, src, dst);
+ if (a shr 6) <> 0 then
+ internalError(68991);
+ end else begin
+ if (a and 31) <> 0 then
+ list.concat(taicpu.op_reg_reg_const(
+ TShiftOpCG2AsmOpConst32[Op], dst, src, a and 31))
+ else
+ a_load_reg_reg(list, size, size, src, dst);
+ if (a shr 5) <> 0 then
+ internalError(68991);
+ end;
+ end
+ else
+ internalerror(200109091);
+ end;
+ { if all else failed, load the constant in a register and then }
+ { perform the operation }
+ if useReg then begin
+ scratchreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_load_const_reg(list, size, a, scratchreg);
+ a_op_reg_reg_reg(list, op, size, scratchreg, src, dst);
+ end;
+end;
+
+procedure tcgppc.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister);
+
+const
+ op_reg_reg_opcg2asmop32: array[TOpCG] of tasmop =
+ (A_NONE, A_ADD, A_AND, A_DIVWU, A_DIVW, A_MULLW, A_MULLW, A_NEG, A_NOT, A_OR,
+ A_SRAW, A_SLW, A_SRW, A_SUB, A_XOR);
+ op_reg_reg_opcg2asmop64: array[TOpCG] of tasmop =
+ (A_NONE, A_ADD, A_AND, A_DIVDU, A_DIVD, A_MULLD, A_MULLD, A_NEG, A_NOT, A_OR,
+ A_SRAD, A_SLD, A_SRD, A_SUB, A_XOR);
+
+begin
+ case op of
+ OP_NEG, OP_NOT:
+ begin
+ list.concat(taicpu.op_reg_reg(op_reg_reg_opcg2asmop64[op], dst, src1));
+ if (op = OP_NOT) and
+ not (size in [OS_64, OS_S64]) then
+ { zero/sign extend result again, fromsize is not important here }
+ a_load_reg_reg(list, OS_S64, size, dst, dst)
+ end;
+ else
+ {$NOTE ts:testme}
+ if (size in [OS_64, OS_S64]) then begin
+ list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop64[op], dst, src2,
+ src1));
+ end else begin
+ list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop32[op], dst, src2,
+ src1));
+ end;
+ end;
+end;
+
+{*************** compare instructructions ****************}
+
+procedure tcgppc.a_cmp_const_reg_label(list: taasmoutput; size: tcgsize; cmp_op:
+ topcmp; a: aint; reg: tregister;
+ l: tasmlabel);
+
+var
+ scratch_register: TRegister;
+ signed: boolean;
+
+begin
+ { todo: use 32 bit compares? }
+ signed := cmp_op in [OC_GT, OC_LT, OC_GTE, OC_LTE];
+ { in the following case, we generate more efficient code when }
+ { signed is true }
+ if (cmp_op in [OC_EQ, OC_NE]) and
+ (aword(a) > $FFFF) then
+ signed := true;
+ if signed then
+ if (a >= low(smallint)) and (a <= high(smallint)) then
+ list.concat(taicpu.op_reg_reg_const(A_CMPDI, NR_CR0, reg, a))
+ else begin
+ scratch_register := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_load_const_reg(list, OS_64, a, scratch_register);
+ list.concat(taicpu.op_reg_reg_reg(A_CMPD, NR_CR0, reg, scratch_register));
+ end
+ else if (aword(a) <= $FFFF) then
+ list.concat(taicpu.op_reg_reg_const(A_CMPLDI, NR_CR0, reg, aword(a)))
+ else begin
+ scratch_register := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_load_const_reg(list, OS_64, a, scratch_register);
+ list.concat(taicpu.op_reg_reg_reg(A_CMPLD, NR_CR0, reg,
+ scratch_register));
+ end;
+ a_jmp(list, A_BC, TOpCmp2AsmCond[cmp_op], 0, l);
+end;
+
+procedure tcgppc.a_cmp_reg_reg_label(list: taasmoutput; size: tcgsize; cmp_op:
+ topcmp;
+ reg1, reg2: tregister; l: tasmlabel);
+
+var
+ op: tasmop;
+
+begin
+ if cmp_op in [OC_GT, OC_LT, OC_GTE, OC_LTE] then
+ if (size in [OS_64, OS_S64]) then
+ op := A_CMPD
+ else
+ op := A_CMPW
+ else
+ if (size in [OS_64, OS_S64]) then
+ op := A_CMPLD
+ else
+ op := A_CMPLW;
+ list.concat(taicpu.op_reg_reg_reg(op, NR_CR0, reg2, reg1));
+ a_jmp(list, A_BC, TOpCmp2AsmCond[cmp_op], 0, l);
+end;
+
+procedure tcgppc.a_jmp_cond(list: taasmoutput; cond: TOpCmp; l: tasmlabel);
+
+begin
+ a_jmp(list, A_BC, TOpCmp2AsmCond[cond], 0, l);
+end;
+
+procedure tcgppc.a_jmp_name(list: taasmoutput; const s: string);
+var
+ p: taicpu;
+begin
+ p := taicpu.op_sym(A_B, objectlibrary.newasmsymbol(s, AB_EXTERNAL,
+ AT_LABEL));
+ p.is_jmp := true;
+ list.concat(p)
+end;
+
+procedure tcgppc.a_jmp_always(list: taasmoutput; l: tasmlabel);
+
+begin
+ a_jmp(list, A_B, C_None, 0, l);
+end;
+
+procedure tcgppc.a_jmp_flags(list: taasmoutput; const f: TResFlags; l:
+ tasmlabel);
+
+var
+ c: tasmcond;
+begin
+ c := flags_to_cond(f);
+ a_jmp(list, A_BC, c.cond, c.cr - RS_CR0, l);
+end;
+
+procedure tcgppc.g_flags2reg(list: taasmoutput; size: TCgSize; const f:
+ TResFlags; reg: TRegister);
+
+var
+ testbit: byte;
+ bitvalue: boolean;
+
+begin
+ { get the bit to extract from the conditional register + its }
+ { requested value (0 or 1) }
+ testbit := ((f.cr - RS_CR0) * 4);
+ case f.flag of
+ F_EQ, F_NE:
+ begin
+ inc(testbit, 2);
+ bitvalue := f.flag = F_EQ;
+ end;
+ F_LT, F_GE:
+ begin
+ bitvalue := f.flag = F_LT;
+ end;
+ F_GT, F_LE:
+ begin
+ inc(testbit);
+ bitvalue := f.flag = F_GT;
+ end;
+ else
+ internalerror(200112261);
+ end;
+ { load the conditional register in the destination reg }
+ list.concat(taicpu.op_reg(A_MFCR, reg));
+ { we will move the bit that has to be tested to bit 0 by rotating }
+ { left }
+ testbit := (testbit + 1) and 31;
+ { extract bit }
+ list.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,reg,reg,testbit,31,31));
+
+ { if we need the inverse, xor with 1 }
+ if not bitvalue then
+ list.concat(taicpu.op_reg_reg_const(A_XORI, reg, reg, 1));
+end;
+
+{ *********** entry/exit code and address loading ************ }
+
+procedure tcgppc.g_save_standard_registers(list: Taasmoutput);
+begin
+ { this work is done in g_proc_entry }
+end;
+
+procedure tcgppc.g_restore_standard_registers(list: Taasmoutput);
+begin
+ { this work is done in g_proc_exit }
+end;
+
+procedure tcgppc.calcFirstUsedFPR(out firstfpr : TSuperRegister; out fprcount : aint);
+var
+ reg : TSuperRegister;
+begin
+ fprcount := 0;
+ firstfpr := RS_F31;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then begin
+ for reg := RS_F14 to RS_F31 do begin
+ if reg in rg[R_FPUREGISTER].used_in_proc then begin
+ fprcount := ord(RS_F31)-ord(reg)+1;
+ firstfpr := reg;
+ break;
+ end;
+ end;
+ end;
+end;
+
+procedure tcgppc.calcFirstUsedGPR(out firstgpr : TSuperRegister; out gprcount : aint);
+var
+ reg : TSuperRegister;
+begin
+ gprcount := 0;
+ firstgpr := RS_R31;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then begin
+ for reg := RS_R14 to RS_R31 do begin
+ if reg in rg[R_INTREGISTER].used_in_proc then begin
+ gprcount := ord(RS_R31)-ord(reg)+1;
+ firstgpr := reg;
+ break;
+ end;
+ end;
+ end;
+end;
+
+procedure tcgppc.g_proc_entry(list: taasmoutput; localsize: longint;
+ nostackframe: boolean);
+{ generated the entry code of a procedure/function. Note: localsize is the }
+{ sum of the size necessary for local variables and the maximum possible }
+{ combined size of ALL the parameters of a procedure called by the current }
+{ one. }
+{ This procedure may be called before, as well as after g_return_from_proc }
+{ is called. NOTE registers are not to be allocated through the register }
+{ allocator here, because the register colouring has already occured !! }
+var
+ firstregfpu, firstreggpr: TSuperRegister;
+ href: treference;
+ needslinkreg: boolean;
+ regcount : TSuperRegister;
+
+ fprcount, gprcount : aint;
+
+begin
+ { CR and LR only have to be saved in case they are modified by the current }
+ { procedure, but currently this isn't checked, so save them always }
+ { following is the entry code as described in "Altivec Programming }
+ { Interface Manual", bar the saving of AltiVec registers }
+ a_reg_alloc(list, NR_STACK_POINTER_REG);
+ a_reg_alloc(list, NR_R0);
+
+ calcFirstUsedFPR(firstregfpu, fprcount);
+ calcFirstUsedGPR(firstreggpr, gprcount);
+
+ // calculate real stack frame size
+ localsize := tppcprocinfo(current_procinfo).calc_stackframe_size(
+ gprcount, fprcount);
+
+ // determine whether we need to save the link register
+ needslinkreg := ((not (po_assembler in current_procinfo.procdef.procoptions)) and
+ (pi_do_call in current_procinfo.flags));
+
+ // move link register to r0
+ if (needslinkreg) then begin
+ list.concat(taicpu.op_reg(A_MFLR, NR_R0));
+ end;
+ // save old stack frame pointer
+ if (localsize > 0) then begin
+ a_reg_alloc(list, NR_R12);
+ list.concat(taicpu.op_reg_reg(A_MR, NR_R12, NR_STACK_POINTER_REG));
+ end;
+ // save registers, FPU first, then GPR
+ reference_reset_base(href, NR_STACK_POINTER_REG, -8);
+ if (fprcount > 0) then begin
+ for regcount := RS_F31 downto firstregfpu do begin
+ a_loadfpu_reg_ref(list, OS_FLOAT, newreg(R_FPUREGISTER, regcount,
+ R_SUBNONE), href);
+ dec(href.offset, tcgsize2size[OS_FLOAT]);
+ end;
+ end;
+ if (gprcount > 0) then begin
+ for regcount := RS_R31 downto firstreggpr do begin
+ a_load_reg_ref(list, OS_INT, OS_INT, newreg(R_INTREGISTER, regcount,
+ R_SUBNONE), href);
+ dec(href.offset, tcgsize2size[OS_INT]);
+ end;
+ end;
+
+ // VMX registers not supported by FPC atm
+
+ // we may need to store R0 (=LR) ourselves
+ if (needslinkreg) then begin
+ reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_ELF);
+ list.concat(taicpu.op_reg_ref(A_STD, NR_R0, href));
+ end;
+
+ // create stack frame
+ if (not nostackframe) and (localsize > 0) then begin
+ if (localsize <= high(smallint)) then begin
+ reference_reset_base(href, NR_STACK_POINTER_REG, -localsize);
+ a_load_store(list, A_STDU, NR_STACK_POINTER_REG, href);
+ end else begin
+ reference_reset_base(href, NR_NO, -localsize);
+
+ // use R0 for loading the constant (which is definitely > 32k when entering
+ // this branch)
+ // inlined because it must not use temp registers because register allocations
+ // have already been done :(
+ { Code template:
+ lis r0,ofs@highest
+ ori r0,r0,ofs@higher
+ sldi r0,r0,32
+ oris r0,r0,ofs@h
+ ori r0,r0,ofs@l
+ }
+ list.concat(taicpu.op_reg_const(A_LIS, NR_R0, word(href.offset shr 48)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(href.offset shr 32)));
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, NR_R0, NR_R0, 32));
+ list.concat(taicpu.op_reg_reg_const(A_ORIS, NR_R0, NR_R0, word(href.offset shr 16)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(href.offset)));
+
+ list.concat(taicpu.op_reg_reg_reg(A_STDUX, NR_R1, NR_R1, NR_R0));
+ end;
+ end;
+ // CR register not used by FPC atm
+
+ // keep R1 allocated???
+ a_reg_dealloc(list, NR_R0);
+end;
+
+procedure tcgppc.g_proc_exit(list: taasmoutput; parasize: longint; nostackframe:
+ boolean);
+{ This procedure may be called before, as well as after g_stackframe_entry }
+{ is called. NOTE registers are not to be allocated through the register }
+{ allocator here, because the register colouring has already occured !! }
+var
+ regcount, firstregfpu, firstreggpr: TSuperRegister;
+ href: treference;
+ needslinkreg : boolean;
+ localsize,
+ fprcount, gprcount: aint;
+begin
+ calcFirstUsedFPR(firstregfpu, fprcount);
+ calcFirstUsedGPR(firstreggpr, gprcount);
+
+ // determine whether we need to restore the link register
+ needslinkreg := ((not (po_assembler in current_procinfo.procdef.procoptions)) and
+ (pi_do_call in current_procinfo.flags));
+ // calculate stack frame
+ localsize := tppcprocinfo(current_procinfo).calc_stackframe_size(
+ gprcount, fprcount);
+
+ // CR register not supported
+
+ // restore stack pointer
+ if (not nostackframe) and (localsize > 0) then begin
+ if (localsize <= high(smallint)) then begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, localsize));
+ end else begin
+ reference_reset_base(href, NR_NO, localsize);
+
+ // use R0 for loading the constant (which is definitely > 32k when entering
+ // this branch)
+ // inlined because it must not use temp registers because register allocations
+ // have already been done :(
+ { Code template:
+ lis r0,ofs@highest
+ ori r0,ofs@higher
+ sldi r0,r0,32
+ oris r0,r0,ofs@h
+ ori r0,r0,ofs@l
+ }
+ list.concat(taicpu.op_reg_const(A_LIS, NR_R0, word(href.offset shr 48)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(href.offset shr 32)));
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, NR_R0, NR_R0, 32));
+ list.concat(taicpu.op_reg_reg_const(A_ORIS, NR_R0, NR_R0, word(href.offset shr 16)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(href.offset)));
+
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, NR_R1, NR_R1, NR_R0));
+ end;
+ end;
+
+ // load registers, FPR first, then GPR
+ {$note ts:todo change order of loading}
+ reference_reset_base(href, NR_STACK_POINTER_REG, -tcgsize2size[OS_FLOAT]);
+ if (fprcount > 0) then begin
+ for regcount := RS_F31 downto firstregfpu do begin
+ a_loadfpu_ref_reg(list, OS_FLOAT, href, newreg(R_FPUREGISTER, regcount,
+ R_SUBNONE));
+ dec(href.offset, tcgsize2size[OS_FLOAT]);
+ end;
+ end;
+ if (gprcount > 0) then begin
+ for regcount := RS_R31 downto firstreggpr do begin
+ a_load_ref_reg(list, OS_INT, OS_INT, href, newreg(R_INTREGISTER, regcount,
+ R_SUBNONE));
+ dec(href.offset, tcgsize2size[OS_INT]);
+ end;
+ end;
+
+ // VMX not supported...
+
+ // restore LR (if needed)
+ if (needslinkreg) then begin
+ reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_ELF);
+ list.concat(taicpu.op_reg_ref(A_LD, NR_R0, href));
+ list.concat(taicpu.op_reg(A_MTLR, NR_R0));
+ end;
+
+ // generate return instruction
+ list.concat(taicpu.op_none(A_BLR));
+end;
+
+
+procedure tcgppc.a_loadaddr_ref_reg(list: taasmoutput; const ref: treference; r:
+ tregister);
+
+var
+ ref2, tmpref: treference;
+ // register used to construct address
+ tempreg : TRegister;
+
+begin
+ ref2 := ref;
+ fixref(list, ref2, OS_64);
+ { load a symbol }
+ if assigned(ref2.symbol) or (hasLargeOffset(ref2)) then begin
+ { add the symbol's value to the base of the reference, and if the }
+ { reference doesn't have a base, create one }
+ reference_reset(tmpref);
+ tmpref.offset := ref2.offset;
+ tmpref.symbol := ref2.symbol;
+ tmpref.relsymbol := ref2.relsymbol;
+ // load 64 bit reference into r. If the reference already has a base register,
+ // first load the 64 bit value into a temp register, then add it to the result
+ // register rD
+ if (ref2.base <> NR_NO) then begin
+ // already have a base register, so allocate a new one
+ tempreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ end else begin
+ tempreg := r;
+ end;
+
+ // code for loading a reference from a symbol into a register rD.
+ (*
+ lis rX,SYM@highest
+ ori rX,SYM@higher
+ sldi rX,rX,32
+ oris rX,rX,SYM@h
+ ori rX,rX,SYM@l
+ *)
+ tmpref.refaddr := addr_highest;
+ list.concat(taicpu.op_reg_ref(A_LIS, tempreg, tmpref));
+ tmpref.refaddr := addr_higher;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tempreg, tempreg, tmpref));
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, tempreg, tempreg, 32));
+ tmpref.refaddr := addr_high;
+ list.concat(taicpu.op_reg_reg_ref(A_ORIS, tempreg, tempreg, tmpref));
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tempreg, tempreg, tmpref));
+
+ // if there's already a base register, add the temp register contents to
+ // the base register
+ if (ref2.base <> NR_NO) then begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, r, tempreg, ref2.base));
+ end;
+ end else if ref2.offset <> 0 then begin
+ { no symbol, but offset <> 0 }
+ if ref2.base <> NR_NO then begin
+ a_op_const_reg_reg(list, OP_ADD, OS_64, ref2.offset, ref2.base, r)
+ { FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never}
+ { occurs, so now only ref.offset has to be loaded }
+ end else begin
+ a_load_const_reg(list, OS_64, ref2.offset, r)
+ end;
+ end else if ref.index <> NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, r, ref2.base, ref2.index))
+ else if (ref2.base <> NR_NO) and
+ (r <> ref2.base) then
+ a_load_reg_reg(list, OS_ADDR, OS_ADDR, ref2.base, r)
+ else begin
+ list.concat(taicpu.op_reg_const(A_LI, r, 0));
+ end;
+end;
+
+{ ************* concatcopy ************ }
+
+const
+ maxmoveunit = 8;
+
+
+procedure tcgppc.g_concatcopy(list: taasmoutput; const source, dest: treference;
+ len: aint);
+
+var
+ countreg, tempreg: TRegister;
+ src, dst: TReference;
+ lab: tasmlabel;
+ count, count2: longint;
+ size: tcgsize;
+
+begin
+{$IFDEF extdebug}
+ if len > high(aint) then
+ internalerror(2002072704);
+{$ENDIF extdebug}
+ { make sure short loads are handled as optimally as possible }
+
+ if (len <= maxmoveunit) and
+ (byte(len) in [1, 2, 4, 8]) then
+ begin
+ if len < 8 then
+ begin
+ size := int_cgsize(len);
+ a_load_ref_ref(list, size, size, source, dest);
+ end
+ else
+ begin
+ a_reg_alloc(list, NR_F0);
+ a_loadfpu_ref_reg(list, OS_F64, source, NR_F0);
+ a_loadfpu_reg_ref(list, OS_F64, NR_F0, dest);
+ a_reg_dealloc(list, NR_F0);
+ end;
+ exit;
+ end;
+
+ count := len div maxmoveunit;
+
+ reference_reset(src);
+ reference_reset(dst);
+ { load the address of source into src.base }
+ if (count > 4) or
+ not issimpleref(source) or
+ ((source.index <> NR_NO) and
+ ((source.offset + len) > high(smallint))) then begin
+ src.base := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_loadaddr_ref_reg(list, source, src.base);
+ end else begin
+ src := source;
+ end;
+ { load the address of dest into dst.base }
+ if (count > 4) or
+ not issimpleref(dest) or
+ ((dest.index <> NR_NO) and
+ ((dest.offset + len) > high(smallint))) then begin
+ dst.base := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_loadaddr_ref_reg(list, dest, dst.base);
+ end else begin
+ dst := dest;
+ end;
+
+ { generate a loop }
+ if count > 4 then begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ inc(dst.offset, 8);
+ inc(src.offset, 8);
+ list.concat(taicpu.op_reg_reg_const(A_SUBI, src.base, src.base, 8));
+ list.concat(taicpu.op_reg_reg_const(A_SUBI, dst.base, dst.base, 8));
+ countreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_load_const_reg(list, OS_32, count, countreg);
+ { explicitely allocate R_0 since it can be used safely here }
+ { (for holding date that's being copied) }
+ a_reg_alloc(list, NR_F0);
+ objectlibrary.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_reg_const(A_SUBIC_, countreg, countreg, 1));
+ list.concat(taicpu.op_reg_ref(A_LFDU, NR_F0, src));
+ list.concat(taicpu.op_reg_ref(A_STFDU, NR_F0, dst));
+ a_jmp(list, A_BC, C_NE, 0, lab);
+ a_reg_dealloc(list, NR_F0);
+ len := len mod 8;
+ end;
+
+ count := len div 8;
+ { unrolled loop }
+ if count > 0 then begin
+ a_reg_alloc(list, NR_F0);
+ for count2 := 1 to count do begin
+ a_loadfpu_ref_reg(list, OS_F64, src, NR_F0);
+ a_loadfpu_reg_ref(list, OS_F64, NR_F0, dst);
+ inc(src.offset, 8);
+ inc(dst.offset, 8);
+ end;
+ a_reg_dealloc(list, NR_F0);
+ len := len mod 8;
+ end;
+
+ if (len and 4) <> 0 then begin
+ a_reg_alloc(list, NR_R0);
+ a_load_ref_reg(list, OS_32, OS_32, src, NR_R0);
+ a_load_reg_ref(list, OS_32, OS_32, NR_R0, dst);
+ inc(src.offset, 4);
+ inc(dst.offset, 4);
+ a_reg_dealloc(list, NR_R0);
+ end;
+ { copy the leftovers }
+ if (len and 2) <> 0 then begin
+ a_reg_alloc(list, NR_R0);
+ a_load_ref_reg(list, OS_16, OS_16, src, NR_R0);
+ a_load_reg_ref(list, OS_16, OS_16, NR_R0, dst);
+ inc(src.offset, 2);
+ inc(dst.offset, 2);
+ a_reg_dealloc(list, NR_R0);
+ end;
+ if (len and 1) <> 0 then begin
+ a_reg_alloc(list, NR_R0);
+ a_load_ref_reg(list, OS_8, OS_8, src, NR_R0);
+ a_load_reg_ref(list, OS_8, OS_8, NR_R0, dst);
+ a_reg_dealloc(list, NR_R0);
+ end;
+
+end;
+
+procedure tcgppc.g_overflowcheck(list: taasmoutput; const l: tlocation; def:
+ tdef);
+var
+ hl: tasmlabel;
+ flags : TResFlags;
+begin
+ if not (cs_check_overflow in aktlocalswitches) then
+ exit;
+ objectlibrary.getjumplabel(hl);
+ if not ((def.deftype = pointerdef) or
+ ((def.deftype = orddef) and
+ (torddef(def).typ in [u64bit, u16bit, u32bit, u8bit, uchar,
+ bool8bit, bool16bit, bool32bit]))) then
+ begin
+ // ... instruction setting overflow flag ...
+ // mfxerf R0
+ // mtcrf 128, R0
+ // ble cr0, label
+ list.concat(taicpu.op_reg(A_MFXER, NR_R0));
+ list.concat(taicpu.op_const_reg(A_MTCRF, 128, NR_R0));
+ flags.cr := RS_CR0;
+ flags.flag := F_LE;
+ a_jmp_flags(list, flags, hl);
+ end else
+ a_jmp_cond(list, OC_AE, hl);
+ a_call_name(list, 'FPC_OVERFLOW');
+ a_label(list, hl);
+end;
+
+procedure tcgppc.g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const
+ labelname: string; ioffset: longint);
+
+ procedure loadvmttor11;
+ var
+ href: treference;
+ begin
+ reference_reset_base(href, NR_R3, 0);
+ cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R11);
+ end;
+
+ procedure op_onr11methodaddr;
+ var
+ href: treference;
+ begin
+ if (procdef.extnumber = $FFFF) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href, NR_R11,
+ procdef._class.vmtmethodoffset(procdef.extnumber));
+ if not (hasLargeOffset(href)) then begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS, NR_R11, NR_R11,
+ smallint((href.offset shr 16) + ord(smallint(href.offset and $FFFF) <
+ 0))));
+ href.offset := smallint(href.offset and $FFFF);
+ end else
+ { add support for offsets > 16 bit }
+ internalerror(200510201);
+ list.concat(taicpu.op_reg_ref(A_LD, NR_R11, href));
+ // the loaded reference is a function descriptor reference, so deref again
+ // (at ofs 0 there's the real pointer)
+ {$warning ts:TODO: update GOT reference}
+ reference_reset_base(href, NR_R11, 0);
+ list.concat(taicpu.op_reg_ref(A_LD, NR_R11, href));
+
+ list.concat(taicpu.op_reg(A_MTCTR, NR_R11));
+ list.concat(taicpu.op_none(A_BCTR));
+ // NOP needed for the linker...?
+ list.concat(taicpu.op_none(A_NOP));
+ end;
+
+var
+ make_global: boolean;
+begin
+ if (not (procdef.proctypeoption in [potype_function, potype_procedure])) then
+ Internalerror(200006137);
+ if not assigned(procdef._class) or
+ (procdef.procoptions * [po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck] <> []) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype <> objectsymtable then
+ Internalerror(200109191);
+
+ make_global := false;
+ if (not current_module.is_unit) or
+ (cs_create_smart in aktmoduleswitches) or
+ (procdef.owner.defowner.owner.symtabletype = globalsymtable) then
+ make_global := true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname, AT_FUNCTION, 0))
+ else
+ List.concat(Tai_symbol.Createname(labelname, AT_FUNCTION, 0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list, procdef, ioffset);
+
+ { case 4 }
+ if po_virtualmethod in procdef.procoptions then begin
+ loadvmttor11;
+ op_onr11methodaddr;
+ end { case 0 } else
+ {$note ts:todo add GOT change?? - think not needed :) }
+ list.concat(taicpu.op_sym(A_B,
+ objectlibrary.newasmsymbol('.' + procdef.mangledname, AB_EXTERNAL,
+ AT_FUNCTION)));
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+end;
+
+{***************** This is private property, keep out! :) *****************}
+
+function tcgppc.issimpleref(const ref: treference): boolean;
+
+begin
+ if (ref.base = NR_NO) and
+ (ref.index <> NR_NO) then
+ internalerror(200208101);
+ result :=
+ not (assigned(ref.symbol)) and
+ (((ref.index = NR_NO) and
+ (ref.offset >= low(smallint)) and
+ (ref.offset <= high(smallint))) or
+ ((ref.index <> NR_NO) and
+ (ref.offset = 0)));
+end;
+
+function tcgppc.fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
+var
+ tmpreg: tregister;
+ needsAlign : boolean;
+begin
+ result := false;
+ needsAlign := size in [OS_S32, OS_64, OS_S64];
+
+ if (ref.base = NR_NO) then begin
+ ref.base := ref.index;
+ ref.index := NR_NO;
+ end;
+ if (ref.base <> NR_NO) and (ref.index <> NR_NO) and
+ ((ref.offset <> 0) or assigned(ref.symbol)) then begin
+ result := true;
+ tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_op_reg_reg_reg(list, OP_ADD, size, ref.base, ref.index, tmpreg);
+ ref.index := NR_NO;
+ ref.base := tmpreg;
+ end;
+end;
+
+procedure tcgppc.a_load_store(list: taasmoutput; op: tasmop; reg: tregister;
+ ref: treference);
+var
+ tmpreg, tmpreg2: tregister;
+ tmpref: treference;
+ largeOffset: Boolean;
+begin
+ { at this point there must not be a combination of values in the ref treference
+ which is not possible to directly map to instructions of the PowerPC architecture }
+ if (ref.index <> NR_NO) and ((ref.offset <> 0) or (assigned(ref.symbol))) then
+ internalerror(200310131);
+
+ { for some instructions we need to check that the offset is divisible by at
+ least four. If not, add the bytes which are "off" to the base register and
+ adjust the offset accordingly }
+ case op of
+ A_LD, A_LDU, A_STD, A_STDU, A_LWA, A_LWAU :
+ if ((ref.offset mod 4) <> 0) then begin
+ tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+
+ if (ref.base <> NR_NO) then begin
+ a_op_const_reg_reg(list, OP_ADD, OS_ADDR, ref.offset mod 4, ref.base, tmpreg);
+ ref.base := tmpreg;
+ end else begin
+ list.concat(taicpu.op_reg_const(A_LI, tmpreg, ref.offset mod 4));
+ ref.base := tmpreg;
+ end;
+ ref.offset := (ref.offset div 4) * 4;
+ end;
+ end;
+
+ { if we have to load/store from a symbol or large addresses, use a temporary register
+ containing the address }
+ if assigned(ref.symbol) or (hasLargeOffset(ref)) then begin
+ tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+
+ if (hasLargeOffset(ref) and (ref.base = NR_NO)) then begin
+ ref.base := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_load_const_reg(list, OS_ADDR, ref.offset, ref.base);
+ ref.offset := 0;
+ end;
+
+ reference_reset(tmpref);
+ tmpref.symbol := ref.symbol;
+ tmpref.relsymbol := ref.relsymbol;
+ tmpref.offset := ref.offset;
+ if (ref.base <> NR_NO) then begin
+ { As long as the TOC isn't working we try to achieve highest speed (in this
+ case by allowing instructions execute in parallel) as possible at the cost
+ of using another temporary register. So the code template when there is
+ a base register and an offset is the following:
+
+ lis rT1, SYM+offs@highest
+ ori rT1, rT1, SYM+offs@higher
+ lis rT2, SYM+offs@hi
+ ori rT2, SYM+offs@lo
+ rldimi rT2, rT1, 32
+
+ <op>X reg, base, rT2
+ }
+
+ tmpreg2 := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ tmpref.refaddr := addr_highest;
+ list.concat(taicpu.op_reg_ref(A_LIS, tmpreg, tmpref));
+ tmpref.refaddr := addr_higher;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tmpreg, tmpreg, tmpref));
+
+ tmpref.refaddr := addr_high;
+ list.concat(taicpu.op_reg_ref(A_LIS, tmpreg2, tmpref));
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tmpreg2, tmpreg2, tmpref));
+
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, tmpreg2, tmpreg, 32, 0));
+
+ reference_reset(tmpref);
+ tmpref.base := ref.base;
+ tmpref.index := tmpreg2;
+ case op of
+ { the code generator doesn't generate update instructions anyway }
+ A_LBZ : op := A_LBZX;
+ A_LHZ : op := A_LHZX;
+ A_LWZ : op := A_LWZX;
+ A_LD : op := A_LDX;
+ A_LHA : op := A_LHAX;
+ A_LWA : op := A_LWAX;
+ A_LFS : op := A_LFSX;
+ A_LFD : op := A_LFDX;
+
+ A_STB : op := A_STBX;
+ A_STH : op := A_STHX;
+ A_STW : op := A_STWX;
+ A_STD : op := A_STDX;
+
+ A_STFS : op := A_STFSX;
+ A_STFD : op := A_STFDX;
+ else
+ { unknown load/store opcode }
+ internalerror(2005101302);
+ end;
+ list.concat(taicpu.op_reg_ref(op, reg, tmpref));
+ end else begin
+ { when accessing value from a reference without a base register, use the
+ following code template:
+
+ lis rT,SYM+offs@highesta
+ ori rT,SYM+offs@highera
+ sldi rT,rT,32
+ oris rT,rT,SYM+offs@ha
+ ld rD,SYM+offs@l(rT)
+ }
+ tmpref.refaddr := addr_highesta;
+ list.concat(taicpu.op_reg_ref(A_LIS, tmpreg, tmpref));
+ tmpref.refaddr := addr_highera;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tmpreg, tmpreg, tmpref));
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, tmpreg, tmpreg, 32));
+ tmpref.refaddr := addr_higha;
+ list.concat(taicpu.op_reg_reg_ref(A_ORIS, tmpreg, tmpreg, tmpref));
+
+ tmpref.base := tmpreg;
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_ref(op, reg, tmpref));
+ end;
+ end else begin
+ list.concat(taicpu.op_reg_ref(op, reg, ref));
+ end;
+end;
+
+procedure tcgppc.a_jmp(list: taasmoutput; op: tasmop; c: tasmcondflag;
+ crval: longint; l: tasmlabel);
+var
+ p: taicpu;
+
+begin
+ p := taicpu.op_sym(op, objectlibrary.newasmsymbol(l.name, AB_EXTERNAL,
+ AT_LABEL));
+ if op <> A_B then
+ create_cond_norm(c, crval, p.condition);
+ p.is_jmp := true;
+ list.concat(p)
+end;
+
+function tcgppc.hasLargeOffset(const ref : TReference) : Boolean;
+begin
+ { this rather strange calculation is required because offsets of TReferences are unsigned }
+ result := aword(ref.offset-low(smallint)) > high(smallint)-low(smallint);
+end;
+
+begin
+ cg := tcgppc.create;
+end.
diff --git a/compiler/powerpc64/cpubase.pas b/compiler/powerpc64/cpubase.pas
new file mode 100644
index 0000000000..3af3693116
--- /dev/null
+++ b/compiler/powerpc64/cpubase.pas
@@ -0,0 +1,541 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the PowerPC
+
+ 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 contains the base types for the PowerPC64
+}
+unit cpubase;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ strings, globtype,
+ cutils, cclasses, aasmbase, cpuinfo, cgbase;
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+type
+ TAsmOp = (A_None,
+ { normal opcodes }
+ a_add, a_add_, a_addo, a_addo_, a_addc, a_addc_, a_addco, a_addco_,
+ a_adde, a_adde_, a_addeo, a_addeo_, a_addi, a_addic, a_addic_, a_addis,
+ a_addme, a_addme_, a_addmeo, a_addmeo_, a_addze, a_addze_, a_addzeo,
+ a_addzeo_, a_and, a_and_, a_andc, a_andc_, a_andi_, a_andis_, a_b,
+ a_ba, a_bl, a_bla, a_bc, a_bca, a_bcl, a_bcla, a_bcctr, a_bcctrl, a_bclr,
+ a_bclrl, a_cmp, a_cmpi, a_cmpl, a_cmpli, a_cntlzw, a_cntlzw_, a_crand,
+ a_crandc, a_creqv, a_crnand, a_crnor, a_cror, a_crorc, a_crxor, a_dcba,
+ a_dcbf, a_dcbi, a_dcbst, a_dcbt, a_dcbtst, a_dcbz, a_divw, a_divw_, a_divwo,
+ a_divwo_,
+ a_divwu, a_divwu_, a_divwuo, a_divwuo_, a_eciwx, a_ecowx, a_eieio, a_eqv,
+ a_eqv_, a_extsb, a_extsb_, a_extsh, a_extsh_, a_fabs, a_fabs_, a_fadd,
+ a_fadd_, a_fadds, a_fadds_, a_fcmpo, a_fcmpu, a_fctiw, a_fctw_, a_fctwz,
+ a_fctwz_, a_fdiv, a_fdiv_, a_fdivs, a_fdivs_, a_fmadd, a_fmadd_, a_fmadds,
+ a_fmadds_, a_fmr, a_fmsub, a_fmsub_, a_fmsubs, a_fmsubs_, a_fmul, a_fmul_,
+ a_fmuls, a_fmuls_, a_fnabs, a_fnabs_, a_fneg, a_fneg_, a_fnmadd,
+ a_fnmadd_, a_fnmadds, a_fnmadds_, a_fnmsub, a_fnmsub_, a_fnmsubs,
+ a_fnmsubs_, a_fres, a_fres_, a_frsp, a_frsp_, a_frsqrte, a_frsqrte_,
+ a_fsel, a_fsel_, a_fsqrt, a_fsqrt_, a_fsqrts, a_fsqrts_, a_fsub, a_fsub_,
+ a_fsubs, a_fsubs_, a_icbi, a_isync, a_lbz, a_lbzu, a_lbzux, a_lbzx,
+ a_lfd, a_lfdu, a_lfdux, a_lfdx, a_lfs, a_lfsu, a_lfsux, a_lfsx, a_lha,
+ a_lhau, a_lhaux, a_lhax, a_hbrx, a_lhz, a_lhzu, a_lhzux, a_lhzx, a_lmw,
+ a_lswi, a_lswx, a_lwarx, a_lwbrx, a_lwz, a_lwzu, a_lwzux, a_lwzx, a_mcrf,
+ a_mcrfs, a_mcrxr, a_mfcr, a_mffs, a_mffs_, a_mfmsr, a_mfspr, a_mfsr,
+ a_mfsrin, a_mftb, a_mtcrf, a_mtfsb0, a_mtfsb1, a_mtfsf, a_mtfsf_,
+ a_mtfsfi, a_mtfsfi_, a_mtmsr, a_mtspr, a_mtsr, a_mtsrin, a_mulhw,
+ a_mulhw_, a_mulhwu, a_mulhwu_, a_mulli, a_mullw, a_mullw_, a_mullwo,
+ a_mullwo_, a_nand, a_nand_, a_neg, a_neg_, a_nego, a_nego_, a_nor, a_nor_,
+ a_or, a_or_, a_orc, a_orc_, a_ori, a_oris, a_rfi, a_rlwimi, a_rlwimi_,
+ a_rlwinm, a_rlwinm_, a_rlwnm, a_sc, a_slw, a_slw_, a_sraw, a_sraw_,
+ a_srawi, a_srawi_, a_srw, a_srw_, a_stb, a_stbu, a_stbux, a_stbx, a_stfd,
+ a_stfdu, a_stfdux, a_stfdx, a_stfiwx, a_stfs, a_stfsu, a_stfsux, a_stfsx,
+ a_sth, a_sthbrx, a_sthu, a_sthux, a_sthx, a_stmw, a_stswi, a_stswx, a_stw,
+ a_stwbrx, a_stwcx_, a_stwu, a_stwux, a_stwx, a_subf, a_subf_, a_subfo,
+ a_subfo_, a_subfc, a_subfc_, a_subfco, a_subfco_, a_subfe, a_subfe_,
+ a_subfeo, a_subfeo_, a_subfic, a_subfme, a_subfme_, a_subfmeo, a_subfmeo_,
+ a_subfze, a_subfze_, a_subfzeo, a_subfzeo_, a_sync, a_tlbia, a_tlbie,
+ a_tlbsync, a_tw, a_twi, a_xor, a_xor_, a_xori, a_xoris,
+ { simplified mnemonics }
+ a_subi, a_subis, a_subic, a_subic_, a_sub, a_sub_, a_subo, a_subo_,
+ a_subc, a_subc_, a_subco, a_subco_, a_cmpwi, a_cmpw, a_cmplwi, a_cmplw,
+ a_extlwi, a_extlwi_, a_extrwi, a_extrwi_, a_inslwi, a_inslwi_, a_insrwi,
+ a_insrwi_, a_rotlwi, a_rotlwi_, a_rotlw, a_rotlw_, a_slwi, a_slwi_,
+ a_srwi, a_srwi_, a_clrlwi, a_clrlwi_, a_clrrwi, a_clrrwi_, a_clrslwi,
+ a_clrslwi_, a_blr, a_bctr, a_blrl, a_bctrl, a_crset, a_crclr, a_crmove,
+ a_crnot, a_mt {move to special prupose reg}, a_mf
+ {move from special purpose reg},
+ a_nop, a_li, a_lis, a_la, a_mr, a_mr_, a_not, a_mtcr, a_mtlr, a_mflr,
+ a_mtctr, a_mfctr,
+ A_EXTSW,
+ A_RLDIMI,
+ A_STD, A_STDU, A_STDX, A_STDUX,
+ A_LD, A_LDU, A_LDX, A_LDUX,
+ A_CMPD, A_CMPDI, A_CMPLD, A_CMPLDI,
+ A_SRDI, A_SRADI,
+ A_SLDI,
+ A_RLDICL,
+ A_DIVDU, A_DIVD, A_MULLD, A_SRAD, A_SLD, A_SRD,
+ A_DIVDUO_, A_DIVDO_,
+ A_LWA, A_LWAU, A_LWAX, A_LWAUX,
+ A_FCFID,
+ A_LDARX, A_STDCX_, A_CNTLZD,
+ A_LVX, A_STVX,
+ A_MULLDO, A_MULLDO_, A_MULHDU, A_MULHDU_,
+ A_MFXER);
+
+ {# This should define the array of instructions as string }
+ op2strtable = array[tasmop] of string[8];
+
+const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+ {*****************************************************************************
+ Registers
+ *****************************************************************************}
+
+type
+ { Number of registers used for indexing in tables }
+ tregisterindex = 0..{$I rppcnor.inc} - 1;
+ totherregisterset = set of tregisterindex;
+
+const
+ maxvarregs = 32 - 6;
+ { 32 int registers - r0 - stackpointer - r2 - 3 scratch registers }
+ maxfpuvarregs = 28; { 32 fpuregisters - some scratch registers (minimally 2) }
+ { Available Superregisters }
+{$I rppcsup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+{$I rppccon.inc}
+
+ { Integer Super registers first and last }
+ first_int_imreg = $20;
+
+ { Float Super register first and last }
+ first_fpu_imreg = $20;
+
+ { MM Super register first and last }
+ first_mm_imreg = $20;
+
+{$WARNING TODO Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table: array[tregisterindex] of tregister = (
+{$I rppcnum.inc}
+ );
+
+ regstabs_table: array[tregisterindex] of shortint = (
+{$I rppcstab.inc}
+ );
+
+ regdwarf_table: array[tregisterindex] of shortint = (
+{$I rppcdwrf.inc}
+ );
+
+ {*****************************************************************************
+ Conditions
+ *****************************************************************************}
+
+type
+ TAsmCondFlag = (C_None { unconditional jumps },
+ { conditions when not using ctr decrement etc }
+ C_LT, C_LE, C_EQ, C_GE, C_GT, C_NL, C_NE, C_NG, C_SO, C_NS, C_UN, C_NU,
+ { conditions when using ctr decrement etc }
+ C_T, C_F, C_DNZ, C_DNZT, C_DNZF, C_DZ, C_DZT, C_DZF);
+
+ TDirHint = (DH_None, DH_Minus, DH_Plus);
+
+const
+ { these are in the XER, but when moved to CR_x they correspond with the }
+ { bits below }
+ C_OV = C_GT;
+ C_CA = C_EQ;
+ C_NO = C_NG;
+ C_NC = C_NE;
+
+type
+ TAsmCond = packed record
+ dirhint: tdirhint;
+ case simple: boolean of
+ false: (BO, BI: byte);
+ true: (
+ cond: TAsmCondFlag;
+ case byte of
+ 0: ();
+ { specifies in which part of the cr the bit has to be }
+ { tested for blt,bgt,beq,..,bnu }
+ 1: (cr: RS_CR0..RS_CR7);
+ { specifies the bit to test for bt,bf,bdz,..,bdzf }
+ 2: (crbit: byte)
+ );
+ end;
+
+const
+ AsmCondFlag2BO: array[C_T..C_DZF] of Byte =
+ (12, 4, 16, 8, 0, 18, 10, 2);
+
+ AsmCondFlag2BOLT_NU: array[C_LT..C_NU] of Byte =
+ (12, 4, 12, 4, 12, 4, 4, 4, 12, 4, 12, 4);
+
+ AsmCondFlag2BI: array[C_LT..C_NU] of Byte =
+ (0, 1, 2, 0, 1, 0, 2, 1, 3, 3, 3, 3);
+
+ AsmCondFlagTF: array[TAsmCondFlag] of Boolean =
+ (false, true, false, true, false, true, false, false, false, true, false,
+ true, false,
+ true, false, false, true, false, false, true, false);
+
+ AsmCondFlag2Str: array[TAsmCondFlag] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'lt', 'le', 'eq', 'ge', 'gt', 'nl', 'ne', 'ng', 'so', 'ns', 'un', 'nu',
+ 't', 'f', 'dnz', 'dnzt', 'dnzf', 'dz', 'dzt', 'dzf');
+
+ UpperAsmCondFlag2Str: array[TAsmCondFlag] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'LT', 'LE', 'EQ', 'GE', 'GT', 'NL', 'NE', 'NG', 'SO', 'NS', 'UN', 'NU',
+ 'T', 'F', 'DNZ', 'DNZT', 'DNZF', 'DZ', 'DZT', 'DZF');
+
+const
+ CondAsmOps = 3;
+ CondAsmOp: array[0..CondAsmOps - 1] of TasmOp = (
+ A_BC, A_TW, A_TWI
+ );
+
+ {*****************************************************************************
+ Flags
+ *****************************************************************************}
+
+type
+ TResFlagsEnum = (F_EQ, F_NE, F_LT, F_LE, F_GT, F_GE, F_SO, F_FX, F_FEX, F_VX,
+ F_OX);
+ TResFlags = record
+ cr: RS_CR0..RS_CR7;
+ flag: TResFlagsEnum;
+ end;
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+const
+ symaddr2str: array[trefaddr] of string[9] = ('', '', '', '@l', '@h', '@higher', '@highest', '@ha', '@highera', '@highesta');
+
+const
+ { MacOS only. Whether the direct data area (TOC) directly contain
+ global variables. Otherwise it contains pointers to global variables. }
+ macos_direct_globals = false;
+
+ {*****************************************************************************
+ Operand Sizes
+ *****************************************************************************}
+
+ {*****************************************************************************
+ Constants
+ *****************************************************************************}
+
+const
+ max_operands = 5;
+
+ {*****************************************************************************
+ Default generic sizes
+ *****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_64;
+ {# the natural int size for a processor, }
+ OS_INT = OS_64;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+ {*****************************************************************************
+ GDB Information
+ *****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from rs6000.h (DBX_REGISTER_NUMBER)
+ from GCC 3.x source code. PowerPC has 1:1 mapping
+ according to the order of the registers defined
+ in GCC
+
+ }
+
+ stab_regindex: array[tregisterindex] of shortint = (
+{$I rppcstab.inc}
+ );
+
+ {*****************************************************************************
+ Generic Register names
+ *****************************************************************************}
+
+ // Stack pointer register
+ NR_STACK_POINTER_REG = NR_R1;
+ RS_STACK_POINTER_REG = RS_R1;
+ // Frame pointer register
+ NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG;
+ RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+
+ Taken from GCC rs6000.h
+ }
+{$WARNING As indicated in rs6000.h, but can't find it anywhere else!}
+ NR_PIC_OFFSET_REG = NR_R30;
+ { Return address of a function }
+ NR_RETURN_ADDRESS_REG = NR_R0;
+ { Results are returned in this register (64-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R3;
+ RS_FUNCTION_RETURN_REG = RS_R3;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+
+ NR_FPU_RESULT_REG = NR_F1;
+ NR_MM_RESULT_REG = NR_M0;
+
+ {*****************************************************************************
+ GCC /ABI linking information
+ *****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers: array[0..17] of tsuperregister = (
+ RS_R14, RS_R15, RS_R16, RS_R17, RS_R18, RS_R19,
+ RS_R20, RS_R21, RS_R22, RS_R23, RS_R24, RS_R25,
+ RS_R26, RS_R27, RS_R28, RS_R29, RS_R30, RS_R31
+ );
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+ }
+ std_param_align = 16;
+
+ {*****************************************************************************
+ CPU Dependent Constants
+ *****************************************************************************}
+
+ LinkageAreaSizeELF = 48;
+ { offset in the linkage area for the saved stack pointer }
+ LA_SP = 0;
+ { offset in the linkage area for the saved conditional register}
+ LA_CR_ELF = 8;
+ { offset in the linkage area for the saved link register}
+ LA_LR_ELF = 16;
+ { offset in the linkage area for the saved RTOC register}
+ LA_RTOC_ELF = 40;
+
+ PARENT_FRAMEPOINTER_OFFSET = 24;
+
+ NR_RTOC = NR_R2;
+
+ ELF_STACK_ALIGN = 16;
+
+ {*****************************************************************************
+ Helpers
+ *****************************************************************************}
+
+function is_calljmp(o: tasmop): boolean;
+
+procedure inverse_flags(var r: TResFlags);
+function flags_to_cond(const f: TResFlags): TAsmCond;
+procedure create_cond_imm(BO, BI: byte; var r: TAsmCond);
+procedure create_cond_norm(cond: TAsmCondFlag; cr: byte; var r: TasmCond);
+
+function cgsize2subreg(s: Tcgsize): Tsubregister;
+{ Returns the tcgsize corresponding with the size of reg.}
+function reg_cgsize(const reg: tregister): tcgsize;
+
+function findreg_by_number(r: Tregister): tregisterindex;
+function std_regnum_search(const s: string): Tregister;
+function std_regname(r: Tregister): string;
+function is_condreg(r: tregister): boolean;
+
+function inverse_cond(const c: TAsmCond): Tasmcond;
+{$IFDEF USEINLINE}inline;
+{$ENDIF USEINLINE}
+function conditions_equal(const c1, c2: TAsmCond): boolean;
+
+implementation
+
+uses
+ rgBase, verbose;
+
+const
+ std_regname_table: array[tregisterindex] of string[7] = (
+{$I rppcstd.inc}
+ );
+
+ regnumber_index: array[tregisterindex] of tregisterindex = (
+{$I rppcrni.inc}
+ );
+
+ std_regname_index: array[tregisterindex] of tregisterindex = (
+{$I rppcsri.inc}
+ );
+
+ {*****************************************************************************
+ Helpers
+ *****************************************************************************}
+
+function is_calljmp(o: tasmop): boolean;
+begin
+ is_calljmp := false;
+ case o of
+ A_B, A_BA, A_BL, A_BLA, A_BC, A_BCA, A_BCL, A_BCLA, A_BCCTR, A_BCCTRL,
+ A_BCLR,
+ A_BCLRL, A_TW, A_TWI: is_calljmp := true;
+ end;
+end;
+
+procedure inverse_flags(var r: TResFlags);
+const
+ inv_flags: array[F_EQ..F_GE] of TResFlagsEnum =
+ (F_NE, F_EQ, F_GE, F_GE, F_LE, F_LT);
+begin
+ r.flag := inv_flags[r.flag];
+end;
+
+function inverse_cond(const c: TAsmCond): Tasmcond;
+{$IFDEF USEINLINE}inline;
+{$ENDIF USEINLINE}
+const
+ inv_condflags: array[TAsmCondFlag] of TAsmCondFlag = (C_None,
+ C_GE, C_GT, C_NE, C_LT, C_LE, C_LT, C_EQ, C_GT, C_NS, C_SO, C_NU, C_UN,
+ C_F, C_T, C_DNZ, C_DNZF, C_DNZT, C_DZ, C_DZF, C_DZT);
+begin
+ if (c.cond in [C_DNZ, C_DZ]) then
+ internalerror(2005022501);
+ result := c;
+ result.cond := inv_condflags[c.cond];
+end;
+
+function conditions_equal(const c1, c2: TAsmCond): boolean;
+begin
+ result :=
+ (c1.simple and c2.simple) and
+ (c1.cond = c2.cond) and
+ ((not (c1.cond in [C_T..C_DZF]) and
+ (c1.cr = c2.cr)) or
+ (c1.crbit = c2.crbit));
+end;
+
+function flags_to_cond(const f: TResFlags): TAsmCond;
+const
+ flag_2_cond: array[F_EQ..F_SO] of TAsmCondFlag =
+ (C_EQ, C_NE, C_LT, C_LE, C_GT, C_GE, C_SO);
+begin
+ if f.flag > high(flag_2_cond) then
+ internalerror(200112301);
+ result.simple := true;
+ result.cr := f.cr;
+ result.cond := flag_2_cond[f.flag];
+end;
+
+procedure create_cond_imm(BO, BI: byte; var r: TAsmCond);
+begin
+ r.simple := false;
+ r.bo := bo;
+ r.bi := bi;
+end;
+
+procedure create_cond_norm(cond: TAsmCondFlag; cr: byte; var r: TasmCond);
+begin
+ r.simple := true;
+ r.cond := cond;
+ case cond of
+ C_NONE: ;
+ C_T..C_DZF: r.crbit := cr
+ else
+ r.cr := RS_CR0 + cr;
+ end;
+end;
+
+function is_condreg(r: tregister): boolean;
+var
+ supreg: tsuperregister;
+begin
+ result := false;
+ if (getregtype(r) = R_SPECIALREGISTER) then
+ begin
+ supreg := getsupreg(r);
+ result := (supreg >= RS_CR0) and (supreg <= RS_CR7);
+ end;
+end;
+
+function reg_cgsize(const reg: tregister): tcgsize;
+begin
+ case getregtype(reg) of
+ R_MMREGISTER,
+ R_FPUREGISTER,
+ R_INTREGISTER:
+ result := OS_64;
+ else
+ internalerror(200303181);
+ end;
+end;
+
+function cgsize2subreg(s: Tcgsize): Tsubregister;
+begin
+ cgsize2subreg := R_SUBWHOLE;
+end;
+
+function findreg_by_number(r: Tregister): tregisterindex;
+begin
+ result := rgBase.findreg_by_number_table(r, regnumber_index);
+end;
+
+function std_regnum_search(const s: string): Tregister;
+begin
+ result := regnumber_table[findreg_by_name_table(s, std_regname_table,
+ std_regname_index)];
+end;
+
+function std_regname(r: Tregister): string;
+var
+ p: tregisterindex;
+begin
+ p := findreg_by_number_table(r, regnumber_index);
+ if p <> 0 then
+ result := std_regname_table[p]
+ else
+ result := generic_regname(r);
+end;
+
+end.
+
diff --git a/compiler/powerpc64/cpuinfo.pas b/compiler/powerpc64/cpuinfo.pas
new file mode 100644
index 0000000000..2c429825ea
--- /dev/null
+++ b/compiler/powerpc64/cpuinfo.pas
@@ -0,0 +1,69 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the PowerPC
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+unit CPUInfo;
+
+interface
+
+uses
+ globtype;
+
+type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = extended;
+ ts64comp = comp;
+
+ pbestreal = ^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors =
+ (no_processor,
+ ppc970
+ );
+
+ tfputype =
+ (no_fpuprocessor,
+ fpu_soft,
+ fpu_standard
+ );
+
+const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions: tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { the difference to stdcall is only the name mangling }
+ pocall_cdecl,
+ { the difference to stdcall is only the name mangling }
+ pocall_cppdecl,
+ { pass all const records by reference }
+ pocall_mwpascal
+ ];
+
+ processorsstr: array[tprocessors] of string[10] = ('',
+ '970'
+ );
+
+ fputypestr: array[tfputype] of string[8] = ('',
+ 'SOFT',
+ 'STANDARD'
+ );
+
+implementation
+
+end.
+
diff --git a/compiler/powerpc64/cpunode.pas b/compiler/powerpc64/cpunode.pas
new file mode 100644
index 0000000000..ffa6532916
--- /dev/null
+++ b/compiler/powerpc64/cpunode.pas
@@ -0,0 +1,51 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the PowerPC64 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
+
+implementation
+
+uses
+ { generic nodes }
+ ncgbas, ncgld, ncgflw, ncgcnv, ncgmem, ncgcon, ncgcal, ncgset, ncginl, ncgopt,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ nppcadd,
+ nppccal,
+ // nppccon,
+ // nppcflw,
+ // nppcmem,
+ nppcset,
+ nppcinl,
+ // nppcopt,
+ nppcmat,
+ nppccnv,
+ nppcld
+ ;
+
+end.
+
diff --git a/compiler/powerpc64/cpupara.pas b/compiler/powerpc64/cpupara.pas
new file mode 100644
index 0000000000..8ea067bb72
--- /dev/null
+++ b/compiler/powerpc64/cpupara.pas
@@ -0,0 +1,479 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ PowerPC64 specific calling conventions
+
+ 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 cpupara;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ globtype,
+ aasmtai,
+ cpubase,
+ symconst, symtype, symdef, symsym,
+ paramgr, parabase, cgbase;
+
+type
+ tppcparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption: tproccalloption):
+ tcpuregisterset; override;
+ function get_volatile_registers_fpu(calloption: tproccalloption):
+ tcpuregisterset; override;
+ function push_addr_param(varspez: tvarspez; def: tdef; calloption:
+ tproccalloption): boolean; override;
+
+ procedure getintparaloc(calloption: tproccalloption; nr: longint; var
+ cgpara: TCGPara); override;
+ function create_paraloc_info(p: tabstractprocdef; side: tcallercallee):
+ longint; override;
+ function create_varargs_paraloc_info(p: tabstractprocdef; varargspara:
+ tvarargsparalist): longint; override;
+ procedure create_funcretloc_info(p: tabstractprocdef; side: tcallercallee);
+
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister;
+ var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p: tabstractprocdef; side:
+ tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var
+ cur_stack_offset: aword): longint;
+ function parseparaloc(p: tparavarsym; const s: string): boolean; override;
+ end;
+
+implementation
+
+uses
+ verbose, systems,
+ defutil,
+ cgutils;
+
+function tppcparamanager.get_volatile_registers_int(calloption:
+ tproccalloption): tcpuregisterset;
+begin
+ result := [RS_R3..RS_R12];
+end;
+
+function tppcparamanager.get_volatile_registers_fpu(calloption:
+ tproccalloption): tcpuregisterset;
+begin
+ result := [RS_F0..RS_F13];
+end;
+
+procedure tppcparamanager.getintparaloc(calloption: tproccalloption; nr:
+ longint; var cgpara: TCGPara);
+var
+ paraloc: pcgparalocation;
+begin
+ cgpara.reset;
+ cgpara.size := OS_INT;
+ cgpara.intsize := tcgsize2size[OS_INT];
+ cgpara.alignment := get_para_align(calloption);
+ paraloc := cgpara.add_location;
+ with paraloc^ do begin
+ size := OS_INT;
+ if (nr <= 8) then begin
+ if nr = 0 then
+ internalerror(200309271);
+ loc := LOC_REGISTER;
+ register := newreg(R_INTREGISTER, RS_R2 + nr, R_SUBWHOLE);
+ end else begin
+ loc := LOC_REFERENCE;
+ paraloc^.reference.index := NR_STACK_POINTER_REG;
+ if (target_info.abi <> abi_powerpc_aix) then
+ reference.offset := sizeof(aint) * (nr - 8)
+ else
+ reference.offset := sizeof(aint) * (nr);
+ end;
+ end;
+end;
+
+function getparaloc(p: tdef): tcgloc;
+
+begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.deftype of
+ orddef:
+ result := LOC_REGISTER;
+ floatdef:
+ result := LOC_FPUREGISTER;
+ enumdef:
+ result := LOC_REGISTER;
+ pointerdef:
+ result := LOC_REGISTER;
+ formaldef:
+ result := LOC_REGISTER;
+ classrefdef:
+ result := LOC_REGISTER;
+ recorddef:
+ result := LOC_REGISTER;
+ objectdef:
+ if is_object(p) then
+ result := LOC_REFERENCE
+ else
+ result := LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ result := LOC_REFERENCE
+ else
+ result := LOC_REGISTER;
+ procvardef:
+ if (po_methodpointer in tprocvardef(p).procoptions) then
+ result := LOC_REFERENCE
+ else
+ result := LOC_REGISTER;
+ filedef:
+ result := LOC_REGISTER;
+ arraydef:
+ result := LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ result := LOC_REGISTER
+ else
+ result := LOC_REFERENCE;
+ variantdef:
+ result := LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ result := LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+end;
+
+function tppcparamanager.push_addr_param(varspez: tvarspez; def: tdef;
+ calloption: tproccalloption): boolean;
+begin
+ result := false;
+ { var,out always require address }
+ if varspez in [vs_var, vs_out] then
+ begin
+ result := true;
+ exit;
+ end;
+ case def.deftype of
+ variantdef,
+ formaldef:
+ result := true;
+ recorddef:
+ result :=
+ ((varspez = vs_const) and
+ ((calloption = pocall_mwpascal) or
+ (not (calloption in [pocall_cdecl, pocall_cppdecl]) and
+ (def.size > 8)
+ )
+ )
+ );
+ arraydef:
+ result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef:
+ result := is_object(def);
+ setdef:
+ result := (tsetdef(def).settype <> smallset);
+ stringdef:
+ result := tstringdef(def).string_typ in [st_shortstring, st_longstring];
+ procvardef:
+ result := po_methodpointer in tprocvardef(def).procoptions;
+ end;
+end;
+
+procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg:
+ tsuperregister; var cur_stack_offset: aword);
+begin
+ { register parameter save area begins at 48(r2) }
+ cur_stack_offset := 48;
+ curintreg := RS_R3;
+ curfloatreg := RS_F1;
+ curmmreg := RS_M2;
+end;
+
+procedure tppcparamanager.create_funcretloc_info(p: tabstractprocdef; side:
+ tcallercallee);
+var
+ retcgsize: tcgsize;
+begin
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption = potype_constructor) then
+ retcgsize := OS_ADDR
+ else
+ retcgsize := def_cgsize(p.rettype.def);
+
+ location_reset(p.funcretloc[side], LOC_INVALID, OS_NO);
+ p.funcretloc[side].size := retcgsize;
+ { void has no location }
+ if is_void(p.rettype.def) then begin
+ p.funcretloc[side].loc := LOC_VOID;
+ exit;
+ end;
+
+ { Return in FPU register? }
+ if p.rettype.def.deftype = floatdef then begin
+ p.funcretloc[side].loc := LOC_FPUREGISTER;
+ p.funcretloc[side].register := NR_FPU_RESULT_REG;
+ p.funcretloc[side].size := retcgsize;
+ end else
+ { Return in register? }
+ if not ret_in_param(p.rettype.def, p.proccalloption) then begin
+ p.funcretloc[side].loc := LOC_REGISTER;
+ p.funcretloc[side].size := retcgsize;
+ if side = callerside then
+ p.funcretloc[side].register := newreg(R_INTREGISTER,
+ RS_FUNCTION_RESULT_REG, cgsize2subreg(retcgsize))
+ else
+ p.funcretloc[side].register := newreg(R_INTREGISTER,
+ RS_FUNCTION_RETURN_REG, cgsize2subreg(retcgsize));
+ end else begin
+ p.funcretloc[side].loc := LOC_REFERENCE;
+ p.funcretloc[side].size := retcgsize;
+ end;
+end;
+
+function tppcparamanager.create_paraloc_info(p: tabstractprocdef; side:
+ tcallercallee): longint;
+
+var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+begin
+ init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
+
+ result := create_paraloc_info_intern(p, side, p.paras, curintreg, curfloatreg,
+ curmmreg, cur_stack_offset);
+
+ create_funcretloc_info(p, side);
+end;
+
+function tppcparamanager.create_paraloc_info_intern(p: tabstractprocdef; side:
+ tcallercallee; paras: tparalist;
+var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
+ aword): longint;
+var
+ stack_offset: longint;
+ paralen: aint;
+ nextintreg, nextfloatreg, nextmmreg, maxfpureg: tsuperregister;
+ paradef: tdef;
+ paraloc: pcgparalocation;
+ i: integer;
+ hp: tparavarsym;
+ loc: tcgloc;
+ paracgsize: tcgsize;
+
+begin
+{$IFDEF extdebug}
+ if po_explicitparaloc in p.procoptions then
+ internalerror(200411141);
+{$ENDIF extdebug}
+
+ result := 0;
+ nextintreg := curintreg;
+ nextfloatreg := curfloatreg;
+ nextmmreg := curmmreg;
+ stack_offset := cur_stack_offset;
+
+ maxfpureg := RS_F13;
+
+ for i := 0 to paras.count - 1 do begin
+ hp := tparavarsym(paras[i]);
+ paradef := hp.vartype.def;
+ { Syscall for Morphos can have already a paraloc set }
+ if (vo_has_explicit_paraloc in hp.varoptions) then begin
+ if not (vo_is_syscall_lib in hp.varoptions) then
+ internalerror(200412153);
+ continue;
+ end;
+ hp.paraloc[side].reset;
+ { currently only support C-style array of const }
+ if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) and
+ is_array_of_const(paradef) then begin
+ paraloc := hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc := LOC_REGISTER;
+ paraloc^.register := NR_R0;
+ paraloc^.size := OS_ADDR;
+ break;
+ end;
+
+ if (hp.varspez in [vs_var, vs_out]) or
+ push_addr_param(hp.varspez, paradef, p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then begin
+ paradef := voidpointertype.def;
+ loc := LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end else begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+ if (paradef.deftype = recorddef) and
+ (hp.varspez in [vs_value, vs_const]) then begin
+ { if a record has only one field and that field is }
+ { non-composite (not array or record), it must be }
+ { passed according to the rules of that type. }
+ if (trecorddef(hp.vartype.def).symtable.symindex.count = 1) and
+ (not trecorddef(hp.vartype.def).isunion) and
+ (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) then begin
+ paradef :=
+ tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
+ loc := getparaloc(paradef);
+ paracgsize := def_cgsize(paradef);
+ end else begin
+ loc := LOC_REGISTER;
+ paracgsize := int_cgsize(paralen);
+ end;
+ end else begin
+ loc := getparaloc(paradef);
+ paracgsize := def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize = OS_NO) then begin
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end
+ end;
+ hp.paraloc[side].alignment := std_param_align;
+ hp.paraloc[side].size := paracgsize;
+ hp.paraloc[side].intsize := paralen;
+ if (paralen = 0) then
+ if (paradef.deftype = recorddef) then begin
+ paraloc := hp.paraloc[side].add_location;
+ paraloc^.loc := LOC_VOID;
+ end else
+ internalerror(2005011310);
+ { can become < 0 for e.g. 3-byte records }
+ while (paralen > 0) do begin
+ paraloc := hp.paraloc[side].add_location;
+ if (loc = LOC_REGISTER) and
+ (nextintreg <= RS_R10) then begin
+ paraloc^.loc := loc;
+ { make sure we don't lose whether or not the type is signed }
+ if (paradef.deftype <> orddef) then
+ paracgsize := int_cgsize(paralen);
+ if (paracgsize in [OS_NO]) then
+ paraloc^.size := OS_INT
+ else
+ paraloc^.size := paracgsize;
+ paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
+ inc(nextintreg);
+ dec(paralen, tcgsize2size[paraloc^.size]);
+
+ inc(stack_offset, tcgsize2size[paraloc^.size]);
+ end else if (loc = LOC_FPUREGISTER) and
+ (nextfloatreg <= maxfpureg) then begin
+ paraloc^.loc := loc;
+ paraloc^.size := paracgsize;
+ paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
+ { the PPC64 ABI says that the GPR index is increased for every parameter, no matter
+ which type it is stored in }
+ inc(nextintreg);
+ inc(nextfloatreg);
+ dec(paralen, tcgsize2size[paraloc^.size]);
+
+ inc(stack_offset, tcgsize2size[paraloc^.size]);
+ end else if (loc = LOC_MMREGISTER) then begin
+ { Altivec not supported }
+ internalerror(200510192);
+ end else begin
+ { either LOC_REFERENCE, or one of the above which must be passed on the
+ stack because of insufficient registers }
+ paraloc^.loc := LOC_REFERENCE;
+ paraloc^.size := int_cgsize(paralen);
+ if (side = callerside) then
+ paraloc^.reference.index := NR_STACK_POINTER_REG
+ else
+ { during procedure entry, R12 contains the old stack pointer }
+ paraloc^.reference.index := NR_R12;
+ paraloc^.reference.offset := stack_offset;
+
+ { TODO: change this to the next power of two (natural alignment) }
+ inc(stack_offset, align(paralen, 8));
+ paralen := 0;
+ end;
+ end;
+ end;
+ curintreg := nextintreg;
+ curfloatreg := nextfloatreg;
+ curmmreg := nextmmreg;
+ cur_stack_offset := stack_offset;
+ result := stack_offset;
+end;
+
+function tppcparamanager.create_varargs_paraloc_info(p: tabstractprocdef;
+ varargspara: tvarargsparalist): longint;
+var
+ cur_stack_offset: aword;
+ parasize, l: longint;
+ curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
+ i: integer;
+ hp: tparavarsym;
+ paraloc: pcgparalocation;
+begin
+ init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
+ firstfloatreg := curfloatreg;
+
+ result := create_paraloc_info_intern(p, callerside, p.paras, curintreg,
+ curfloatreg, curmmreg, cur_stack_offset);
+ if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) then
+ { just continue loading the parameters in the registers }
+ begin
+ result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
+ curfloatreg, curmmreg, cur_stack_offset);
+ { varargs routines have to reserve at least 64 bytes for the AIX abi }
+ if (result < 64) then
+ result := 64;
+ end
+ else
+ begin
+ parasize := cur_stack_offset;
+ for i := 0 to varargspara.count - 1 do
+ begin
+ hp := tparavarsym(varargspara[i]);
+ hp.paraloc[callerside].alignment := 8;
+ paraloc := hp.paraloc[callerside].add_location;
+ paraloc^.loc := LOC_REFERENCE;
+ paraloc^.size := def_cgsize(hp.vartype.def);
+ paraloc^.reference.index := NR_STACK_POINTER_REG;
+ l := push_size(hp.varspez, hp.vartype.def, p.proccalloption);
+ paraloc^.reference.offset := parasize;
+ parasize := parasize + l;
+ end;
+ result := parasize;
+ end;
+ if curfloatreg <> firstfloatreg then
+ include(varargspara.varargsinfo, va_uses_float_reg);
+end;
+
+function tppcparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;
+begin
+ { not supported/required for PowerPC64-linux target }
+ internalerror(200404182);
+ result := true;
+end;
+
+begin
+ paramanager := tppcparamanager.create;
+end.
+
diff --git a/compiler/powerpc64/cpupi.pas b/compiler/powerpc64/cpupi.pas
new file mode 100644
index 0000000000..bfde833b9c
--- /dev/null
+++ b/compiler/powerpc64/cpupi.pas
@@ -0,0 +1,111 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ 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 contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ cutils,
+ procinfo, cpuinfo, psub;
+
+type
+ tppcprocinfo = class(tcgprocinfo)
+ { offset where the frame pointer from the outer procedure is stored. }
+ parent_framepointer_offset: longint;
+ constructor create(aparent: tprocinfo); override;
+ procedure set_first_temp_offset; override;
+ procedure allocate_push_parasize(size: longint); override;
+ function calc_stackframe_size: longint; override;
+ function calc_stackframe_size(numgpr, numfpr : longint): longint;
+ end;
+
+implementation
+
+uses
+ globtype, globals, systems,
+ cpubase, cgbase,
+ aasmtai,
+ tgobj,
+ symconst, symsym, paramgr, symutil,
+ verbose;
+
+constructor tppcprocinfo.create(aparent: tprocinfo);
+
+begin
+ inherited create(aparent);
+ maxpushedparasize := 0;
+end;
+
+procedure tppcprocinfo.set_first_temp_offset;
+var
+ ofs: aword;
+ locals: longint;
+begin
+ if not (po_assembler in procdef.procoptions) then begin
+ { the ABI specification says that it is required to always allocate space for 8 * 8 bytes
+ for registers R3-R10 and stack header if there's a stack frame, but GCC doesn't do that,
+ so we don't that too. Uncomment the next three lines if this is required }
+ // if (maxpushedparasize < 64) then begin
+ // maxpushedparasize := 64;
+ // end;
+ { align the stack properly }
+ ofs := align(maxpushedparasize + LinkageAreaSizeELF, ELF_STACK_ALIGN);
+ tg.setfirsttemp(ofs);
+ end else begin
+ locals := 0;
+ current_procinfo.procdef.localst.foreach_static(@count_locals, @locals);
+ if locals <> 0 then
+ { at 0(r1), the previous value of r1 will be stored }
+ tg.setfirsttemp(8);
+ end;
+end;
+
+procedure tppcprocinfo.allocate_push_parasize(size: longint);
+begin
+ if size > maxpushedparasize then
+ maxpushedparasize := size;
+end;
+
+function tppcprocinfo.calc_stackframe_size: longint;
+begin
+ calc_stackframe_size(18, 18);
+end;
+
+function tppcprocinfo.calc_stackframe_size(numgpr, numfpr : longint) : longint;
+begin
+ { more or less copied from cgcpu.pas/g_stackframe_entry }
+ if not (po_assembler in procdef.procoptions) then begin
+ // no VMX support
+ result := align(align(numgpr * tcgsize2size[OS_INT] +
+ numfpr * tcgsize2size[OS_FLOAT], ELF_STACK_ALIGN) + tg.lasttemp, ELF_STACK_ALIGN);
+ end else
+ result := align(tg.lasttemp, ELF_STACK_ALIGN);
+end;
+
+begin
+ cprocinfo := tppcprocinfo;
+end.
+
diff --git a/compiler/powerpc64/cpuswtch.pas b/compiler/powerpc64/cpuswtch.pas
new file mode 100644
index 0000000000..455aa1966e
--- /dev/null
+++ b/compiler/powerpc64/cpuswtch.pas
@@ -0,0 +1,125 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ interprets the commandline options which are PowerPC64 specific
+
+ 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 cpuswtch;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ options;
+
+type
+ toptionpowerpc = class(toption)
+ procedure interpret_proc_specific_options(const opt: string); override;
+ end;
+
+implementation
+
+uses
+ cutils, globtype, systems, globals;
+
+procedure toptionpowerpc.interpret_proc_specific_options(const opt: string);
+var
+ more: string;
+ j: longint;
+begin
+ More := Upper(copy(opt, 3, length(opt) - 2));
+ case opt[2] of
+ 'O':
+ begin
+ j := 3;
+ while (j <= Length(Opt)) do
+ begin
+ case opt[j] of
+ '-':
+ begin
+ initglobalswitches := initglobalswitches - [cs_optimize,
+ cs_fastoptimize, cs_slowoptimize, cs_littlesize,
+ cs_regvars, cs_uncertainopts];
+ FillChar(ParaAlignment, sizeof(ParaAlignment), 0);
+ end;
+ 'a':
+ begin
+ UpdateAlignmentStr(Copy(Opt, j + 1, 255), ParaAlignment);
+ j := length(Opt);
+ end;
+ 'g': initglobalswitches := initglobalswitches + [cs_littlesize];
+ 'G': initglobalswitches := initglobalswitches - [cs_littlesize];
+ 'r':
+ begin
+ initglobalswitches := initglobalswitches + [cs_regvars];
+ Simplify_ppu := false;
+ end;
+ 'u': initglobalswitches := initglobalswitches + [cs_uncertainopts];
+ '1': initglobalswitches := initglobalswitches - [cs_fastoptimize,
+ cs_slowoptimize] + [cs_optimize];
+ '2': initglobalswitches := initglobalswitches - [cs_slowoptimize] +
+ [cs_optimize, cs_fastoptimize];
+ '3': initglobalswitches := initglobalswitches + [cs_optimize,
+ cs_fastoptimize, cs_slowoptimize];
+{$IFDEF dummy}
+ 'p':
+ begin
+ if j < Length(Opt) then
+ begin
+ case opt[j + 1] of
+ '1': initoptprocessor := Class386;
+ '2': initoptprocessor := ClassP5;
+ '3': initoptprocessor := ClassP6
+ else
+ IllegalPara(Opt)
+ end;
+ Inc(j);
+ end
+ else
+ IllegalPara(opt)
+ end;
+{$ENDIF dummy}
+ else
+ IllegalPara(opt);
+ end;
+ Inc(j)
+ end;
+ end;
+{$IFDEF dummy}
+ 'R':
+ begin
+ if More = 'GAS' then
+ initasmmode := asmmode_ppc_gas
+ else if More = 'MOTOROLA' then
+ initasmmode := asmmode_ppc_motorola
+ else if More = 'DIRECT' then
+ initasmmode := asmmode_direct
+ else
+ IllegalPara(opt);
+ end;
+{$ENDIF dummy}
+ else
+ IllegalPara(opt);
+ end;
+end;
+
+initialization
+ coption := toptionpowerpc;
+end.
+
diff --git a/compiler/powerpc64/cputarg.pas b/compiler/powerpc64/cputarg.pas
new file mode 100644
index 0000000000..412ec516eb
--- /dev/null
+++ b/compiler/powerpc64/cputarg.pas
@@ -0,0 +1,78 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the powerpc dependent target units
+
+ 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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGPPCGAS}
+ ,agppcgas
+ {$endif}
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaPPCGas}
+ ,rappcgas
+ {$endif NoRaPPCGas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+{**************************************
+ Optimizer
+**************************************}
+
+ {$ifndef NOOPT}
+ , aoptcpu
+ {$endif NOOPT}
+ ;
+
+end.
diff --git a/compiler/powerpc64/itcpugas.pas b/compiler/powerpc64/itcpugas.pas
new file mode 100644
index 0000000000..41b376b1dc
--- /dev/null
+++ b/compiler/powerpc64/itcpugas.pas
@@ -0,0 +1,158 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the PowerPC GAS instruction tables
+
+ 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 itcpugas;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ cpubase, cgbase;
+
+const
+ gas_op2str: array[tasmop] of string[14] = ('<none>',
+ 'add', 'add.', 'addo', 'addo.', 'addc', 'addc.', 'addco', 'addco.',
+ 'adde', 'adde.', 'addeo', 'addeo.', 'addi', 'addic', 'addic.', 'addis',
+ 'addme', 'addme.', 'addmeo', 'addmeo.', 'addze', 'addze.', 'addzeo',
+ 'addzeo.', 'and', 'and.', 'andc', 'andc.', 'andi.', 'andis.', 'b',
+ 'ba', 'bl', 'bla', 'bc', 'bca', 'bcl', 'bcla', 'bcctr', 'bcctrl', 'bclr',
+ 'bclrl', 'cmp', 'cmpi', 'cmpl', 'cmpli', 'cntlzw', 'cntlzw.', 'crand',
+ 'crandc', 'creqv', 'crnand', 'crnor', 'cror', 'crorc', 'crxor', 'dcba',
+ 'dcbf', 'dcbi', 'dcbst', 'dcbt', 'dcbtst', 'dcbz', 'divw', 'divw.', 'divwo',
+ 'divwo.',
+ 'divwu', 'divwu.', 'divwuo', 'divwuo.', 'eciwx', 'ecowx', 'eieio', 'eqv',
+ 'eqv.', 'extsb', 'extsb.', 'extsh', 'extsh.', 'fabs', 'fabs.', 'fadd',
+ 'fadd.', 'fadds', 'fadds.', 'fcmpo', 'fcmpu', 'fctiw', 'fctiw.', 'fctiwz',
+ 'fctiwz.', 'fdiv', 'fdiv.', 'fdivs', 'fdivs.', 'fmadd', 'fmadd.', 'fmadds',
+ 'fmadds.', 'fmr', 'fmsub', 'fmsub.', 'fmsubs', 'fmsubs.', 'fmul', 'fmul.',
+ 'fmuls', 'fmuls.', 'fnabs', 'fnabs.', 'fneg', 'fneg.', 'fnmadd',
+ 'fnmadd.', 'fnmadds', 'fnmadds.', 'fnmsub', 'fnmsub.', 'fnmsubs',
+ 'fnmsubs.', 'fres', 'fres.', 'frsp', 'frsp.', 'frsqrte', 'frsqrte.',
+ 'fsel', 'fsel.', 'fsqrt', 'fsqrt.', 'fsqrts', 'fsqrts.', 'fsub', 'fsub.',
+ 'fsubs', 'fsubs.', 'icbi', 'isync', 'lbz', 'lbzu', 'lbzux', 'lbzx',
+ 'lfd', 'lfdu', 'lfdux', 'lfdx', 'lfs', 'lfsu', 'lfsux', 'lfsx', 'lha',
+ 'lhau', 'lhaux', 'lhax', 'hbrx', 'lhz', 'lhzu', 'lhzux', 'lhzx', 'lmw',
+ 'lswi', 'lswx', 'lwarx', 'lwbrx', 'lwz', 'lwzu', 'lwzux', 'lwzx', 'mcrf',
+ 'mcrfs', 'mcrxr', 'mfcr', 'mffs', 'mffs.', 'mfmsr', 'mfspr', 'mfsr',
+ 'mfsrin', 'mftb', 'mtcrf', 'mtfsb0', 'mtfsb1', 'mtfsf', 'mtfsf.',
+ 'mtfsfi', 'mtfsfi.', 'mtmsr', 'mtspr', 'mtsr', 'mtsrin', 'mulhw',
+ 'mulhw.', 'mulhwu', 'mulhwu.', 'mulli', 'mullw', 'mullw.', 'mullwo',
+ 'mullwo.', 'nand', 'nand.', 'neg', 'neg.', 'nego', 'nego.', 'nor', 'nor.',
+ 'or', 'or.', 'orc', 'orc.', 'ori', 'oris', 'rfi', 'rlwimi', 'rlwimi.',
+ 'rlwinm', 'rlwinm.', 'rlwnm', 'sc', 'slw', 'slw.', 'sraw', 'sraw.',
+ 'srawi', 'srawi.', 'srw', 'srw.', 'stb', 'stbu', 'stbux', 'stbx', 'stfd',
+ 'stfdu', 'stfdux', 'stfdx', 'stfiwx', 'stfs', 'stfsu', 'stfsux', 'stfsx',
+ 'sth', 'sthbrx', 'sthu', 'sthux', 'sthx', 'stmw', 'stswi', 'stswx', 'stw',
+ 'stwbrx', 'stwcx.', 'stwu', 'stwux', 'stwx', 'subf', 'subf.', 'subfo',
+ 'subfo.', 'subfc', 'subc.', 'subfco', 'subfco.', 'subfe', 'subfe.',
+ 'subfeo', 'subfeo.', 'subfic', 'subfme', 'subfme.', 'subfmeo', 'subfmeo.',
+ 'subfze', 'subfze.', 'subfzeo', 'subfzeo.', 'sync', 'tlbia', 'tlbie',
+ 'tlbsync', 'tw', 'twi', 'xor', 'xor.', 'xori', 'xoris',
+ { some simplified mnemonics }
+ 'subi', 'subis', 'subic', 'subic.', 'sub', 'sub.', 'subo', 'subo.',
+ 'subc', 'subc.', 'subco', 'subco.', 'cmpwi', 'cmpw', 'cmplwi', 'cmplw',
+ 'extlwi', 'extlwi.', 'extrwi', 'extrwi.', 'inslwi', 'inslwi.', 'insrwi',
+ 'insrwi.', 'rotlwi', 'rotlwi.', 'rotlw', 'rotlw.', 'slwi', 'slwi.',
+ 'srwi', 'srwi.', 'clrlwi', 'clrlwi.', 'clrrwi', 'clrrwi.', 'clrslwi',
+ 'clrslwi.', 'blr', 'bctr', 'blrl', 'bctrl', 'crset', 'crclr', 'crmove',
+ 'crnot', 'mt', 'mf', 'nop', 'li', 'lis', 'la', 'mr', 'mr.', 'not', 'mtcr',
+ 'mtlr', 'mflr',
+ 'mtctr', 'mfctr',
+ 'extsw', 'rldimi',
+ 'std', 'stdu', 'stdx', 'stdux',
+ 'ld', 'ldu', 'ldx', 'ldux',
+ 'cmpd', 'cmpdi', 'cmpld', 'cmpldi',
+ 'srdi', 'sradi',
+ 'sldi',
+ 'rldicl',
+ 'divdu', 'divd', 'mulld', 'srad', 'sld', 'srd',
+ 'divduo.', 'divdo.',
+ 'lwa', '<illegal lwau>', 'lwax', 'lwaux',
+ 'fcfid',
+ 'ldarx', 'stdcx.', 'cntlzd',
+ 'lvx', 'stvx',
+ 'mulldo', 'mulldo.', 'mulhdu', 'mulhdu.',
+ 'mfxer');
+
+function gas_regnum_search(const s: string): Tregister;
+function gas_regname(r: Tregister): string;
+
+implementation
+
+uses
+ globtype, globals,
+ cutils, verbose, systems;
+
+const
+ gas_regname_table: array[tregisterindex] of string[7] = (
+{$I rppcgas.inc}
+ );
+
+ gas_regname_short_table: array[tregisterindex] of string[7] = (
+{$I rppcgss.inc}
+ );
+
+ gas_regname_index: array[tregisterindex] of tregisterindex = (
+{$I rppcgri.inc}
+ );
+
+function findreg_by_gasname(const s: string): tregisterindex;
+var
+ i, p: tregisterindex;
+begin
+ {Binary search.}
+ p := 0;
+ i := regnumber_count_bsstart;
+ repeat
+ if (p + i <= high(tregisterindex)) and (gas_regname_table[gas_regname_index[p
+ + i]] <= s) then
+ p := p + i;
+ i := i shr 1;
+ until i = 0;
+ if gas_regname_table[gas_regname_index[p]] = s then
+ findreg_by_gasname := gas_regname_index[p]
+ else
+ findreg_by_gasname := 0;
+end;
+
+function gas_regnum_search(const s: string): Tregister;
+begin
+ result := regnumber_table[findreg_by_gasname(s)];
+end;
+
+function gas_regname(r: Tregister): string;
+var
+ p: longint;
+begin
+ p := findreg_by_number(r);
+ if p <> 0 then
+ if (cs_create_smart in aktmoduleswitches) and
+ (target_info.system <> system_powerpc_darwin) then
+ result := gas_regname_short_table[p]
+ else
+ result := gas_regname_table[p]
+ else
+ result := generic_regname(r);
+end;
+
+end.
+
diff --git a/compiler/powerpc64/nppcadd.pas b/compiler/powerpc64/nppcadd.pas
new file mode 100644
index 0000000000..ecae422fe6
--- /dev/null
+++ b/compiler/powerpc64/nppcadd.pas
@@ -0,0 +1,851 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the PowerPC64
+
+ 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 nppcadd;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, nadd, ncgadd, cpubase;
+
+type
+ tppcaddnode = class(tcgaddnode)
+ function pass_1: tnode; override;
+ procedure pass_2; override;
+ private
+ procedure pass_left_and_right;
+ procedure load_left_right(cmpop, load_constants: boolean);
+ function getresflags: tresflags;
+ procedure emit_compare(unsigned: boolean);
+ procedure second_addfloat; override;
+ procedure second_addboolean; override;
+ procedure second_addsmallset; override;
+ end;
+
+implementation
+
+uses
+ sysutils,
+
+ globtype, systems,
+ cutils, verbose, globals,
+ symconst, symdef, paramgr,
+ aasmbase, aasmtai, aasmcpu, defutil, htypechk,
+ cgbase, cpuinfo, pass_1, pass_2, regvars,
+ cpupara, cgcpu, cgutils,
+ ncon, nset,
+ ncgutil, tgobj, rgobj, rgcpu, cgobj;
+
+{*****************************************************************************
+ Pass 1
+*****************************************************************************}
+
+function tppcaddnode.pass_1: tnode;
+begin
+ resulttypepass(left);
+ if (nodetype in [equaln, unequaln]) and
+ (left.resulttype.def.deftype = orddef) {and
+ is_64bit(left.resulttype.def)}then
+ begin
+ result := nil;
+ firstpass(left);
+ firstpass(right);
+ expectloc := LOC_FLAGS;
+ calcregisters(self, 2, 0, 0);
+ exit;
+ end;
+ result := inherited pass_1;
+end;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+procedure tppcaddnode.pass_left_and_right;
+begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ { in case of constant put it to the left }
+ if (left.nodetype = ordconstn) then
+ swapleftright;
+
+ secondpass(left);
+ secondpass(right);
+end;
+
+procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean);
+
+ procedure load_node(var n: tnode);
+ begin
+ case n.location.loc of
+ LOC_REGISTER:
+ if not cmpop then
+ begin
+ location.register := n.location.register;
+ end;
+ LOC_REFERENCE, LOC_CREFERENCE:
+ begin
+ location_force_reg(exprasmlist, n.location,
+ def_cgsize(n.resulttype.def), false);
+ if not cmpop then
+ begin
+ location.register := n.location.register;
+ end;
+ end;
+ LOC_CONSTANT:
+ begin
+ if load_constants then
+ begin
+ location_force_reg(exprasmlist, n.location,
+ def_cgsize(n.resulttype.def), false);
+ if not cmpop then
+ location.register := n.location.register;
+ end;
+ end;
+ end;
+ end;
+
+begin
+ load_node(left);
+ load_node(right);
+ if not (cmpop) and
+ (location.register = NR_NO) then
+ begin
+ location.register := cg.getintregister(exprasmlist, OS_INT);
+ end;
+end;
+
+function tppcaddnode.getresflags: tresflags;
+begin
+ if (left.resulttype.def.deftype <> floatdef) then
+ result.cr := RS_CR0
+ else
+ result.cr := RS_CR1;
+ case nodetype of
+ equaln: result.flag := F_EQ;
+ unequaln: result.flag := F_NE;
+ else
+ if nf_swaped in flags then
+ case nodetype of
+ ltn: result.flag := F_GT;
+ lten: result.flag := F_GE;
+ gtn: result.flag := F_LT;
+ gten: result.flag := F_LE;
+ end
+ else
+ case nodetype of
+ ltn: result.flag := F_LT;
+ lten: result.flag := F_LE;
+ gtn: result.flag := F_GT;
+ gten: result.flag := F_GE;
+ end;
+ end
+end;
+
+// Todo: ts: allow emiting word compares...
+procedure tppcaddnode.emit_compare(unsigned: boolean);
+var
+ op: tasmop;
+ tmpreg: tregister;
+ useconst: boolean;
+begin
+ // get the constant on the right if there is one
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ // can we use an immediate, or do we have to load the
+ // constant in a register first?
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if (nodetype in [equaln, unequaln]) then
+ if (unsigned and
+ (aword(right.location.value) > high(word))) or
+ (not unsigned and
+ (aint(right.location.value) < low(smallint)) or
+ (aint(right.location.value) > high(smallint))) then
+ { we can then maybe use a constant in the 'othersigned' case
+ (the sign doesn't matter for // equal/unequal)}
+ unsigned := not unsigned;
+
+ if (unsigned and
+ (aword(right.location.value) <= high(word))) or
+ (not (unsigned) and
+ (aint(right.location.value) >= low(smallint)) and
+ (aint(right.location.value) <= high(smallint))) then
+ useconst := true
+ else
+ begin
+ useconst := false;
+ tmpreg := cg.getintregister(exprasmlist, OS_INT);
+ cg.a_load_const_reg(exprasmlist, OS_INT,
+ right.location.value, tmpreg);
+ end
+ end
+ else
+ useconst := false;
+ location.loc := LOC_FLAGS;
+ location.resflags := getresflags;
+ if not unsigned then
+ if useconst then
+ op := A_CMPDI
+ else
+ op := A_CMPD
+ else if useconst then
+ op := A_CMPLDI
+ else
+ op := A_CMPLD;
+
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if useconst then
+ exprasmlist.concat(taicpu.op_reg_const(op, left.location.register,
+ longint(right.location.value)))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(op, left.location.register, tmpreg));
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(op,
+ left.location.register, right.location.register));
+end;
+
+{*****************************************************************************
+ AddBoolean
+*****************************************************************************}
+
+procedure tppcaddnode.second_addboolean;
+var
+ cgop: TOpCg;
+ cgsize: TCgSize;
+ cmpop,
+ isjump: boolean;
+ otl, ofl: tasmlabel;
+begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ cmpop := false;
+ if (torddef(left.resulttype.def).typ = bool8bit) or
+ (torddef(right.resulttype.def).typ = bool8bit) then
+ cgsize := OS_8
+ else if (torddef(left.resulttype.def).typ = bool16bit) or
+ (torddef(right.resulttype.def).typ = bool16bit) then
+ cgsize := OS_16
+ else
+ cgsize := OS_32;
+
+ if (cs_full_boolean_eval in aktlocalswitches) or
+ (nodetype in [unequaln, ltn, lten, gtn, gten, equaln, xorn]) then
+ begin
+ if left.nodetype in [ordconstn, realconstn] then
+ swapleftright;
+
+ isjump := (left.expectloc = LOC_JUMP);
+ if isjump then
+ begin
+ otl := truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl := falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(left);
+ if left.location.loc in [LOC_FLAGS, LOC_JUMP] then
+ location_force_reg(exprasmlist, left.location, cgsize, false);
+ if isjump then
+ begin
+ truelabel := otl;
+ falselabel := ofl;
+ end
+ else if left.location.loc = LOC_JUMP then
+ internalerror(2003122901);
+
+ isjump := (right.expectloc = LOC_JUMP);
+ if isjump then
+ begin
+ otl := truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ ofl := falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ end;
+ secondpass(right);
+ if right.location.loc in [LOC_FLAGS, LOC_JUMP] then
+ location_force_reg(exprasmlist, right.location, cgsize, false);
+ if isjump then
+ begin
+ truelabel := otl;
+ falselabel := ofl;
+ end
+ else if right.location.loc = LOC_JUMP then
+ internalerror(200312292);
+
+ cmpop := nodetype in [ltn, lten, gtn, gten, equaln, unequaln];
+
+ { set result location }
+ if not cmpop then
+ location_reset(location, LOC_REGISTER, def_cgsize(resulttype.def))
+ else
+ location_reset(location, LOC_FLAGS, OS_NO);
+
+ load_left_right(cmpop, false);
+
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+
+ { compare the }
+ case nodetype of
+ ltn, lten, gtn, gten,
+ equaln, unequaln:
+ begin
+ if (right.location.loc <> LOC_CONSTANT) then
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
+ left.location.register, right.location.register))
+ else
+ exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
+ left.location.register, longint(right.location.value)));
+ location.resflags := getresflags;
+ end;
+ else
+ begin
+ case nodetype of
+ xorn:
+ cgop := OP_XOR;
+ orn:
+ cgop := OP_OR;
+ andn:
+ cgop := OP_AND;
+ else
+ internalerror(200203247);
+ end;
+
+ if right.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(exprasmlist, cgop, OS_INT,
+ left.location.register, right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(exprasmlist, cgop, OS_INT,
+ right.location.value, left.location.register,
+ location.register);
+ end;
+ end;
+ end
+ else
+ begin
+ // just to make sure we free the right registers
+ cmpop := true;
+ case nodetype of
+ andn,
+ orn:
+ begin
+ location_reset(location, LOC_JUMP, OS_NO);
+ case nodetype of
+ andn:
+ begin
+ otl := truelabel;
+ objectlibrary.getjumplabel(truelabel);
+ secondpass(left);
+ maketojumpbool(exprasmlist, left, lr_load_regvars);
+ cg.a_label(exprasmlist, truelabel);
+ truelabel := otl;
+ end;
+ orn:
+ begin
+ ofl := falselabel;
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ maketojumpbool(exprasmlist, left, lr_load_regvars);
+ cg.a_label(exprasmlist, falselabel);
+ falselabel := ofl;
+ end;
+ else
+ internalerror(200403181);
+ end;
+ secondpass(right);
+ maketojumpbool(exprasmlist, right, lr_load_regvars);
+ end;
+ end;
+ end;
+end;
+
+{*****************************************************************************
+ AddFloat
+*****************************************************************************}
+
+procedure tppcaddnode.second_addfloat;
+var
+ op: TAsmOp;
+ cmpop: boolean;
+begin
+ pass_left_and_right;
+
+ cmpop := false;
+ case nodetype of
+ addn:
+ op := A_FADD;
+ muln:
+ op := A_FMUL;
+ subn:
+ op := A_FSUB;
+ slashn:
+ op := A_FDIV;
+ ltn, lten, gtn, gten,
+ equaln, unequaln:
+ begin
+ op := A_FCMPO;
+ cmpop := true;
+ end;
+ else
+ internalerror(200403182);
+ end;
+
+ // get the operands in the correct order, there are no special cases
+ // here, everything is register-based
+ if nf_swaped in flags then
+ swapleftright;
+
+ // put both operands in a register
+ location_force_fpureg(exprasmlist, right.location, true);
+ location_force_fpureg(exprasmlist, left.location, true);
+
+ // initialize de result
+ if not cmpop then
+ begin
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resulttype.def));
+ if left.location.loc = LOC_FPUREGISTER then
+ location.register := left.location.register
+ else if right.location.loc = LOC_FPUREGISTER then
+ location.register := right.location.register
+ else
+ location.register := cg.getfpuregister(exprasmlist, location.size);
+ end
+ else
+ begin
+ location_reset(location, LOC_FLAGS, OS_NO);
+ location.resflags := getresflags;
+ end;
+
+ // emit the actual operation
+ if not cmpop then
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op,
+ location.register, left.location.register,
+ right.location.register))
+ end
+ else
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op,
+ newreg(R_SPECIALREGISTER, location.resflags.cr, R_SUBNONE),
+ left.location.register, right.location.register))
+ end;
+end;
+
+{*****************************************************************************
+ AddSmallSet
+*****************************************************************************}
+
+procedure tppcaddnode.second_addsmallset;
+var
+ cgop: TOpCg;
+ tmpreg: tregister;
+ opdone,
+ cmpop: boolean;
+
+ astring : string;
+ // ts: todo - speed up by using 32 bit compares/adds/ands here
+begin
+ pass_left_and_right;
+
+ { when a setdef is passed, it has to be a smallset }
+ if ((left.resulttype.def.deftype = setdef) and
+ (tsetdef(left.resulttype.def).settype <> smallset)) or
+ ((right.resulttype.def.deftype = setdef) and
+ (tsetdef(right.resulttype.def).settype <> smallset)) then
+ internalerror(200203301);
+
+ opdone := false;
+ cmpop := nodetype in [equaln, unequaln, lten, gten];
+
+ { set result location }
+ if not cmpop then
+ location_reset(location, LOC_REGISTER, def_cgsize(resulttype.def))
+ else
+ location_reset(location, LOC_FLAGS, OS_NO);
+
+ load_left_right(cmpop, false);
+
+ if not (cmpop) and
+ (location.register = NR_NO) then
+ location.register := cg.getintregister(exprasmlist, OS_64);
+
+ astring := 'addsmallset0 ' + inttostr(aword(1) shl aword(right.location.value)) + ' ' + inttostr(right.location.value);
+ exprasmlist.concat(tai_comment.create(strpnew(astring)));
+
+
+ case nodetype of
+ addn:
+ begin
+ if (nf_swaped in flags) and (left.nodetype = setelementn) then
+ swapleftright;
+ { are we adding set elements ? }
+ if right.nodetype = setelementn then begin
+ { no range support for smallsets! }
+ if assigned(tsetelementnode(right).right) then
+ internalerror(43244);
+ if (right.location.loc = LOC_CONSTANT) then begin
+
+ astring := 'addsmallset1 ' + inttostr(aword(1) shl aword(right.location.value)) + ' ' + inttostr(right.location.value);
+ exprasmlist.concat(tai_comment.create(strpnew(astring)));
+
+
+ cg.a_op_const_reg_reg(exprasmlist, OP_OR, OS_64,
+ aint(1) shl aint(right.location.value),
+ left.location.register, location.register)
+ end else
+ begin
+ tmpreg := cg.getintregister(exprasmlist, OS_64);
+ cg.a_load_const_reg(exprasmlist, OS_64, 1, tmpreg);
+ cg.a_op_reg_reg(exprasmlist, OP_SHL, OS_64,
+ right.location.register, tmpreg);
+ if left.location.loc <> LOC_CONSTANT then begin
+
+ cg.a_op_reg_reg_reg(exprasmlist, OP_OR, OS_64, tmpreg,
+ left.location.register, location.register)
+ end else begin
+ astring := 'addsmallset2 ' + inttostr(left.location.value);
+ exprasmlist.concat(tai_comment.create(strpnew(astring)));
+
+ cg.a_op_const_reg_reg(exprasmlist, OP_OR, OS_64,
+ left.location.value, tmpreg, location.register);
+ end;
+ end;
+ opdone := true;
+ end else begin
+ cgop := OP_OR;
+ end;
+ end;
+ symdifn:
+ cgop := OP_XOR;
+ muln:
+ cgop := OP_AND;
+ subn:
+ begin
+ cgop := OP_AND;
+ if (not (nf_swaped in flags)) then
+ if (right.location.loc = LOC_CONSTANT) then
+ right.location.value := not (right.location.value)
+ else
+ opdone := true
+ else if (left.location.loc = LOC_CONSTANT) then
+ left.location.value := not (left.location.value)
+ else begin
+ swapleftright;
+ opdone := true;
+ end;
+ if opdone then begin
+ if left.location.loc = LOC_CONSTANT then
+ begin
+ tmpreg := cg.getintregister(exprasmlist, OS_64);
+ cg.a_load_const_reg(exprasmlist, OS_64,
+ left.location.value, tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
+ location.register, tmpreg, right.location.register));
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
+ location.register, left.location.register,
+ right.location.register));
+ end;
+ end;
+ equaln,
+ unequaln:
+ begin
+ emit_compare(true);
+ opdone := true;
+ end;
+ lten, gten:
+ begin
+ if (not (nf_swaped in flags) and
+ (nodetype = lten)) or
+ ((nf_swaped in flags) and
+ (nodetype = gten)) then
+ swapleftright;
+ // now we have to check whether left >= right
+ tmpreg := cg.getintregister(exprasmlist, OS_64);
+ if left.location.loc = LOC_CONSTANT then begin
+ cg.a_op_const_reg_reg(exprasmlist, OP_AND, OS_64,
+ not (left.location.value), right.location.register, tmpreg);
+ exprasmlist.concat(taicpu.op_reg_const(A_CMPDI, tmpreg, 0));
+ // the two instructions above should be folded together by
+ // the peepholeoptimizer
+ end else begin
+ if right.location.loc = LOC_CONSTANT then begin
+ cg.a_load_const_reg(exprasmlist, OS_64,
+ right.location.value, tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_, tmpreg,
+ tmpreg, left.location.register));
+ end else
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_, tmpreg,
+ right.location.register, left.location.register));
+ end;
+ location.resflags.cr := RS_CR0;
+ location.resflags.flag := F_EQ;
+ opdone := true;
+ end;
+ else
+ internalerror(2002072701);
+ end;
+
+ if not opdone then begin
+ // these are all commutative operations
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then begin
+ astring := 'addsmallset4 ' + inttostr(right.location.value);
+ exprasmlist.concat(tai_comment.create(strpnew(astring)));
+
+ cg.a_op_const_reg_reg(exprasmlist, cgop, OS_64,
+ right.location.value, left.location.register,
+ location.register)
+ end else begin
+ cg.a_op_reg_reg_reg(exprasmlist, cgop, OS_64,
+ right.location.register, left.location.register,
+ location.register);
+ end;
+ end;
+end;
+
+{*****************************************************************************
+ pass_2
+*****************************************************************************}
+
+procedure tppcaddnode.pass_2;
+{ is also being used for xor, and "mul", "sub, or and comparative }
+{ operators }
+var
+ cgop: topcg;
+ op: tasmop;
+ tmpreg: tregister;
+ hl: tasmlabel;
+ cmpop: boolean;
+
+ { true, if unsigned types are compared }
+ unsigned: boolean;
+
+begin
+ { to make it more readable, string and set (not smallset!) have their
+ own procedures }
+ case left.resulttype.def.deftype of
+ orddef:
+ begin
+ { handling boolean expressions }
+ if is_boolean(left.resulttype.def) and
+ is_boolean(right.resulttype.def) then
+ begin
+ second_addboolean;
+ exit;
+ end;
+ end;
+ stringdef:
+ begin
+ internalerror(2002072402);
+ exit;
+ end;
+ setdef:
+ begin
+ { normalsets are already handled in pass1 }
+ if (tsetdef(left.resulttype.def).settype <> smallset) then
+ internalerror(200109041);
+ second_addsmallset;
+ exit;
+ end;
+ arraydef:
+ begin
+{$IFDEF SUPPORT_MMX}
+ if is_mmx_able_array(left.resulttype.def) then
+ begin
+ second_addmmx;
+ exit;
+ end;
+{$ENDIF SUPPORT_MMX}
+ end;
+ floatdef:
+ begin
+ second_addfloat;
+ exit;
+ end;
+ end;
+
+ { defaults }
+ cmpop := nodetype in [ltn, lten, gtn, gten, equaln, unequaln];
+ unsigned := not (is_signed(left.resulttype.def)) or
+ not (is_signed(right.resulttype.def));
+
+ pass_left_and_right;
+
+ { Convert flags to register first }
+ { can any of these things be in the flags actually?? (JM) }
+
+ if (left.location.loc = LOC_FLAGS) or
+ (right.location.loc = LOC_FLAGS) then
+ internalerror(2002072602);
+
+ { set result location }
+ if not cmpop then
+ location_reset(location, LOC_REGISTER, def_cgsize(resulttype.def))
+ else
+ location_reset(location, LOC_FLAGS, OS_NO);
+
+ load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
+ (nodetype in [addn, subn, muln]));
+
+ if (location.register = NR_NO) and
+ not (cmpop) then
+ location.register := cg.getintregister(exprasmlist, OS_INT);
+
+ if not (cs_check_overflow in aktlocalswitches) or
+ (cmpop) or
+ (nodetype in [orn, andn, xorn]) then
+ begin
+ case nodetype of
+ addn, muln, xorn, orn, andn:
+ begin
+ case nodetype of
+ addn:
+ cgop := OP_ADD;
+ muln:
+ if unsigned then
+ cgop := OP_MUL
+ else
+ cgop := OP_IMUL;
+ xorn:
+ cgop := OP_XOR;
+ orn:
+ cgop := OP_OR;
+ andn:
+ cgop := OP_AND;
+ end;
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc <> LOC_CONSTANT) then
+ cg.a_op_reg_reg_reg(exprasmlist, cgop, OS_INT,
+ left.location.register, right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(exprasmlist, cgop, OS_INT,
+ right.location.value, left.location.register,
+ location.register);
+ end;
+ subn:
+ begin
+ if (nf_swaped in flags) then
+ swapleftright;
+ if left.location.loc <> LOC_CONSTANT then
+ if right.location.loc <> LOC_CONSTANT then begin
+ cg.a_op_reg_reg_reg(exprasmlist, OP_SUB, OS_INT,
+ right.location.register, left.location.register,
+ location.register);
+ end else begin
+ cg.a_op_const_reg_reg(exprasmlist, OP_SUB, OS_INT,
+ right.location.value, left.location.register,
+ location.register);
+ end
+ else
+ begin
+ tmpreg := cg.getintregister(exprasmlist, OS_INT);
+ cg.a_load_const_reg(exprasmlist, OS_INT,
+ left.location.value, tmpreg);
+ cg.a_op_reg_reg_reg(exprasmlist, OP_SUB, OS_INT,
+ right.location.register, tmpreg, location.register);
+ end;
+ end;
+ ltn, lten, gtn, gten, equaln, unequaln:
+ begin
+ emit_compare(unsigned);
+ end;
+ end;
+ end
+ else
+ // overflow checking is on and we have an addn, subn or muln
+ begin
+ if is_signed(resulttype.def) then
+ begin
+ case nodetype of
+ addn:
+ op := A_ADDO;
+ subn:
+ begin
+ op := A_SUBO;
+ if (nf_swaped in flags) then
+ swapleftright;
+ end;
+ muln:
+ op := A_MULLDO;
+ else
+ internalerror(2002072601);
+ end;
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op, location.register,
+ left.location.register, right.location.register));
+ cg.g_overflowcheck(exprasmlist, location, resulttype.def);
+ end
+ else
+ begin
+ case nodetype of
+ addn:
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD, location.register,
+ left.location.register, right.location.register));
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMPLD, location.register,
+ left.location.register));
+ cg.g_overflowcheck(exprasmlist, location, resulttype.def);
+ end;
+ subn:
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB, location.register,
+ left.location.register, right.location.register));
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMPLD,
+ left.location.register, location.register));
+ cg.g_overflowcheck(exprasmlist, location, resulttype.def);
+ end;
+ muln:
+ begin
+ { calculate the upper 64 bits of the product, = 0 if no overflow }
+ cg.a_reg_alloc(exprasmlist, NR_R0);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHDU_, NR_R0,
+ left.location.register, right.location.register));
+ cg.a_reg_dealloc(exprasmlist, NR_R0);
+ { calculate the real result }
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLD, location.register,
+ left.location.register, right.location.register));
+ { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
+ objectlibrary.getjumplabel(hl);
+ tcgppc(cg).a_jmp_cond(exprasmlist, OC_EQ, hl);
+ cg.a_call_name(exprasmlist, 'FPC_OVERFLOW');
+ cg.a_label(exprasmlist, hl);
+ end;
+ end;
+ end;
+ end;
+end;
+
+begin
+ caddnode := tppcaddnode;
+end.
+
diff --git a/compiler/powerpc64/nppccal.pas b/compiler/powerpc64/nppccal.pas
new file mode 100644
index 0000000000..b8f947f158
--- /dev/null
+++ b/compiler/powerpc64/nppccal.pas
@@ -0,0 +1,51 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the PowerPC specific part of call 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 bymethodpointer
+ 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 nppccal;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ symdef, node, ncal, ncgcal;
+
+type
+ tppccallnode = class(tcgcallnode)
+ end;
+
+implementation
+
+uses
+ globtype, systems,
+ cutils, verbose, globals,
+ symconst, symbase, symsym, symtable, defutil, paramgr, parabase,
+ cgbase, pass_2,
+ cpuinfo, cpubase, aasmbase, aasmtai, aasmcpu,
+ nmem, nld, ncnv,
+ ncgutil, cgutils, cgobj, tgobj, regvars, rgobj, rgcpu,
+ cgcpu, cpupi, procinfo;
+
+
+begin
+ ccallnode := tppccallnode;
+end.
+
diff --git a/compiler/powerpc64/nppccnv.pas b/compiler/powerpc64/nppccnv.pas
new file mode 100644
index 0000000000..7cdcf2a434
--- /dev/null
+++ b/compiler/powerpc64/nppccnv.pas
@@ -0,0 +1,303 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for type converting 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 nppccnv;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, ncnv, ncgcnv, defcmp;
+
+type
+ tppctypeconvnode = class(tcgtypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real; override;
+ { procedure second_real_to_real; override;}
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool; override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+uses
+ verbose, globtype, globals, systems,
+ symconst, symdef, aasmbase, aasmtai,
+ defutil,
+ cgbase, cgutils, pass_1, pass_2,
+ ncon, ncal,
+ ncgutil,
+ cpubase, aasmcpu,
+ rgobj, tgobj, cgobj;
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+function tppctypeconvnode.first_int_to_real: tnode;
+begin
+ if (is_currency(left.resulttype.def)) then begin
+ // hack to avoid double division by 10000, as it's
+ // already done by resulttypepass.resulttype_int_to_real
+ left.resulttype := s64inttype;
+ end else begin
+ // everything that is less than 64 bits is converted to a 64 bit signed
+ // integer - because the int_to_real conversion is faster for 64 bit
+ // signed ints compared to 64 bit unsigned ints.
+ if (not (torddef(left.resulttype.def).typ in [s64bit, u64bit])) then begin
+ inserttypeconv(left, s64inttype);
+ end;
+ end;
+ firstpass(left);
+ result := nil;
+ if registersfpu < 1 then
+ registersfpu := 1;
+ expectloc := LOC_FPUREGISTER;
+end;
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+procedure tppctypeconvnode.second_int_to_real;
+const
+ convconst : double = $100000000;
+var
+ tempconst : trealconstnode;
+ disp, disp2: treference;
+ // temp registers for converting signed ints
+ valuereg, leftreg,
+ // additional temp registers for converting unsigned 64 bit ints
+ tmpintreg1, tmpintreg2, tmpfpureg, tmpfpuconst : tregister;
+ size: tcgsize;
+ signed: boolean;
+begin
+
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resulttype.def));
+
+ { the code here comes from the PowerPC Compiler Writer's Guide }
+ { * longint to double (works for all rounding modes) }
+ { std R3,disp(R1) # store doubleword }
+ { lfd FR1,disp(R1) # load float double }
+ { fcfid FR1,FR1 # convert to floating-point integer }
+
+ { * unsigned 64 bit int to fp value (works for all rounding modes) }
+ { rldicl rT1,rS,32,32 # isolate high half }
+ { rldicl rT2,rS,0,32 # isolate low half }
+ { std rT1,disp(R1) # store high half }
+ { std rT2,disp+8(R1) # store low half }
+ { lfd frT1,disp(R1) # load high half }
+ { lfd frD,disp+8(R1) # load low half }
+ { fcfid frT1,frT1 # convert each half to floating }
+ { fcfid frD,frD # point integer (no round) }
+ { fmadd frD,frC,frT1,frD # (2^32)*high + low }
+ { # (only add can round) }
+ tg.Gettemp(exprasmlist, 8, tt_normal, disp);
+
+ { do the signed case for everything but 64 bit unsigned integers }
+ signed := (left.location.size <> OS_64);
+
+ { we need a certain constant for the conversion of unsigned 64 bit integers,
+ so create them here. Additonally another temporary location is neeted }
+ if (not signed) then begin
+ // allocate temp for constant value used for unsigned 64 bit ints
+ tempconst :=
+ crealconstnode.create(convconst, pbestrealtype^);
+ resulttypepass(tempconst);
+ firstpass(tempconst);
+ secondpass(tempconst);
+ if (tempconst.location.loc <> LOC_CREFERENCE) then
+ internalerror(200110011);
+
+ // allocate second temp memory
+ tg.Gettemp(exprasmlist, 8, tt_normal, disp2);
+ end;
+
+ case left.location.loc of
+ // the conversion algorithm does not modify the input register, so it can
+ // be used for both LOC_REGISTER and LOC_CREGISTER
+ LOC_REGISTER, LOC_CREGISTER:
+ begin
+ leftreg := left.location.register;
+ valuereg := leftreg;
+ end;
+ LOC_REFERENCE, LOC_CREFERENCE:
+ begin
+ leftreg := cg.getintregister(exprasmlist, OS_INT);
+ valuereg := leftreg;
+ if signed then
+ size := OS_S64
+ else
+ size := OS_64;
+ cg.a_load_ref_reg(exprasmlist, def_cgsize(left.resulttype.def),
+ size, left.location.reference, leftreg);
+ end
+ else
+ internalerror(200110012);
+ end;
+
+ if (signed) then begin
+ // std rS, disp(r1)
+ cg.a_load_reg_ref(exprasmlist, OS_S64, OS_S64, valuereg, disp);
+ // lfd frD, disp(r1)
+ location.register := cg.getfpuregister(exprasmlist,OS_F64);
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F64, disp, location.register);
+ // fcfid frD, frD
+ exprasmlist.concat(taicpu.op_reg_reg(A_FCFID, location.register,
+ location.register));
+ end else begin
+ { ts:todo use TOC for this constant or at least schedule better }
+ // lfd frC, const
+ tmpfpuconst := cg.getfpuregister(exprasmlist,OS_F64);
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F64,tempconst.location.reference,
+ tmpfpuconst);
+ tempconst.free;
+
+ tmpintreg1 := cg.getintregister(exprasmlist, OS_64);
+ // rldicl rT1, rS, 32, 32
+ exprasmlist.concat(taicpu.op_reg_reg_const_const(A_RLDICL, tmpintreg1, valuereg, 32, 32));
+ // rldicl rT2, rS, 0, 32
+ tmpintreg2 := cg.getintregister(exprasmlist, OS_64);
+ exprasmlist.concat(taicpu.op_reg_reg_const_const(A_RLDICL, tmpintreg2, valuereg, 0, 32));
+
+ // std rT1, disp(r1)
+ cg.a_load_reg_ref(exprasmlist, OS_S64, OS_S64, tmpintreg1, disp);
+ // std rT2, disp2(r1)
+ cg.a_load_reg_ref(exprasmlist, OS_S64, OS_S64, tmpintreg2, disp2);
+
+ // lfd frT1, disp(R1)
+ tmpfpureg := cg.getfpuregister(exprasmlist,OS_F64);
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F64, disp, tmpfpureg);
+ // lfd frD, disp+8(R1)
+ location.register := cg.getfpuregister(exprasmlist,OS_F64);
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F64, disp2, location.register);
+
+ // fcfid frT1, frT1
+ exprasmlist.concat(taicpu.op_reg_reg(A_FCFID, tmpfpureg,
+ tmpfpureg));
+ // fcfid frD, frD
+ exprasmlist.concat(taicpu.op_reg_reg(A_FCFID, location.register,
+ location.register));
+ // fmadd frD,frC,frT1,frD # (2^32)*high + low }
+ exprasmlist.concat(taicpu.op_reg_reg_reg_reg(A_FMADD, location.register, tmpfpuconst,
+ tmpfpureg, location.register));
+
+ // free used temps
+ tg.ungetiftemp(exprasmlist, disp2);
+ end;
+ // free reference
+ tg.ungetiftemp(exprasmlist, disp);
+
+end;
+
+procedure tppctypeconvnode.second_int_to_bool;
+var
+ hreg1,
+ hreg2: tregister;
+ resflags: tresflags;
+ opsize: tcgsize;
+ hlabel, oldtruelabel, oldfalselabel: tasmlabel;
+begin
+ oldtruelabel := truelabel;
+ oldfalselabel := falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { byte(boolean) or word(wordbool) or longint(longbool) must }
+ { be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resulttype.def.size = resulttype.def.size) and
+ (left.location.loc in [LOC_REFERENCE, LOC_CREFERENCE, LOC_CREGISTER]) then
+ begin
+ truelabel := oldtruelabel;
+ falselabel := oldfalselabel;
+ location_copy(location, left.location);
+ exit;
+ end;
+
+ location_reset(location, LOC_REGISTER, def_cgsize(resulttype.def));
+ opsize := def_cgsize(left.resulttype.def);
+ case left.location.loc of
+ LOC_CREFERENCE, LOC_REFERENCE, LOC_REGISTER, LOC_CREGISTER:
+ begin
+ if left.location.loc in [LOC_CREFERENCE, LOC_REFERENCE] then
+ begin
+ hreg1 := cg.getintregister(exprasmlist, OS_INT);
+ cg.a_load_ref_reg(exprasmlist, opsize, opsize,
+ left.location.reference, hreg1);
+ end
+ else
+ begin
+ hreg1 := left.location.register;
+ end;
+ hreg2 := cg.getintregister(exprasmlist, OS_INT);
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBIC, hreg2, hreg1, 1));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE, hreg1, hreg2, hreg1));
+ end;
+ LOC_FLAGS:
+ begin
+ hreg1 := cg.getintregister(exprasmlist, OS_INT);
+ resflags := left.location.resflags;
+ cg.g_flags2reg(exprasmlist, location.size, resflags, hreg1);
+ end;
+ LOC_JUMP:
+ begin
+ hreg1 := cg.getintregister(exprasmlist, OS_INT);
+ objectlibrary.getjumplabel(hlabel);
+ cg.a_label(exprasmlist, truelabel);
+ cg.a_load_const_reg(exprasmlist, OS_INT, 1, hreg1);
+ cg.a_jmp_always(exprasmlist, hlabel);
+ cg.a_label(exprasmlist, falselabel);
+ cg.a_load_const_reg(exprasmlist, OS_INT, 0, hreg1);
+ cg.a_label(exprasmlist, hlabel);
+ end;
+ else
+ internalerror(10062);
+ end;
+ location.register := hreg1;
+ truelabel := oldtruelabel;
+ falselabel := oldfalselabel;
+end;
+
+begin
+ ctypeconvnode := tppctypeconvnode;
+end.
+
diff --git a/compiler/powerpc64/nppcinl.pas b/compiler/powerpc64/nppcinl.pas
new file mode 100644
index 0000000000..5d758db142
--- /dev/null
+++ b/compiler/powerpc64/nppcinl.pas
@@ -0,0 +1,148 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 inline 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 nppcinl;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, ninl, ncginl;
+
+type
+ tppcinlinenode = class(tcginlinenode)
+ { first pass override
+ so that the code generator will actually generate
+ these nodes.
+ }
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_prefetch; override;
+ private
+ procedure load_fpu_location;
+ end;
+
+implementation
+
+uses
+ cutils, globals, verbose,
+ aasmtai, aasmcpu,
+ symconst, symdef,
+ defutil,
+ cgbase, pass_2,
+ cpubase, ncgutil,
+ cgutils, cgobj, rgobj;
+
+{*****************************************************************************
+ TPPCINLINENODE
+*****************************************************************************}
+
+function tppcinlinenode.first_abs_real: tnode;
+begin
+ expectloc := LOC_FPUREGISTER;
+ registersint := left.registersint;
+ registersfpu := max(left.registersfpu, 1);
+{$IFDEF SUPPORT_MMX}
+ registersmmx := left.registersmmx;
+{$ENDIF SUPPORT_MMX}
+ first_abs_real := nil;
+end;
+
+function tppcinlinenode.first_sqr_real: tnode;
+begin
+ expectloc := LOC_FPUREGISTER;
+ registersint := left.registersint;
+ registersfpu := max(left.registersfpu, 1);
+{$IFDEF SUPPORT_MMX}
+ registersmmx := left.registersmmx;
+{$ENDIF SUPPORT_MMX}
+ first_sqr_real := nil;
+end;
+
+{ load the FPU into the an fpu register }
+
+procedure tppcinlinenode.load_fpu_location;
+begin
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resulttype.def));
+ secondpass(left);
+ location_force_fpureg(exprasmlist, left.location, true);
+ location_copy(location, left.location);
+ if (location.loc = LOC_CFPUREGISTER) then
+ begin
+ location.loc := LOC_FPUREGISTER;
+ location.register := cg.getfpuregister(exprasmlist, OS_F64);
+ end;
+end;
+
+procedure tppcinlinenode.second_abs_real;
+begin
+ location.loc := LOC_FPUREGISTER;
+ load_fpu_location;
+ exprasmlist.concat(taicpu.op_reg_reg(A_FABS, location.register,
+ left.location.register));
+end;
+
+procedure tppcinlinenode.second_sqr_real;
+begin
+ location.loc := LOC_FPUREGISTER;
+ load_fpu_location;
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_FMUL, location.register,
+ left.location.register, left.location.register));
+end;
+
+procedure tppcinlinenode.second_prefetch;
+var
+ r: tregister;
+begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ r := cg.getintregister(exprasmlist, OS_ADDR);
+ if (left.location.reference.offset = 0) and
+ not assigned(left.location.reference.symbol) then
+ begin
+ if (left.location.reference.index = NR_NO) then
+ exprasmlist.concat(taicpu.op_const_reg(A_DCBT, 0,
+ left.location.reference.base))
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(A_DCBT,
+ left.location.reference.base, left.location.reference.index));
+ end
+ else
+ begin
+ cg.a_loadaddr_ref_reg(exprasmlist, left.location.reference, r);
+ exprasmlist.concat(taicpu.op_const_reg(A_DCBT, 0, r));
+ end;
+ end;
+ else
+ internalerror(200402021);
+ end;
+end;
+
+begin
+ cinlinenode := tppcinlinenode;
+end.
+
diff --git a/compiler/powerpc64/nppcld.pas b/compiler/powerpc64/nppcld.pas
new file mode 100644
index 0000000000..f60c3c50cf
--- /dev/null
+++ b/compiler/powerpc64/nppcld.pas
@@ -0,0 +1,62 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate ppc assembler for nodes that handle loads and assignments
+
+ 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 nppcld;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, ncgld;
+
+type
+ tppcloadnode = class(tcgloadnode)
+ procedure pass_2; override;
+ procedure generate_picvaraccess; override;
+ end;
+
+implementation
+
+uses
+ verbose,
+ systems,
+ cpubase,
+ cgutils, cgobj,
+ aasmbase, aasmtai,
+ symconst, symsym,
+ procinfo,
+ nld;
+
+procedure tppcloadnode.pass_2;
+begin
+ inherited pass_2;
+end;
+
+procedure tppcloadnode.generate_picvaraccess;
+begin
+ internalerror(200402291);
+end;
+
+begin
+ cloadnode := tppcloadnode;
+end.
+
diff --git a/compiler/powerpc64/nppcmat.pas b/compiler/powerpc64/nppcmat.pas
new file mode 100644
index 0000000000..b5809bbbba
--- /dev/null
+++ b/compiler/powerpc64/nppcmat.pas
@@ -0,0 +1,376 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for math 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 nppcmat;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, nmat;
+
+type
+ tppcmoddivnode = class(tmoddivnode)
+ function pass_1: tnode; override;
+ procedure pass_2; override;
+ end;
+
+ tppcshlshrnode = class(tshlshrnode)
+ procedure pass_2; override;
+ end;
+
+ tppcunaryminusnode = class(tunaryminusnode)
+ procedure pass_2; override;
+ end;
+
+ tppcnotnode = class(tnotnode)
+ procedure pass_2; override;
+ end;
+
+implementation
+
+uses
+ globtype, systems,
+ cutils, verbose, globals,
+ symconst, symdef,
+ aasmbase, aasmcpu, aasmtai,
+ defutil,
+ cgbase, cgutils, cgobj, pass_1, pass_2,
+ ncon, procinfo,
+ cpubase, cpuinfo,
+ ncgutil, cgcpu, rgobj;
+
+{*****************************************************************************
+ TPPCMODDIVNODE
+*****************************************************************************}
+
+function tppcmoddivnode.pass_1: tnode;
+begin
+ result := inherited pass_1;
+ if not assigned(result) then
+ include(current_procinfo.flags, pi_do_call);
+end;
+
+procedure tppcmoddivnode.pass_2;
+const
+ // ts: todo, use 32 bit operations if possible (much faster!)
+ { signed overflow }
+ divops: array[boolean, boolean] of tasmop =
+ ((A_DIVDU, A_DIVDUO_), (A_DIVD, A_DIVDO_));
+ zerocond: tasmcond = (dirhint: DH_Plus; simple: true; cond: C_NE; cr: RS_CR1);
+var
+ power: longint;
+ op: tasmop;
+ numerator,
+ divider,
+ resultreg: tregister;
+ size: Tcgsize;
+ hl: tasmlabel;
+
+begin
+ secondpass(left);
+ secondpass(right);
+ location_copy(location, left.location);
+
+ { put numerator in register }
+ size := def_cgsize(left.resulttype.def);
+ location_force_reg(exprasmlist, left.location,
+ size, true);
+ location_copy(location, left.location);
+ numerator := location.register;
+ resultreg := location.register;
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(exprasmlist, size);
+ resultreg := location.register;
+ end;
+ if (nodetype = modn) then
+ begin
+ resultreg := cg.getintregister(exprasmlist, size);
+ end;
+
+ if (nodetype = divn) and
+ (right.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(right).value, power) then
+ begin
+ if (is_signed(right.resulttype.def)) then begin
+ { From "The PowerPC Compiler Writer's Guide": }
+ { This code uses the fact that, in the PowerPC architecture, }
+ { the shift right algebraic instructions set the Carry bit if }
+ { the source register contains a negative number and one or }
+ { more 1-bits are shifted out. Otherwise, the carry bit is }
+ { cleared. The addze instruction corrects the quotient, if }
+ { necessary, when the dividend is negative. For example, if }
+ { n = -13, (0xFFFF_FFF3), and k = 2, after executing the srawi }
+ { instruction, q = -4 (0xFFFF_FFFC) and CA = 1. After executing }
+ { the addze instruction, q = -3, the correct quotient. }
+ cg.a_op_const_reg_reg(exprasmlist, OP_SAR, OS_64, power,
+ numerator, resultreg);
+ exprasmlist.concat(taicpu.op_reg_reg(A_ADDZE, resultreg, resultreg));
+ end else begin
+ cg.a_op_const_reg_reg(exprasmlist, OP_SHR, OS_INT, power, numerator, resultreg);
+ end;
+ end
+ else
+ begin
+ { load divider in a register if necessary }
+ location_force_reg(exprasmlist, right.location,
+ def_cgsize(right.resulttype.def), true);
+ if (right.nodetype <> ordconstn) then
+{$NOTE ts: testme}
+ exprasmlist.concat(taicpu.op_reg_reg_const(A_CMPDI, NR_CR1,
+ right.location.register, 0));
+ divider := right.location.register;
+
+ { needs overflow checking, (-maxlongint-1) div (-1) overflows! }
+ { And on PPC, the only way to catch a div-by-0 is by checking }
+ { the overflow flag (JM) }
+ op := divops[is_signed(right.resulttype.def),
+ cs_check_overflow in aktlocalswitches];
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op, resultreg, numerator,
+ divider));
+
+ if (nodetype = modn) then
+ begin
+{$NOTE ts:testme}
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLD, resultreg,
+ divider, resultreg));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB, location.register,
+ numerator, resultreg));
+ resultreg := location.register;
+ end;
+ end;
+ { set result location }
+ location.loc := LOC_REGISTER;
+ location.register := resultreg;
+ if right.nodetype <> ordconstn then
+ begin
+ objectlibrary.getjumplabel(hl);
+ exprasmlist.concat(taicpu.op_cond_sym(A_BC, zerocond, hl));
+ cg.a_call_name(exprasmlist, 'FPC_DIVBYZERO');
+ cg.a_label(exprasmlist, hl);
+ end;
+ cg.g_overflowcheck(exprasmlist, location, resulttype.def);
+end;
+
+{*****************************************************************************
+ TPPCSHLRSHRNODE
+*****************************************************************************}
+
+
+procedure tppcshlshrnode.pass_2;
+
+var
+ resultreg, hregister1, hregister2,
+ hreg64hi, hreg64lo: tregister;
+ op: topcg;
+ asmop1, asmop2: tasmop;
+ shiftval: aint;
+
+begin
+ secondpass(left);
+ secondpass(right);
+
+ { load left operators in a register }
+ location_force_reg(exprasmlist, left.location,
+ def_cgsize(left.resulttype.def), true);
+ location_copy(location, left.location);
+ resultreg := location.register;
+ hregister1 := location.register;
+ if (location.loc = LOC_CREGISTER) then begin
+ location.loc := LOC_REGISTER;
+ resultreg := cg.getintregister(exprasmlist, OS_64);
+ location.register := resultreg;
+ end;
+
+ { determine operator }
+ if nodetype = shln then
+ op := OP_SHL
+ else
+ op := OP_SHR;
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype = ordconstn) then begin
+ // result types with size < 32 bits have their shift values masked
+ // differently... :/
+ shiftval := tordconstnode(right).value and (tcgsize2size[def_cgsize(resulttype.def)] * 8 -1);
+ cg.a_op_const_reg_reg(exprasmlist, op, def_cgsize(resulttype.def),
+ shiftval, hregister1, resultreg)
+ end else begin
+ { load shift count in a register if necessary }
+ location_force_reg(exprasmlist, right.location,
+ def_cgsize(right.resulttype.def), true);
+ hregister2 := right.location.register;
+ cg.a_op_reg_reg_reg(exprasmlist, op, def_cgsize(resulttype.def), hregister2,
+ hregister1, resultreg);
+ end;
+end;
+
+{*****************************************************************************
+ TPPCUNARYMINUSNODE
+*****************************************************************************}
+
+procedure tppcunaryminusnode.pass_2;
+
+var
+ src1: tregister;
+ op: tasmop;
+
+begin
+ secondpass(left);
+ begin
+ location_copy(location, left.location);
+ location.loc := LOC_REGISTER;
+ case left.location.loc of
+ LOC_FPUREGISTER, LOC_REGISTER:
+ begin
+ src1 := left.location.register;
+ location.register := src1;
+ end;
+ LOC_CFPUREGISTER, LOC_CREGISTER:
+ begin
+ src1 := left.location.register;
+ if left.location.loc = LOC_CREGISTER then
+ location.register := cg.getintregister(exprasmlist, OS_INT)
+ else
+ location.register := cg.getfpuregister(exprasmlist, location.size);
+ end;
+ LOC_REFERENCE, LOC_CREFERENCE:
+ begin
+ if (left.resulttype.def.deftype = floatdef) then
+ begin
+ src1 := cg.getfpuregister(exprasmlist,
+ def_cgsize(left.resulttype.def));
+ location.register := src1;
+ cg.a_loadfpu_ref_reg(exprasmlist,
+ def_cgsize(left.resulttype.def),
+ left.location.reference, src1);
+ end
+ else
+ begin
+ src1 := cg.getintregister(exprasmlist, OS_64);
+ location.register := src1;
+ cg.a_load_ref_reg(exprasmlist, OS_64, OS_64,
+ left.location.reference, src1);
+ end;
+ end;
+ end;
+ { choose appropriate operand }
+ if left.resulttype.def.deftype <> floatdef then
+ begin
+ if not (cs_check_overflow in aktlocalswitches) then
+ op := A_NEG
+ else
+ op := A_NEGO_;
+ location.loc := LOC_REGISTER;
+ end
+ else
+ begin
+ op := A_FNEG;
+ location.loc := LOC_FPUREGISTER;
+ end;
+ { emit operation }
+ exprasmlist.concat(taicpu.op_reg_reg(op, location.register, src1));
+ end;
+ { Here was a problem... }
+ { Operand to be negated always }
+ { seems to be converted to signed }
+ { 32-bit before doing neg!! }
+ { So this is useless... }
+ { that's not true: -2^31 gives an overflow error if it is negated (FK) }
+ cg.g_overflowcheck(exprasmlist, location, resulttype.def);
+end;
+
+{*****************************************************************************
+ TPPCNOTNODE
+*****************************************************************************}
+
+procedure tppcnotnode.pass_2;
+
+var
+ hl: tasmlabel;
+
+begin
+ if is_boolean(resulttype.def) then
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc = LOC_JUMP then
+ begin
+ hl := truelabel;
+ truelabel := falselabel;
+ falselabel := hl;
+ secondpass(left);
+ maketojumpbool(exprasmlist, left, lr_load_regvars);
+ hl := truelabel;
+ truelabel := falselabel;
+ falselabel := hl;
+ location.loc := LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS:
+ begin
+ location_copy(location, left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER, LOC_CREGISTER, LOC_REFERENCE, LOC_CREFERENCE:
+ begin
+ location_force_reg(exprasmlist, left.location,
+ def_cgsize(left.resulttype.def), true);
+ exprasmlist.concat(taicpu.op_reg_const(A_CMPDI,
+ left.location.register, 0));
+ location_reset(location, LOC_FLAGS, OS_NO);
+ location.resflags.cr := RS_CR0;
+ location.resflags.flag := F_EQ;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end
+ else
+ begin
+ secondpass(left);
+ location_force_reg(exprasmlist, left.location,
+ def_cgsize(left.resulttype.def), true);
+ location_copy(location, left.location);
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(exprasmlist, OS_INT);
+ { perform the NOT operation }
+ cg.a_op_reg_reg(exprasmlist, OP_NOT, def_cgsize(resulttype.def),
+ left.location.register,
+ location.register);
+ end;
+end;
+
+begin
+ cmoddivnode := tppcmoddivnode;
+ cshlshrnode := tppcshlshrnode;
+ cunaryminusnode := tppcunaryminusnode;
+ cnotnode := tppcnotnode;
+end.
+
diff --git a/compiler/powerpc64/nppcset.pas b/compiler/powerpc64/nppcset.pas
new file mode 100644
index 0000000000..97fdb837ba
--- /dev/null
+++ b/compiler/powerpc64/nppcset.pas
@@ -0,0 +1,209 @@
+{
+ 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, cgbase, cgobj, aasmbase, aasmtai, globtype;
+
+type
+
+ tppccasenode = class(tcgcasenode)
+ protected
+ procedure optimizevalues(var max_linear_list : aint; var max_dist : aword); override;
+
+ function has_jumptable : boolean; override;
+ procedure genjumptable(hp: pcaselabel; min_, max_ : aint); override;
+ procedure genlinearlist(hp: pcaselabel); override;
+ end;
+
+implementation
+
+uses
+ systems,
+ verbose, globals,
+ symconst, symdef, defutil,
+ paramgr,
+ cpuinfo,
+ pass_2, cgcpu,
+ ncon,
+ tgobj, ncgutil, regvars, rgobj, aasmcpu,
+ procinfo, cgutils;
+
+{*****************************************************************************
+ TCGCASENODE
+*****************************************************************************}
+
+procedure tppccasenode.optimizevalues(var max_linear_list : aint; var max_dist : aword);
+begin
+ max_linear_list := 10;
+end;
+
+function tppccasenode.has_jumptable : boolean;
+begin
+ has_jumptable := true;
+end;
+
+procedure tppccasenode.genjumptable(hp : pcaselabel; min_, max_ : aint);
+var
+ table : tasmlabel;
+ last : TConstExprInt;
+ indexreg : tregister;
+ href : treference;
+
+ procedure genitem(list:taasmoutput;t : pcaselabel);
+ var
+ i : aint;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ for i:=last+1 to t^._low-1 do
+ list.concat(Tai_const.Create_sym(elselabel));
+ for i:=t^._low to t^._high do
+ list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+ last:=t^._high;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+begin
+ { this is exactly the same code as for 32 bit PowerPC processors. It might be useful to change this
+ later (with e.g. TOC support) into a method which uses relative values in the jumptable to save space
+ and memory bandwidth. At the moment this is not a good idea, since these methods involve loading of
+ one or more 64 bit integer adresses which is slow }
+ if not(jumptable_no_range) then begin
+ { case expr less than min_ => goto elselabel }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_lt,aint(min_),hregister,elselabel);
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_gt,aint(max_),hregister,elselabel);
+ end;
+ objectlibrary.getjumplabel(table);
+ { allocate base and index registers register }
+ indexreg:= cg.makeregsize(exprasmlist, hregister, OS_INT);
+ { indexreg := hregister; }
+ cg.a_load_reg_reg(exprasmlist, opsize, OS_INT, hregister, indexreg);
+ { create reference, indexreg := indexreg * sizeof(OS_ADDR) }
+ cg.a_op_const_reg(exprasmlist, OP_MUL, OS_INT, tcgsize2size[OS_ADDR], indexreg);
+ reference_reset_symbol(href, table, (-aint(min_)) * tcgsize2size[OS_ADDR]);
+ href.index := indexreg;
+
+ cg.a_load_ref_reg(exprasmlist, OS_INT, OS_INT, href, indexreg);
+
+ exprasmlist.concat(taicpu.op_reg(A_MTCTR, indexreg));
+ exprasmlist.concat(taicpu.op_none(A_BCTR));
+
+ { generate jump table }
+ new_section(current_procinfo.aktlocaldata,sec_data,current_procinfo.procdef.mangledname,sizeof(aint));
+ current_procinfo.aktlocaldata.concat(Tai_label.Create(table));
+ last:=min_;
+ genitem(current_procinfo.aktlocaldata,hp);
+end;
+
+procedure tppccasenode.genlinearlist(hp: pcaselabel);
+var
+ first, lastrange: boolean;
+ last: TConstExprInt;
+
+ procedure genitem(t: pcaselabel);
+
+ procedure gensub(value: aint);
+ 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.getintregister(exprasmlist, OS_INT);
+ cg.a_load_const_reg(exprasmlist, OS_INT, value, tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD_, hregister,
+ hregister, 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
+ if t^._low - last = 0 then
+ cg.a_cmp_const_reg_label(exprasmlist, opsize, OC_EQ, 0, hregister,
+ blocklabel(t^.blockid))
+ else
+ gensub(aint(t^._low - last));
+ tcgppc(cg).a_jmp_cond(exprasmlist, OC_EQ, blocklabel(t^.blockid));
+ last := t^._low;
+ lastrange := false;
+ 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(aint(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(aint(t^._low - last));
+ if ((t^._low - last) <> 1) or (not lastrange) then
+ tcgppc(cg).a_jmp_cond(exprasmlist, jmp_lt, elselabel);
+ end;
+ gensub(aint(t^._high - t^._low));
+ tcgppc(cg).a_jmp_cond(exprasmlist, jmp_le, blocklabel(t^.blockid));
+ last := t^._high;
+ lastrange := true;
+ 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;
+ lastrange := false;
+ first := true;
+ genitem(hp);
+ cg.a_jmp_always(exprasmlist, elselabel);
+ end;
+end;
+
+begin
+ ccasenode := tppccasenode;
+end.
+
diff --git a/compiler/powerpc64/ppcins.dat b/compiler/powerpc64/ppcins.dat
new file mode 100644
index 0000000000..708b1f8c0d
--- /dev/null
+++ b/compiler/powerpc64/ppcins.dat
@@ -0,0 +1,75 @@
+;****************************************************************************
+;
+; Copyright (c) 2002 by Florian Klaempfl
+;
+; Instruction template table for the PowerPC
+;
+; 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.
+;
+;****************************************************************************
+;
+add rD,rA,rB opcode=31,op22=266,oe=0,rc=0
+add_ rD,rA,rB opcode=31,op22=266,oe=0,rc=1
+addo rD,rA,rB opcode=31,op22=266,oe=1,rc=0
+addo_ rD,rA,rB opcode=31,op22=266,oe=1,rc=1
+addc rD,rA,rB opcode=31,op22=10,oe=0,rc=0
+addc_ rD,rA,rB opcode=31,op22=10,oe=0,rc=1
+addco rD,rA,rB opcode=31,op22=10,oe=1,rc=0
+addco_ rD,rA,rB opcode=31,op22=10,oe=1,rc=1
+adde rD,rA,rB opcode=31,op22=138,oe=0,rc=0
+adde_ rD,rA,rB opcode=31,op22=138,oe=0,rc=1
+addeo rD,rA,rB opcode=31,op22=138,oe=1,rc=0
+addeo_ rD,rA,rB opcode=31,op22=138,oe=1,rc=1
+addi rD,rA,SIMM opcode=14
+addic rD,rA,SIMM opcode=12
+addic_ rD,rA,SIMM opcode=13
+addis rD,rA,SIMM opcode=15
+addme rD,rA opcode=31,op22=234,oe=0,rc=0,reserved=$000f0000
+addme_ rD,rA opcode=31,op22=234,oe=0,rc=1,reserved=$000f0000
+addmeo rD,rA opcode=31,op22=234,oe=1,rc=0,reserved=$000f0000
+addmeo_ rD,rA opcode=31,op22=234,oe=1,rc=1,reserved=$000f0000
+addze rD,rA opcode=31,op22=202,oe=0,rc=0,reserved=$000f0000
+addze_ rD,rA opcode=31,op22=202,oe=0,rc=1,reserved=$000f0000
+addzeo rD,rA opcode=31,op22=202,oe=1,rc=0,reserved=$000f0000
+addzeo_ rD,rA opcode=31,op22=202,oe=1,rc=1,reserved=$000f0000
+and rA,rS,rB opcode=31,op21=28,rc=0
+and_ rA,rS,rB opcode=31,op21=28,rc=1
+andc rA,rS,rB opcode=31,op21=60,rc=0
+andc_ rA,rS,rB opcode=31,op21=60,rc=1
+andi_ rA,rS,UIMM opcode=28
+andis_ rA,rS,UIMM opcode=29
+b TA24 opcode=18,aa=0,lk=0
+ba TA24 opcode=18,aa=1,lk=0
+bl TA24 opcode=18,aa=0,lk=1
+bla TA24 opcode=18,aa=1,lk=1
+bc BO,BI,TA14 opcode=16,aa=0,lk=0
+bca BO,BI,TA14 opcode=16,aa=1,lk=0
+bcl BO,BI,TA14 opcode=16,aa=0,lk=1
+bcla BO,BI,TA14 opcode=16,aa=1,lk=1
+bcctr BO,BI opcode=19,op21=528,lk=0,reserved=$000f0000
+bcctrl BO,BI opcode=19,op21=528,lk=1,reserved=$000f0000
+bcltr BO,BI opcode=19,op21=16,lk=0,reserved=$000f0000
+bcltrl BO,BI opcode=19,op21=16,lk=1,reserved=$000f0000
+cmp crfD,L,rA,rB opcode=31,op21=0,reserved=$80000200
+cmpi crfD,L,rA,SIMM opcode=11,reserved=$00000200
+cmpl crfD,L,rA,rB opcode=31,op21=32,reserved=$80000200
+cmpli crfD,L,rA,UIMM opcode=10,reserved=$00000200
+
+;
+
+; Revision 1.1 2002/07/13 21:50:34 florian
+; + initial version, a lot of instructions need to be added
+;
+;
diff --git a/compiler/powerpc64/ppcreg.dat b/compiler/powerpc64/ppcreg.dat
new file mode 100644
index 0000000000..aaf0542621
--- /dev/null
+++ b/compiler/powerpc64/ppcreg.dat
@@ -0,0 +1,143 @@
+;
+;
+; PowerPC registers
+;
+; layout
+; <name>,<value>,<stdname>,<gasname>,<gasshortname>,<motname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,INVALID,INVALID,-1,-1
+
+R0,$01,$00,r0,r0,0,r0,0,0
+R1,$01,$01,r1,r1,1,r1,1,1
+R2,$01,$02,r2,r2,2,r2,2,2
+R3,$01,$03,r3,r3,3,r3,3,3
+R4,$01,$04,r4,r4,4,r4,4,4
+R5,$01,$05,r5,r5,5,r5,5,5
+R6,$01,$06,r6,r6,6,r6,6,6
+R7,$01,$07,r7,r7,7,r7,7,7
+R8,$01,$08,r8,r8,8,r8,8,8
+R9,$01,$09,r9,r9,9,r9,9,9
+R10,$01,$0a,r10,r10,10,r10,10,10
+R11,$01,$0b,r11,r11,11,r11,11,11
+R12,$01,$0c,r12,r12,12,r12,12,12
+R13,$01,$0d,r13,r13,13,r13,13,13
+R14,$01,$0e,r14,r14,14,r14,14,14
+R15,$01,$0f,r15,r15,15,r15,15,15
+R16,$01,$10,r16,r16,16,r16,16,16
+R17,$01,$11,r17,r17,17,r17,17,17
+R18,$01,$12,r18,r18,18,r18,18,18
+R19,$01,$13,r19,r19,19,r19,19,19
+R20,$01,$14,r20,r20,20,r20,20,20
+R21,$01,$15,r21,r21,21,r21,21,21
+R22,$01,$16,r22,r22,22,r22,22,22
+R23,$01,$17,r23,r23,23,r23,23,23
+R24,$01,$18,r24,r24,24,r24,24,24
+R25,$01,$19,r25,r25,25,r25,25,25
+R26,$01,$1a,r26,r26,26,r26,26,26
+R27,$01,$1b,r27,r27,27,r27,27,27
+R28,$01,$1c,r28,r28,28,r28,28,28
+R29,$01,$1d,r29,r29,29,r29,29,29
+R30,$01,$1e,r30,r30,30,r30,30,30
+R31,$01,$1f,r31,r31,31,r31,31,31
+
+F0,$02,$00,F0,f0,0,F0,32,32
+F1,$02,$01,F1,f1,1,F1,33,33
+F2,$02,$02,F2,f2,2,F2,34,34
+F3,$02,$03,F3,f3,3,F3,35,35
+F4,$02,$04,F4,f4,4,F4,36,36
+F5,$02,$05,F5,f5,5,F5,37,37
+F6,$02,$06,F6,f6,6,F6,38,38
+F7,$02,$07,F7,f7,7,F7,39,39
+F8,$02,$08,F8,f8,8,F8,40,40
+F9,$02,$09,F9,f9,9,F9,41,41
+F10,$02,$0a,F10,f10,10,F10,42,42
+F11,$02,$0b,F11,f11,11,F11,43,43
+F12,$02,$0c,F12,f12,12,F12,44,44
+F13,$02,$0d,F13,f13,13,F13,45,45
+F14,$02,$0e,F14,f14,14,F14,46,46
+F15,$02,$0f,F15,f15,15,F15,47,47
+F16,$02,$10,F16,f16,16,F16,48,48
+F17,$02,$11,F17,f17,17,F17,49,49
+F18,$02,$12,F18,f18,18,F18,50,50
+F19,$02,$13,F19,f19,19,F19,51,51
+F20,$02,$14,F20,f20,20,F20,52,52
+F21,$02,$15,F21,f21,21,F21,53,53
+F22,$02,$16,F22,f22,22,F22,54,54
+F23,$02,$17,F23,f23,23,F23,55,55
+F24,$02,$18,F24,f24,24,F24,56,56
+F25,$02,$19,F25,f25,25,F25,57,57
+F26,$02,$1a,F26,f26,26,F26,58,58
+F27,$02,$1b,F27,f27,27,F27,59,59
+F28,$02,$1c,F28,f28,28,F28,60,60
+F29,$02,$1d,F29,f29,29,F29,61,61
+F30,$02,$1e,F30,f30,30,F30,62,62
+F31,$02,$1f,F31,f31,31,F31,63,63
+
+M0,$03,$00,M0,v0,0,M0,-1,-1
+M1,$03,$01,M1,v1,1,M1,-1,-1
+M2,$03,$02,M2,v2,2,M2,-1,-1
+M3,$03,$03,M3,v3,3,M3,-1,-1
+M4,$03,$04,M4,v4,4,M4,-1,-1
+M5,$03,$05,M5,v5,5,M5,-1,-1
+M6,$03,$06,M6,v6,6,M6,-1,-1
+M7,$03,$07,M7,v7,7,M7,-1,-1
+M8,$03,$08,M8,v8,8,M8,-1,-1
+M9,$03,$09,M9,v9,9,M9,-1,-1
+M10,$03,$0a,M10,v10,10,M10,-1,-1
+M11,$03,$0b,M11,v11,11,M11,-1,-1
+M12,$03,$0c,M12,v12,12,M12,-1,-1
+M13,$03,$0d,M13,v13,13,M13,-1,-1
+M14,$03,$0e,M14,v14,14,M14,-1,-1
+M15,$03,$0f,M15,v15,15,M15,-1,-1
+M16,$03,$10,M16,v16,16,M16,-1,-1
+M17,$03,$11,M17,v17,17,M17,-1,-1
+M18,$03,$12,M18,v18,18,M18,-1,-1
+M19,$03,$13,M19,v19,19,M19,-1,-1
+M20,$03,$14,M20,v20,20,M20,-1,-1
+M21,$03,$15,M21,v21,21,M21,-1,-1
+M22,$03,$16,M22,v22,22,M22,-1,-1
+M23,$03,$17,M23,v23,23,M23,-1,-1
+M24,$03,$18,M24,v24,24,M24,-1,-1
+M25,$03,$19,M25,v25,25,M25,-1,-1
+M26,$03,$1a,M26,v26,26,M26,-1,-1
+M27,$03,$1b,M27,v27,27,M27,-1,-1
+M28,$03,$1c,M28,v28,28,M28,-1,-1
+M29,$03,$1d,M29,v29,29,M29,-1,-1
+M30,$03,$1e,M30,v30,30,M30,-1,-1
+M31,$03,$1f,M31,v31,31,M31,-1,-1
+
+CR,$05,$00,CR,cr,cr,CR,-1,-1
+CR0,$05,$01,CR0,cr0,cr0,CR0,68,68
+CR1,$05,$02,CR1,cr1,cr1,CR1,69,69
+CR2,$05,$03,CR2,cr2,cr2,CR2,70,70
+CR3,$05,$04,CR3,cr3,cr3,CR3,71,71
+CR4,$05,$05,CR4,cr4,cr4,CR4,72,72
+CR5,$05,$06,CR5,cr5,cr5,CR5,73,73
+CR6,$05,$07,CR6,cr6,cr5,CR6,74,74
+CR7,$05,$08,CR7,cr7,cr6,CR7,75,75
+XER,$05,$09,XER,xer,xer,XER,76,76
+LR,$05,$0a,LR,lr,lr,LR,65,65
+CTR,$05,$0b,CTR,ctr,ctr,CTR,66,66
+FPSCR,$05,$0c,FPSCR,fpscr,fpscr,FPSCR,-1,-1
+
+;
+
+; Revision 1.6 2004/06/17 16:55:46 peter
+; * powerpc compiles again
+;
+; Revision 1.5 2003/12/10 22:19:27 florian
+; + short gas register names for smartlinking added
+;
+; Revision 1.4 2003/09/04 21:07:03 florian
+; * ARM compiler compiles again
+;
+; Revision 1.3 2003/09/03 19:35:24 peter
+; * powerpc compiles again
+;
+; Revision 1.2 2003/09/03 15:55:01 peter
+; * NEWRA branch merged
+;
+; Revision 1.1.2.1 2003/09/02 20:48:22 peter
+; * powerpc registers
+;
+;
diff --git a/compiler/powerpc64/rappc.pas b/compiler/powerpc64/rappc.pas
new file mode 100644
index 0000000000..4b16f7055d
--- /dev/null
+++ b/compiler/powerpc64/rappc.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common ppc assembler reader routines
+
+ 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 rappc;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ aasmbase, aasmtai, aasmcpu,
+ cpubase, rautils, cclasses;
+
+type
+ TPPCOperand = class(TOperand)
+ end;
+
+ TPPCInstruction = class(TInstruction)
+ end;
+
+implementation
+
+end.
+
diff --git a/compiler/powerpc64/rappcgas.pas b/compiler/powerpc64/rappcgas.pas
new file mode 100644
index 0000000000..941496f392
--- /dev/null
+++ b/compiler/powerpc64/rappcgas.pas
@@ -0,0 +1,731 @@
+{
+ $Id: rappcgas.pas,v 1.19 2005/02/14 17:13:10 peter Exp $
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the PowerPC GNU AS styled inline assembler.
+
+ 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 rappcgas;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ raatt, rappc;
+
+type
+ tppcattreader = class(tattreader)
+ function is_asmopcode(const s: string): boolean; override;
+ procedure handleopcode; override;
+ procedure BuildReference(oper: tppcoperand);
+ procedure BuildOperand(oper: tppcoperand);
+ procedure BuildOpCode(instr: tppcinstruction);
+ procedure ReadAt(oper: tppcoperand);
+ procedure ReadSym(oper: tppcoperand);
+ procedure ConvertCalljmp(instr: tppcinstruction);
+ end;
+
+implementation
+
+uses
+ { helpers }
+ cutils,
+ { global }
+ globtype, verbose,
+ systems,
+ { aasm }
+ cpubase, aasmbase, aasmtai, aasmcpu,
+ { symtable }
+ symconst, symsym,
+ { parser }
+ procinfo,
+ rabase, rautils,
+ cgbase, cgobj
+ ;
+
+procedure tppcattreader.ReadSym(oper: tppcoperand);
+var
+ tempstr: string;
+ typesize, l, k: aint;
+begin
+ tempstr := actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken = AS_LPAREN) and
+ SearchType(tempstr, typesize) then
+ begin
+ oper.hastype := true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE, OPR_LOCAL] then
+ oper.SetSize(typesize, true);
+ end
+ else if not oper.SetupVar(tempstr, false) then
+ Message1(sym_e_unknown_id, tempstr);
+ { record.field ? }
+ if actasmtoken = AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr, l, k);
+ inc(oper.opr.ref.offset, l);
+ end;
+end;
+
+procedure tppcattreader.ReadAt(oper: tppcoperand);
+begin
+ { check for ...@ }
+ if actasmtoken = AS_AT then
+ begin
+ if (oper.opr.ref.symbol = nil) and
+ (oper.opr.ref.offset = 0) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_AT);
+ if actasmtoken = AS_ID then
+ begin
+ if upper(actasmpattern) = 'L' then
+ oper.opr.ref.refaddr := addr_low
+ else if upper(actasmpattern) = 'HA' then
+ oper.opr.ref.refaddr := addr_higha
+ else if upper(actasmpattern) = 'H' then
+ oper.opr.ref.refaddr := addr_high
+ else if upper(actasmpattern) = 'HIGHERA' then
+ oper.opr.ref.refaddr := addr_highera
+ else if upper(actasmpattern) = 'HIGHESTA' then
+ oper.opr.ref.refaddr := addr_highesta
+ else if upper(actasmpattern) = 'HIGHER' then
+ oper.opr.ref.refaddr := addr_higher
+ else if upper(actasmpattern) = 'HIGHEST' then
+ oper.opr.ref.refaddr := addr_highest
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+end;
+
+procedure tppcattreader.BuildReference(oper: tppcoperand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken <> AS_RPAREN then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA, AS_SEPARATOR, AS_END]) then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+var
+ l: aint;
+
+begin
+ Consume(AS_LPAREN);
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ begin
+ { offset(offset) is invalid }
+ if oper.opr.Ref.Offset <> 0 then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ oper.opr.Ref.Offset := BuildConstExpression(false, true);
+ Consume(AS_RPAREN);
+ if actasmtoken = AS_AT then
+ ReadAt(oper);
+ end;
+ exit;
+ end;
+ AS_REGISTER: { (reg ... }
+ begin
+ if ((oper.opr.typ = OPR_REFERENCE) and (oper.opr.ref.base <> NR_NO)) or
+ ((oper.opr.typ = OPR_LOCAL) and (oper.opr.localsym.localloc.loc <>
+ LOC_REGISTER)) then
+ message(asmr_e_cannot_index_relative_var);
+ oper.opr.ref.base := actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { (reg) }
+ if actasmtoken = AS_RPAREN then
+ begin
+ Consume_RParen;
+ exit;
+ end;
+ { (reg,reg .. }
+ Consume(AS_COMMA);
+ if (actasmtoken = AS_REGISTER) and
+ (oper.opr.Ref.Offset = 0) then
+ begin
+ oper.opr.ref.index := actasmregister;
+ Consume(AS_REGISTER);
+ Consume_RParen;
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; {end case }
+ AS_ID:
+ begin
+ ReadSym(oper);
+ { add a constant expression? }
+ if (actasmtoken = AS_PLUS) then
+ begin
+ l := BuildConstExpression(true, true);
+ case oper.opr.typ of
+ OPR_CONSTANT:
+ inc(oper.opr.val, l);
+ OPR_LOCAL:
+ inc(oper.opr.localsymofs, l);
+ OPR_REFERENCE:
+ inc(oper.opr.ref.offset, l);
+ else
+ internalerror(200309202);
+ end;
+ end;
+ Consume(AS_RPAREN);
+ if actasmtoken = AS_AT then
+ ReadAt(oper);
+ end;
+ AS_COMMA: { (, ... can either be scaling, or index }
+ begin
+ Consume(AS_COMMA);
+ { Index }
+ if (actasmtoken = AS_REGISTER) then
+ begin
+ oper.opr.ref.index := actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ Consume_RParen;
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+end;
+
+procedure tppcattreader.BuildOperand(oper: tppcoperand);
+var
+ expr: string;
+ typesize, l: aint;
+
+ procedure AddLabelOperand(hl: tasmlabel);
+ begin
+ if not (actasmtoken in [AS_PLUS, AS_MINUS, AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ := OPR_SYMBOL;
+ oper.opr.symbol := hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol := hl;
+ end;
+ end;
+
+ procedure MaybeRecordOffset;
+ var
+ hasdot: boolean;
+ l,
+ toffset,
+ tsize: aint;
+ begin
+ if not (actasmtoken in [AS_DOT, AS_PLUS, AS_MINUS]) then
+ exit;
+ l := 0;
+ hasdot := (actasmtoken = AS_DOT);
+ if hasdot then
+ begin
+ if expr <> '' then
+ begin
+ BuildRecordOffsetSize(expr, toffset, tsize);
+ inc(l, toffset);
+ oper.SetSize(tsize, true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS, AS_MINUS] then
+ inc(l, BuildConstExpression(true, false));
+ case oper.opr.typ of
+ OPR_LOCAL:
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractvarsym(oper.opr.localsym).owner.symtabletype =
+ parasymtable) and
+ (current_procinfo.procdef.proccalloption <> pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs, l)
+ end;
+ OPR_CONSTANT:
+ inc(oper.opr.val, l);
+ OPR_REFERENCE:
+ inc(oper.opr.ref.offset, l);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+ function MaybeBuildReference: boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference := true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ begin
+ oper.opr.ref.offset := BuildConstExpression(True, False);
+ if actasmtoken <> AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference := false;
+ end; { end case }
+ end;
+
+var
+ tempreg: tregister;
+ hl: tasmlabel;
+ ofs: aint;
+begin
+ expr := '';
+ case actasmtoken of
+ AS_LPAREN: { Memory reference or constant expression }
+ begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset := BuildConstExpression(True, False);
+ if actasmtoken <> AS_LPAREN then
+ begin
+ ofs := oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val, ofs);
+ end
+ else
+ BuildReference(oper);
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern, hl, false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label } if SearchLabel(actasmpattern, hl, false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern, l) then
+ begin
+ if not (oper.opr.typ in [OPR_NONE, OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr := actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken = AS_LPAREN) and
+ SearchType(expr, typesize) then
+ begin
+ oper.hastype := true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE, OPR_LOCAL] then
+ oper.SetSize(typesize, true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr, false) then
+ ReadAt(oper)
+ else
+ begin
+ { look for special symbols ... }
+ if expr = '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high' + actasmpattern, false) then
+ Message1(sym_e_unknown_id, 'high' + actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else if expr = '__RESULT' then
+ oper.SetUpResult
+ else if expr = '__SELF' then
+ oper.SetupSelf
+ else if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id, expr);
+ end;
+ end;
+ end;
+ if actasmtoken = AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken = AS_PLUS) then
+ begin
+ l := BuildConstExpression(true, false);
+ case oper.opr.typ of
+ OPR_CONSTANT:
+ inc(oper.opr.val, l);
+ OPR_LOCAL:
+ inc(oper.opr.localsymofs, l);
+ OPR_REFERENCE:
+ inc(oper.opr.ref.offset, l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken = AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ begin
+ { save the type of register used. }
+ tempreg := actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_END, AS_SEPARATOR, AS_COMMA]) then
+ if is_condreg(tempreg) and
+ ((actopcode = A_BC) or
+ (actopcode = A_BCCTR) or
+ (actopcode = A_BCLR) or
+ (actopcode = A_TW) or
+ (actopcode = A_TWI)) then
+ begin
+ { it isn't a real operand, everything is stored in the condition }
+ oper.opr.typ := OPR_NONE;
+ actcondition.cr := getsupreg(tempreg);
+ end
+ else
+ begin
+ if not (oper.opr.typ in [OPR_NONE, OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ := OPR_REGISTER;
+ oper.opr.reg := tempreg;
+ end
+ else if is_condreg(tempreg) then
+ begin
+ if not (actcondition.cond in [C_T..C_DZF]) then
+ Message(asmr_e_syn_operand);
+ if actasmtoken = AS_STAR then
+ begin
+ consume(AS_STAR);
+ if (actasmtoken = AS_INTNUM) then
+ begin
+ consume(AS_INTNUM);
+ if actasmtoken = AS_PLUS then
+ begin
+ consume(AS_PLUS);
+ if (actasmtoken = AS_ID) then
+ begin
+ oper.opr.typ := OPR_NONE;
+ if actasmpattern = 'LT' then
+ actcondition.crbit := (getsupreg(tempreg) - (RS_CR0)) * 4
+ else if actasmpattern = 'GT' then
+ actcondition.crbit := (getsupreg(tempreg) - (RS_CR0)) * 4 + 1
+ else if actasmpattern = 'EQ' then
+ actcondition.crbit := (getsupreg(tempreg) - (RS_CR0)) * 4 + 2
+ else if actasmpattern = 'SO' then
+ actcondition.crbit := (getsupreg(tempreg) - (RS_CR0)) * 4 + 3
+ else
+ Message(asmr_e_syn_operand);
+ consume(AS_ID);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+end;
+
+{*****************************************************************************
+ tppcattreader
+*****************************************************************************}
+
+procedure tppcattreader.BuildOpCode(instr: tppcinstruction);
+var
+ operandnum: longint;
+begin
+ { opcode }
+ if (actasmtoken <> AS_OPCODE) then
+ begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode := ActOpcode;
+ condition := ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum := 1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR, AS_END] then
+ begin
+ operandnum := 0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ begin
+ if operandnum > Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ begin
+ { condition operands doesn't set the operand but write to the
+ condition field of the instruction
+ }
+ if instr.Operands[operandnum].opr.typ <> OPR_NONE then
+ Inc(operandnum);
+ end;
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END: { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tppcoperand);
+ end; { end case }
+ until false;
+ if (operandnum = 1) and (instr.Operands[operandnum].opr.typ = OPR_NONE) then
+ dec(operandnum);
+ instr.Ops := operandnum;
+end;
+
+function tppcattreader.is_asmopcode(const s: string): boolean;
+var
+ str2opentry: tstr2opentry;
+ cond: tasmcondflag;
+ hs: string;
+
+begin
+ { making s a value parameter would break other assembler readers }
+ hs := s;
+ is_asmopcode := false;
+
+ { clear op code }
+ actopcode := A_None;
+ { clear condition }
+ fillchar(actcondition, sizeof(actcondition), 0);
+
+ { check for direction hint }
+ if hs[length(s)] = '-' then
+ begin
+ dec(ord(hs[0]));
+ actcondition.dirhint := DH_Minus;
+ end
+ else if hs[length(s)] = '+' then
+ begin
+ dec(ord(hs[0]));
+ actcondition.dirhint := DH_Plus;
+ end;
+ str2opentry := tstr2opentry(iasmops.search(hs));
+ if assigned(str2opentry) then
+ begin
+ if actcondition.dirhint <> DH_None then
+ message1(asmr_e_unknown_opcode, actasmpattern);
+ actopcode := str2opentry.op;
+ actasmtoken := AS_OPCODE;
+ is_asmopcode := true;
+ exit;
+ end;
+ { not found, check branch instructions }
+ if hs[1] = 'B' then
+ begin
+ { we can search here without an extra table which is sorted by string length
+ because we take the whole remaining string without the leading B }
+ if copy(hs, length(s) - 1, 2) = 'LR' then
+ begin
+ actopcode := A_BCLR;
+ setlength(hs, length(hs) - 2)
+ end
+ else if copy(hs, length(s) - 2, 3) = 'CTR' then
+ begin
+ actopcode := A_BCCTR;
+ setlength(hs, length(hs) - 3)
+ end
+ else
+ actopcode := A_BC;
+ for cond := low(TAsmCondFlag) to high(TAsmCondFlag) do
+ if copy(hs, 2, length(s) - 1) = UpperAsmCondFlag2Str[cond] then
+ begin
+ actcondition.simple := true;
+ actcondition.cond := cond;
+ if (cond in [C_LT, C_LE, C_EQ, C_GE, C_GT, C_NL, C_NE, C_NG, C_SO, C_NS,
+ C_UN, C_NU]) then
+ actcondition.cr := RS_CR0;
+ actasmtoken := AS_OPCODE;
+ is_asmopcode := true;
+ exit;
+ end;
+ end;
+end;
+
+procedure tppcattreader.ConvertCalljmp(instr: tppcinstruction);
+begin
+ if instr.Operands[1].opr.typ = OPR_REFERENCE then
+ begin
+ instr.Operands[1].opr.ref.refaddr := addr_full;
+ if (instr.Operands[1].opr.ref.base <> NR_NO) or
+ (instr.Operands[1].opr.ref.index <> NR_NO) then
+ Message(asmr_e_syn_operand);
+ end;
+end;
+
+procedure tppcattreader.handleopcode;
+var
+ instr: tppcinstruction;
+begin
+ instr := TPPCInstruction.Create(TPPCOperand);
+ BuildOpcode(instr);
+ instr.condition := actcondition;
+ if is_calljmp(instr.opcode) then
+ ConvertCalljmp(instr);
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_ppc_att_info: tasmmodeinfo =
+ (
+ id: asmmode_ppc_gas;
+ idtxt: 'GAS';
+ casmreader: tppcattreader;
+ );
+
+ asmmode_ppc_standard_info: tasmmodeinfo =
+ (
+ id: asmmode_standard;
+ idtxt: 'STANDARD';
+ casmreader: tppcattreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_ppc_att_info);
+ RegisterAsmMode(asmmode_ppc_standard_info);
+end.
+
diff --git a/compiler/powerpc64/rgcpu.pas b/compiler/powerpc64/rgcpu.pas
new file mode 100644
index 0000000000..fd8d33fe21
--- /dev/null
+++ b/compiler/powerpc64/rgcpu.pas
@@ -0,0 +1,46 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the powerpc specific class for the register
+ allocator
+
+ 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 rgcpu;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ aasmbase, aasmtai,
+ cpubase,
+ rgobj;
+
+type
+ trgcpu = class(trgobj)
+ end;
+
+implementation
+
+uses
+ cgobj, verbose, cutils;
+
+
+end.
+
diff --git a/compiler/powerpc64/rppccon.inc b/compiler/powerpc64/rppccon.inc
new file mode 100644
index 0000000000..4ff6799228
--- /dev/null
+++ b/compiler/powerpc64/rppccon.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_R16 = tregister($01000010);
+NR_R17 = tregister($01000011);
+NR_R18 = tregister($01000012);
+NR_R19 = tregister($01000013);
+NR_R20 = tregister($01000014);
+NR_R21 = tregister($01000015);
+NR_R22 = tregister($01000016);
+NR_R23 = tregister($01000017);
+NR_R24 = tregister($01000018);
+NR_R25 = tregister($01000019);
+NR_R26 = tregister($0100001a);
+NR_R27 = tregister($0100001b);
+NR_R28 = tregister($0100001c);
+NR_R29 = tregister($0100001d);
+NR_R30 = tregister($0100001e);
+NR_R31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_M0 = tregister($03000000);
+NR_M1 = tregister($03000001);
+NR_M2 = tregister($03000002);
+NR_M3 = tregister($03000003);
+NR_M4 = tregister($03000004);
+NR_M5 = tregister($03000005);
+NR_M6 = tregister($03000006);
+NR_M7 = tregister($03000007);
+NR_M8 = tregister($03000008);
+NR_M9 = tregister($03000009);
+NR_M10 = tregister($0300000a);
+NR_M11 = tregister($0300000b);
+NR_M12 = tregister($0300000c);
+NR_M13 = tregister($0300000d);
+NR_M14 = tregister($0300000e);
+NR_M15 = tregister($0300000f);
+NR_M16 = tregister($03000010);
+NR_M17 = tregister($03000011);
+NR_M18 = tregister($03000012);
+NR_M19 = tregister($03000013);
+NR_M20 = tregister($03000014);
+NR_M21 = tregister($03000015);
+NR_M22 = tregister($03000016);
+NR_M23 = tregister($03000017);
+NR_M24 = tregister($03000018);
+NR_M25 = tregister($03000019);
+NR_M26 = tregister($0300001a);
+NR_M27 = tregister($0300001b);
+NR_M28 = tregister($0300001c);
+NR_M29 = tregister($0300001d);
+NR_M30 = tregister($0300001e);
+NR_M31 = tregister($0300001f);
+NR_CR = tregister($05000000);
+NR_CR0 = tregister($05000001);
+NR_CR1 = tregister($05000002);
+NR_CR2 = tregister($05000003);
+NR_CR3 = tregister($05000004);
+NR_CR4 = tregister($05000005);
+NR_CR5 = tregister($05000006);
+NR_CR6 = tregister($05000007);
+NR_CR7 = tregister($05000008);
+NR_XER = tregister($05000009);
+NR_LR = tregister($0500000a);
+NR_CTR = tregister($0500000b);
+NR_FPSCR = tregister($0500000c);
diff --git a/compiler/powerpc64/rppcdwrf.inc b/compiler/powerpc64/rppcdwrf.inc
new file mode 100644
index 0000000000..2c9c9942a8
--- /dev/null
+++ b/compiler/powerpc64/rppcdwrf.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+65,
+66,
+-1
diff --git a/compiler/powerpc64/rppcgas.inc b/compiler/powerpc64/rppcgas.inc
new file mode 100644
index 0000000000..3c68549ce1
--- /dev/null
+++ b/compiler/powerpc64/rppcgas.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'v0',
+'v1',
+'v2',
+'v3',
+'v4',
+'v5',
+'v6',
+'v7',
+'v8',
+'v9',
+'v10',
+'v11',
+'v12',
+'v13',
+'v14',
+'v15',
+'v16',
+'v17',
+'v18',
+'v19',
+'v20',
+'v21',
+'v22',
+'v23',
+'v24',
+'v25',
+'v26',
+'v27',
+'v28',
+'v29',
+'v30',
+'v31',
+'cr',
+'cr0',
+'cr1',
+'cr2',
+'cr3',
+'cr4',
+'cr5',
+'cr6',
+'cr7',
+'xer',
+'lr',
+'ctr',
+'fpscr'
diff --git a/compiler/powerpc64/rppcgri.inc b/compiler/powerpc64/rppcgri.inc
new file mode 100644
index 0000000000..b26f900caa
--- /dev/null
+++ b/compiler/powerpc64/rppcgri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+0,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+107,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106
diff --git a/compiler/powerpc64/rppcgss.inc b/compiler/powerpc64/rppcgss.inc
new file mode 100644
index 0000000000..df78c36d00
--- /dev/null
+++ b/compiler/powerpc64/rppcgss.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'cr',
+'cr0',
+'cr1',
+'cr2',
+'cr3',
+'cr4',
+'cr5',
+'cr5',
+'cr6',
+'xer',
+'lr',
+'ctr',
+'fpscr'
diff --git a/compiler/powerpc64/rppcmot.inc b/compiler/powerpc64/rppcmot.inc
new file mode 100644
index 0000000000..4fc340afd7
--- /dev/null
+++ b/compiler/powerpc64/rppcmot.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'M0',
+'M1',
+'M2',
+'M3',
+'M4',
+'M5',
+'M6',
+'M7',
+'M8',
+'M9',
+'M10',
+'M11',
+'M12',
+'M13',
+'M14',
+'M15',
+'M16',
+'M17',
+'M18',
+'M19',
+'M20',
+'M21',
+'M22',
+'M23',
+'M24',
+'M25',
+'M26',
+'M27',
+'M28',
+'M29',
+'M30',
+'M31',
+'CR',
+'CR0',
+'CR1',
+'CR2',
+'CR3',
+'CR4',
+'CR5',
+'CR6',
+'CR7',
+'XER',
+'LR',
+'CTR',
+'FPSCR'
diff --git a/compiler/powerpc64/rppcmri.inc b/compiler/powerpc64/rppcmri.inc
new file mode 100644
index 0000000000..9a59178c7d
--- /dev/null
+++ b/compiler/powerpc64/rppcmri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+0,
+107,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/compiler/powerpc64/rppcnor.inc b/compiler/powerpc64/rppcnor.inc
new file mode 100644
index 0000000000..387be62acb
--- /dev/null
+++ b/compiler/powerpc64/rppcnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from ppcreg.dat }
+110
diff --git a/compiler/powerpc64/rppcnum.inc b/compiler/powerpc64/rppcnum.inc
new file mode 100644
index 0000000000..d612e34d8a
--- /dev/null
+++ b/compiler/powerpc64/rppcnum.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($03000008),
+tregister($03000009),
+tregister($0300000a),
+tregister($0300000b),
+tregister($0300000c),
+tregister($0300000d),
+tregister($0300000e),
+tregister($0300000f),
+tregister($03000010),
+tregister($03000011),
+tregister($03000012),
+tregister($03000013),
+tregister($03000014),
+tregister($03000015),
+tregister($03000016),
+tregister($03000017),
+tregister($03000018),
+tregister($03000019),
+tregister($0300001a),
+tregister($0300001b),
+tregister($0300001c),
+tregister($0300001d),
+tregister($0300001e),
+tregister($0300001f),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c)
diff --git a/compiler/powerpc64/rppcrni.inc b/compiler/powerpc64/rppcrni.inc
new file mode 100644
index 0000000000..1a49189c1d
--- /dev/null
+++ b/compiler/powerpc64/rppcrni.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+109
diff --git a/compiler/powerpc64/rppcsri.inc b/compiler/powerpc64/rppcsri.inc
new file mode 100644
index 0000000000..9a59178c7d
--- /dev/null
+++ b/compiler/powerpc64/rppcsri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+0,
+107,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/compiler/powerpc64/rppcstab.inc b/compiler/powerpc64/rppcstab.inc
new file mode 100644
index 0000000000..2c9c9942a8
--- /dev/null
+++ b/compiler/powerpc64/rppcstab.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+65,
+66,
+-1
diff --git a/compiler/powerpc64/rppcstd.inc b/compiler/powerpc64/rppcstd.inc
new file mode 100644
index 0000000000..4fc340afd7
--- /dev/null
+++ b/compiler/powerpc64/rppcstd.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'M0',
+'M1',
+'M2',
+'M3',
+'M4',
+'M5',
+'M6',
+'M7',
+'M8',
+'M9',
+'M10',
+'M11',
+'M12',
+'M13',
+'M14',
+'M15',
+'M16',
+'M17',
+'M18',
+'M19',
+'M20',
+'M21',
+'M22',
+'M23',
+'M24',
+'M25',
+'M26',
+'M27',
+'M28',
+'M29',
+'M30',
+'M31',
+'CR',
+'CR0',
+'CR1',
+'CR2',
+'CR3',
+'CR4',
+'CR5',
+'CR6',
+'CR7',
+'XER',
+'LR',
+'CTR',
+'FPSCR'
diff --git a/compiler/powerpc64/rppcsup.inc b/compiler/powerpc64/rppcsup.inc
new file mode 100644
index 0000000000..4e6f879355
--- /dev/null
+++ b/compiler/powerpc64/rppcsup.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_R16 = $10;
+RS_R17 = $11;
+RS_R18 = $12;
+RS_R19 = $13;
+RS_R20 = $14;
+RS_R21 = $15;
+RS_R22 = $16;
+RS_R23 = $17;
+RS_R24 = $18;
+RS_R25 = $19;
+RS_R26 = $1a;
+RS_R27 = $1b;
+RS_R28 = $1c;
+RS_R29 = $1d;
+RS_R30 = $1e;
+RS_R31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_M0 = $00;
+RS_M1 = $01;
+RS_M2 = $02;
+RS_M3 = $03;
+RS_M4 = $04;
+RS_M5 = $05;
+RS_M6 = $06;
+RS_M7 = $07;
+RS_M8 = $08;
+RS_M9 = $09;
+RS_M10 = $0a;
+RS_M11 = $0b;
+RS_M12 = $0c;
+RS_M13 = $0d;
+RS_M14 = $0e;
+RS_M15 = $0f;
+RS_M16 = $10;
+RS_M17 = $11;
+RS_M18 = $12;
+RS_M19 = $13;
+RS_M20 = $14;
+RS_M21 = $15;
+RS_M22 = $16;
+RS_M23 = $17;
+RS_M24 = $18;
+RS_M25 = $19;
+RS_M26 = $1a;
+RS_M27 = $1b;
+RS_M28 = $1c;
+RS_M29 = $1d;
+RS_M30 = $1e;
+RS_M31 = $1f;
+RS_CR = $00;
+RS_CR0 = $01;
+RS_CR1 = $02;
+RS_CR2 = $03;
+RS_CR3 = $04;
+RS_CR4 = $05;
+RS_CR5 = $06;
+RS_CR6 = $07;
+RS_CR7 = $08;
+RS_XER = $09;
+RS_LR = $0a;
+RS_CTR = $0b;
+RS_FPSCR = $0c;
diff --git a/compiler/pp.lpi b/compiler/pp.lpi
new file mode 100644
index 0000000000..86eb149efb
--- /dev/null
+++ b/compiler/pp.lpi
@@ -0,0 +1,136 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <PathDelim Value="\"/>
+ <Version Value="5"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ </Flags>
+ <MainUnit Value="0"/>
+ <ActiveEditorIndexAtStart Value="0"/>
+ <IconPath Value="./"/>
+ <TargetFileExt Value=".exe"/>
+ <Title Value="pp"/>
+ </General>
+ <JumpHistory Count="0" HistoryIndex="-1"/>
+ <Units Count="7">
+ <Unit0>
+ <CursorPos X="1" Y="208"/>
+ <EditorIndex Value="0"/>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <Loaded Value="True"/>
+ <TopLine Value="171"/>
+ <UnitName Value="pp"/>
+ <UsageCount Value="23"/>
+ </Unit0>
+ <Unit1>
+ <CursorPos X="1" Y="1"/>
+ <Filename Value="cstreams.pas"/>
+ <TopLine Value="1"/>
+ <UnitName Value="cstreams"/>
+ <UsageCount Value="10"/>
+ </Unit1>
+ <Unit2>
+ <CursorPos X="5" Y="1548"/>
+ <Filename Value="globals.pas"/>
+ <TopLine Value="1544"/>
+ <UnitName Value="globals"/>
+ <UsageCount Value="10"/>
+ </Unit2>
+ <Unit3>
+ <CursorPos X="1" Y="1"/>
+ <Filename Value="fpcdefs.inc"/>
+ <TopLine Value="1"/>
+ <UsageCount Value="10"/>
+ </Unit3>
+ <Unit4>
+ <CursorPos X="5" Y="32"/>
+ <Filename Value="x86\cpubase.pas"/>
+ <TopLine Value="13"/>
+ <UsageCount Value="10"/>
+ </Unit4>
+ <Unit5>
+ <CursorPos X="1" Y="140"/>
+ <Filename Value="options.pas"/>
+ <TopLine Value="121"/>
+ <UnitName Value="options"/>
+ <UsageCount Value="10"/>
+ </Unit5>
+ <Unit6>
+ <CursorPos X="28" Y="292"/>
+ <Filename Value="compiler.pas"/>
+ <TopLine Value="290"/>
+ <UnitName Value="compiler"/>
+ <UsageCount Value="10"/>
+ </Unit6>
+ </Units>
+ <PublishOptions>
+ <Version Value="2"/>
+ <DestinationDirectory Value="c:\temp/publishedproject/"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="5"/>
+ <PathDelim Value="\"/>
+ <SearchPaths>
+ <IncludeFiles Value="i386\"/>
+ <OtherUnitFiles Value="i386\;x86\;systems\"/>
+ <UnitOutputDirectory Value="C:\fpc\compiler\myunits"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <D2Extensions Value="False"/>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <CodeGeneration>
+ <Generate Value="Faster"/>
+ <TargetProcessor Value="3"/>
+ <TargetOS Value="Win32"/>
+ </CodeGeneration>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CustomOptions Value="-dGDB
+-di386
+"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+ <Debugging>
+ <BreakPoints Count="1">
+ <Item1>
+ <Source Value="pp.pas"/>
+ <Line Value="208"/>
+ </Item1>
+ </BreakPoints>
+ <Exceptions Count="2">
+ <Item1>
+ <Name Value="ECodetoolError"/>
+ </Item1>
+ <Item2>
+ <Name Value="EFOpenError"/>
+ </Item2>
+ </Exceptions>
+ </Debugging>
+</CONFIG>
diff --git a/compiler/pp.pas b/compiler/pp.pas
new file mode 100644
index 0000000000..5d7c4b5c3e
--- /dev/null
+++ b/compiler/pp.pas
@@ -0,0 +1,207 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Commandline compiler for Free Pascal
+
+ 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.
+
+ ****************************************************************************
+}
+program pp;
+
+{
+ possible compiler switches:
+ -----------------------------------------------------------------
+ CMEM use cmem unit for better memory debugging
+ I386 generate a compiler for the Intel i386+
+ x86_64 generate a compiler for the AMD x86-64 architecture
+ M68K generate a compiler for the M68000
+ SPARC generate a compiler for SPARC
+ POWERPC generate a compiler for the PowerPC
+ POWERPC64 generate a compiler for the PowerPC64 architecture
+ VIS generate a compile for the VIS
+ DEBUG version with debug code is generated
+ EXTDEBUG some extra debug code is executed
+ SUPPORT_MMX only i386: releases the compiler switch
+ MMX which allows the compiler to generate
+ MMX instructions
+ EXTERN_MSG Don't compile the msgfiles in the compiler, always
+ use external messagefiles, default for TP
+ TEST_GENERIC Test Generic version of code generator
+ (uses generic RTL calls)
+ -----------------------------------------------------------------
+ cpuflags The target processor has status flags (on by default)
+ cpufpemu The target compiler will also support emitting software
+ floating point operations
+ cpu64bit The target is a 64-bit processor
+ -----------------------------------------------------------------
+
+ Required switches for a i386 compiler be compiled by Free Pascal Compiler:
+ I386
+}
+
+{$i fpcdefs.inc}
+
+{$ifdef FPC}
+ { exactly one target CPU must be defined }
+ {$ifdef I386}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif I386}
+ {$ifdef x86_64}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif x86_64}
+ {$ifdef M68K}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif M68K}
+ {$ifdef vis}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif}
+ {$ifdef iA64}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif iA64}
+ {$ifdef POWERPC}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif POWERPC}
+ {$ifdef POWERPC64}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif POWERPC64}
+ {$ifdef ALPHA}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif ALPHA}
+ {$ifdef SPARC}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif SPARC}
+ {$ifdef ARM}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif ARM}
+ {$ifdef MIPS}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+ {$endif MIPS}
+ {$ifndef CPUDEFINED}
+ {$fatal A CPU type switch must be defined}
+ {$endif CPUDEFINED}
+ {$ifdef support_mmx}
+ {$ifndef i386}
+ {$fatal I386 switch must be on for MMX support}
+ {$endif i386}
+ {$endif support_mmx}
+{$endif}
+
+uses
+{$ifdef cmem}
+ cmem,
+{$endif cmem}
+{$ifdef FPC}
+ {$ifdef profile}
+ profile,
+ {$endif profile}
+ {$ifndef NOCATCH}
+ {$ifdef Unix}
+ catch,
+ {$endif}
+ {$ifdef go32v2}
+ catch,
+ {$endif}
+ {$ifdef WATCOM}
+ catch,
+ {$endif}
+ {$endif NOCATCH}
+{$endif FPC}
+ globals,compiler;
+
+var
+ oldexit : pointer;
+procedure myexit;
+begin
+ exitproc:=oldexit;
+{$ifdef nocatch}
+ exit;
+{$endif nocatch}
+{ Show Runtime error if there was an error }
+ if (erroraddr<>nil) then
+ begin
+ case exitcode of
+ 100:
+ begin
+ erroraddr:=nil;
+ writeln('Error while reading file');
+ end;
+ 101:
+ begin
+ erroraddr:=nil;
+ writeln('Error while writing file');
+ end;
+ 202:
+ begin
+ erroraddr:=nil;
+ writeln('Error: Stack Overflow');
+ end;
+ 203:
+ begin
+ erroraddr:=nil;
+ writeln('Error: Out of memory');
+ end;
+ end;
+ { we cannot use aktfilepos.file because all memory might have been
+ freed already !
+ But we can use global parser_current_file var }
+ Writeln('Compilation aborted ',parser_current_file,':',aktfilepos.line);
+ end;
+end;
+
+begin
+ oldexit:=exitproc;
+ exitproc:=@myexit;
+{$ifdef extheaptrc}
+ keepreleased:=true;
+{$endif extheaptrc}
+ SetFPUExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,
+ exOverflow, exUnderflow, exPrecision]);
+{ Call the compiler with empty command, so it will take the parameters }
+ Halt(compiler.Compile(''));
+end.
diff --git a/compiler/ppc.cfg b/compiler/ppc.cfg
new file mode 100644
index 0000000000..ff4473a418
--- /dev/null
+++ b/compiler/ppc.cfg
@@ -0,0 +1,40 @@
+-$A8
+-$B-
+-$C-
+-$D+
+-$E-
+-$F-
+-$G+
+-$H-
+-$I+
+-$J+
+-$K-
+-$L+
+-$M-
+-$N+
+-$O-
+-$P+
+-$Q+
+-$R+
+-$S-
+-$T-
+-$U-
+-$V-
+-$W+
+-$X+
+-$YD
+-$Z1
+-cc
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-LE"e:\program files\borland\delphi6\Projects\Bpl"
+-LN"e:\program files\borland\delphi6\Projects\Bpl"
+-U"i386;x86;systems"
+-O"i386;x86;systems"
+-I"i386;x86;systems"
+-R"i386;x86;systems"
+-Ddelphi i386 gdb support_mmx cpu86 noopt
diff --git a/compiler/ppc.conf b/compiler/ppc.conf
new file mode 100644
index 0000000000..7d716c1679
--- /dev/null
+++ b/compiler/ppc.conf
@@ -0,0 +1,39 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"."
+-N"."
+-U"i386:targets"
+-O"i386:targets"
+-I"i386:targets"
+-R"i386:targets"
+-DDELPHI;i386
diff --git a/compiler/ppc.dof b/compiler/ppc.dof
new file mode 100644
index 0000000000..3c3966031f
--- /dev/null
+++ b/compiler/ppc.dof
@@ -0,0 +1,95 @@
+[FileVersion]
+Version=6.0
+[Compiler]
+A=8
+B=0
+C=0
+D=1
+E=0
+F=0
+G=1
+H=0
+I=1
+J=1
+K=0
+L=1
+M=0
+N=1
+O=0
+P=1
+Q=1
+R=1
+S=0
+T=0
+U=0
+V=0
+W=1
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=0
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+[Directories]
+OutputDir=
+UnitOutputDir=
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=i386;x86;systems
+Packages=VCL50;VCLX50;VCLSMP50;VCLDB50;VCLADO50;ibevnt50;VCLBDE50;VCLDBX50;QRPT50;TEEUI50;TEEDB50;TEE50;DSS50;TEEQR50;VCLIB50;VCLMID50;VCLIE50;INETDB50;INET50;NMFAST50;WEBMID50;dclocx50;dclaxserver50
+Conditionals=delphi i386 gdb support_mmx cpu86 noopt
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Version Info]
+IncludeVerInfo=0
+AutoIncBuild=0
+MajorVer=1
+MinorVer=0
+Release=0
+Build=0
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=1043
+CodePage=1252
+[Version Info Keys]
+CompanyName=
+FileDescription=
+FileVersion=1.0.0.0
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=1.0.0.0
+Comments=
+[HistoryLists\hlConditionals]
+Count=2
+Item0=delphi i386 gdb support_mmx cpu86 noopt
+Item1=delphi i386 gdb support_mmx cpu86
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[HistoryLists\hlSearchPath]
+Count=3
+Item0=i386;x86;systems
+Item1=i386;x86
+Item2=i386 x86
diff --git a/compiler/ppc.dpr b/compiler/ppc.dpr
new file mode 100644
index 0000000000..1dca40280f
--- /dev/null
+++ b/compiler/ppc.dpr
@@ -0,0 +1,157 @@
+{
+ $Id: ppc.dpr,v 1.6 2002/10/05 12:43:27 carl Exp $
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ Commandline compiler for Free Pascal
+
+ 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.
+
+ ****************************************************************************
+}
+program ppc;
+
+{$MINSTACKSIZE $00004000}
+{$MAXSTACKSIZE $00100000}
+{$IMAGEBASE $00400000}
+{$APPTYPE CONSOLE}
+
+{
+ possible compiler switches (* marks a currently required switch):
+ -----------------------------------------------------------------
+ USE_RHIDE generates errors and warning in an format recognized
+ by rhide
+ GDB* support of the GNU Debugger
+ I386 generate a compiler for the Intel i386+
+ M68K generate a compiler for the M68000
+ USEOVERLAY compiles a TP version which uses overlays
+ DEBUG version with debug code is generated
+ EXTDEBUG some extra debug code is executed
+ SUPPORT_MMX only i386: releases the compiler switch
+ MMX which allows the compiler to generate
+ MMX instructions
+ EXTERN_MSG Don't compile the msgfiles in the compiler, always
+ use external messagefiles, default for TP
+ NOAG386INT no Intel Assembler output
+ NOAG386NSM no NASM output
+ NOAG386BIN leaves out the binary writer, default for TP
+ LOGMEMBLOCKS adds memory manager which logs the size of
+ each allocated memory block, the information
+ is written to memuse.log after compiling
+ -----------------------------------------------------------------
+
+ Required switches for a i386 compiler be compiled by Free Pascal Compiler:
+ GDB;I386
+
+ Required switches for a i386 compiler be compiled by Turbo Pascal:
+ GDB;I386;TP
+
+ Required switches for a 68000 compiler be compiled by Turbo Pascal:
+ GDB;M68k;TP
+}
+
+{$i fpcdefs.inc}
+
+{$ifdef FPC}
+ {$ifndef GDB}
+ { people can try to compile without GDB }
+ { $error The compiler switch GDB must be defined}
+ {$endif GDB}
+ { but I386 or M68K must be defined }
+ { and only one of the two }
+ {$ifndef I386}
+ {$ifndef M68K}
+ {$fatal One of the switches I386 or M68K must be defined}
+ {$endif M68K}
+ {$endif I386}
+ {$ifdef I386}
+ {$ifdef M68K}
+ {$fatal ONLY one of the switches I386 or M68K must be defined}
+ {$endif M68K}
+ {$endif I386}
+ {$ifdef support_mmx}
+ {$ifndef i386}
+ {$fatal I386 switch must be on for MMX support}
+ {$endif i386}
+ {$endif support_mmx}
+{$endif}
+
+uses
+{$ifdef FPC}
+ {$ifdef profile}
+ profile,
+ {$endif profile}
+ {$ifdef heaptrc}
+ ppheap,
+ {$endif heaptrc}
+ {$ifdef Unix}
+ catch,
+ {$endif}
+ {$ifdef go32v2}
+ {$ifdef DEBUG}
+ {$define NOCATCH}
+ {$endif DEBUG}
+ catch,
+ {$endif}
+ { we've now a lineinfo unit for all OSes }
+ {$ifdef DEBUG}
+ lineinfo,
+ {$endif DEBUG}
+{$endif FPC}
+ globals,compiler;
+
+var
+ oldexit : pointer;
+procedure myexit;
+begin
+ exitproc:=oldexit;
+{ Show Runtime error if there was an error }
+ if (erroraddr<>nil) then
+ begin
+ case exitcode of
+ 100:
+ begin
+ erroraddr:=nil;
+ writeln('Error while reading file');
+ end;
+ 101:
+ begin
+ erroraddr:=nil;
+ writeln('Error while writing file');
+ end;
+ 202:
+ begin
+ erroraddr:=nil;
+ writeln('Error: Stack Overflow');
+ end;
+ 203:
+ begin
+ erroraddr:=nil;
+ writeln('Error: Out of memory');
+ end;
+ end;
+ { we cannot use aktfilepos.file because all memory might have been
+ freed already !
+ But we can use global parser_current_file var }
+ Writeln('Compilation aborted ',parser_current_file,':',aktfilepos.line);
+ end;
+end;
+
+begin
+ oldexit:=exitproc;
+ exitproc:=@myexit;
+
+{ Call the compiler with empty command, so it will take the parameters }
+ Halt(compiler.Compile(''));
+end.
diff --git a/compiler/ppheap.pas b/compiler/ppheap.pas
new file mode 100644
index 0000000000..11ca168799
--- /dev/null
+++ b/compiler/ppheap.pas
@@ -0,0 +1,147 @@
+{
+ Copyright (c) 1998-2002 by Pierre Muller
+
+ Simple unit to add source line and column to each
+ memory allocation made with heaptrc unit
+
+ 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 ppheap;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses heaptrc;
+
+ { call this function before any memory allocation
+ in a unit initialization code (PM) }
+
+ procedure pp_heap_init;
+
+ procedure ppheap_register_file(name : string;index : longint);
+
+
+implementation
+
+ uses
+ cutils,globtype,globals,fmodule;
+
+{*****************************************************************************
+ Filename registration
+*****************************************************************************}
+
+ const
+ MaxFiles = 1024;
+ MaxNameLength = 39;
+
+ type
+ theapfileinfo = record
+ name : string[MaxNameLength];
+ index : longint;
+ end;
+
+ tfileinfoarray = array [1..MaxFiles] of theapfileinfo;
+
+ var
+ fileinfoarray : tfileinfoarray;
+ last_index : longint;
+
+
+ procedure ppheap_register_file(name : string;index : longint);
+ begin
+ inc(last_index);
+ if last_index <= MaxFiles then
+ begin
+ fileinfoarray[last_index].name:=copy(name,1,MaxNameLength);
+ fileinfoarray[last_index].index:=index;
+ end
+ else
+ writeln(stderr,'file',name,' has index ',index);
+ end;
+
+
+ function getfilename(index : longint) : string;
+ var
+ i : longint;
+ begin
+ for i:=1 to last_index do
+ begin
+ if fileinfoarray[i].index=index then
+ begin
+ getfilename:=fileinfoarray[i].name;
+ exit;
+ end;
+ end;
+ getfilename:=tostr(index);
+ end;
+
+
+{*****************************************************************************
+ Heaptrc callbacks
+*****************************************************************************}
+
+ type
+ pextra_info = ^textra_info;
+ textra_info = record
+ line,
+ col,
+ fileindex : longint;
+ end;
+
+ procedure set_extra_info(p : pointer);
+ begin
+ with pextra_info(p)^ do
+ begin
+ line:=aktfilepos.line;
+ col:=aktfilepos.column;
+ if assigned(current_module) then
+ fileindex:=current_module.unit_index*100000+aktfilepos.fileindex
+ else
+ fileindex:=aktfilepos.fileindex;
+ end;
+ end;
+
+
+ procedure show_extra_info(var t : text;p : pointer);
+ begin
+ with pextra_info(p)^ do
+ begin
+ writeln(t,getfilename(fileindex)+'('+tostr(line)+','+tostr(col)+') ');
+ end;
+ end;
+
+
+ const
+ pp_heap_inited : boolean = false;
+
+ procedure pp_heap_init;
+ begin
+ if not pp_heap_inited then
+ begin
+ keepreleased:=true;
+ SetHeapTraceOutput('heap.log');
+ SetHeapExtraInfo(sizeof(textra_info),
+ @set_extra_info,
+ @show_extra_info);
+ end;
+ pp_heap_inited:=true;
+ end;
+
+
+begin
+ pp_heap_init;
+end.
diff --git a/compiler/ppu.pas b/compiler/ppu.pas
new file mode 100644
index 0000000000..3f06f7a7b8
--- /dev/null
+++ b/compiler/ppu.pas
@@ -0,0 +1,1068 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Routines to read/write ppu files
+
+ 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 ppu;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype;
+
+{ Also write the ppu if only crc if done, this can be used with ppudump to
+ see the differences between the intf and implementation }
+{ define INTFPPU}
+
+{$ifdef Test_Double_checksum}
+var
+ CRCFile : text;
+const
+ CRC_array_Size = 200000;
+type
+ tcrc_array = array[0..crc_array_size] of longint;
+ pcrc_array = ^tcrc_array;
+{$endif Test_Double_checksum}
+
+const
+ CurrentPPUVersion=50;
+
+{ buffer sizes }
+ maxentrysize = 1024;
+ ppubufsize = 16384;
+
+{ppu entries}
+ mainentryid = 1;
+ subentryid = 2;
+ {special}
+ iberror = 0;
+ ibstartdefs = 248;
+ ibenddefs = 249;
+ ibstartsyms = 250;
+ ibendsyms = 251;
+ ibendinterface = 252;
+ ibendimplementation = 253;
+ ibendbrowser = 254;
+ ibend = 255;
+ {general}
+ ibmodulename = 1;
+ ibsourcefiles = 2;
+ ibloadunit = 3;
+ ibinitunit = 4;
+ iblinkunitofiles = 5;
+ iblinkunitstaticlibs = 6;
+ iblinkunitsharedlibs = 7;
+ iblinkotherofiles = 8;
+ iblinkotherstaticlibs = 9;
+ iblinkothersharedlibs = 10;
+ ibsymref = 12;
+ ibdefref = 13;
+ ibendsymtablebrowser = 14;
+ ibbeginsymtablebrowser = 15;
+{$IFDEF MACRO_DIFF_HINT}
+ ibusedmacros = 16;
+{$ENDIF}
+ ibderefdata = 17;
+ ibexportedmacros = 18;
+ ibderefmap = 19;
+ {syms}
+ ibtypesym = 20;
+ ibprocsym = 21;
+ ibglobalvarsym = 22;
+ ibconstsym = 23;
+ ibenumsym = 24;
+ ibtypedconstsym = 25;
+ ibabsolutevarsym = 26;
+ ibpropertysym = 27;
+ ibfieldvarsym = 28;
+ ibunitsym = 29; { needed for browser }
+ iblabelsym = 30;
+ ibsyssym = 31;
+ ibrttisym = 32;
+ iblocalvarsym = 33;
+ ibparavarsym = 34;
+ ibmacrosym = 35;
+ {definitions}
+ iborddef = 40;
+ ibpointerdef = 41;
+ ibarraydef = 42;
+ ibprocdef = 43;
+ ibshortstringdef = 44;
+ ibrecorddef = 45;
+ ibfiledef = 46;
+ ibformaldef = 47;
+ ibobjectdef = 48;
+ ibenumdef = 49;
+ ibsetdef = 50;
+ ibprocvardef = 51;
+ ibfloatdef = 52;
+ ibclassrefdef = 53;
+ iblongstringdef = 54;
+{$ifdef ansistring_bits}
+ ibansistring16def = 58;
+ ibansistring32def = 55;
+ ibansistring64def = 59;
+{$else}
+ ibansistringdef = 55;
+{$endif}
+ ibwidestringdef = 56;
+ ibvariantdef = 57;
+ {implementation/objectdata}
+ ibnodetree = 80;
+ ibasmsymbols = 81;
+
+{ unit flags }
+ uf_init = $1;
+ uf_finalize = $2;
+ uf_big_endian = $4;
+ uf_has_browser = $10;
+ uf_in_library = $20; { is the file in another file than <ppufile>.* ? }
+ uf_smart_linked = $40; { the ppu can be smartlinked }
+ uf_static_linked = $80; { the ppu can be linked static }
+ uf_shared_linked = $100; { the ppu can be linked shared }
+ uf_local_browser = $200;
+ uf_no_link = $400; { unit has no .o generated, but can still have
+ external linking! }
+ uf_has_resources = $800; { unit has resource string section }
+ uf_little_endian = $1000;
+ uf_release = $2000; { unit was compiled with -Ur option }
+ uf_threadvars = $4000; { unit has threadvars }
+ uf_fpu_emulation = $8000; { this unit was compiled with fpu emulation on }
+ uf_has_debuginfo = $10000; { this unit has debuginfo generated }
+ uf_local_symtable = $20000; { this unit has a local symtable stored }
+ uf_uses_variants = $40000; { this unit uses variants }
+ uf_has_resourcefiles = $80000; { this unit has external resources (using $R directive)}
+
+
+type
+ ppureal=extended;
+
+ tppuerror=(ppuentrytoobig,ppuentryerror);
+
+ tppuheader=record
+ id : array[1..3] of char; { = 'PPU' }
+ ver : array[1..3] of char;
+ compiler : word;
+ cpu : word;
+ target : word;
+ flags : longint;
+ size : longint; { size of the ppufile without header }
+ checksum : cardinal; { checksum for this ppufile }
+ interface_checksum : cardinal;
+ future : array[0..2] of longint;
+ end;
+
+ tppuentry=packed record
+ size : longint;
+ id : byte;
+ nr : byte;
+ end;
+
+ tppufile=class
+ private
+ f : file;
+ mode : byte; {0 - Closed, 1 - Reading, 2 - Writing}
+ fname : string;
+ fsize : integer;
+{$ifdef Test_Double_checksum}
+ public
+ crcindex,
+ crc_index,
+ crcindex2,
+ crc_index2 : cardinal;
+ crc_test,
+ crc_test2 : pcrc_array;
+ private
+{$endif def Test_Double_checksum}
+ change_endian : boolean;
+ buf : pchar;
+ bufstart,
+ bufsize,
+ bufidx : integer;
+ entrybufstart,
+ entrystart,
+ entryidx : integer;
+ entry : tppuentry;
+ closed,
+ tempclosed : boolean;
+ closepos : integer;
+ public
+ entrytyp : byte;
+ header : tppuheader;
+ size : integer;
+ crc,
+ interface_crc : cardinal;
+ error,
+ do_crc,
+ do_interface_crc : boolean;
+ crc_only : boolean; { used to calculate interface_crc before implementation }
+ constructor Create(const fn:string);
+ destructor Destroy;override;
+ procedure flush;
+ procedure closefile;
+ function CheckPPUId:boolean;
+ function GetPPUVersion:integer;
+ procedure NewHeader;
+ procedure NewEntry;
+ {read}
+ function openfile:boolean;
+ procedure reloadbuf;
+ procedure readdata(var b;len:integer);
+ procedure skipdata(len:integer);
+ function readentry:byte;
+ function EndOfEntry:boolean;
+ function entrysize:longint;
+ procedure getdatabuf(var b;len:integer;var res:integer);
+ procedure getdata(var b;len:integer);
+ function getbyte:byte;
+ function getword:word;
+ function getlongint:longint;
+ function getint64:int64;
+ function getaint:aint;
+ function getreal:ppureal;
+ function getstring:string;
+ procedure getnormalset(var b);
+ procedure getsmallset(var b);
+ function skipuntilentry(untilb:byte):boolean;
+ {write}
+ function createfile:boolean;
+ procedure writeheader;
+ procedure writebuf;
+ procedure writedata(const b;len:integer);
+ procedure writeentry(ibnr:byte);
+ procedure putdata(const b;len:integer);
+ procedure putbyte(b:byte);
+ procedure putword(w:word);
+ procedure putlongint(l:longint);
+ procedure putint64(i:int64);
+ procedure putaint(i:aint);
+ procedure putreal(d:ppureal);
+ procedure putstring(s:string);
+ procedure putnormalset(const b);
+ procedure putsmallset(const b);
+ procedure tempclose;
+ function tempopen:boolean;
+ end;
+
+implementation
+
+ uses
+{$ifdef Test_Double_checksum}
+ comphook,
+{$endif def Test_Double_checksum}
+ crc,
+ cutils;
+
+{*****************************************************************************
+ Endian Handling
+*****************************************************************************}
+
+Function SwapLong(x : longint): longint;
+var
+ y : word;
+ z : word;
+Begin
+ y := x shr 16;
+ y := word(longint(y) shl 8) or (y shr 8);
+ z := x and $FFFF;
+ z := word(longint(z) shl 8) or (z shr 8);
+ SwapLong := (longint(z) shl 16) or longint(y);
+End;
+
+
+Function SwapWord(x : word): word;
+var
+ z : byte;
+Begin
+ z := x shr 8;
+ x := x and $ff;
+ x := word(x shl 8);
+ SwapWord := x or z;
+End;
+
+
+{*****************************************************************************
+ TPPUFile
+*****************************************************************************}
+
+constructor tppufile.Create(const fn:string);
+begin
+ fname:=fn;
+ change_endian:=false;
+ crc_only:=false;
+ Mode:=0;
+ NewHeader;
+ Error:=false;
+ closed:=true;
+ tempclosed:=false;
+ getmem(buf,ppubufsize);
+end;
+
+
+destructor tppufile.destroy;
+begin
+ closefile;
+ if assigned(buf) then
+ freemem(buf,ppubufsize);
+end;
+
+
+procedure tppufile.flush;
+begin
+ if Mode=2 then
+ writebuf;
+end;
+
+
+procedure tppufile.closefile;
+begin
+{$ifdef Test_Double_checksum}
+ if mode=2 then
+ begin
+ if assigned(crc_test) then
+ dispose(crc_test);
+ if assigned(crc_test2) then
+ dispose(crc_test2);
+ end;
+{$endif Test_Double_checksum}
+ if Mode<>0 then
+ begin
+ Flush;
+ {$I-}
+ system.close(f);
+ {$I+}
+ if ioresult<>0 then;
+ Mode:=0;
+ closed:=true;
+ end;
+end;
+
+
+function tppufile.CheckPPUId:boolean;
+begin
+ CheckPPUId:=((Header.Id[1]='P') and (Header.Id[2]='P') and (Header.Id[3]='U'));
+end;
+
+
+function tppufile.GetPPUVersion:integer;
+var
+ l : integer;
+ code : integer;
+begin
+ Val(header.ver[1]+header.ver[2]+header.ver[3],l,code);
+ if code=0 then
+ GetPPUVersion:=l
+ else
+ GetPPUVersion:=0;
+end;
+
+
+procedure tppufile.NewHeader;
+var
+ s : string;
+begin
+ fillchar(header,sizeof(tppuheader),0);
+ str(currentppuversion,s);
+ while length(s)<3 do
+ s:='0'+s;
+ with header do
+ begin
+ Id[1]:='P';
+ Id[2]:='P';
+ Id[3]:='U';
+ Ver[1]:=s[1];
+ Ver[2]:=s[2];
+ Ver[3]:=s[3];
+ end;
+end;
+
+
+{*****************************************************************************
+ TPPUFile Reading
+*****************************************************************************}
+
+function tppufile.openfile:boolean;
+var
+ ofmode : byte;
+ i : integer;
+begin
+ openfile:=false;
+ assign(f,fname);
+ ofmode:=filemode;
+ filemode:=$0;
+ {$I-}
+ reset(f,1);
+ {$I+}
+ filemode:=ofmode;
+ if ioresult<>0 then
+ exit;
+ closed:=false;
+{read ppuheader}
+ fsize:=filesize(f);
+ if fsize<sizeof(tppuheader) then
+ exit;
+ blockread(f,header,sizeof(tppuheader),i);
+ { The header is always stored in little endian order }
+ { therefore swap if on a big endian machine }
+{$IFDEF ENDIAN_BIG}
+ header.compiler := SwapWord(header.compiler);
+ header.cpu := SwapWord(header.cpu);
+ header.target := SwapWord(header.target);
+ header.flags := SwapLong(header.flags);
+ header.size := SwapLong(header.size);
+ header.checksum := cardinal(SwapLong(longint(header.checksum)));
+ header.interface_checksum := cardinal(SwapLong(longint(header.interface_checksum)));
+{$ENDIF}
+ { the PPU DATA is stored in native order }
+ if (header.flags and uf_big_endian) = uf_big_endian then
+ Begin
+{$IFDEF ENDIAN_LITTLE}
+ change_endian := TRUE;
+{$ELSE}
+ change_endian := FALSE;
+{$ENDIF}
+ End
+ else if (header.flags and uf_little_endian) = uf_little_endian then
+ Begin
+{$IFDEF ENDIAN_BIG}
+ change_endian := TRUE;
+{$ELSE}
+ change_endian := FALSE;
+{$ENDIF}
+ End;
+{reset buffer}
+ bufstart:=i;
+ bufsize:=0;
+ bufidx:=0;
+ Mode:=1;
+ FillChar(entry,sizeof(tppuentry),0);
+ entryidx:=0;
+ entrystart:=0;
+ entrybufstart:=0;
+ Error:=false;
+ openfile:=true;
+end;
+
+
+procedure tppufile.reloadbuf;
+begin
+ inc(bufstart,bufsize);
+ blockread(f,buf^,ppubufsize,bufsize);
+ bufidx:=0;
+end;
+
+
+procedure tppufile.readdata(var b;len:integer);
+var
+ p : pchar;
+ left,
+ idx : integer;
+begin
+ p:=pchar(@b);
+ idx:=0;
+ while len>0 do
+ begin
+ left:=bufsize-bufidx;
+ if len>left then
+ begin
+ move(buf[bufidx],p[idx],left);
+ dec(len,left);
+ inc(idx,left);
+ reloadbuf;
+ if bufsize=0 then
+ exit;
+ end
+ else
+ begin
+ move(buf[bufidx],p[idx],len);
+ inc(bufidx,len);
+ exit;
+ end;
+ end;
+end;
+
+
+procedure tppufile.skipdata(len:integer);
+var
+ left : integer;
+begin
+ while len>0 do
+ begin
+ left:=bufsize-bufidx;
+ if len>left then
+ begin
+ dec(len,left);
+ reloadbuf;
+ if bufsize=0 then
+ exit;
+ end
+ else
+ begin
+ inc(bufidx,len);
+ exit;
+ end;
+ end;
+end;
+
+
+function tppufile.readentry:byte;
+begin
+ if entryidx<entry.size then
+ skipdata(entry.size-entryidx);
+ readdata(entry,sizeof(tppuentry));
+ if change_endian then
+ entry.size:=swaplong(entry.size);
+ entrystart:=bufstart+bufidx;
+ entryidx:=0;
+ if not(entry.id in [mainentryid,subentryid]) then
+ begin
+ readentry:=iberror;
+ error:=true;
+ exit;
+ end;
+ readentry:=entry.nr;
+end;
+
+
+function tppufile.endofentry:boolean;
+begin
+ endofentry:=(entryidx>=entry.size);
+end;
+
+
+function tppufile.entrysize:longint;
+begin
+ entrysize:=entry.size;
+end;
+
+
+procedure tppufile.getdatabuf(var b;len:integer;var res:integer);
+begin
+ if entryidx+len>entry.size then
+ res:=entry.size-entryidx
+ else
+ res:=len;
+ readdata(b,res);
+ inc(entryidx,res);
+end;
+
+
+procedure tppufile.getdata(var b;len:integer);
+begin
+ if entryidx+len>entry.size then
+ begin
+ error:=true;
+ exit;
+ end;
+ readdata(b,len);
+ inc(entryidx,len);
+end;
+
+
+function tppufile.getbyte:byte;
+var
+ b : byte;
+begin
+ if entryidx+1>entry.size then
+ begin
+ error:=true;
+ getbyte:=0;
+ exit;
+ end;
+ readdata(b,1);
+ getbyte:=b;
+ inc(entryidx);
+end;
+
+
+function tppufile.getword:word;
+var
+ w : word;
+begin
+ if entryidx+2>entry.size then
+ begin
+ error:=true;
+ getword:=0;
+ exit;
+ end;
+ readdata(w,2);
+ if change_endian then
+ getword:=swapword(w)
+ else
+ getword:=w;
+ inc(entryidx,2);
+end;
+
+
+function tppufile.getlongint:longint;
+var
+ l : longint;
+begin
+ if entryidx+4>entry.size then
+ begin
+ error:=true;
+ getlongint:=0;
+ exit;
+ end;
+ readdata(l,4);
+ if change_endian then
+ getlongint:=swaplong(l)
+ else
+ getlongint:=l;
+ inc(entryidx,4);
+end;
+
+
+function tppufile.getint64:int64;
+var
+ i : int64;
+begin
+ if entryidx+8>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ readdata(i,8);
+ if change_endian then
+ result:=swapint64(i)
+ else
+ result:=i;
+ inc(entryidx,8);
+end;
+
+
+function tppufile.getaint:aint;
+begin
+{$ifdef cpu64bit}
+ result:=getint64;
+{$else cpu64bit}
+ result:=getlongint;
+{$endif cpu64bit}
+end;
+
+
+function tppufile.getreal:ppureal;
+var
+ d : ppureal;
+begin
+ if entryidx+sizeof(ppureal)>entry.size then
+ begin
+ error:=true;
+ getreal:=0;
+ exit;
+ end;
+ readdata(d,sizeof(ppureal));
+ getreal:=d;
+ inc(entryidx,sizeof(ppureal));
+end;
+
+
+function tppufile.getstring:string;
+var
+ s : string;
+begin
+ s[0]:=chr(getbyte);
+ if entryidx+length(s)>entry.size then
+ begin
+ error:=true;
+ exit;
+ end;
+ ReadData(s[1],length(s));
+ getstring:=s;
+ inc(entryidx,length(s));
+end;
+
+
+procedure tppufile.getsmallset(var b);
+var
+ l : longint;
+begin
+ l:=getlongint;
+ longint(b):=l;
+end;
+
+
+procedure tppufile.getnormalset(var b);
+type
+ SetLongintArray = Array [0..7] of longint;
+var
+ i : longint;
+begin
+ if change_endian then
+ begin
+ for i:=0 to 7 do
+ SetLongintArray(b)[i]:=getlongint;
+ end
+ else
+ getdata(b,32);
+end;
+
+
+function tppufile.skipuntilentry(untilb:byte):boolean;
+var
+ b : byte;
+begin
+ repeat
+ b:=readentry;
+ until (b in [ibend,iberror]) or ((b=untilb) and (entry.id=mainentryid));
+ skipuntilentry:=(b=untilb);
+end;
+
+
+{*****************************************************************************
+ TPPUFile Writing
+*****************************************************************************}
+
+function tppufile.createfile:boolean;
+begin
+ createfile:=false;
+{$ifdef INTFPPU}
+ if crc_only then
+ begin
+ fname:=fname+'.intf';
+ crc_only:=false;
+ end;
+{$endif}
+ if not crc_only then
+ begin
+ assign(f,fname);
+ {$ifdef MACOS}
+ {FPas is FreePascal's creator code on MacOS. See systems/mac_crea.txt}
+ SetDefaultMacOSCreator('FPas');
+ SetDefaultMacOSFiletype('FPPU');
+ {$endif}
+ {$I-}
+ rewrite(f,1);
+ {$I+}
+ {$ifdef MACOS}
+ SetDefaultMacOSCreator('MPS ');
+ SetDefaultMacOSFiletype('TEXT');
+ {$endif}
+ if ioresult<>0 then
+ exit;
+ Mode:=2;
+ {write header for sure}
+ blockwrite(f,header,sizeof(tppuheader));
+ end;
+ bufsize:=ppubufsize;
+ bufstart:=sizeof(tppuheader);
+ bufidx:=0;
+{reset}
+ crc:=cardinal($ffffffff);
+ interface_crc:=cardinal($ffffffff);
+ do_interface_crc:=true;
+ Error:=false;
+ do_crc:=true;
+ size:=0;
+ entrytyp:=mainentryid;
+{start}
+ NewEntry;
+ createfile:=true;
+end;
+
+
+procedure tppufile.writeheader;
+var
+ opos : integer;
+begin
+ if crc_only then
+ exit;
+ { flush buffer }
+ writebuf;
+ { update size (w/o header!) in the header }
+ header.size:=bufstart-sizeof(tppuheader);
+ { set the endian flag }
+{$ifndef FPC_BIG_ENDIAN}
+ header.flags := header.flags or uf_little_endian;
+{$else not FPC_BIG_ENDIAN}
+ header.flags := header.flags or uf_big_endian;
+ { Now swap the header in the correct endian (always little endian) }
+ header.compiler := SwapWord(header.compiler);
+ header.cpu := SwapWord(header.cpu);
+ header.target := SwapWord(header.target);
+ header.flags := SwapLong(header.flags);
+ header.size := SwapLong(header.size);
+ header.checksum := cardinal(SwapLong(longint(header.checksum)));
+ header.interface_checksum := cardinal(SwapLong(longint(header.interface_checksum)));
+{$endif not FPC_BIG_ENDIAN}
+{ write header and restore filepos after it }
+ opos:=filepos(f);
+ seek(f,0);
+ blockwrite(f,header,sizeof(tppuheader));
+ seek(f,opos);
+end;
+
+
+procedure tppufile.writebuf;
+begin
+ if not crc_only then
+ blockwrite(f,buf^,bufidx);
+ inc(bufstart,bufidx);
+ bufidx:=0;
+end;
+
+
+procedure tppufile.writedata(const b;len:integer);
+var
+ p : pchar;
+ left,
+ idx : integer;
+begin
+ if crc_only then
+ exit;
+ p:=pchar(@b);
+ idx:=0;
+ while len>0 do
+ begin
+ left:=bufsize-bufidx;
+ if len>left then
+ begin
+ move(p[idx],buf[bufidx],left);
+ dec(len,left);
+ inc(idx,left);
+ inc(bufidx,left);
+ writebuf;
+ end
+ else
+ begin
+ move(p[idx],buf[bufidx],len);
+ inc(bufidx,len);
+ exit;
+ end;
+ end;
+end;
+
+
+procedure tppufile.NewEntry;
+begin
+ with entry do
+ begin
+ id:=entrytyp;
+ nr:=ibend;
+ size:=0;
+ end;
+{Reset Entry State}
+ entryidx:=0;
+ entrybufstart:=bufstart;
+ entrystart:=bufstart+bufidx;
+{Alloc in buffer}
+ writedata(entry,sizeof(tppuentry));
+end;
+
+
+procedure tppufile.writeentry(ibnr:byte);
+var
+ opos : integer;
+begin
+{create entry}
+ entry.id:=entrytyp;
+ entry.nr:=ibnr;
+ entry.size:=entryidx;
+{it's already been sent to disk ?}
+ if entrybufstart<>bufstart then
+ begin
+ if not crc_only then
+ begin
+ {flush to be sure}
+ WriteBuf;
+ {write entry}
+ opos:=filepos(f);
+ seek(f,entrystart);
+ blockwrite(f,entry,sizeof(tppuentry));
+ seek(f,opos);
+ end;
+ entrybufstart:=bufstart;
+ end
+ else
+ move(entry,buf[entrystart-bufstart],sizeof(entry));
+{Add New Entry, which is ibend by default}
+ entrystart:=bufstart+bufidx; {next entry position}
+ NewEntry;
+end;
+
+
+procedure tppufile.putdata(const b;len:integer);
+begin
+ if do_crc then
+ begin
+ crc:=UpdateCrc32(crc,b,len);
+{$ifdef Test_Double_checksum}
+ if crc_only then
+ begin
+ crc_test2^[crc_index2]:=crc;
+{$ifdef Test_Double_checksum_write}
+ Writeln(CRCFile,crc);
+{$endif Test_Double_checksum_write}
+ if crc_index2<crc_array_size then
+ inc(crc_index2);
+ end
+ else
+ begin
+ if (crcindex2<crc_array_size) and (crcindex2<crc_index2) and
+ (crc_test2^[crcindex2]<>crc) then
+ Do_comment(V_Note,'impl CRC changed');
+{$ifdef Test_Double_checksum_write}
+ Writeln(CRCFile,crc);
+{$endif Test_Double_checksum_write}
+ inc(crcindex2);
+ end;
+{$endif def Test_Double_checksum}
+ if do_interface_crc then
+ begin
+ interface_crc:=UpdateCrc32(interface_crc,b,len);
+{$ifdef Test_Double_checksum}
+ if crc_only then
+ begin
+ crc_test^[crc_index]:=interface_crc;
+{$ifdef Test_Double_checksum_write}
+ Writeln(CRCFile,interface_crc);
+{$endif Test_Double_checksum_write}
+ if crc_index<crc_array_size then
+ inc(crc_index);
+ end
+ else
+ begin
+ if (crcindex<crc_array_size) and (crcindex<crc_index) and
+ (crc_test^[crcindex]<>interface_crc) then
+ Do_comment(V_Warning,'CRC changed');
+{$ifdef Test_Double_checksum_write}
+ Writeln(CRCFile,interface_crc);
+{$endif Test_Double_checksum_write}
+ inc(crcindex);
+ end;
+{$endif def Test_Double_checksum}
+ end;
+ end;
+ if not crc_only then
+ writedata(b,len);
+ inc(entryidx,len);
+end;
+
+
+procedure tppufile.putbyte(b:byte);
+begin
+ putdata(b,1);
+end;
+
+
+procedure tppufile.putword(w:word);
+begin
+ putdata(w,2);
+end;
+
+
+procedure tppufile.putlongint(l:longint);
+begin
+ putdata(l,4);
+end;
+
+
+procedure tppufile.putint64(i:int64);
+begin
+ putdata(i,8);
+end;
+
+
+procedure tppufile.putaint(i:aint);
+begin
+ putdata(i,sizeof(aint));
+end;
+
+
+procedure tppufile.putreal(d:ppureal);
+begin
+ putdata(d,sizeof(ppureal));
+end;
+
+
+ procedure tppufile.putstring(s:string);
+ begin
+ putdata(s,length(s)+1);
+ end;
+
+
+ procedure tppufile.putsmallset(const b);
+ var
+ l : longint;
+ begin
+ l:=longint(b);
+ putlongint(l);
+ end;
+
+
+ procedure tppufile.putnormalset(const b);
+ type
+ SetLongintArray = Array [0..7] of longint;
+ var
+ i : longint;
+ tempb : setlongintarray;
+ begin
+ if change_endian then
+ begin
+ for i:=0 to 7 do
+ tempb[i]:=SwapLong(SetLongintArray(b)[i]);
+ putdata(tempb,32);
+ end
+ else
+ putdata(b,32);
+ end;
+
+
+ procedure tppufile.tempclose;
+ begin
+ if not closed then
+ begin
+ closepos:=filepos(f);
+ {$I-}
+ system.close(f);
+ {$I+}
+ if ioresult<>0 then;
+ closed:=true;
+ tempclosed:=true;
+ end;
+ end;
+
+
+ function tppufile.tempopen:boolean;
+ var
+ ofm : byte;
+ begin
+ tempopen:=false;
+ if not closed or not tempclosed then
+ exit;
+ ofm:=filemode;
+ filemode:=0;
+ {$I-}
+ reset(f,1);
+ {$I+}
+ filemode:=ofm;
+ if ioresult<>0 then
+ exit;
+ closed:=false;
+ tempclosed:=false;
+
+ { restore state }
+ seek(f,closepos);
+ tempopen:=true;
+ end;
+
+end.
diff --git a/compiler/procinfo.pas b/compiler/procinfo.pas
new file mode 100644
index 0000000000..262fefb6d1
--- /dev/null
+++ b/compiler/procinfo.pas
@@ -0,0 +1,183 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Information about the current procedure that is being compiled
+
+ 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 procinfo;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ { common }
+ cclasses,
+ { global }
+ globtype,globals,verbose,
+ { symtable }
+ symconst,symtype,symdef,symsym,
+ { aasm }
+ cpubase,cpuinfo,cgbase,cgutils,
+ aasmbase,aasmtai
+ ;
+
+ const
+ inherited_inlining_flags : tprocinfoflags = [pi_do_call];
+
+
+ type
+ {# This object gives information on the current routine being
+ compiled.
+ }
+ tprocinfo = class(tlinkedlistitem)
+ { pointer to parent in nested procedures }
+ parent : tprocinfo;
+ {# the definition of the routine itself }
+ procdef : tprocdef;
+ { procinfo of the main procedure that is inlining
+ the current function, only used in tcgcallnode.inlined_pass2 }
+ inlining_procinfo : tprocinfo;
+ { file location of begin of procedure }
+ entrypos : tfileposinfo;
+ { file location of end of procedure }
+ exitpos : tfileposinfo;
+ { local switches at begin of procedure }
+ entryswitches : tlocalswitches;
+ { local switches at end of procedure }
+ exitswitches : tlocalswitches;
+
+ { Size of the parameters on the stack }
+ para_stack_size : longint;
+
+ { Offset of temp after para/local are allocated }
+ tempstart : longint;
+
+ {# some collected informations about the procedure
+ see pi_xxxx constants above
+ }
+ flags : tprocinfoflags;
+
+ { register used as frame pointer }
+ framepointer : tregister;
+
+ { register containing currently the got }
+ got : tregister;
+ gotlabel : tasmlabel;
+
+ { Holds the reference used to store all saved registers. }
+ save_regs_ref : treference;
+
+ { label to leave the sub routine }
+ aktexitlabel : tasmlabel;
+
+ {# The code for the routine itself, excluding entry and
+ exit code. This is a linked list of tai classes.
+ }
+ aktproccode : taasmoutput;
+ { Data (like jump tables) that belongs to this routine }
+ aktlocaldata : taasmoutput;
+
+ { max. of space need for parameters }
+ maxpushedparasize : aint;
+
+ constructor create(aparent:tprocinfo);virtual;
+ destructor destroy;override;
+
+ procedure allocate_push_parasize(size:longint);virtual;
+
+ function calc_stackframe_size:longint;virtual;
+
+ { Set the address of the first temp, can be used to allocate
+ space for pushing parameters }
+ procedure set_first_temp_offset;virtual;
+
+ { Generate parameter information }
+ procedure generate_parameter_info;virtual;
+ end;
+ tcprocinfo = class of tprocinfo;
+
+ var
+ cprocinfo : tcprocinfo;
+ { information about the current sub routine being parsed (@var(pprocinfo))}
+ current_procinfo : tprocinfo;
+
+
+implementation
+
+ uses
+ cutils,systems,
+ tgobj,cgobj,
+ paramgr
+ ;
+
+
+{****************************************************************************
+ TProcInfo
+****************************************************************************}
+
+ constructor tprocinfo.create(aparent:tprocinfo);
+ begin
+ parent:=aparent;
+ procdef:=nil;
+ para_stack_size:=0;
+ flags:=[];
+ framepointer:=NR_FRAME_POINTER_REG;
+ maxpushedparasize:=0;
+ { asmlists }
+ aktproccode:=Taasmoutput.Create;
+ aktlocaldata:=Taasmoutput.Create;
+ reference_reset(save_regs_ref);
+ { labels }
+ objectlibrary.getjumplabel(aktexitlabel);
+ objectlibrary.getjumplabel(gotlabel);
+ end;
+
+
+ destructor tprocinfo.destroy;
+ begin
+ aktproccode.free;
+ aktlocaldata.free;
+ end;
+
+
+ procedure tprocinfo.allocate_push_parasize(size:longint);
+ begin
+ end;
+
+
+ function tprocinfo.calc_stackframe_size:longint;
+ begin
+ result:=Align(tg.direction*tg.lasttemp,aktalignment.localalignmin);
+ end;
+
+
+ procedure tprocinfo.set_first_temp_offset;
+ begin
+ end;
+
+
+ procedure tprocinfo.generate_parameter_info;
+ begin
+ { generate callee paraloc register info, it returns the size that
+ is allocated on the stack }
+ para_stack_size:=paramanager.create_paraloc_info(procdef,calleeside);
+ end;
+
+
+end.
diff --git a/compiler/pstatmnt.pas b/compiler/pstatmnt.pas
new file mode 100644
index 0000000000..8109042fd3
--- /dev/null
+++ b/compiler/pstatmnt.pas
@@ -0,0 +1,1182 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does the parsing of the statements
+
+ 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 pstatmnt;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ tokens,node;
+
+
+ function statement_block(starttoken : ttoken) : tnode;
+
+ { reads an assembler block }
+ function assembler_block : tnode;
+
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,
+ { symtable }
+ symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
+ paramgr,symutil,
+ { pass 1 }
+ pass_1,htypechk,
+ nutils,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
+ { parser }
+ scanner,
+ pbase,pexpr,
+ { codegen }
+ procinfo,cgbase,
+ { assembler reader }
+ rabase
+ ;
+
+
+ function statement : tnode;forward;
+
+
+ function if_statement : tnode;
+ var
+ ex,if_a,else_a : tnode;
+ begin
+ consume(_IF);
+ ex:=comp_expr(true);
+ consume(_THEN);
+ if token<>_ELSE then
+ if_a:=statement
+ else
+ if_a:=nil;
+
+ if try_to_consume(_ELSE) then
+ else_a:=statement
+ else
+ else_a:=nil;
+ result:=cifnode.create(ex,if_a,else_a);
+ end;
+
+ { creates a block (list) of statements, til the next END token }
+ function statements_til_end : tnode;
+
+ var
+ first,last : tstatementnode;
+
+ begin
+ first:=nil;
+ while token<>_END do
+ begin
+ if first=nil then
+ begin
+ last:=cstatementnode.create(statement,nil);
+ first:=last;
+ end
+ else
+ begin
+ last.right:=cstatementnode.create(statement,nil);
+ last:=tstatementnode(last.right);
+ end;
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ consume_emptystats;
+ end;
+ consume(_END);
+ statements_til_end:=cblocknode.create(first);
+ end;
+
+
+ function case_statement : tnode;
+ var
+ casedef : tdef;
+ caseexpr,p : tnode;
+ blockid : longint;
+ hl1,hl2 : TConstExprInt;
+ casedeferror : boolean;
+ casenode : tcasenode;
+ begin
+ consume(_CASE);
+ caseexpr:=comp_expr(true);
+ { determines result type }
+ do_resulttypepass(caseexpr);
+ set_varstate(caseexpr,vs_used,[vsf_must_be_valid]);
+ casedeferror:=false;
+ casedef:=caseexpr.resulttype.def;
+ if (not assigned(casedef)) or
+ not(is_ordinal(casedef)) then
+ begin
+ CGMessage(type_e_ordinal_expr_expected);
+ { create a correct tree }
+ caseexpr.free;
+ caseexpr:=cordconstnode.create(0,u32inttype,false);
+ { set error flag so no rangechecks are done }
+ casedeferror:=true;
+ end;
+ { Create casenode }
+ casenode:=ccasenode.create(caseexpr);
+ consume(_OF);
+ { Parse all case blocks }
+ blockid:=0;
+ repeat
+ { maybe an instruction has more case labels }
+ repeat
+ p:=expr;
+ if is_widechar(casedef) then
+ begin
+ if (p.nodetype=rangen) then
+ begin
+ trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
+ trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
+ do_resulttypepass(trangenode(p).left);
+ do_resulttypepass(trangenode(p).right);
+ end
+ else
+ begin
+ p:=ctypeconvnode.create(p,cwidechartype);
+ do_resulttypepass(p);
+ end;
+ end;
+
+ hl1:=0;
+ hl2:=0;
+ if (p.nodetype=rangen) then
+ begin
+ { type checking for case statements }
+ if is_subequal(casedef, trangenode(p).left.resulttype.def) and
+ is_subequal(casedef, trangenode(p).right.resulttype.def) then
+ begin
+ hl1:=get_ordinal_value(trangenode(p).left);
+ hl2:=get_ordinal_value(trangenode(p).right);
+ if hl1>hl2 then
+ CGMessage(parser_e_case_lower_less_than_upper_bound);
+ if not casedeferror then
+ begin
+ testrange(casedef,hl1,false);
+ testrange(casedef,hl2,false);
+ end;
+ end
+ else
+ CGMessage(parser_e_case_mismatch);
+ casenode.addlabel(blockid,hl1,hl2);
+ end
+ else
+ begin
+ { type checking for case statements }
+ if not is_subequal(casedef, p.resulttype.def) then
+ CGMessage(parser_e_case_mismatch);
+ hl1:=get_ordinal_value(p);
+ if not casedeferror then
+ testrange(casedef,hl1,false);
+ casenode.addlabel(blockid,hl1,hl1);
+ end;
+ p.free;
+ if token=_COMMA then
+ consume(_COMMA)
+ else
+ break;
+ until false;
+ consume(_COLON);
+
+ { add instruction block }
+ casenode.addblock(blockid,statement);
+
+ { next block }
+ inc(blockid);
+
+ if not(token in [_ELSE,_OTHERWISE,_END]) then
+ consume(_SEMICOLON);
+ until (token in [_ELSE,_OTHERWISE,_END]);
+
+ if (token in [_ELSE,_OTHERWISE]) then
+ begin
+ if not try_to_consume(_ELSE) then
+ consume(_OTHERWISE);
+ casenode.addelseblock(statements_til_end);
+ end
+ else
+ consume(_END);
+
+ result:=casenode;
+ end;
+
+
+ function repeat_statement : tnode;
+
+ var
+ first,last,p_e : tnode;
+
+ begin
+ consume(_REPEAT);
+ first:=nil;
+
+ while token<>_UNTIL do
+ begin
+ if first=nil then
+ begin
+ last:=cstatementnode.create(statement,nil);
+ first:=last;
+ end
+ else
+ begin
+ tstatementnode(last).right:=cstatementnode.create(statement,nil);
+ last:=tstatementnode(last).right;
+ end;
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ consume_emptystats;
+ end;
+ consume(_UNTIL);
+
+ first:=cblocknode.create(first);
+ p_e:=comp_expr(true);
+ result:=cwhilerepeatnode.create(p_e,first,false,true);
+ end;
+
+
+ function while_statement : tnode;
+
+ var
+ p_e,p_a : tnode;
+
+ begin
+ consume(_WHILE);
+ p_e:=comp_expr(true);
+ consume(_DO);
+ p_a:=statement;
+ result:=cwhilerepeatnode.create(p_e,p_a,true,false);
+ end;
+
+
+ function for_statement : tnode;
+
+ procedure check_range(hp:tnode);
+ begin
+{$ifndef cpu64bit}
+ if hp.nodetype=ordconstn then
+ begin
+ if (tordconstnode(hp).value<low(longint)) or
+ (tordconstnode(hp).value>high(longint)) then
+ begin
+ CGMessage(parser_e_range_check_error);
+ { recover, prevent more warnings/errors }
+ tordconstnode(hp).value:=0;
+ end;
+ end;
+{$endif cpu64bit}
+ end;
+
+ var
+ hp,
+ hloopvar,
+ hblock,
+ hto,hfrom : tnode;
+ backward : boolean;
+ loopvarsym : tabstractvarsym;
+ begin
+ { parse loop header }
+ consume(_FOR);
+
+ hloopvar:=factor(false);
+
+ { Check loop variable }
+ loopvarsym:=nil;
+
+ { variable must be an ordinal, int64 is not allowed for 32bit targets }
+ if not(is_ordinal(hloopvar.resulttype.def))
+{$ifndef cpu64bit}
+ or is_64bitint(hloopvar.resulttype.def)
+{$endif cpu64bit}
+ then
+ MessagePos(hloopvar.fileinfo,type_e_ordinal_expr_expected);
+
+ hp:=hloopvar;
+ while assigned(hp) and
+ (
+ { record/object fields are allowed in tp7 mode only }
+ (
+ (m_tp7 in aktmodeswitches) and
+ (hp.nodetype=subscriptn) and
+ ((tsubscriptnode(hp).left.resulttype.def.deftype=recorddef) or
+ is_object(tsubscriptnode(hp).left.resulttype.def))
+ ) or
+ { constant array index }
+ (
+ (hp.nodetype=vecn) and
+ is_constintnode(tvecnode(hp).right)
+ ) or
+ { equal typeconversions }
+ (
+ (hp.nodetype=typeconvn) and
+ (ttypeconvnode(hp).convtype=tc_equal)
+ )
+ ) do
+ begin
+ { Use the recordfield for loopvarsym }
+ if not assigned(loopvarsym) and
+ (hp.nodetype=subscriptn) then
+ loopvarsym:=tsubscriptnode(hp).vs;
+ hp:=tunarynode(hp).left;
+ end;
+
+ if assigned(hp) and
+ (hp.nodetype=loadn) then
+ begin
+ case tloadnode(hp).symtableentry.typ of
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ { we need a simple loadn and the load must be in a global symtable or
+ in the same level as the para of the current proc }
+ if (
+ (tloadnode(hp).symtable.symtablelevel=main_program_level) or
+ (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
+ ) and
+ not(
+ ((tabstractvarsym(tloadnode(hp).symtableentry).varspez in [vs_var,vs_out]) or
+ (vo_is_thread_var in tabstractvarsym(tloadnode(hp).symtableentry).varoptions))
+ ) then
+ begin
+ { Assigning for-loop variable is only allowed in tp7 }
+ if not(m_tp7 in aktmodeswitches) then
+ begin
+ if not assigned(loopvarsym) then
+ loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
+ include(loopvarsym.varoptions,vo_is_loop_counter);
+ end;
+ end
+ else
+ MessagePos(hp.fileinfo,type_e_illegal_count_var);
+ end;
+ typedconstsym :
+ begin
+ { Bad programming, only allowed in tp7 mode }
+ if not(m_tp7 in aktmodeswitches) then
+ MessagePos(hp.fileinfo,type_e_illegal_count_var);
+ end;
+ else
+ MessagePos(hp.fileinfo,type_e_illegal_count_var);
+ end;
+ end
+ else
+ MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
+
+ consume(_ASSIGNMENT);
+
+ hfrom:=comp_expr(true);
+
+ if try_to_consume(_DOWNTO) then
+ backward:=true
+ else
+ begin
+ consume(_TO);
+ backward:=false;
+ end;
+
+ hto:=comp_expr(true);
+ consume(_DO);
+
+ { Check if the constants fit in the range }
+ check_range(hfrom);
+ check_range(hto);
+
+ { first set the varstate for from and to, so
+ uses of loopvar in those expressions will also
+ trigger a warning when it is not used yet. This
+ needs to be done before the instruction block is
+ parsed to have a valid hloopvar }
+ resulttypepass(hfrom);
+ set_varstate(hfrom,vs_used,[vsf_must_be_valid]);
+ resulttypepass(hto);
+ set_varstate(hto,vs_used,[vsf_must_be_valid]);
+ resulttypepass(hloopvar);
+ set_varstate(hloopvar,vs_used,[]);
+
+ { ... now the instruction block }
+ hblock:=statement;
+
+ { variable is not used for loop counter anymore }
+ if assigned(loopvarsym) then
+ exclude(loopvarsym.varoptions,vo_is_loop_counter);
+
+ result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
+ end;
+
+
+ function _with_statement : tnode;
+
+ var
+ right,p : tnode;
+ i,levelcount : longint;
+ withsymtable,symtab : tsymtable;
+ obj : tobjectdef;
+ hp : tnode;
+ newblock : tblocknode;
+ newstatement : tstatementnode;
+ calltempp,
+ loadp : ttempcreatenode;
+ refp : tnode;
+ htype : ttype;
+ hasimplicitderef : boolean;
+ begin
+ p:=comp_expr(true);
+ do_resulttypepass(p);
+ right:=nil;
+ if (not codegenerror) and
+ (p.resulttype.def.deftype in [objectdef,recorddef]) then
+ begin
+ newblock:=nil;
+ { ignore nodes that don't add instructions in the tree }
+ hp:=p;
+ while { equal type conversions }
+ (
+ (hp.nodetype=typeconvn) and
+ (ttypeconvnode(hp).convtype=tc_equal)
+ ) or
+ { constant array index }
+ (
+ (hp.nodetype=vecn) and
+ (tvecnode(hp).right.nodetype=ordconstn)
+ ) do
+ hp:=tunarynode(hp).left;
+ if (hp.nodetype=loadn) and
+ (
+ (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
+ (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
+ (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
+ ) then
+ begin
+ { simple load, we can reference direct }
+ loadp:=nil;
+ refp:=p;
+ end
+ else
+ begin
+ calltempp:=nil;
+ { complex load, load in temp first }
+ newblock:=internalstatements(newstatement);
+ { when right is a call then load it first in a temp }
+ if p.nodetype=calln then
+ begin
+ calltempp:=ctempcreatenode.create(p.resulttype,p.resulttype.def.size,tt_persistent,false);
+ addstatement(newstatement,calltempp);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(calltempp),
+ p));
+ p:=ctemprefnode.create(calltempp);
+ resulttypepass(p);
+ end;
+ { classes and interfaces have implicit dereferencing }
+ hasimplicitderef:=is_class_or_interface(p.resulttype.def);
+ if hasimplicitderef then
+ htype:=p.resulttype
+ else
+ htype.setdef(tpointerdef.create(p.resulttype));
+{$ifdef WITHNODEDEBUG}
+ { we can't generate debuginfo for a withnode stored in a }
+ { register }
+ if (cs_debuginfo in aktmoduleswitches) then
+ loadp:=ctempcreatenode.create(htype,sizeof(aint),tt_persistent,false)
+ else
+{$endif WITHNODEDEBUG}
+ loadp:=ctempcreatenode.create(htype,sizeof(aint),tt_persistent,true);
+ resulttypepass(loadp);
+ if hasimplicitderef then
+ begin
+ hp:=p;
+ refp:=ctemprefnode.create(loadp);
+ end
+ else
+ begin
+ hp:=caddrnode.create_internal(p);
+ refp:=cderefnode.create(ctemprefnode.create(loadp));
+ end;
+ addstatement(newstatement,loadp);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(loadp),
+ hp));
+ resulttypepass(refp);
+ end;
+
+ case p.resulttype.def.deftype of
+ objectdef :
+ begin
+ obj:=tobjectdef(p.resulttype.def);
+ withsymtable:=twithsymtable.Create(obj,obj.symtable.symsearch,refp);
+ { include also all parent symtables }
+ levelcount:=1;
+ obj:=obj.childof;
+ symtab:=withsymtable;
+ while assigned(obj) do
+ begin
+ { keep the original tobjectdef as owner, because that is used for
+ visibility of the symtable }
+ symtab.next:=twithsymtable.create(tobjectdef(p.resulttype.def),obj.symtable.symsearch,refp.getcopy);
+ symtab:=symtab.next;
+ obj:=obj.childof;
+ inc(levelcount);
+ end;
+ symtab.next:=symtablestack;
+ symtablestack:=withsymtable;
+ end;
+ recorddef :
+ begin
+ symtab:=trecorddef(p.resulttype.def).symtable;
+ levelcount:=1;
+ withsymtable:=twithsymtable.create(trecorddef(p.resulttype.def),symtab.symsearch,refp);
+ withsymtable.next:=symtablestack;
+ symtablestack:=withsymtable;
+ end;
+ end;
+ if try_to_consume(_COMMA) then
+ right:=_with_statement()
+ else
+ begin
+ consume(_DO);
+ if token<>_SEMICOLON then
+ right:=statement
+ else
+ right:=cerrornode.create;
+ end;
+ { remove symtables from the stack }
+ for i:=1 to levelcount do
+ symtablestack:=symtablestack.next;
+ p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refp);
+ { Finalize complex withnode with destroy of temp }
+ if assigned(newblock) then
+ begin
+ addstatement(newstatement,p);
+ addstatement(newstatement,ctempdeletenode.create(loadp));
+ if assigned(calltempp) then
+ addstatement(newstatement,ctempdeletenode.create(calltempp));
+ p:=newblock;
+ end;
+ _with_statement:=p;
+ end
+ else
+ begin
+ p.free;
+ Message(parser_e_false_with_expr);
+ { try to recover from error }
+ if try_to_consume(_COMMA) then
+ begin
+ hp:=_with_statement();
+ if (hp=nil) then; { remove warning about unused }
+ end
+ else
+ begin
+ consume(_DO);
+ { ignore all }
+ if token<>_SEMICOLON then
+ statement;
+ end;
+ _with_statement:=nil;
+ end;
+ end;
+
+
+ function with_statement : tnode;
+ begin
+ consume(_WITH);
+ with_statement:=_with_statement();
+ end;
+
+
+ function raise_statement : tnode;
+
+ var
+ p,pobj,paddr,pframe : tnode;
+
+ begin
+ pobj:=nil;
+ paddr:=nil;
+ pframe:=nil;
+ consume(_RAISE);
+ if not(token in endtokens) then
+ begin
+ { object }
+ pobj:=comp_expr(true);
+ if try_to_consume(_AT) then
+ begin
+ paddr:=comp_expr(true);
+ if try_to_consume(_COMMA) then
+ pframe:=comp_expr(true);
+ end;
+ end
+ else
+ begin
+ if (block_type<>bt_except) then
+ Message(parser_e_no_reraise_possible);
+ end;
+ p:=craisenode.create(pobj,paddr,pframe);
+ raise_statement:=p;
+ end;
+
+
+ function try_statement : tnode;
+
+ var
+ p_try_block,p_finally_block,first,last,
+ p_default,p_specific,hp : tnode;
+ ot : ttype;
+ sym : tlocalvarsym;
+ old_block_type : tblock_type;
+ exceptsymtable : tsymtable;
+ objname,objrealname : stringid;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ oldaktexceptblock: integer;
+
+ begin
+ include(current_procinfo.flags,pi_uses_exceptions);
+
+ p_default:=nil;
+ p_specific:=nil;
+
+ { read statements to try }
+ consume(_TRY);
+ first:=nil;
+ inc(exceptblockcounter);
+ oldaktexceptblock := aktexceptblock;
+ aktexceptblock := exceptblockcounter;
+
+ while (token<>_FINALLY) and (token<>_EXCEPT) do
+ begin
+ if first=nil then
+ begin
+ last:=cstatementnode.create(statement,nil);
+ first:=last;
+ end
+ else
+ begin
+ tstatementnode(last).right:=cstatementnode.create(statement,nil);
+ last:=tstatementnode(last).right;
+ end;
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ consume_emptystats;
+ end;
+ p_try_block:=cblocknode.create(first);
+
+ if try_to_consume(_FINALLY) then
+ begin
+ inc(exceptblockcounter);
+ aktexceptblock := exceptblockcounter;
+ p_finally_block:=statements_til_end;
+ try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
+ end
+ else
+ begin
+ consume(_EXCEPT);
+ old_block_type:=block_type;
+ block_type:=bt_except;
+ inc(exceptblockcounter);
+ aktexceptblock := exceptblockcounter;
+ ot:=generrortype;
+ p_specific:=nil;
+ if (idtoken=_ON) then
+ { catch specific exceptions }
+ begin
+ repeat
+ consume(_ON);
+ if token=_ID then
+ begin
+ objname:=pattern;
+ objrealname:=orgpattern;
+ { can't use consume_sym here, because we need already
+ to check for the colon }
+ searchsym(objname,srsym,srsymtable);
+ consume(_ID);
+ { is a explicit name for the exception given ? }
+ if try_to_consume(_COLON) then
+ begin
+ consume_sym(srsym,srsymtable);
+ if (srsym.typ=typesym) and
+ is_class(ttypesym(srsym).restype.def) then
+ begin
+ ot:=ttypesym(srsym).restype;
+ sym:=tlocalvarsym.create(objrealname,vs_value,ot,[]);
+ end
+ else
+ begin
+ sym:=tlocalvarsym.create(objrealname,vs_value,generrortype,[]);
+ if (srsym.typ=typesym) then
+ Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
+ else
+ Message1(type_e_class_type_expected,ot.def.typename);
+ end;
+ exceptsymtable:=tstt_exceptsymtable.create;
+ exceptsymtable.insert(sym);
+ { insert the exception symtable stack }
+ exceptsymtable.next:=symtablestack;
+ symtablestack:=exceptsymtable;
+ end
+ else
+ begin
+ { check if type is valid, must be done here because
+ with "e: Exception" the e is not necessary }
+ if srsym=nil then
+ begin
+ identifier_not_found(objrealname);
+ srsym:=generrorsym;
+ end;
+ { support unit.identifier }
+ if srsym.typ=unitsym then
+ begin
+ consume(_POINT);
+ srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
+ if srsym=nil then
+ begin
+ identifier_not_found(orgpattern);
+ srsym:=generrorsym;
+ end;
+ consume(_ID);
+ end;
+ { check if type is valid, must be done here because
+ with "e: Exception" the e is not necessary }
+ if (srsym.typ=typesym) and
+ is_class(ttypesym(srsym).restype.def) then
+ ot:=ttypesym(srsym).restype
+ else
+ begin
+ ot:=generrortype;
+ if (srsym.typ=typesym) then
+ Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
+ else
+ Message1(type_e_class_type_expected,ot.def.typename);
+ end;
+ exceptsymtable:=nil;
+ end;
+ end
+ else
+ consume(_ID);
+ consume(_DO);
+ hp:=connode.create(nil,statement);
+ if ot.def.deftype=errordef then
+ begin
+ hp.free;
+ hp:=cerrornode.create;
+ end;
+ if p_specific=nil then
+ begin
+ last:=hp;
+ p_specific:=last;
+ end
+ else
+ begin
+ tonnode(last).left:=hp;
+ last:=tonnode(last).left;
+ end;
+ { set the informations }
+ { only if the creation of the onnode was succesful, it's possible }
+ { that last and hp are errornodes (JM) }
+ if last.nodetype = onn then
+ begin
+ tonnode(last).excepttype:=tobjectdef(ot.def);
+ tonnode(last).exceptsymtable:=exceptsymtable;
+ end;
+ { remove exception symtable }
+ if assigned(exceptsymtable) then
+ begin
+ symtablestack:=symtablestack.next;
+ if last.nodetype <> onn then
+ exceptsymtable.free;
+ end;
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ consume_emptystats;
+ until (token in [_END,_ELSE]);
+ if try_to_consume(_ELSE) then
+ begin
+ { catch the other exceptions }
+ p_default:=statements_til_end;
+ end
+ else
+ consume(_END);
+ end
+ else
+ begin
+ { catch all exceptions }
+ p_default:=statements_til_end;
+ end;
+
+ block_type:=old_block_type;
+ try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
+ end;
+ aktexceptblock := oldaktexceptblock;
+ end;
+
+
+ function _asm_statement : tnode;
+ var
+ asmstat : tasmnode;
+ Marker : tai;
+ reg : tregister;
+ asmreader : tbaseasmreader;
+ begin
+ Inside_asm_statement:=true;
+ if assigned(asmmodeinfos[aktasmmode]) then
+ begin
+ asmreader:=asmmodeinfos[aktasmmode]^.casmreader.create;
+ asmstat:=casmnode.create(asmreader.assemble as taasmoutput);
+ asmreader.free;
+ end
+ else
+ Message(parser_f_assembler_reader_not_supported);
+
+ { Mark procedure that it has assembler blocks }
+ include(current_procinfo.flags,pi_has_assembler_block);
+
+ { Read first the _ASM statement }
+ consume(_ASM);
+
+ { END is read, got a list of changed registers? }
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+ asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
+ if token<>_RECKKLAMMER then
+ begin
+ repeat
+ { it's possible to specify the modified registers }
+ reg:=std_regnum_search(lower(pattern));
+ if reg<>NR_NO then
+ begin
+ if getregtype(reg)=R_INTREGISTER then
+ include(asmstat.used_regs_int,getsupreg(reg));
+ end
+ else
+ Message(asmr_e_invalid_register);
+ consume(_CSTRING);
+ if not try_to_consume(_COMMA) then
+ break;
+ until false;
+ end;
+ consume(_RECKKLAMMER);
+ end
+ else
+ begin
+ asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
+ asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
+ end;
+
+ { mark the start and the end of the assembler block
+ this is needed for the optimizer }
+ If Assigned(AsmStat.p_asm) Then
+ Begin
+ Marker := Tai_Marker.Create(AsmBlockStart);
+ AsmStat.p_asm.Insert(Marker);
+ Marker := Tai_Marker.Create(AsmBlockEnd);
+ AsmStat.p_asm.Concat(Marker);
+ End;
+ Inside_asm_statement:=false;
+ _asm_statement:=asmstat;
+ end;
+
+
+ function statement : tnode;
+ var
+ p : tnode;
+ code : tnode;
+ filepos : tfileposinfo;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ s : stringid;
+ begin
+ filepos:=akttokenpos;
+ case token of
+ _GOTO :
+ begin
+ if not(cs_support_goto in aktmoduleswitches)then
+ Message(sym_e_goto_and_label_not_supported);
+ consume(_GOTO);
+ if (token<>_INTCONST) and (token<>_ID) then
+ begin
+ Message(sym_e_label_not_found);
+ code:=cerrornode.create;
+ end
+ else
+ begin
+ if token=_ID then
+ consume_sym(srsym,srsymtable)
+ else
+ begin
+ searchsym(pattern,srsym,srsymtable);
+ if srsym=nil then
+ begin
+ identifier_not_found(pattern);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ end;
+ consume(token);
+ end;
+
+ if srsym.typ<>labelsym then
+ begin
+ Message(sym_e_id_is_no_label_id);
+ code:=cerrornode.create;
+ end
+ else
+ begin
+ { goto is only allowed to labels within the current scope }
+ if srsym.owner<>current_procinfo.procdef.localst then
+ CGMessage(parser_e_goto_outside_proc);
+ code:=cgotonode.create_sym(tlabelsym(srsym));
+ tgotonode(code).labelsym:=tlabelsym(srsym);
+ { set flag that this label is used }
+ tlabelsym(srsym).used:=true;
+ end;
+ end;
+ end;
+ _BEGIN :
+ code:=statement_block(_BEGIN);
+ _IF :
+ code:=if_statement;
+ _CASE :
+ code:=case_statement;
+ _REPEAT :
+ code:=repeat_statement;
+ _WHILE :
+ code:=while_statement;
+ _FOR :
+ code:=for_statement;
+ _WITH :
+ code:=with_statement;
+ _TRY :
+ code:=try_statement;
+ _RAISE :
+ code:=raise_statement;
+ { semicolons,else until and end are ignored }
+ _SEMICOLON,
+ _ELSE,
+ _UNTIL,
+ _END:
+ code:=cnothingnode.create;
+ _FAIL :
+ begin
+ if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
+ Message(parser_e_fail_only_in_constructor);
+ consume(_FAIL);
+ code:=call_fail_node;
+ end;
+ _ASM :
+ code:=_asm_statement;
+ _EOF :
+ Message(scan_f_end_of_file);
+ else
+ begin
+ p:=expr;
+ { save the pattern here for latter usage, the label could be "000",
+ even if we read an expression, the pattern is still valid if it's really
+ a label (FK)
+ if you want to mess here, take care of
+ tests/webtbs/tw3546.pp
+ }
+ s:=pattern;
+
+ { When a colon follows a intconst then transform it into a label }
+ if (p.nodetype=ordconstn) and
+ try_to_consume(_COLON) then
+ begin
+ p.free;
+ searchsym(s,srsym,srsymtable);
+ if assigned(srsym) and
+ (srsym.typ=labelsym) then
+ begin
+ if tlabelsym(srsym).defined then
+ Message(sym_e_label_already_defined);
+ tlabelsym(srsym).defined:=true;
+ p:=clabelnode.create(nil);
+ tlabelsym(srsym).code:=p;
+ end
+ else
+ begin
+ Message1(sym_e_label_used_and_not_defined,s);
+ p:=cnothingnode.create;
+ end;
+ end;
+
+ if p.nodetype=labeln then
+ begin
+ { the pointer to the following instruction }
+ { isn't a very clean way }
+ if token in endtokens then
+ tlabelnode(p).left:=cnothingnode.create
+ else
+ tlabelnode(p).left:=statement();
+ { be sure to have left also resulttypepass }
+ resulttypepass(tlabelnode(p).left);
+ end
+ else
+
+ { change a load of a procvar to a call. this is also
+ supported in fpc mode }
+ if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
+ maybe_call_procvar(p,false);
+
+ { blockn support because a read/write is changed into a blocknode }
+ { with a separate statement for each read/write operation (JM) }
+ { the same is true for val() if the third parameter is not 32 bit }
+ if not(p.nodetype in [nothingn,calln,ifn,assignn,breakn,inlinen,
+ continuen,labeln,blockn,exitn]) then
+ Message(parser_e_illegal_expression);
+
+ { Specify that we don't use the value returned by the call.
+ This is used for :
+ - dispose of temp stack space
+ - dispose on FPU stack }
+ if (p.nodetype=calln) then
+ exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
+
+ code:=p;
+ end;
+ end;
+ if assigned(code) then
+ begin
+ resulttypepass(code);
+ code.fileinfo:=filepos;
+ end;
+ statement:=code;
+ end;
+
+
+ function statement_block(starttoken : ttoken) : tnode;
+
+ var
+ first,last : tnode;
+ filepos : tfileposinfo;
+
+ begin
+ first:=nil;
+ filepos:=akttokenpos;
+ consume(starttoken);
+
+ while not(token in [_END,_FINALIZATION]) do
+ begin
+ if first=nil then
+ begin
+ last:=cstatementnode.create(statement,nil);
+ first:=last;
+ end
+ else
+ begin
+ tstatementnode(last).right:=cstatementnode.create(statement,nil);
+ last:=tstatementnode(last).right;
+ end;
+ if (token in [_END,_FINALIZATION]) then
+ break
+ else
+ begin
+ { if no semicolon, then error and go on }
+ if token<>_SEMICOLON then
+ begin
+ consume(_SEMICOLON);
+ consume_all_until(_SEMICOLON);
+ end;
+ consume(_SEMICOLON);
+ end;
+ consume_emptystats;
+ end;
+
+ { don't consume the finalization token, it is consumed when
+ reading the finalization block, but allow it only after
+ an initalization ! }
+ if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
+ consume(_END);
+
+ last:=cblocknode.create(first);
+ last.fileinfo:=filepos;
+ statement_block:=last;
+ end;
+
+
+ function assembler_block : tnode;
+ var
+ p : tnode;
+ locals : longint;
+ begin
+ { Rename the funcret so that recursive calls are possible }
+ if not is_void(current_procinfo.procdef.rettype.def) then
+ symtablestack.rename(current_procinfo.procdef.resultname,'$hiddenresult');
+
+ { delphi uses register calling for assembler methods }
+ if (m_delphi in aktmodeswitches) and
+ (po_assembler in current_procinfo.procdef.procoptions) and
+ not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
+ current_procinfo.procdef.proccalloption:=pocall_register;
+
+ { force the asm statement }
+ if token<>_ASM then
+ consume(_ASM);
+ include(current_procinfo.flags,pi_is_assembler);
+ p:=_asm_statement;
+
+{$ifndef sparc}
+{$ifndef arm}
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { set the framepointer to esp for assembler functions when the
+ following conditions are met:
+ - if the are no local variables and parameters (except the allocated result)
+ - no reference to the result variable (refcount<=1)
+ - result is not stored as parameter
+ - target processor has optional frame pointer save
+ (vm, i386, vm only currently)
+ }
+ locals:=0;
+ current_procinfo.procdef.localst.foreach_static(@count_locals,@locals);
+ current_procinfo.procdef.parast.foreach_static(@count_locals,@locals);
+ if (locals=0) and
+ (current_procinfo.procdef.owner.symtabletype<>objectsymtable) and
+ (not assigned(current_procinfo.procdef.funcretsym) or
+ (tabstractvarsym(current_procinfo.procdef.funcretsym).refcount<=1)) and
+ not(paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption)) then
+ begin
+ { Only need to set the framepointer, the locals will
+ be inserted with the correct reference in tcgasmnode.pass_2 }
+ current_procinfo.framepointer:=NR_STACK_POINTER_REG;
+ end;
+ end;
+{$endif arm}
+{$endif sparc}
+
+ { Flag the result as assigned when it is returned in a
+ register.
+ }
+ if assigned(current_procinfo.procdef.funcretsym) and
+ (not paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption)) then
+ tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_assigned;
+
+ { because the END is already read we need to get the
+ last_endtoken_filepos here (PFV) }
+ last_endtoken_filepos:=akttokenpos;
+
+ assembler_block:=p;
+ end;
+
+end.
diff --git a/compiler/psub.pas b/compiler/psub.pas
new file mode 100644
index 0000000000..28e3fea805
--- /dev/null
+++ b/compiler/psub.pas
@@ -0,0 +1,1475 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Daniel Mantione
+
+ Does the parsing and codegeneration at subroutine level
+
+ 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 psub;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,globals,
+ node,nbas,
+ symdef,procinfo;
+
+ type
+ tcgprocinfo = class(tprocinfo)
+ private
+ procedure add_entry_exit_code;
+ public
+ { code for the subroutine as tree }
+ code : tnode;
+ { positions in the tree for init/final }
+ entry_asmnode,
+ loadpara_asmnode,
+ exitlabel_asmnode,
+ stackcheck_asmnode,
+ init_asmnode,
+ final_asmnode : tasmnode;
+ { list to store the procinfo's of the nested procedures }
+ nestedprocs : tlinkedlist;
+ constructor create(aparent:tprocinfo);override;
+ destructor destroy;override;
+ procedure printproc;
+ procedure generate_code;
+ procedure resetprocdef;
+ procedure add_to_symtablestack;
+ procedure remove_from_symtablestack;
+ procedure parse_body;
+ end;
+
+
+ procedure printnode_reset;
+
+ { reads the declaration blocks }
+ procedure read_declarations(islibrary : boolean);
+
+ { reads declarations in the interface part of a unit }
+ procedure read_interface_declarations;
+
+
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globtype,tokens,verbose,comphook,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,
+ { symtable }
+ symconst,symbase,symsym,symtype,symtable,defutil,
+ paramgr,
+ ppu,fmodule,
+ { pass 1 }
+ nutils,nld,ncal,ncon,nflw,nadd,ncnv,nmem,
+ pass_1,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif state_tracking}
+ { pass 2 }
+{$ifndef NOPASS2}
+ pass_2,
+{$endif}
+ { parser }
+ scanner,import,gendef,
+ pbase,pstatmnt,pdecl,pdecsub,pexports,
+ { codegen }
+ tgobj,cgobj,dbgbase,
+ ncgutil,regvars
+{$if defined(arm) or defined(powerpc) or defined(powerpc64)}
+ ,aasmcpu
+{$endif arm}
+ {$ifndef NOOPT}
+ {$ifdef i386}
+ ,aopt386
+ {$else i386}
+ ,aopt
+ {$endif i386}
+ {$endif}
+ ;
+
+{****************************************************************************
+ PROCEDURE/FUNCTION BODY PARSING
+****************************************************************************}
+
+ procedure initializevars(p:tnamedindexitem;arg:pointer);
+ var
+ b : tblocknode;
+ begin
+ if not (tsym(p).typ in [localvarsym,globalvarsym]) then
+ exit;
+ with tabstractnormalvarsym(p) do
+ begin
+ if assigned(defaultconstsym) then
+ begin
+ b:=tblocknode(arg);
+ b.left:=cstatementnode.create(
+ cassignmentnode.create(
+ cloadnode.create(tsym(p),tsym(p).owner),
+ cloadnode.create(defaultconstsym,defaultconstsym.owner)),
+ b.left);
+ end;
+ end;
+ end;
+
+
+ procedure check_finalize_paras(p : tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ=paravarsym) and
+ (tparavarsym(p).varspez=vs_value) and
+ not is_class(tparavarsym(p).vartype.def) and
+ tparavarsym(p).vartype.def.needs_inittable then
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ end;
+
+
+ procedure check_finalize_locals(p : tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ=localvarsym) and
+ (tlocalvarsym(p).refs>0) and
+ not(vo_is_funcret in tlocalvarsym(p).varoptions) and
+ not(is_class(tlocalvarsym(p).vartype.def)) and
+ tlocalvarsym(p).vartype.def.needs_inittable then
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ end;
+
+
+ function block(islibrary : boolean) : tnode;
+ begin
+ { parse const,types and vars }
+ read_declarations(islibrary);
+
+ { do we have an assembler block without the po_assembler?
+ we should allow this for Delphi compatibility (PFV) }
+ if (token=_ASM) and (m_delphi in aktmodeswitches) then
+ include(current_procinfo.procdef.procoptions,po_assembler);
+
+ { Handle assembler block different }
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ block:=assembler_block;
+ exit;
+ end;
+
+ {Unit initialization?.}
+ if (
+ assigned(current_procinfo.procdef.localst) and
+ (current_procinfo.procdef.localst.symtablelevel=main_program_level) and
+ (current_module.is_unit)
+ ) or
+ islibrary then
+ begin
+ if (token=_END) then
+ begin
+ consume(_END);
+ { We need at least a node, else the entry/exit code is not
+ generated and thus no PASCALMAIN symbol which we need (PFV) }
+ if islibrary then
+ block:=cnothingnode.create
+ else
+ block:=nil;
+ end
+ else
+ begin
+ if token=_INITIALIZATION then
+ begin
+ { The library init code is already called and does not
+ need to be in the initfinal table (PFV) }
+ if not islibrary then
+ current_module.flags:=current_module.flags or uf_init;
+ block:=statement_block(_INITIALIZATION);
+ end
+ else if (token=_FINALIZATION) then
+ begin
+ if (current_module.flags and uf_finalize)<>0 then
+ block:=statement_block(_FINALIZATION)
+ else
+ begin
+ { can we allow no INITIALIZATION for DLL ??
+ I think it should work PM }
+ block:=nil;
+ exit;
+ end;
+ end
+ else
+ begin
+ { The library init code is already called and does not
+ need to be in the initfinal table (PFV) }
+ if not islibrary then
+ current_module.flags:=current_module.flags or uf_init;
+ block:=statement_block(_BEGIN);
+ end;
+ end;
+ end
+ else
+ begin
+ block:=statement_block(_BEGIN);
+ if symtablestack.symtabletype=localsymtable then
+ symtablestack.foreach_static(@initializevars,block);
+ end;
+ end;
+
+
+{****************************************************************************
+ PROCEDURE/FUNCTION COMPILING
+****************************************************************************}
+
+ procedure printnode_reset;
+ begin
+ assign(printnodefile,treelogfilename);
+ {$I-}
+ rewrite(printnodefile);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ Comment(V_Error,'Error creating '+treelogfilename);
+ exit;
+ end;
+ close(printnodefile);
+ end;
+
+
+ function generate_bodyentry_block:tnode;
+ var
+ srsym : tsym;
+ para : tcallparanode;
+ newstatement : tstatementnode;
+ htype : ttype;
+ begin
+ result:=internalstatements(newstatement);
+
+ if assigned(current_procinfo.procdef._class) then
+ begin
+ { a constructor needs a help procedure }
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) then
+ begin
+ if is_class(current_procinfo.procdef._class) then
+ begin
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ srsym:=search_class_member(current_procinfo.procdef._class,'NEWINSTANCE');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { if vmt>1 then newinstance }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(gtn,
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,
+ voidpointertype),
+ cpointerconstnode.create(1,voidpointertype)),
+ cassignmentnode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_vmt_pointer_node,[])),
+ nil));
+ end
+ else
+ internalerror(200305108);
+ end
+ else
+ if is_object(current_procinfo.procdef._class) then
+ begin
+ htype.setdef(current_procinfo.procdef._class);
+ htype.setdef(tpointerdef.create(htype));
+ { parameter 3 : vmt_offset }
+ { parameter 2 : address of pointer to vmt,
+ this is required to allow setting the vmt to -1 to indicate
+ that memory was allocated }
+ { parameter 1 : self pointer }
+ para:=ccallparanode.create(
+ cordconstnode.create(current_procinfo.procdef._class.vmt_offset,s32inttype,false),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,
+ voidpointertype),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ nil)));
+ addstatement(newstatement,cassignmentnode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ ccallnode.createintern('fpc_help_constructor',para)));
+ end
+ else
+ internalerror(200305103);
+ { if self=nil then exit
+ calling fail instead of exit is useless because
+ there is nothing to dispose (PFV) }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(equaln,
+ load_self_pointer_node,
+ cnilnode.create),
+ cexitnode.create(nil),
+ nil));
+ end;
+
+ { maybe call BeforeDestruction for classes }
+ if (current_procinfo.procdef.proctypeoption=potype_destructor) and
+ is_class(current_procinfo.procdef._class) then
+ begin
+ srsym:=search_class_member(current_procinfo.procdef._class,'BEFOREDESTRUCTION');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { if vmt<>0 then beforedestruction }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(unequaln,
+ load_vmt_pointer_node,
+ cnilnode.create),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
+ nil));
+ end
+ else
+ internalerror(200305104);
+ end;
+ end;
+ end;
+
+
+ function generate_bodyexit_block:tnode;
+ var
+ srsym : tsym;
+ para : tcallparanode;
+ newstatement : tstatementnode;
+ begin
+ result:=internalstatements(newstatement);
+
+ if assigned(current_procinfo.procdef._class) then
+ begin
+ { maybe call AfterConstruction for classes }
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+ is_class(current_procinfo.procdef._class) then
+ begin
+ srsym:=search_class_member(current_procinfo.procdef._class,'AFTERCONSTRUCTION');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { Self can be nil when fail is called }
+ { if self<>nil and vmt<>nil then afterconstruction }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(andn,
+ caddnode.create(unequaln,
+ load_self_pointer_node,
+ cnilnode.create),
+ caddnode.create(unequaln,
+ load_vmt_pointer_node,
+ cnilnode.create)),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
+ nil));
+ end
+ else
+ internalerror(200305106);
+ end;
+
+ { a destructor needs a help procedure }
+ if (current_procinfo.procdef.proctypeoption=potype_destructor) then
+ begin
+ if is_class(current_procinfo.procdef._class) then
+ begin
+ srsym:=search_class_member(current_procinfo.procdef._class,'FREEINSTANCE');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { if self<>0 and vmt=1 then freeinstance }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(andn,
+ caddnode.create(unequaln,
+ load_self_pointer_node,
+ cnilnode.create),
+ caddnode.create(equaln,
+ ctypeconvnode.create(
+ load_vmt_pointer_node,
+ voidpointertype),
+ cpointerconstnode.create(1,voidpointertype))),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
+ nil));
+ end
+ else
+ internalerror(200305108);
+ end
+ else
+ if is_object(current_procinfo.procdef._class) then
+ begin
+ { finalize object data }
+ if current_procinfo.procdef._class.needs_inittable then
+ addstatement(newstatement,finalize_data_node(load_self_node));
+ { parameter 3 : vmt_offset }
+ { parameter 2 : pointer to vmt }
+ { parameter 1 : self pointer }
+ para:=ccallparanode.create(
+ cordconstnode.create(current_procinfo.procdef._class.vmt_offset,s32inttype,false),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,
+ voidpointertype),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ nil)));
+ addstatement(newstatement,
+ ccallnode.createintern('fpc_help_destructor',para));
+ end
+ else
+ internalerror(200305105);
+ end;
+ end;
+ end;
+
+
+ function generate_except_block:tnode;
+ var
+ pd : tprocdef;
+ newstatement : tstatementnode;
+ begin
+ generate_except_block:=internalstatements(newstatement);
+
+ { a constructor needs call destructor (if available) when it
+ is not inherited }
+ if assigned(current_procinfo.procdef._class) and
+ (current_procinfo.procdef.proctypeoption=potype_constructor) then
+ begin
+ pd:=current_procinfo.procdef._class.searchdestructor;
+ if assigned(pd) then
+ begin
+ { if vmt<>0 then call destructor }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(unequaln,
+ load_vmt_pointer_node,
+ cnilnode.create),
+ ccallnode.create(nil,tprocsym(pd.procsym),pd.procsym.owner,load_self_node,[]),
+ nil));
+ end;
+ end
+ else
+ begin
+ { no constructor }
+ { must be the return value finalized before reraising the exception? }
+ if (not is_void(current_procinfo.procdef.rettype.def)) and
+ (current_procinfo.procdef.rettype.def.needs_inittable) and
+ (not is_class(current_procinfo.procdef.rettype.def)) then
+ addstatement(newstatement,finalize_data_node(load_result_node));
+ end;
+ end;
+
+
+{****************************************************************************
+ TCGProcInfo
+****************************************************************************}
+
+ constructor tcgprocinfo.create(aparent:tprocinfo);
+ begin
+ inherited Create(aparent);
+ nestedprocs:=tlinkedlist.create;
+ end;
+
+
+ destructor tcgprocinfo.destroy;
+ begin
+ nestedprocs.free;
+ if assigned(code) then
+ code.free;
+ inherited destroy;
+ end;
+
+
+ procedure tcgprocinfo.printproc;
+ begin
+ assign(printnodefile,treelogfilename);
+ {$I-}
+ append(printnodefile);
+ if ioresult<>0 then
+ rewrite(printnodefile);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ Comment(V_Error,'Error creating '+treelogfilename);
+ exit;
+ end;
+ writeln(printnodefile);
+ writeln(printnodefile,'*******************************************************************************');
+ writeln(printnodefile,procdef.fullprocname(false));
+ writeln(printnodefile,'*******************************************************************************');
+ printnode(printnodefile,code);
+ close(printnodefile);
+ end;
+
+
+ procedure tcgprocinfo.add_entry_exit_code;
+ var
+ finalcode,
+ bodyentrycode,
+ bodyexitcode,
+ exceptcode : tnode;
+ newblock : tblocknode;
+ codestatement,
+ newstatement : tstatementnode;
+ oldfilepos : tfileposinfo;
+ begin
+ oldfilepos:=aktfilepos;
+ { Generate code/locations used at start of proc }
+ aktfilepos:=entrypos;
+ entry_asmnode:=casmnode.create_get_position;
+ loadpara_asmnode:=casmnode.create_get_position;
+ stackcheck_asmnode:=casmnode.create_get_position;
+ init_asmnode:=casmnode.create_get_position;
+ bodyentrycode:=generate_bodyentry_block;
+ { Generate code/locations used at end of proc }
+ aktfilepos:=exitpos;
+ exitlabel_asmnode:=casmnode.create_get_position;
+ final_asmnode:=casmnode.create_get_position;
+ bodyexitcode:=generate_bodyexit_block;
+
+ { Generate procedure by combining init+body+final,
+ depending on the implicit finally we need to add
+ an try...finally...end wrapper }
+ newblock:=internalstatements(newstatement);
+ if (cs_implicit_exceptions in aktmoduleswitches) and
+ (pi_needs_implicit_finally in flags) and
+ { but it's useless in init/final code of units }
+ not(procdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
+ begin
+ { Generate special exception block only needed when
+ implicit finaly is used }
+ aktfilepos:=exitpos;
+ exceptcode:=generate_except_block;
+ { Generate code that will be in the try...finally }
+ finalcode:=internalstatements(codestatement);
+ addstatement(codestatement,bodyexitcode);
+ addstatement(codestatement,final_asmnode);
+ { Initialize before try...finally...end frame }
+ addstatement(newstatement,loadpara_asmnode);
+ addstatement(newstatement,stackcheck_asmnode);
+ addstatement(newstatement,entry_asmnode);
+ addstatement(newstatement,init_asmnode);
+ addstatement(newstatement,bodyentrycode);
+ aktfilepos:=entrypos;
+ addstatement(newstatement,ctryfinallynode.create_implicit(
+ code,
+ finalcode,
+ exceptcode));
+ addstatement(newstatement,exitlabel_asmnode);
+ { set flag the implicit finally has been generated }
+ include(flags,pi_has_implicit_finally);
+ end
+ else
+ begin
+ addstatement(newstatement,loadpara_asmnode);
+ addstatement(newstatement,stackcheck_asmnode);
+ addstatement(newstatement,entry_asmnode);
+ addstatement(newstatement,init_asmnode);
+ addstatement(newstatement,bodyentrycode);
+ addstatement(newstatement,code);
+ addstatement(newstatement,exitlabel_asmnode);
+ addstatement(newstatement,bodyexitcode);
+ addstatement(newstatement,final_asmnode);
+ end;
+ do_firstpass(newblock);
+ code:=newblock;
+ aktfilepos:=oldfilepos;
+ end;
+
+
+ procedure clearrefs(p : tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ in [localvarsym,paravarsym,globalvarsym]) then
+ if tabstractvarsym(p).refs>1 then
+ tabstractvarsym(p).refs:=1;
+ end;
+
+
+ procedure tcgprocinfo.generate_code;
+ var
+ oldprocinfo : tprocinfo;
+ oldaktmaxfpuregisters : longint;
+ oldfilepos : tfileposinfo;
+ templist : Taasmoutput;
+ headertai : tai;
+ curralign : longint;
+ begin
+ { the initialization procedure can be empty, then we
+ don't need to generate anything. When it was an empty
+ procedure there would be at least a blocknode }
+ if not assigned(code) then
+ exit;
+
+ { We need valid code }
+ if Errorcount<>0 then
+ exit;
+
+ { The RA and Tempgen shall not be available yet }
+ if assigned(tg) then
+ internalerror(200309201);
+
+ oldprocinfo:=current_procinfo;
+ oldfilepos:=aktfilepos;
+ oldaktmaxfpuregisters:=aktmaxfpuregisters;
+
+ current_procinfo:=self;
+ aktfilepos:=entrypos;
+
+ { get new labels }
+ aktbreaklabel:=nil;
+ aktcontinuelabel:=nil;
+ templist:=Taasmoutput.create;
+
+ { add parast/localst to symtablestack }
+ add_to_symtablestack;
+
+ { when size optimization only count occurrence }
+ if cs_littlesize in aktglobalswitches then
+ cg.t_times:=1
+ else
+ { reference for repetition is 100 }
+ cg.t_times:=100;
+
+ { clear register count }
+ symtablestack.foreach_static(@clearrefs,nil);
+ symtablestack.next.foreach_static(@clearrefs,nil);
+
+ { there's always a call to FPC_INITIALIZEUNITS/FPC_DO_EXIT in the main program }
+ if (procdef.localst.symtablelevel=main_program_level) and
+ (not current_module.is_unit) then
+ include(flags,pi_do_call);
+
+ { set implicit_finally flag when there are locals/paras to be finalized }
+ current_procinfo.procdef.parast.foreach_static(@check_finalize_paras,nil);
+ current_procinfo.procdef.localst.foreach_static(@check_finalize_locals,nil);
+
+ { firstpass everything }
+ flowcontrol:=[];
+ do_firstpass(code);
+ if code.registersfpu>0 then
+ include(current_procinfo.flags,pi_uses_fpu);
+
+ { add implicit entry and exit code }
+ add_entry_exit_code;
+
+ { only do secondpass if there are no errors }
+ if ErrorCount=0 then
+ begin
+ { set the start offset to the start of the temp area in the stack }
+ tg:=ttgobj.create;
+
+ { Create register allocator }
+ cg.init_register_allocators;
+
+ set_first_temp_offset;
+ generate_parameter_info;
+
+ { Allocate space in temp/registers for parast and localst }
+ aktfilepos:=entrypos;
+ gen_alloc_symtable(aktproccode,procdef.parast);
+ gen_alloc_symtable(aktproccode,procdef.localst);
+
+ { Store temp offset for information about 'real' temps }
+ tempstart:=tg.lasttemp;
+
+ { Generate code to load register parameters in temps and insert local
+ copies for values parameters. This must be done before the code for the
+ body is generated because the localloc is updated.
+ Note: The generated code will be inserted after the code generation of
+ the body is finished, because only then the position is known }
+{$ifdef oldregvars}
+ assign_regvars(code);
+{$endif oldreg}
+ aktfilepos:=entrypos;
+ gen_load_para_value(templist);
+
+ { caller paraloc info is also necessary in the stackframe_entry
+ code of the ppc (and possibly other processors) }
+ if not procdef.has_paraloc_info then
+ begin
+ procdef.requiredargarea:=paramanager.create_paraloc_info(procdef,callerside);
+ procdef.has_paraloc_info:=true;
+ end;
+
+ { generate code for the node tree }
+ do_secondpass(code);
+ aktproccode.concatlist(exprasmlist);
+{$ifdef i386}
+ procdef.fpu_used:=code.registersfpu;
+{$endif i386}
+
+ { The position of the loadpara_asmnode is now known }
+ aktproccode.insertlistafter(loadpara_asmnode.currenttai,templist);
+
+ { first generate entry and initialize code with the correct
+ position and switches }
+ aktfilepos:=entrypos;
+ aktlocalswitches:=entryswitches;
+ gen_entry_code(templist);
+ aktproccode.insertlistafter(entry_asmnode.currenttai,templist);
+ gen_initialize_code(templist);
+ aktproccode.insertlistafter(init_asmnode.currenttai,templist);
+
+ { now generate finalize and exit code with the correct position
+ and switches }
+ aktfilepos:=exitpos;
+ aktlocalswitches:=exitswitches;
+ gen_finalize_code(templist);
+ { the finalcode must be concated if there was no position available,
+ using insertlistafter will result in an insert at the start
+ when currentai=nil }
+ if assigned(final_asmnode.currenttai) then
+ aktproccode.insertlistafter(final_asmnode.currenttai,templist)
+ else
+ aktproccode.concatlist(templist);
+ { insert exit label at the correct position }
+ cg.a_label(templist,aktexitlabel);
+ if assigned(exitlabel_asmnode.currenttai) then
+ aktproccode.insertlistafter(exitlabel_asmnode.currenttai,templist)
+ else
+ aktproccode.concatlist(templist);
+ { exit code }
+ gen_exit_code(templist);
+ aktproccode.concatlist(templist);
+
+{$ifdef OLDREGVARS}
+ { note: this must be done only after as much code as possible has }
+ { been generated. The result is that when you ungetregister() a }
+ { regvar, it will actually free the regvar (and alse free the }
+ { the regvars at the same time). Doing this too early will }
+ { confuse the register allocator, as the regvars will still be }
+ { used. It should be done before loading the result regs (so }
+ { they don't conflict with the regvars) and before }
+ { gen_entry_code (that one has to be able to allocate the }
+ { regvars again) (JM) }
+ free_regvars(aktproccode);
+{$endif OLDREGVARS}
+
+ { add code that will load the return value, this is not done
+ for assembler routines when they didn't reference the result
+ variable }
+ gen_load_return_value(templist);
+ aktproccode.concatlist(templist);
+
+ { generate symbol and save end of header position }
+ aktfilepos:=entrypos;
+ gen_proc_symbol(templist);
+ headertai:=tai(templist.last);
+ { insert symbol }
+ aktproccode.insertlist(templist);
+
+ { Free space in temp/registers for parast and localst, must be
+ done after gen_entry_code }
+ aktfilepos:=exitpos;
+ gen_free_symtable(aktproccode,procdef.localst);
+ gen_free_symtable(aktproccode,procdef.parast);
+
+ { Already reserve all registers for stack checking code and
+ generate the call to the helper function }
+ if (cs_check_stack in entryswitches) and
+ not(po_assembler in procdef.procoptions) and
+ (current_procinfo.procdef.proctypeoption<>potype_proginit) then
+ begin
+ aktfilepos:=entrypos;
+ gen_stack_check_call(templist);
+ aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
+ end;
+
+ { The procedure body is finished, we can now
+ allocate the registers }
+ cg.do_register_allocation(aktproccode,headertai);
+
+ { Add save and restore of used registers }
+ aktfilepos:=entrypos;
+ gen_save_used_regs(templist);
+ aktproccode.insertlistafter(headertai,templist);
+ aktfilepos:=exitpos;
+ gen_restore_used_regs(aktproccode);
+ { We know the size of the stack, now we can generate the
+ parameter that is passed to the stack checking code }
+ if (cs_check_stack in entryswitches) and
+ not(po_assembler in procdef.procoptions) and
+ (current_procinfo.procdef.proctypeoption<>potype_proginit) then
+ begin
+ aktfilepos:=entrypos;
+ gen_stack_check_size_para(templist);
+ aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
+ end;
+ { Add entry code (stack allocation) after header }
+ aktfilepos:=entrypos;
+ gen_proc_entry_code(templist);
+ aktproccode.insertlistafter(headertai,templist);
+ { Add exit code at the end }
+ aktfilepos:=exitpos;
+ gen_proc_exit_code(templist);
+ aktproccode.concatlist(templist);
+
+ { check if the implicit finally has been generated. The flag
+ should already be set in pass1 }
+ if (cs_implicit_exceptions in aktmoduleswitches) and
+ not(procdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) and
+ (pi_needs_implicit_finally in flags) and
+ not(pi_has_implicit_finally in flags) then
+ internalerror(200405231);
+
+{$ifndef NoOpt}
+ if not(cs_no_regalloc in aktglobalswitches) then
+ begin
+ if (cs_optimize in aktglobalswitches) and
+ { do not optimize pure assembler procedures }
+ not(pi_is_assembler in flags) then
+ optimize(aktproccode);
+ end;
+{$endif NoOpt}
+
+ { Add end symbol and debug info }
+ aktfilepos:=exitpos;
+ gen_proc_symbol_end(templist);
+ aktproccode.concatlist(templist);
+
+{$ifdef ARM}
+ { because of the limited constant size of the arm, all data access is done pc relative }
+ insertpcrelativedata(aktproccode,aktlocaldata);
+{$endif ARM}
+
+{$ifdef POWERPC}
+ fixup_jmps(aktproccode);
+{$endif POWERPC}
+{$ifdef POWERPC64}
+ fixup_jmps(aktproccode);
+{$endif POWERPC64}
+ { insert line debuginfo }
+ if (cs_debuginfo in aktmoduleswitches) or
+ (cs_use_lineinfo in aktglobalswitches) then
+ debuginfo.insertlineinfo(aktproccode);
+
+ { gprof uses 16 byte granularity }
+ if (cs_profile in aktmoduleswitches) then
+ curralign:=16
+ else
+ curralign:=aktalignment.procalign;
+
+ { add the procedure to the al_procedures }
+ maybe_new_object_file(asmlist[al_procedures]);
+ new_section(asmlist[al_procedures],sec_code,lower(procdef.mangledname),curralign);
+ asmlist[al_procedures].concatlist(aktproccode);
+ { save local data (casetable) also in the same file }
+ if assigned(aktlocaldata) and
+ (not aktlocaldata.empty) then
+ asmlist[al_procedures].concatlist(aktlocaldata);
+
+ { only now we can remove the temps }
+ tg.resettempgen;
+
+ { stop tempgen and ra }
+ tg.free;
+ cg.done_register_allocators;
+ tg:=nil;
+ end;
+
+ { restore symtablestack }
+ remove_from_symtablestack;
+
+ { restore }
+ templist.free;
+ aktmaxfpuregisters:=oldaktmaxfpuregisters;
+ aktfilepos:=oldfilepos;
+ current_procinfo:=oldprocinfo;
+ end;
+
+
+ procedure tcgprocinfo.add_to_symtablestack;
+ var
+ _class,hp : tobjectdef;
+ begin
+ { insert symtables for the class, but only if it is no nested function }
+ if assigned(procdef._class) and
+ not(assigned(parent) and
+ assigned(parent.procdef) and
+ assigned(parent.procdef._class)) then
+ begin
+ { insert them in the reverse order }
+ hp:=nil;
+ repeat
+ _class:=procdef._class;
+ while _class.childof<>hp do
+ _class:=_class.childof;
+ hp:=_class;
+ _class.symtable.next:=symtablestack;
+ symtablestack:=_class.symtable;
+ until hp=procdef._class;
+ end;
+
+ { insert parasymtable in symtablestack when parsing
+ a function }
+ if procdef.parast.symtablelevel>=normal_function_level then
+ begin
+ procdef.parast.next:=symtablestack;
+ symtablestack:=procdef.parast;
+ end;
+
+ procdef.localst.next:=symtablestack;
+ symtablestack:=procdef.localst;
+ end;
+
+
+ procedure tcgprocinfo.remove_from_symtablestack;
+ begin
+ { remove localst/parast }
+ if procdef.parast.symtablelevel>=normal_function_level then
+ symtablestack:=symtablestack.next.next
+ else
+ symtablestack:=symtablestack.next;
+
+ { remove class member symbol tables }
+ while symtablestack.symtabletype=objectsymtable do
+ symtablestack:=symtablestack.next;
+ end;
+
+
+ procedure tcgprocinfo.resetprocdef;
+ begin
+ { remove code tree, if not inline procedure }
+ if assigned(code) then
+ begin
+ { the inline procedure has already got a copy of the tree
+ stored in procdef.inlininginfo }
+ code.free;
+ code:=nil;
+ end;
+ end;
+
+
+ function checknodeinlining(procdef: tprocdef): boolean;
+ var
+ i : integer;
+ currpara : tparavarsym;
+ begin
+ result := false;
+ if (pi_has_assembler_block in current_procinfo.flags) then
+ exit;
+ for i:=0 to procdef.paras.count-1 do
+ begin
+ currpara:=tparavarsym(procdef.paras[i]);
+ { we can't handle formaldefs and special arrays (the latter may need a }
+ { re-basing of the index, i.e. if you pass an array[1..10] as open array, }
+ { you have to add 1 to all index operations if you directly inline it }
+ if ((currpara.varspez in [vs_out,vs_var,vs_const]) and
+ (currpara.vartype.def.deftype=formaldef)) or
+ is_special_array(currpara.vartype.def) then
+ exit;
+ end;
+ result:=true;
+ end;
+
+
+ procedure tcgprocinfo.parse_body;
+ var
+ oldprocinfo : tprocinfo;
+ oldblock_type : tblock_type;
+ begin
+ oldprocinfo:=current_procinfo;
+ oldblock_type:=block_type;
+ { reset break and continue labels }
+ block_type:=bt_body;
+
+ current_procinfo:=self;
+
+ { calculate the lexical level }
+ if procdef.parast.symtablelevel>maxnesting then
+ Message(parser_e_too_much_lexlevel);
+
+ { static is also important for local procedures !! }
+ if (po_staticmethod in procdef.procoptions) then
+ allow_only_static:=true
+ else if (procdef.parast.symtablelevel=normal_function_level) then
+ allow_only_static:=false;
+
+ {$ifdef state_tracking}
+{ aktstate:=Tstate_storage.create;}
+ {$endif state_tracking}
+
+ { create a local symbol table for this routine }
+ if not assigned(procdef.localst) then
+ procdef.insert_localst;
+
+ { add parast/localst to symtablestack }
+ add_to_symtablestack;
+
+ { constant symbols are inserted in this symboltable }
+ constsymtable:=symtablestack;
+
+ { save entry info }
+ entrypos:=aktfilepos;
+ entryswitches:=aktlocalswitches;
+
+ { parse the code ... }
+ code:=block(current_module.islibrary);
+ { save exit info }
+ exitswitches:=aktlocalswitches;
+ exitpos:=last_endtoken_filepos;
+
+ { the procedure is now defined }
+ procdef.forwarddef:=false;
+
+ if assigned(code) then
+ begin
+ { get a better entry point }
+ entrypos:=code.fileinfo;
+
+ { Finish type checking pass }
+ do_resulttypepass(code);
+ end;
+
+ { Check for unused labels, forwards, symbols for procedures. Static
+ symtable is checked in pmodules.
+ The check must be done after the resulttypepass }
+ if (Errorcount=0) and
+ (tstoredsymtable(procdef.localst).symtabletype<>staticsymtable) then
+ begin
+ { check if forwards are resolved }
+ tstoredsymtable(procdef.localst).check_forwards;
+ { check if all labels are used }
+ tstoredsymtable(procdef.localst).checklabels;
+ { remove cross unit overloads }
+ tstoredsymtable(procdef.localst).unchain_overloaded;
+ { check for unused symbols, but only if there is no asm block }
+ if not(pi_has_assembler_block in flags) then
+ begin
+ tstoredsymtable(procdef.localst).allsymbolsused;
+ tstoredsymtable(procdef.parast).allsymbolsused;
+ end;
+ end;
+
+ if (po_inline in procdef.procoptions) then
+ begin
+ { Can we inline this procedure? }
+ if checknodeinlining(procdef) then
+ begin
+ new(procdef.inlininginfo);
+ include(procdef.procoptions,po_has_inlininginfo);
+ procdef.inlininginfo^.code:=code.getcopy;
+ procdef.inlininginfo^.flags:=current_procinfo.flags;
+ { The blocknode needs to set an exit label }
+ if procdef.inlininginfo^.code.nodetype=blockn then
+ include(procdef.inlininginfo^.code.flags,nf_block_with_exit);
+ end;
+ end;
+
+ { Print the node to tree.log }
+ if paraprintnodetree=1 then
+ printproc;
+
+ { ... remove symbol tables }
+ remove_from_symtablestack;
+
+ {$ifdef state_tracking}
+{ aktstate.destroy;}
+ {$endif state_tracking}
+
+ { reset to normal non static function }
+ if (procdef.parast.symtablelevel=normal_function_level) then
+ allow_only_static:=false;
+ current_procinfo:=oldprocinfo;
+
+ block_type:=oldblock_type;
+ end;
+
+
+{****************************************************************************
+ PROCEDURE/FUNCTION PARSING
+****************************************************************************}
+
+
+ procedure check_init_paras(p:tnamedindexitem;arg:pointer);
+ begin
+ if tsym(p).typ<>paravarsym then
+ exit;
+ with tparavarsym(p) do
+ if (not is_class(vartype.def) and
+ vartype.def.needs_inittable and
+ (varspez in [vs_value,vs_out])) then
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure read_proc;
+ {
+ Parses the procedure directives, then parses the procedure body, then
+ generates the code for it
+ }
+
+ procedure do_generate_code(pi:tcgprocinfo);
+ var
+ hpi : tcgprocinfo;
+ begin
+ { generate code for this procedure }
+ pi.generate_code;
+ { process nested procs }
+ hpi:=tcgprocinfo(pi.nestedprocs.first);
+ while assigned(hpi) do
+ begin
+ do_generate_code(hpi);
+ hpi:=tcgprocinfo(hpi.next);
+ end;
+ pi.resetprocdef;
+ end;
+
+ var
+ old_current_procinfo : tprocinfo;
+ oldconstsymtable : tsymtable;
+ oldfailtokenmode : tmodeswitch;
+ pdflags : tpdflags;
+ pd : tprocdef;
+ isnestedproc : boolean;
+ s : string;
+ begin
+ { save old state }
+ oldconstsymtable:=constsymtable;
+ old_current_procinfo:=current_procinfo;
+
+ { reset current_procinfo.procdef to nil to be sure that nothing is writing
+ to an other procdef }
+ current_procinfo:=nil;
+
+ { parse procedure declaration }
+ if assigned(old_current_procinfo) and
+ assigned(old_current_procinfo.procdef) then
+ pd:=parse_proc_dec(old_current_procinfo.procdef._class)
+ else
+ pd:=parse_proc_dec(nil);
+
+ { set the default function options }
+ if parse_only then
+ begin
+ pd.forwarddef:=true;
+ { set also the interface flag, for better error message when the
+ implementation doesn't much this header }
+ pd.interfacedef:=true;
+ include(pd.procoptions,po_global);
+ pdflags:=[pd_interface];
+ end
+ else
+ begin
+ pdflags:=[pd_body];
+ if (not current_module.in_interface) then
+ include(pdflags,pd_implemen);
+ if (not current_module.is_unit) or
+ maybe_smartlink_symbol then
+ include(pd.procoptions,po_global);
+ pd.forwarddef:=false;
+ end;
+
+ { parse the directives that may follow }
+ parse_proc_directives(pd,pdflags);
+
+ { hint directives, these can be separated by semicolons here,
+ that needs to be handled here with a loop (PFV) }
+ while try_consume_hintdirective(pd.symoptions) do
+ Consume(_SEMICOLON);
+
+ { Set calling convention }
+ handle_calling_convention(pd);
+
+ { search for forward declarations }
+ if not proc_add_definition(pd) then
+ begin
+ { A method must be forward defined (in the object declaration) }
+ if assigned(pd._class) and
+ (not assigned(old_current_procinfo.procdef._class)) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_any_member,pd.fullprocname(false));
+ tprocsym(pd.procsym).write_parameter_lists(pd);
+ end
+ else
+ begin
+ { Give a better error if there is a forward def in the interface and only
+ a single implementation }
+ if (not pd.forwarddef) and
+ (not pd.interfacedef) and
+ (tprocsym(pd.procsym).procdef_count>1) and
+ tprocsym(pd.procsym).first_procdef.forwarddef and
+ tprocsym(pd.procsym).first_procdef.interfacedef and
+ not(tprocsym(pd.procsym).procdef_count>2) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
+ tprocsym(pd.procsym).write_parameter_lists(pd);
+ end;
+ end;
+ end;
+
+ { Set mangled name }
+ proc_set_mangledname(pd);
+
+ { compile procedure when a body is needed }
+ if (pd_body in pdflags) then
+ begin
+ Message1(parser_d_procedure_start,pd.fullprocname(false));
+
+ { create a new procedure }
+ current_procinfo:=cprocinfo.create(old_current_procinfo);
+ current_module.procinfo:=current_procinfo;
+ current_procinfo.procdef:=pd;
+ isnestedproc:=(current_procinfo.procdef.parast.symtablelevel>normal_function_level);
+
+ { Insert mangledname }
+ pd.aliasnames.insert(pd.mangledname);
+
+ { Handle Export of this procedure }
+ if (po_exports in pd.procoptions) and
+ (target_info.system in [system_i386_os2,system_i386_emx]) then
+ begin
+ pd.aliasnames.insert(pd.procsym.realname);
+ if cs_link_deffile in aktglobalswitches then
+ deffile.AddExport(pd.mangledname);
+ end;
+
+ { Insert result variables in the localst }
+ insert_funcret_local(pd);
+
+ { check if there are para's which require initing -> set }
+ { pi_do_call (if not yet set) }
+ if not(pi_do_call in current_procinfo.flags) then
+ pd.parast.foreach_static(@check_init_paras,nil);
+
+ { set _FAIL as keyword if constructor }
+ if (pd.proctypeoption=potype_constructor) then
+ begin
+ oldfailtokenmode:=tokeninfo^[_FAIL].keyword;
+ tokeninfo^[_FAIL].keyword:=m_all;
+ end;
+
+ tcgprocinfo(current_procinfo).parse_body;
+
+ { When it's a nested procedure then defer the code generation,
+ when back at normal function level then generate the code
+ for all defered nested procedures and the current procedure }
+ if isnestedproc then
+ tcgprocinfo(current_procinfo.parent).nestedprocs.insert(current_procinfo)
+ else
+ begin
+ { We can't support inlining for procedures that have nested
+ procedures because the nested procedures use a fixed offset
+ for accessing locals in the parent procedure (PFV) }
+ if (po_inline in current_procinfo.procdef.procoptions) and
+ (tcgprocinfo(current_procinfo).nestedprocs.count>0) then
+ begin
+ Message1(parser_w_not_supported_for_inline,'nested procedures');
+ Message(parser_w_inlining_disabled);
+ current_procinfo.procdef.proccalloption:=pocall_default;
+ end;
+ do_generate_code(tcgprocinfo(current_procinfo));
+ end;
+
+ { reset _FAIL as _SELF normal }
+ if (pd.proctypeoption=potype_constructor) then
+ tokeninfo^[_FAIL].keyword:=oldfailtokenmode;
+
+ { release procinfo }
+ if tprocinfo(current_module.procinfo)<>current_procinfo then
+ internalerror(200304274);
+ current_module.procinfo:=current_procinfo.parent;
+ if not isnestedproc then
+ current_procinfo.free;
+
+ consume(_SEMICOLON);
+ end
+ else
+ begin
+ { Handle imports }
+ if (po_external in pd.procoptions) then
+ begin
+ { External declared in implementation, and there was already a
+ forward (or interface) declaration then we need to generate
+ a stub that calls the external routine }
+ if (not pd.forwarddef) and
+ (pd.hasforward) and
+ not(
+ assigned(pd.import_dll) and
+ (target_info.system in [system_i386_win32,system_i386_wdosx,
+ system_i386_emx,system_i386_os2,system_arm_wince,system_i386_wince])
+ ) then
+ begin
+ s:=proc_get_importname(pd);
+ if s<>'' then
+ gen_external_stub(asmlist[al_procedures],pd,{$IFDEF POWERPC64}'.'+{$ENDIF}s);
+ end;
+
+ { Import DLL specified? }
+ if assigned(pd.import_dll) then
+ begin
+ { create importlib if not already done }
+ if not(current_module.uses_imports) then
+ begin
+ current_module.uses_imports:=true;
+ importlib.preparelib(current_module.realmodulename^);
+ end;
+
+ if assigned(pd.import_name) then
+ importlib.importprocedure(pd,pd.import_dll^,pd.import_nr,pd.import_name^)
+ else
+ importlib.importprocedure(pd,pd.import_dll^,pd.import_nr,'');
+ end
+ else
+ begin
+ { add import name to external list for DLL scanning }
+ if target_info.DllScanSupported then
+ current_module.externals.insert(tExternalsItem.create(proc_get_importname(pd)));
+ end;
+ end;
+ end;
+
+ { Restore old state }
+ constsymtable:=oldconstsymtable;
+
+ current_procinfo:=old_current_procinfo;
+ end;
+
+
+{****************************************************************************
+ DECLARATION PARSING
+****************************************************************************}
+
+ { search in symtablestack for not complete classes }
+ procedure check_forward_class(p : tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ=typesym) and
+ (ttypesym(p).restype.def.deftype=objectdef) and
+ (oo_is_forward in tobjectdef(ttypesym(p).restype.def).objectoptions) then
+ MessagePos1(tsym(p).fileinfo,sym_e_forward_type_not_resolved,tsym(p).realname);
+ end;
+
+
+ procedure read_declarations(islibrary : boolean);
+ begin
+ repeat
+ if not assigned(current_procinfo) then
+ internalerror(200304251);
+ case token of
+ _LABEL:
+ label_dec;
+ _CONST:
+ const_dec;
+ _TYPE:
+ type_dec;
+ _VAR:
+ var_dec;
+ _THREADVAR:
+ threadvar_dec;
+ _CONSTRUCTOR,
+ _DESTRUCTOR,
+ _FUNCTION,
+ _PROCEDURE,
+ _OPERATOR,
+ _CLASS:
+ read_proc;
+ _EXPORTS:
+ begin
+ if not(assigned(current_procinfo.procdef.localst)) or
+ (current_procinfo.procdef.localst.symtablelevel>main_program_level) then
+ begin
+ Message(parser_e_syntax_error);
+ consume_all_until(_SEMICOLON);
+ end
+ else if islibrary or
+ (target_info.system in system_unit_program_exports) then
+ read_exports
+ else
+ begin
+ Message(parser_w_unsupported_feature);
+ consume(_BEGIN);
+ end;
+ end
+ else
+ begin
+ case idtoken of
+ _RESOURCESTRING :
+ begin
+ { m_class is needed, because the resourcestring
+ loading is in the ObjPas unit }
+ if (m_class in aktmodeswitches) then
+ resourcestring_dec
+ else
+ break;
+ end;
+ _PROPERTY:
+ begin
+ if (m_fpc in aktmodeswitches) then
+ property_dec
+ else
+ break;
+ end;
+ else
+ break;
+ end;
+ end;
+ end;
+ until false;
+
+ { check for incomplete class definitions, this is only required
+ for fpc modes }
+ if (m_fpc in aktmodeswitches) then
+ symtablestack.foreach_static(@check_forward_class,nil);
+ end;
+
+
+ procedure read_interface_declarations;
+ begin
+ repeat
+ case token of
+ _CONST :
+ const_dec;
+ _TYPE :
+ type_dec;
+ _VAR :
+ var_dec;
+ _THREADVAR :
+ threadvar_dec;
+ _FUNCTION,
+ _PROCEDURE,
+ _OPERATOR :
+ read_proc;
+ else
+ begin
+ case idtoken of
+ _RESOURCESTRING :
+ resourcestring_dec;
+ _PROPERTY:
+ begin
+ if (m_fpc in aktmodeswitches) then
+ property_dec
+ else
+ break;
+ end;
+ else
+ break;
+ end;
+ end;
+ end;
+ until false;
+ { check for incomplete class definitions, this is only required
+ for fpc modes }
+ if (m_fpc in aktmodeswitches) then
+ symtablestack.foreach_static(@check_forward_class,nil);
+ end;
+
+
+end.
diff --git a/compiler/psystem.pas b/compiler/psystem.pas
new file mode 100644
index 0000000000..40f1e86cc6
--- /dev/null
+++ b/compiler/psystem.pas
@@ -0,0 +1,557 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Load the system unit, create required defs for systemunit
+
+ 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 psystem;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symbase;
+
+ procedure insertinternsyms(p : tsymtable);
+ procedure insert_intern_types(p : tsymtable);
+
+ procedure readconstdefs;
+ procedure createconstdefs;
+
+ procedure registernodes;
+ procedure registertais;
+
+
+implementation
+
+ uses
+ globals,globtype,verbose,
+ systems,
+ symconst,symtype,symsym,symdef,symtable,
+ aasmtai,aasmcpu,ncgutil,fmodule,
+ node,nbas,nflw,nset,ncon,ncnv,nld,nmem,ncal,nmat,nadd,ninl,nopt
+ ;
+
+
+ procedure insertinternsyms(p : tsymtable);
+ {
+ all intern procedures for the system unit
+ }
+ begin
+ p.insert(tsyssym.create('Concat',in_concat_x));
+ p.insert(tsyssym.create('Write',in_write_x));
+ p.insert(tsyssym.create('WriteLn',in_writeln_x));
+ p.insert(tsyssym.create('Assigned',in_assigned_x));
+ p.insert(tsyssym.create('Read',in_read_x));
+ p.insert(tsyssym.create('ReadLn',in_readln_x));
+ p.insert(tsyssym.create('Ofs',in_ofs_x));
+ p.insert(tsyssym.create('SizeOf',in_sizeof_x));
+ p.insert(tsyssym.create('TypeOf',in_typeof_x));
+ p.insert(tsyssym.create('Low',in_low_x));
+ p.insert(tsyssym.create('High',in_high_x));
+ p.insert(tsyssym.create('Slice',in_slice_x));
+ p.insert(tsyssym.create('Seg',in_seg_x));
+ p.insert(tsyssym.create('Ord',in_ord_x));
+ p.insert(tsyssym.create('Pred',in_pred_x));
+ p.insert(tsyssym.create('Succ',in_succ_x));
+ p.insert(tsyssym.create('Exclude',in_exclude_x_y));
+ p.insert(tsyssym.create('Include',in_include_x_y));
+ p.insert(tsyssym.create('Break',in_break));
+ p.insert(tsyssym.create('Exit',in_exit));
+ p.insert(tsyssym.create('Continue',in_continue));
+ p.insert(tsyssym.create('Leave',in_leave)); {macpas only}
+ p.insert(tsyssym.create('Cycle',in_cycle)); {macpas only}
+ p.insert(tsyssym.create('Dec',in_dec_x));
+ p.insert(tsyssym.create('Inc',in_inc_x));
+ p.insert(tsyssym.create('Str',in_str_x_string));
+ p.insert(tsyssym.create('Assert',in_assert_x_y));
+ p.insert(tsyssym.create('Val',in_val_x));
+ p.insert(tsyssym.create('Addr',in_addr_x));
+ p.insert(tsyssym.create('TypeInfo',in_typeinfo_x));
+ p.insert(tsyssym.create('SetLength',in_setlength_x));
+ p.insert(tsyssym.create('Copy',in_copy_x));
+ p.insert(tsyssym.create('Initialize',in_initialize_x));
+ p.insert(tsyssym.create('Finalize',in_finalize_x));
+ p.insert(tsyssym.create('Length',in_length_x));
+ p.insert(tsyssym.create('New',in_new_x));
+ p.insert(tsyssym.create('Dispose',in_dispose_x));
+ end;
+
+
+ procedure insert_intern_types(p : tsymtable);
+ {
+ all the types inserted into the system unit
+ }
+
+ function addtype(const s:string;const t:ttype):ttypesym;
+ begin
+ result:=ttypesym.create(s,t);
+ p.insert(result);
+ { add init/final table if required }
+ if t.def.needs_inittable then
+ generate_inittable(result);
+ end;
+
+ procedure adddef(const s:string;def:tdef);
+ var
+ t : ttype;
+ begin
+ t.setdef(def);
+ p.insert(ttypesym.create(s,t));
+ end;
+
+ var
+ hrecst : trecordsymtable;
+ begin
+ if target_info.system=system_x86_64_win64 then
+ pbestrealtype:=@s64floattype;
+
+{$ifdef cpufpemu}
+ { Normal types }
+ (* we use the same types as without emulator, the only
+ difference is that direct calls to the emulator are generated
+ if (cs_fp_emulation in aktmoduleswitches) then
+ begin
+ addtype('Single',s32floattype);
+ { extended size is the best real type for the target }
+ addtype('Real',s32floattype);
+ pbestrealtype:=@s32floattype;
+ { extended size is the best real type for the target }
+ addtype('Extended',pbestrealtype^);
+ end
+ else
+ *)
+{$endif cpufpemu}
+ begin
+ addtype('Single',s32floattype);
+ addtype('Double',s64floattype);
+ { extended size is the best real type for the target }
+ addtype('Extended',pbestrealtype^);
+ addtype('Real',s64floattype);
+ end;
+{$ifdef x86}
+ if target_info.system<>system_x86_64_win64 then
+ adddef('Comp',tfloatdef.create(s64comp));
+{$endif x86}
+ addtype('Currency',s64currencytype);
+ addtype('Pointer',voidpointertype);
+{$ifdef x86}
+ addtype('FarPointer',voidfarpointertype);
+{$endif x86}
+ addtype('ShortString',cshortstringtype);
+{$ifdef support_longstring}
+ addtype('LongString',clongstringtype);
+{$endif support_longstring}
+{$ifdef ansistring_bits}
+ addtype('AnsiString',cansistringtype16);
+ addtype('AnsiString',cansistringtype32);
+ addtype('AnsiString',cansistringtype64);
+{$else}
+ addtype('AnsiString',cansistringtype);
+{$endif}
+ addtype('WideString',cwidestringtype);
+ addtype('Boolean',booltype);
+ addtype('ByteBool',booltype);
+ adddef('WordBool',torddef.create(bool16bit,0,1));
+ adddef('LongBool',torddef.create(bool32bit,0,1));
+ addtype('Byte',u8inttype);
+ addtype('ShortInt',s8inttype);
+ addtype('Word',u16inttype);
+ addtype('SmallInt',s16inttype);
+ addtype('LongWord',u32inttype);
+ addtype('LongInt',s32inttype);
+ addtype('QWord',u64inttype);
+ addtype('Int64',s64inttype);
+ addtype('Char',cchartype);
+ addtype('WideChar',cwidechartype);
+ adddef('Text',tfiledef.createtext);
+ adddef('TypedFile',tfiledef.createtyped(voidtype));
+ addtype('Variant',cvarianttype);
+ addtype('OleVariant',colevarianttype);
+ { Internal types }
+ addtype('$formal',cformaltype);
+ addtype('$void',voidtype);
+ addtype('$byte',u8inttype);
+ addtype('$shortint',s8inttype);
+ addtype('$word',u16inttype);
+ addtype('$smallint',s16inttype);
+ addtype('$ulong',u32inttype);
+ addtype('$longint',s32inttype);
+ addtype('$qword',u64inttype);
+ addtype('$int64',s64inttype);
+ addtype('$char',cchartype);
+ addtype('$widechar',cwidechartype);
+ addtype('$shortstring',cshortstringtype);
+ addtype('$longstring',clongstringtype);
+ {$ifdef ansistring_bits}
+ addtype('$ansistring16',cansistringtype16);
+ addtype('$ansistring32',cansistringtype32);
+ addtype('$ansistring64',cansistringtype64);
+ {$else}
+ addtype('$ansistring',cansistringtype);
+ {$endif}
+ addtype('$widestring',cwidestringtype);
+ addtype('$openshortstring',openshortstringtype);
+ addtype('$boolean',booltype);
+ addtype('$void_pointer',voidpointertype);
+ addtype('$char_pointer',charpointertype);
+ addtype('$widechar_pointer',widecharpointertype);
+ addtype('$void_farpointer',voidfarpointertype);
+ addtype('$openchararray',openchararraytype);
+ addtype('$file',cfiletype);
+ addtype('$variant',cvarianttype);
+ addtype('$olevariant',cvarianttype);
+ addtype('$s32real',s32floattype);
+ addtype('$s64real',s64floattype);
+ addtype('$s80real',s80floattype);
+ addtype('$s64currency',s64currencytype);
+ { Add a type for virtual method tables }
+ hrecst:=trecordsymtable.create(aktpackrecords);
+ vmttype.setdef(trecorddef.create(hrecst));
+ pvmttype.setdef(tpointerdef.create(vmttype));
+ hrecst.insertfield(tfieldvarsym.create('$parent',vs_value,pvmttype,[]),true);
+ hrecst.insertfield(tfieldvarsym.create('$length',vs_value,s32inttype,[]),true);
+ hrecst.insertfield(tfieldvarsym.create('$mlength',vs_value,s32inttype,[]),true);
+ vmtarraytype.setdef(tarraydef.create(0,1,s32inttype));
+ tarraydef(vmtarraytype.def).setelementtype(voidpointertype);
+ hrecst.insertfield(tfieldvarsym.create('$__pfn',vs_value,vmtarraytype,[]),true);
+ addtype('$__vtbl_ptr_type',vmttype);
+ addtype('$pvmt',pvmttype);
+ vmtarraytype.setdef(tarraydef.create(0,1,s32inttype));
+ tarraydef(vmtarraytype.def).setelementtype(pvmttype);
+ addtype('$vtblarray',vmtarraytype);
+ { Add a type for methodpointers }
+ hrecst:=trecordsymtable.create(1);
+ hrecst.insertfield(tfieldvarsym.create('$proc',vs_value,voidpointertype,[]),true);
+ hrecst.insertfield(tfieldvarsym.create('$self',vs_value,voidpointertype,[]),true);
+ methodpointertype.setdef(trecorddef.create(hrecst));
+ addtype('$methodpointer',methodpointertype);
+ { Add functions that require compiler magic }
+ insertinternsyms(p);
+ end;
+
+
+ procedure readconstdefs;
+ {
+ Load all default definitions for consts from the system unit
+ }
+
+
+ procedure loadtype(const s:string;var t:ttype);
+ var
+ srsym : tsym;
+ begin
+ srsym:=searchsymonlyin(systemunit,s);
+ if not(assigned(srsym) and
+ (srsym.typ=typesym)) then
+ internalerror(200403231);
+ t:=ttypesym(srsym).restype;
+ end;
+
+ var
+ oldcurrentmodule : tmodule;
+ begin
+ oldcurrentmodule:=current_module;
+ current_module:=nil;
+ loadtype('byte',u8inttype);
+ loadtype('shortint',s8inttype);
+ loadtype('word',u16inttype);
+ loadtype('smallint',s16inttype);
+ loadtype('ulong',u32inttype);
+ loadtype('longint',s32inttype);
+ loadtype('qword',u64inttype);
+ loadtype('int64',s64inttype);
+ loadtype('formal',cformaltype);
+ loadtype('void',voidtype);
+ loadtype('char',cchartype);
+ loadtype('widechar',cwidechartype);
+ loadtype('shortstring',cshortstringtype);
+ loadtype('longstring',clongstringtype);
+ {$ifdef ansistring_bits}
+ loadtype('ansistring16',cansistringtype16);
+ loadtype('ansistring32',cansistringtype32);
+ loadtype('ansistring64',cansistringtype64);
+ {$else}
+ loadtype('ansistring',cansistringtype);
+ {$endif}
+ loadtype('widestring',cwidestringtype);
+ loadtype('openshortstring',openshortstringtype);
+ loadtype('openchararray',openchararraytype);
+ loadtype('s32real',s32floattype);
+ loadtype('s64real',s64floattype);
+ loadtype('s80real',s80floattype);
+ loadtype('s64currency',s64currencytype);
+ loadtype('boolean',booltype);
+ loadtype('void_pointer',voidpointertype);
+ loadtype('char_pointer',charpointertype);
+ loadtype('widechar_pointer',widecharpointertype);
+ loadtype('void_farpointer',voidfarpointertype);
+ loadtype('file',cfiletype);
+ loadtype('pvmt',pvmttype);
+ loadtype('vtblarray',vmtarraytype);
+ loadtype('__vtbl_ptr_type',vmttype);
+ loadtype('variant',cvarianttype);
+ loadtype('olevariant',colevarianttype);
+ loadtype('methodpointer',methodpointertype);
+{$ifdef cpu64bit}
+ uinttype:=u64inttype;
+ sinttype:=s64inttype;
+ ptrinttype:=u64inttype;
+{$else cpu64bit}
+ uinttype:=u32inttype;
+ sinttype:=s32inttype;
+ ptrinttype:=u32inttype;
+{$endif cpu64bit}
+ current_module:=oldcurrentmodule;
+ end;
+
+
+ procedure createconstdefs;
+ {
+ Create all default definitions for consts for the system unit
+ }
+ var
+ oldregisterdef : boolean;
+ begin
+ { create definitions for constants }
+ oldregisterdef:=registerdef;
+ registerdef:=false;
+ cformaltype.setdef(tformaldef.create);
+ voidtype.setdef(torddef.create(uvoid,0,0));
+ u8inttype.setdef(torddef.create(u8bit,0,255));
+ s8inttype.setdef(torddef.create(s8bit,-128,127));
+ u16inttype.setdef(torddef.create(u16bit,0,65535));
+ s16inttype.setdef(torddef.create(s16bit,-32768,32767));
+ u32inttype.setdef(torddef.create(u32bit,0,high(longword)));
+ s32inttype.setdef(torddef.create(s32bit,low(longint),high(longint)));
+ u64inttype.setdef(torddef.create(u64bit,low(qword),TConstExprInt(high(qword))));
+ s64inttype.setdef(torddef.create(s64bit,low(int64),high(int64)));
+ booltype.setdef(torddef.create(bool8bit,0,1));
+ cchartype.setdef(torddef.create(uchar,0,255));
+ cwidechartype.setdef(torddef.create(uwidechar,0,65535));
+ cshortstringtype.setdef(tstringdef.createshort(255));
+ { should we give a length to the default long and ansi string definition ?? }
+ clongstringtype.setdef(tstringdef.createlong(-1));
+ {$ifdef ansistring_bits}
+ cansistringtype16.setdef(tstringdef.createansi(-1,sb_16));
+ cansistringtype32.setdef(tstringdef.createansi(-1,sb_32));
+ cansistringtype64.setdef(tstringdef.createansi(-1,sb_64));
+ {$else}
+ cansistringtype.setdef(tstringdef.createansi(-1));
+ {$endif}
+ cwidestringtype.setdef(tstringdef.createwide(-1));
+ { length=0 for shortstring is open string (needed for readln(string) }
+ openshortstringtype.setdef(tstringdef.createshort(0));
+ openchararraytype.setdef(tarraydef.create(0,-1,s32inttype));
+ tarraydef(openchararraytype.def).setelementtype(cchartype);
+{$ifdef x86}
+ s32floattype.setdef(tfloatdef.create(s32real));
+ s64floattype.setdef(tfloatdef.create(s64real));
+ s80floattype.setdef(tfloatdef.create(s80real));
+ if target_info.system<>system_x86_64_win64 then
+ s64currencytype.setdef(tfloatdef.create(s64currency))
+ else
+ s64currencytype.setdef(torddef.create(scurrency,low(int64),high(int64)));
+{$endif x86}
+{$ifdef powerpc}
+ s32floattype.setdef(tfloatdef.create(s32real));
+ s64floattype.setdef(tfloatdef.create(s64real));
+ s80floattype.setdef(tfloatdef.create(s80real));
+ s64currencytype.setdef(torddef.create(scurrency,low(int64),high(int64)));
+{$endif powerpc}
+{$ifdef POWERPC64}
+ s32floattype.setdef(tfloatdef.create(s32real));
+ s64floattype.setdef(tfloatdef.create(s64real));
+ s80floattype.setdef(tfloatdef.create(s80real));
+ s64currencytype.setdef(torddef.create(scurrency,low(int64),high(int64)));
+{$endif POWERPC64}
+{$ifdef sparc}
+ s32floattype.setdef(tfloatdef.create(s32real));
+ s64floattype.setdef(tfloatdef.create(s64real));
+ s80floattype.setdef(tfloatdef.create(s80real));
+ s64currencytype.setdef(torddef.create(scurrency,low(int64),high(int64)));
+{$endif sparc}
+{$ifdef m68k}
+ s32floattype.setdef(tfloatdef.create(s32real));
+ s64floattype.setdef(tfloatdef.create(s64real));
+ s80floattype.setdef(tfloatdef.create(s80real));
+ s64currencytype.setdef(torddef.create(scurrency,low(int64),high(int64)));
+{$endif}
+{$ifdef arm}
+ s32floattype.setdef(tfloatdef.create(s32real));
+ s64floattype.setdef(tfloatdef.create(s64real));
+ s80floattype.setdef(tfloatdef.create(s80real));
+ s64currencytype.setdef(torddef.create(scurrency,low(int64),high(int64)));
+{$endif arm}
+{$ifdef cpu64bit}
+ uinttype:=u64inttype;
+ sinttype:=s64inttype;
+ ptrinttype:=u64inttype;
+{$else cpu64bit}
+ uinttype:=u32inttype;
+ sinttype:=s32inttype;
+ ptrinttype:=u32inttype;
+{$endif cpu64bit}
+ { some other definitions }
+ voidpointertype.setdef(tpointerdef.create(voidtype));
+ charpointertype.setdef(tpointerdef.create(cchartype));
+ widecharpointertype.setdef(tpointerdef.create(cwidechartype));
+ voidfarpointertype.setdef(tpointerdef.createfar(voidtype));
+ cfiletype.setdef(tfiledef.createuntyped);
+ cvarianttype.setdef(tvariantdef.create(vt_normalvariant));
+ colevarianttype.setdef(tvariantdef.create(vt_olevariant));
+ registerdef:=oldregisterdef;
+ end;
+
+
+ procedure registernodes;
+ {
+ Register all possible nodes in the nodeclass array that
+ will be used for loading the nodes from a ppu
+ }
+ begin
+ nodeclass[addn]:=caddnode;
+ nodeclass[muln]:=caddnode;
+ nodeclass[subn]:=caddnode;
+ nodeclass[divn]:=cmoddivnode;
+ nodeclass[symdifn]:=caddnode;
+ nodeclass[modn]:=cmoddivnode;
+ nodeclass[assignn]:=cassignmentnode;
+ nodeclass[loadn]:=cloadnode;
+ nodeclass[rangen]:=crangenode;
+ nodeclass[ltn]:=caddnode;
+ nodeclass[lten]:=caddnode;
+ nodeclass[gtn]:=caddnode;
+ nodeclass[gten]:=caddnode;
+ nodeclass[equaln]:=caddnode;
+ nodeclass[unequaln]:=caddnode;
+ nodeclass[inn]:=cinnode;
+ nodeclass[orn]:=caddnode;
+ nodeclass[xorn]:=caddnode;
+ nodeclass[shrn]:=cshlshrnode;
+ nodeclass[shln]:=cshlshrnode;
+ nodeclass[slashn]:=caddnode;
+ nodeclass[andn]:=caddnode;
+ nodeclass[subscriptn]:=csubscriptnode;
+ nodeclass[derefn]:=cderefnode;
+ nodeclass[addrn]:=caddrnode;
+ nodeclass[ordconstn]:=cordconstnode;
+ nodeclass[typeconvn]:=ctypeconvnode;
+ nodeclass[calln]:=ccallnode;
+ nodeclass[callparan]:=ccallparanode;
+ nodeclass[realconstn]:=crealconstnode;
+ nodeclass[unaryminusn]:=cunaryminusnode;
+ nodeclass[asmn]:=casmnode;
+ nodeclass[vecn]:=cvecnode;
+ nodeclass[pointerconstn]:=cpointerconstnode;
+ nodeclass[stringconstn]:=cstringconstnode;
+ nodeclass[notn]:=cnotnode;
+ nodeclass[inlinen]:=cinlinenode;
+ nodeclass[niln]:=cnilnode;
+ nodeclass[errorn]:=cerrornode;
+ nodeclass[typen]:=ctypenode;
+ nodeclass[setelementn]:=csetelementnode;
+ nodeclass[setconstn]:=csetconstnode;
+ nodeclass[blockn]:=cblocknode;
+ nodeclass[statementn]:=cstatementnode;
+ nodeclass[ifn]:=cifnode;
+ nodeclass[breakn]:=cbreaknode;
+ nodeclass[continuen]:=ccontinuenode;
+ nodeclass[whilerepeatn]:=cwhilerepeatnode;
+ nodeclass[forn]:=cfornode;
+ nodeclass[exitn]:=cexitnode;
+ nodeclass[withn]:=cwithnode;
+ nodeclass[casen]:=ccasenode;
+ nodeclass[labeln]:=clabelnode;
+ nodeclass[goton]:=cgotonode;
+ nodeclass[tryexceptn]:=ctryexceptnode;
+ nodeclass[raisen]:=craisenode;
+ nodeclass[tryfinallyn]:=ctryfinallynode;
+ nodeclass[onn]:=connode;
+ nodeclass[isn]:=cisnode;
+ nodeclass[asn]:=casnode;
+ nodeclass[caretn]:=caddnode;
+ nodeclass[starstarn]:=caddnode;
+ nodeclass[arrayconstructorn]:=carrayconstructornode;
+ nodeclass[arrayconstructorrangen]:=carrayconstructorrangenode;
+ nodeclass[tempcreaten]:=ctempcreatenode;
+ nodeclass[temprefn]:=ctemprefnode;
+ nodeclass[tempdeleten]:=ctempdeletenode;
+ nodeclass[addoptn]:=caddnode;
+ nodeclass[nothingn]:=cnothingnode;
+ nodeclass[loadvmtaddrn]:=cloadvmtaddrnode;
+ nodeclass[guidconstn]:=cguidconstnode;
+ nodeclass[rttin]:=crttinode;
+ nodeclass[loadparentfpn]:=cloadparentfpnode;
+ end;
+
+
+ procedure registertais;
+ {
+ Register all possible tais in the taiclass array that
+ will be used for loading the tais from a ppu
+ }
+ begin
+ aiclass[ait_none]:=nil;
+ aiclass[ait_align]:=tai_align;
+ aiclass[ait_section]:=tai_section;
+ aiclass[ait_comment]:=tai_comment;
+ aiclass[ait_string]:=tai_string;
+ aiclass[ait_instruction]:=taicpu;
+ aiclass[ait_datablock]:=tai_datablock;
+ aiclass[ait_symbol]:=tai_symbol;
+ aiclass[ait_symbol_end]:=tai_symbol_end;
+ aiclass[ait_directive]:=tai_directive;
+ aiclass[ait_label]:=tai_label;
+ aiclass[ait_const_64bit]:=tai_const;
+ aiclass[ait_const_32bit]:=tai_const;
+ aiclass[ait_const_16bit]:=tai_const;
+ aiclass[ait_const_8bit]:=tai_const;
+ aiclass[ait_const_indirect_symbol]:=tai_const;
+ aiclass[ait_const_rva_symbol]:=tai_const;
+ aiclass[ait_real_32bit]:=tai_real_32bit;
+ aiclass[ait_real_64bit]:=tai_real_64bit;
+ aiclass[ait_real_80bit]:=tai_real_80bit;
+ aiclass[ait_comp_64bit]:=tai_comp_64bit;
+ aiclass[ait_stab]:=tai_stab;
+ aiclass[ait_force_line]:=tai_force_line;
+ aiclass[ait_function_name]:=tai_function_name;
+{$ifdef alpha}
+ { the follow is for the DEC Alpha }
+ aiclass[ait_frame]:=tai_frame;
+ aiclass[ait_ent]:=tai_ent;
+{$endif alpha}
+{$ifdef m68k}
+{$warning FIXME: tai_labeled_instruction doesn't exists}
+// aiclass[ait_labeled_instruction]:=tai_labeled_instruction;
+{$endif m68k}
+{$ifdef ia64}
+ aiclass[ait_bundle]:=tai_bundle;
+ aiclass[ait_stop]:=tai_stop;
+{$endif ia64}
+{$ifdef SPARC}
+// aiclass[ait_labeled_instruction]:=tai_labeled_instruction;
+{$endif SPARC}
+ aiclass[ait_cutobject]:=tai_cutobject;
+ aiclass[ait_regalloc]:=tai_regalloc;
+ aiclass[ait_tempalloc]:=tai_tempalloc;
+ aiclass[ait_marker]:=tai_marker;
+ end;
+
+end.
diff --git a/compiler/ptconst.pas b/compiler/ptconst.pas
new file mode 100644
index 0000000000..5bd0a085cb
--- /dev/null
+++ b/compiler/ptconst.pas
@@ -0,0 +1,1030 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Reads typed constants
+
+ 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 ptconst;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses symtype,symsym;
+
+ { this procedure reads typed constants }
+ { sym is only needed for ansi strings }
+ { the assembler label is in the middle (PM) }
+ procedure readtypedconst(const t:ttype;sym : ttypedconstsym;writable : boolean);
+
+implementation
+
+ uses
+ strings,
+ globtype,systems,tokens,verbose,
+ cutils,globals,widestr,scanner,
+ symconst,symbase,symdef,symtable,
+ aasmbase,aasmtai,aasmcpu,defutil,defcmp,
+ { pass 1 }
+ node,htypechk,procinfo,
+ nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
+ { parser specific stuff }
+ pbase,pexpr,
+ { codegen }
+ cpuinfo,cgbase,dbgbase
+ ;
+
+{$ifdef fpc}
+ {$maxfpuregisters 0}
+{$endif fpc}
+ { this procedure reads typed constants }
+ procedure readtypedconst(const t:ttype;sym : ttypedconstsym;writable : boolean);
+ label
+ myexit;
+ type
+ setbytes = array[0..31] of byte;
+ Psetbytes = ^setbytes;
+ var
+ len,base : longint;
+ p,hp : tnode;
+ i,j,l,
+ varalign : longint;
+ offset,
+ strlength : aint;
+ ll : tasmlabel;
+ s,sorg : string;
+ c : char;
+ ca : pchar;
+ tmpguid : tguid;
+ aktpos : longint;
+ obj : tobjectdef;
+ recsym,
+ srsym : tsym;
+ symt : tsymtable;
+ value : bestreal;
+ intvalue : tconstexprint;
+ strval : pchar;
+ pw : pcompilerwidestring;
+ error : boolean;
+ old_block_type : tblock_type;
+ storefilepos : tfileposinfo;
+ cursectype : TAsmSectionType;
+ cural : tasmlist;
+
+ procedure check_range(def:torddef);
+ begin
+ if ((tordconstnode(p).value>def.high) or
+ (tordconstnode(p).value<def.low)) then
+ begin
+ if (cs_check_range in aktlocalswitches) then
+ Message(parser_e_range_check_error)
+ else
+ Message(parser_w_range_check_error);
+ end;
+ end;
+
+ begin
+ old_block_type:=block_type;
+ block_type:=bt_const;
+
+ if writable then
+ begin
+ cural:=al_typedconsts;
+ cursectype:=sec_data;
+ end
+ else
+ begin
+ cural:=al_rotypedconsts;
+ cursectype:=sec_rodata;
+ end;
+
+ { Add symbol name if this is specified. For array
+ elements sym=nil and we should skip this }
+ if assigned(sym) then
+ begin
+ storefilepos:=aktfilepos;
+ aktfilepos:=sym.fileinfo;
+
+ { insert cut for smartlinking or alignment }
+ l:=sym.getsize;
+ maybe_new_object_file(asmlist[cural]);
+ new_section(asmlist[cural],cursectype,lower(sym.mangledname),const_align(l));
+
+ if (sym.owner.symtabletype=globalsymtable) or
+ maybe_smartlink_symbol or
+ (assigned(current_procinfo) and
+ (po_inline in current_procinfo.procdef.procoptions)) or
+ DLLSource then
+ asmlist[cural].concat(Tai_symbol.Createname_global(sym.mangledname,AT_DATA,l))
+ else
+ asmlist[cural].concat(Tai_symbol.Createname(sym.mangledname,AT_DATA,l));
+ aktfilepos:=storefilepos;
+ end;
+
+ case t.def.deftype of
+ orddef:
+ begin
+ p:=comp_expr(true);
+ case torddef(t.def).typ of
+ bool8bit :
+ begin
+ if is_constboolnode(p) then
+ asmlist[cural].concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)))
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ bool16bit :
+ begin
+ if is_constboolnode(p) then
+ asmlist[cural].concat(Tai_const.Create_16bit(word(tordconstnode(p).value)))
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ bool32bit :
+ begin
+ if is_constboolnode(p) then
+ asmlist[cural].concat(Tai_const.Create_32bit(longint(tordconstnode(p).value)))
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ uchar :
+ begin
+ if is_constcharnode(p) then
+ asmlist[cural].concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)))
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ uwidechar :
+ begin
+ if is_constcharnode(p) then
+ inserttypeconv(p,cwidechartype);
+ if is_constwidecharnode(p) then
+ asmlist[cural].concat(Tai_const.Create_16bit(word(tordconstnode(p).value)))
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ s8bit,
+ u8bit :
+ begin
+ if is_constintnode(p) then
+ begin
+ asmlist[cural].concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)));
+ check_range(torddef(t.def));
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ u16bit,
+ s16bit :
+ begin
+ if is_constintnode(p) then
+ begin
+ asmlist[cural].concat(Tai_const.Create_16bit(word(tordconstnode(p).value)));
+ check_range(torddef(t.def));
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ s32bit,
+ u32bit :
+ begin
+ if is_constintnode(p) then
+ begin
+ asmlist[cural].concat(Tai_const.Create_32bit(longint(tordconstnode(p).value)));
+ if torddef(t.def).typ<>u32bit then
+ check_range(torddef(t.def));
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ s64bit,
+ u64bit,
+ scurrency:
+ begin
+ if is_constintnode(p) then
+ intvalue := tordconstnode(p).value
+ else if is_constrealnode(p) and
+ (torddef(t.def).typ=scurrency)
+ { allow bootstrapping }
+ then
+ begin
+ intvalue:=round(trealconstnode(p).value_real*10000);
+ end
+ else
+ begin
+ intvalue:=0;
+ Message(parser_e_illegal_expression);
+ end;
+ asmlist[cural].concat(Tai_const.Create_64bit(intvalue));
+ end;
+ else
+ internalerror(3799);
+ end;
+ p.free;
+ end;
+ floatdef:
+ begin
+ p:=comp_expr(true);
+ if is_constrealnode(p) then
+ value:=trealconstnode(p).value_real
+ else if is_constintnode(p) then
+ value:=tordconstnode(p).value
+ else
+ Message(parser_e_illegal_expression);
+
+ case tfloatdef(t.def).typ of
+ s32real :
+ asmlist[cural].concat(Tai_real_32bit.Create(ts32real(value)));
+ s64real :
+{$ifdef ARM}
+ if aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11] then
+ asmlist[cural].concat(Tai_real_64bit.Create_hiloswapped(ts64real(value)))
+ else
+{$endif ARM}
+ asmlist[cural].concat(Tai_real_64bit.Create(ts64real(value)));
+ s80real :
+ asmlist[cural].concat(Tai_real_80bit.Create(value));
+
+ { the round is necessary for native compilers where comp isn't a float }
+ s64comp :
+ asmlist[cural].concat(Tai_comp_64bit.Create(round(value)));
+ s64currency:
+ asmlist[cural].concat(Tai_comp_64bit.Create(round(value*10000)));
+ s128real:
+ asmlist[cural].concat(Tai_real_128bit.Create(value));
+ else
+ internalerror(18);
+ end;
+ p.free;
+ end;
+ classrefdef:
+ begin
+ p:=comp_expr(true);
+ case p.nodetype of
+ loadvmtaddrn:
+ with Tclassrefdef(p.resulttype.def) do
+ begin
+ if not Tobjectdef(pointertype.def).is_related(Tobjectdef(pointertype.def)) then
+ message(parser_e_illegal_expression);
+ asmlist[cural].concat(Tai_const.Create_sym(objectlibrary.newasmsymbol(
+ Tobjectdef(pointertype.def).vmt_mangledname,AB_EXTERNAL,AT_DATA)));
+ end;
+ niln:
+ asmlist[cural].concat(Tai_const.Create_sym(nil));
+ else Message(parser_e_illegal_expression);
+ end;
+ p.free;
+ end;
+ pointerdef:
+ begin
+ p:=comp_expr(true);
+ if (p.nodetype=typeconvn) then
+ with Ttypeconvnode(p) do
+ if (left.nodetype in [addrn,niln]) and equal_defs(t.def,p.resulttype.def) then
+ begin
+ hp:=left;
+ left:=nil;
+ p.free;
+ p:=hp;
+ end;
+ { allows horrible ofs(typeof(TButton)^) code !! }
+ if (p.nodetype=addrn) then
+ with Taddrnode(p) do
+ if left.nodetype=derefn then
+ begin
+ hp:=tderefnode(left).left;
+ tderefnode(left).left:=nil;
+ p.free;
+ p:=hp;
+ end;
+ { const pointer ? }
+ if (p.nodetype = pointerconstn) then
+ begin
+ if sizeof(TConstPtrUInt)=8 then
+ asmlist[cural].concat(Tai_const.Create_64bit(TConstPtrUInt(tpointerconstnode(p).value)))
+ else
+ if sizeof(TConstPtrUInt)=4 then
+ asmlist[cural].concat(Tai_const.Create_32bit(TConstPtrUInt(tpointerconstnode(p).value)))
+ else
+ internalerror(200404122);
+ end
+ { nil pointer ? }
+ else if p.nodetype=niln then
+ asmlist[cural].concat(Tai_const.Create_sym(nil))
+ { maybe pchar ? }
+ else
+ if is_char(tpointerdef(t.def).pointertype.def) and
+ (p.nodetype<>addrn) then
+ begin
+ objectlibrary.getdatalabel(ll);
+ asmlist[cural].concat(Tai_const.Create_sym(ll));
+ if p.nodetype=stringconstn then
+ varalign:=size_2_align(tstringconstnode(p).len)
+ else
+ varalign:=0;
+ varalign:=const_align(varalign);
+ asmlist[al_const].concat(Tai_align.Create(varalign));
+ asmlist[al_const].concat(Tai_label.Create(ll));
+ if p.nodetype=stringconstn then
+ begin
+ len:=tstringconstnode(p).len;
+ { For tp7 the maximum lentgh can be 255 }
+ if (m_tp7 in aktmodeswitches) and
+ (len>255) then
+ len:=255;
+ getmem(ca,len+2);
+ move(tstringconstnode(p).value_str^,ca^,len+1);
+ asmlist[al_const].concat(Tai_string.Create_pchar(ca,len+1));
+ end
+ else
+ if is_constcharnode(p) then
+ asmlist[al_const].concat(Tai_string.Create(char(byte(tordconstnode(p).value))+#0))
+ else
+ message(parser_e_illegal_expression);
+ end
+ { maybe pwidechar ? }
+ else
+ if is_widechar(tpointerdef(t.def).pointertype.def) and
+ (p.nodetype<>addrn) then
+ begin
+ objectlibrary.getdatalabel(ll);
+ asmlist[cural].concat(Tai_const.Create_sym(ll));
+ asmlist[al_typedconsts].concat(tai_align.create(const_align(sizeof(aint))));
+ asmlist[al_typedconsts].concat(Tai_label.Create(ll));
+ if (p.nodetype in [stringconstn,ordconstn]) then
+ begin
+ { convert to widestring stringconstn }
+ inserttypeconv(p,cwidestringtype);
+ if (p.nodetype=stringconstn) and
+ (tstringconstnode(p).st_type=st_widestring) then
+ begin
+ pw:=pcompilerwidestring(tstringconstnode(p).value_str);
+ for i:=0 to tstringconstnode(p).len-1 do
+ asmlist[al_typedconsts].concat(Tai_const.Create_16bit(pw^.data[i]));
+ { ending #0 }
+ asmlist[al_typedconsts].concat(Tai_const.Create_16bit(0))
+ end;
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end
+ else
+ if (p.nodetype=addrn) or
+ is_procvar_load(p) then
+ begin
+ { insert typeconv }
+ inserttypeconv(p,t);
+ hp:=p;
+ while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
+ hp:=tunarynode(hp).left;
+ if (hp.nodetype=loadn) then
+ begin
+ hp:=p;
+ offset:=0;
+ while assigned(hp) and (hp.nodetype<>loadn) do
+ begin
+ case hp.nodetype of
+ vecn :
+ begin
+ case tvecnode(hp).left.resulttype.def.deftype of
+ stringdef :
+ begin
+ { this seems OK for shortstring and ansistrings PM }
+ { it is wrong for widestrings !! }
+ len:=1;
+ base:=0;
+ end;
+ arraydef :
+ begin
+ len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
+ base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ if is_constintnode(tvecnode(hp).right) then
+ inc(offset,len*(get_ordinal_value(tvecnode(hp).right)-base))
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ subscriptn :
+ inc(offset,tsubscriptnode(hp).vs.fieldoffset);
+ typeconvn :
+ begin
+ if not(ttypeconvnode(hp).convtype in [tc_equal,tc_proc_2_procvar]) then
+ Message(parser_e_illegal_expression);
+ end;
+ addrn :
+ ;
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ hp:=tunarynode(hp).left;
+ end;
+ srsym:=tloadnode(hp).symtableentry;
+ case srsym.typ of
+ procsym :
+ begin
+ if Tprocsym(srsym).procdef_count>1 then
+ Message(parser_e_no_overloaded_procvars);
+ if po_abstractmethod in tprocsym(srsym).first_procdef.procoptions then
+ Message(type_e_cant_take_address_of_abstract_method)
+ else
+ asmlist[cural].concat(Tai_const.Createname(tprocsym(srsym).first_procdef.mangledname,AT_FUNCTION,offset));
+ end;
+ globalvarsym :
+ asmlist[cural].concat(Tai_const.Createname(tglobalvarsym(srsym).mangledname,AT_DATA,offset));
+ typedconstsym :
+ asmlist[cural].concat(Tai_const.Createname(ttypedconstsym(srsym).mangledname,AT_DATA,offset));
+ labelsym :
+ asmlist[cural].concat(Tai_const.Createname(tlabelsym(srsym).mangledname,AT_LABEL,offset));
+ constsym :
+ if tconstsym(srsym).consttyp=constresourcestring then
+ asmlist[cural].concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',tconstsym(srsym).owner,''),AT_DATA,tconstsym(srsym).resstrindex*(4+sizeof(aint)*3)+4+sizeof(aint)))
+ else
+ Message(type_e_variable_id_expected);
+ else
+ Message(type_e_variable_id_expected);
+ end;
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end
+ else
+ { allow typeof(Object type)}
+ if (p.nodetype=inlinen) and
+ (tinlinenode(p).inlinenumber=in_typeof_x) then
+ begin
+ if (tinlinenode(p).left.nodetype=typen) then
+ begin
+ asmlist[cural].concat(Tai_const.createname(
+ tobjectdef(tinlinenode(p).left.resulttype.def).vmt_mangledname,AT_DATA,0));
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ end;
+ setdef:
+ begin
+ p:=comp_expr(true);
+ if p.nodetype=setconstn then
+ begin
+ { be sure to convert to the correct result, else
+ it can generate smallset data instead of normalset (PFV) }
+ inserttypeconv(p,t);
+ { we only allow const sets }
+ if assigned(tsetconstnode(p).left) then
+ Message(parser_e_illegal_expression)
+ else
+ begin
+ { this writing is endian independant }
+ { untrue - because they are considered }
+ { arrays of 32-bit values CEC }
+
+ if source_info.endian = target_info.endian then
+ begin
+ for l:=0 to p.resulttype.def.size-1 do
+ asmlist[cural].concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[l]));
+ end
+ else
+ begin
+ { store as longint values in swaped format }
+ j:=0;
+ for l:=0 to ((p.resulttype.def.size-1) div 4) do
+ begin
+ asmlist[cural].concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+3]));
+ asmlist[cural].concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+2]));
+ asmlist[cural].concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+1]));
+ asmlist[cural].concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j]));
+ Inc(j,4);
+ end;
+ end;
+ end;
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ end;
+ enumdef:
+ begin
+ p:=comp_expr(true);
+ if p.nodetype=ordconstn then
+ begin
+ if equal_defs(p.resulttype.def,t.def) or
+ is_subequal(p.resulttype.def,t.def) then
+ begin
+ case longint(p.resulttype.def.size) of
+ 1 : asmlist[cural].concat(Tai_const.Create_8bit(Byte(tordconstnode(p).value)));
+ 2 : asmlist[cural].concat(Tai_const.Create_16bit(Word(tordconstnode(p).value)));
+ 4 : asmlist[cural].concat(Tai_const.Create_32bit(Longint(tordconstnode(p).value)));
+ end;
+ end
+ else
+ IncompatibleTypes(p.resulttype.def,t.def);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ end;
+ stringdef:
+ begin
+ p:=comp_expr(true);
+ { load strval and strlength of the constant tree }
+ if (p.nodetype=stringconstn) or is_widestring(t.def) then
+ begin
+ { convert to the expected string type so that
+ for widestrings strval is a pcompilerwidestring }
+ inserttypeconv(p,t);
+ strlength:=tstringconstnode(p).len;
+ strval:=tstringconstnode(p).value_str;
+ end
+ else if is_constcharnode(p) then
+ begin
+ { strval:=pchar(@tordconstnode(p).value);
+ THIS FAIL on BIG_ENDIAN MACHINES PM }
+ c:=chr(tordconstnode(p).value and $ff);
+ strval:=@c;
+ strlength:=1
+ end
+ else if is_constresourcestringnode(p) then
+ begin
+ strval:=pchar(tconstsym(tloadnode(p).symtableentry).value.valueptr);
+ strlength:=tconstsym(tloadnode(p).symtableentry).value.len;
+ end
+ else
+ begin
+ Message(parser_e_illegal_expression);
+ strlength:=-1;
+ end;
+ if strlength>=0 then
+ begin
+ case tstringdef(t.def).string_typ of
+ st_shortstring:
+ begin
+ if strlength>=t.def.size then
+ begin
+ message2(parser_w_string_too_long,strpas(strval),tostr(t.def.size-1));
+ strlength:=t.def.size-1;
+ end;
+ asmlist[cural].concat(Tai_const.Create_8bit(strlength));
+ { this can also handle longer strings }
+ getmem(ca,strlength+1);
+ move(strval^,ca^,strlength);
+ ca[strlength]:=#0;
+ asmlist[cural].concat(Tai_string.Create_pchar(ca,strlength));
+ { fillup with spaces if size is shorter }
+ if t.def.size>strlength then
+ begin
+ getmem(ca,t.def.size-strlength);
+ { def.size contains also the leading length, so we }
+ { we have to subtract one }
+ fillchar(ca[0],t.def.size-strlength-1,' ');
+ ca[t.def.size-strlength-1]:=#0;
+ { this can also handle longer strings }
+ asmlist[cural].concat(Tai_string.Create_pchar(ca,t.def.size-strlength-1));
+ end;
+ end;
+ st_ansistring:
+ begin
+ { an empty ansi string is nil! }
+ if (strlength=0) then
+ asmlist[cural].concat(Tai_const.Create_sym(nil))
+ else
+ begin
+ objectlibrary.getdatalabel(ll);
+ asmlist[cural].concat(Tai_const.Create_sym(ll));
+ asmlist[al_const].concat(tai_align.create(const_align(sizeof(aint))));
+ asmlist[al_const].concat(Tai_const.Create_aint(-1));
+ asmlist[al_const].concat(Tai_const.Create_aint(strlength));
+ asmlist[al_const].concat(Tai_label.Create(ll));
+ getmem(ca,strlength+1);
+ move(strval^,ca^,strlength);
+ { The terminating #0 to be stored in the .data section (JM) }
+ ca[strlength]:=#0;
+ asmlist[al_const].concat(Tai_string.Create_pchar(ca,strlength+1));
+ end;
+ end;
+ st_widestring:
+ begin
+ { an empty ansi string is nil! }
+ if (strlength=0) then
+ asmlist[cural].concat(Tai_const.Create_sym(nil))
+ else
+ begin
+ objectlibrary.getdatalabel(ll);
+ asmlist[cural].concat(Tai_const.Create_sym(ll));
+ asmlist[al_const].concat(tai_align.create(const_align(sizeof(aint))));
+ asmlist[al_const].concat(Tai_const.Create_aint(-1));
+ asmlist[al_const].concat(Tai_const.Create_aint(strlength*cwidechartype.def.size));
+ asmlist[al_const].concat(Tai_label.Create(ll));
+ for i:=0 to strlength-1 do
+ asmlist[al_const].concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
+ { ending #0 }
+ asmlist[al_const].concat(Tai_const.Create_16bit(0))
+ end;
+ end;
+ st_longstring:
+ begin
+ internalerror(200107081);
+ end;
+ end;
+ end;
+ p.free;
+ end;
+ arraydef:
+ begin
+ { dynamic array nil }
+ if is_dynamic_array(t.def) then
+ begin
+ { Only allow nil initialization }
+ consume(_NIL);
+ asmlist[cural].concat(Tai_const.Create_sym(nil));
+ end
+ else
+ if try_to_consume(_LKLAMMER) then
+ begin
+ for l:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange-1 do
+ begin
+ readtypedconst(tarraydef(t.def).elementtype,nil,writable);
+ consume(_COMMA);
+ end;
+ readtypedconst(tarraydef(t.def).elementtype,nil,writable);
+ consume(_RKLAMMER);
+ end
+ else
+ { if array of char then we allow also a string }
+ if is_char(tarraydef(t.def).elementtype.def) then
+ begin
+ p:=comp_expr(true);
+ if p.nodetype=stringconstn then
+ begin
+ len:=tstringconstnode(p).len;
+ { For tp7 the maximum lentgh can be 255 }
+ if (m_tp7 in aktmodeswitches) and
+ (len>255) then
+ len:=255;
+ ca:=tstringconstnode(p).value_str;
+ end
+ else
+ if is_constcharnode(p) then
+ begin
+ c:=chr(tordconstnode(p).value and $ff);
+ ca:=@c;
+ len:=1;
+ end
+ else
+ begin
+ Message(parser_e_illegal_expression);
+ len:=0;
+ end;
+ if len>(tarraydef(t.def).highrange-tarraydef(t.def).lowrange+1) then
+ Message(parser_e_string_larger_array);
+ for i:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange do
+ begin
+ if i+1-tarraydef(t.def).lowrange<=len then
+ begin
+ asmlist[cural].concat(Tai_const.Create_8bit(byte(ca^)));
+ inc(ca);
+ end
+ else
+ {Fill the remaining positions with #0.}
+ asmlist[cural].concat(Tai_const.Create_8bit(0));
+ end;
+ p.free;
+ end
+ else
+ begin
+ { we want the ( }
+ consume(_LKLAMMER);
+ end;
+ end;
+ procvardef:
+ begin
+ { Procvars and pointers are no longer compatible. }
+ { under tp: =nil or =var under fpc: =nil or =@var }
+ if token=_NIL then
+ begin
+ asmlist[cural].concat(Tai_const.Create_sym(nil));
+ if (po_methodpointer in tprocvardef(t.def).procoptions) then
+ asmlist[cural].concat(Tai_const.Create_sym(nil));
+ consume(_NIL);
+ goto myexit;
+ end;
+ { you can't assign a value other than NIL to a typed constant }
+ { which is a "procedure of object", because this also requires }
+ { address of an object/class instance, which is not known at }
+ { compile time (JM) }
+ if (po_methodpointer in tprocvardef(t.def).procoptions) then
+ Message(parser_e_no_procvarobj_const);
+ { parse the rest too, so we can continue with error checking }
+ getprocvardef:=tprocvardef(t.def);
+ p:=comp_expr(true);
+ getprocvardef:=nil;
+ if codegenerror then
+ begin
+ p.free;
+ goto myexit;
+ end;
+ { let type conversion check everything needed }
+ inserttypeconv(p,t);
+ if codegenerror then
+ begin
+ p.free;
+ goto myexit;
+ end;
+ { remove typeconvs, that will normally insert a lea
+ instruction which is not necessary for us }
+ while p.nodetype=typeconvn do
+ begin
+ hp:=ttypeconvnode(p).left;
+ ttypeconvnode(p).left:=nil;
+ p.free;
+ p:=hp;
+ end;
+ { remove addrn which we also don't need here }
+ if p.nodetype=addrn then
+ begin
+ hp:=taddrnode(p).left;
+ taddrnode(p).left:=nil;
+ p.free;
+ p:=hp;
+ end;
+ { we now need to have a loadn with a procsym }
+ if (p.nodetype=loadn) and
+ (tloadnode(p).symtableentry.typ=procsym) then
+ begin
+ asmlist[cural].concat(Tai_const.createname(
+ tprocsym(tloadnode(p).symtableentry).first_procdef.mangledname,AT_FUNCTION,0));
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ end;
+ { reads a typed constant record }
+ recorddef:
+ begin
+ { KAZ }
+ if (trecorddef(t.def)=rec_tguid) and
+ ((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
+ begin
+ p:=comp_expr(true);
+ inserttypeconv(p,cshortstringtype);
+ if p.nodetype=stringconstn then
+ begin
+ s:=strpas(tstringconstnode(p).value_str);
+ p.free;
+ if string2guid(s,tmpguid) then
+ begin
+ asmlist[cural].concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
+ asmlist[cural].concat(Tai_const.Create_16bit(tmpguid.D2));
+ asmlist[cural].concat(Tai_const.Create_16bit(tmpguid.D3));
+ for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
+ asmlist[cural].concat(Tai_const.Create_8bit(tmpguid.D4[i]));
+ end
+ else
+ Message(parser_e_improper_guid_syntax);
+ end
+ else
+ begin
+ p.free;
+ Message(parser_e_illegal_expression);
+ goto myexit;
+ end;
+ end
+ else
+ begin
+ consume(_LKLAMMER);
+ sorg:='';
+ aktpos:=0;
+ srsym := tsym(trecorddef(t.def).symtable.symindex.first);
+ recsym := nil;
+ while token<>_RKLAMMER do
+ begin
+ s:=pattern;
+ sorg:=orgpattern;
+ consume(_ID);
+ consume(_COLON);
+ error := false;
+ recsym := tsym(trecorddef(t.def).symtable.search(s));
+ if not assigned(recsym) then
+ begin
+ Message1(sym_e_illegal_field,sorg);
+ error := true;
+ end;
+ if (not error) and
+ (not assigned(srsym) or
+ (s <> srsym.name)) then
+ { possible variant record (JM) }
+ begin
+ { All parts of a variant start at the same offset }
+ { Also allow jumping from one variant part to another, }
+ { as long as the offsets match }
+ if (assigned(srsym) and
+ (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
+ { srsym is not assigned after parsing w2 in the }
+ { typed const in the next example: }
+ { type tr = record case byte of }
+ { 1: (l1,l2: dword); }
+ { 2: (w1,w2: word); }
+ { end; }
+ { const r: tr = (w1:1;w2:1;l2:5); }
+ (tfieldvarsym(recsym).fieldoffset = aktpos) then
+ srsym := recsym
+ { going backwards isn't allowed in any mode }
+ else if (tfieldvarsym(recsym).fieldoffset<aktpos) then
+ begin
+ Message(parser_e_invalid_record_const);
+ error := true;
+ end
+ { Delphi allows you to skip fields }
+ else if (m_delphi in aktmodeswitches) then
+ begin
+ Message1(parser_w_skipped_fields_before,sorg);
+ srsym := recsym;
+ end
+ { FPC and TP don't }
+ else
+ begin
+ Message1(parser_e_skipped_fields_before,sorg);
+ error := true;
+ end;
+ end;
+ if error then
+ consume_all_until(_SEMICOLON)
+ else
+ begin
+
+ { if needed fill (alignment) }
+ if tfieldvarsym(srsym).fieldoffset>aktpos then
+ for i:=1 to tfieldvarsym(srsym).fieldoffset-aktpos do
+ asmlist[cural].concat(Tai_const.Create_8bit(0));
+
+ { new position }
+ aktpos:=tfieldvarsym(srsym).fieldoffset+tfieldvarsym(srsym).vartype.def.size;
+
+ { read the data }
+ readtypedconst(tfieldvarsym(srsym).vartype,nil,writable);
+
+ { keep previous field for checking whether whole }
+ { record was initialized (JM) }
+ recsym := srsym;
+ { goto next field }
+ srsym := tsym(srsym.indexnext);
+
+ if token=_SEMICOLON then
+ consume(_SEMICOLON)
+ else break;
+ end;
+ end;
+
+ { are there any fields left? }
+ if assigned(srsym) and
+ { don't complain if there only come other variant parts }
+ { after the last initialized field }
+ ((recsym=nil) or
+ (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)) then
+ Message1(parser_w_skipped_fields_after,sorg);
+
+ for i:=1 to t.def.size-aktpos do
+ asmlist[cural].concat(Tai_const.Create_8bit(0));
+
+ consume(_RKLAMMER);
+ end;
+ end;
+ { reads a typed object }
+ objectdef:
+ begin
+ if is_class_or_interface(t.def) then
+ begin
+ p:=comp_expr(true);
+ if p.nodetype<>niln then
+ begin
+ Message(parser_e_type_const_not_possible);
+ consume_all_until(_RKLAMMER);
+ end
+ else
+ begin
+ asmlist[cural].concat(Tai_const.Create_sym(nil));
+ end;
+ p.free;
+ end
+ { for objects we allow it only if it doesn't contain a vmt }
+ else if (oo_has_vmt in tobjectdef(t.def).objectoptions) and
+ (m_fpc in aktmodeswitches) then
+ Message(parser_e_type_const_not_possible)
+ else
+ begin
+ consume(_LKLAMMER);
+ aktpos:=0;
+ while token<>_RKLAMMER do
+ begin
+ s:=pattern;
+ sorg:=orgpattern;
+ consume(_ID);
+ consume(_COLON);
+ srsym:=nil;
+ obj:=tobjectdef(t.def);
+ symt:=obj.symtable;
+ while (srsym=nil) and assigned(symt) do
+ begin
+ srsym:=tsym(symt.search(s));
+ if assigned(obj) then
+ obj:=obj.childof;
+ if assigned(obj) then
+ symt:=obj.symtable
+ else
+ symt:=nil;
+ end;
+
+ if srsym=nil then
+ begin
+ Message1(sym_e_id_not_found,sorg);
+ consume_all_until(_SEMICOLON);
+ end
+ else
+ with tfieldvarsym(srsym) do
+ begin
+ { check position }
+ if fieldoffset<aktpos then
+ message(parser_e_invalid_record_const);
+
+ { check in VMT needs to be added for TP mode }
+ with Tobjectdef(t.def) do
+ if not(m_fpc in aktmodeswitches) and
+ (oo_has_vmt in objectoptions) and
+ (vmt_offset<fieldoffset) then
+ begin
+ for i:=1 to vmt_offset-aktpos do
+ asmlist[cural].concat(tai_const.create_8bit(0));
+ asmlist[cural].concat(tai_const.createname(vmt_mangledname,AT_DATA,0));
+ { this is more general }
+ aktpos:=vmt_offset + sizeof(aint);
+ end;
+
+ { if needed fill }
+ if fieldoffset>aktpos then
+ for i:=1 to fieldoffset-aktpos do
+ asmlist[cural].concat(Tai_const.Create_8bit(0));
+
+ { new position }
+ aktpos:=fieldoffset+vartype.def.size;
+
+ { read the data }
+ readtypedconst(vartype,nil,writable);
+
+ if token=_SEMICOLON then
+ consume(_SEMICOLON)
+ else break;
+ end;
+ end;
+ if not(m_fpc in aktmodeswitches) and
+ (oo_has_vmt in tobjectdef(t.def).objectoptions) and
+ (tobjectdef(t.def).vmt_offset>=aktpos) then
+ begin
+ for i:=1 to tobjectdef(t.def).vmt_offset-aktpos do
+ asmlist[cural].concat(tai_const.create_8bit(0));
+ asmlist[cural].concat(tai_const.createname(tobjectdef(t.def).vmt_mangledname,AT_DATA,0));
+ { this is more general }
+ aktpos:=tobjectdef(t.def).vmt_offset + sizeof(aint);
+ end;
+ for i:=1 to t.def.size-aktpos do
+ asmlist[cural].concat(Tai_const.Create_8bit(0));
+ consume(_RKLAMMER);
+ end;
+ end;
+ errordef:
+ begin
+ { try to consume something useful }
+ if token=_LKLAMMER then
+ consume_all_until(_RKLAMMER)
+ else
+ consume_all_until(_SEMICOLON);
+ end;
+ else Message(parser_e_type_const_not_possible);
+ end;
+ myexit:
+ block_type:=old_block_type;
+ end;
+{$ifdef fpc}
+ {$maxfpuregisters default}
+{$endif fpc}
+
+end.
diff --git a/compiler/ptype.pas b/compiler/ptype.pas
new file mode 100644
index 0000000000..1e24339775
--- /dev/null
+++ b/compiler/ptype.pas
@@ -0,0 +1,658 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does parsing types for Free Pascal
+
+ 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 ptype;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,symtype;
+
+ const
+ { forward types should only be possible inside a TYPE statement }
+ typecanbeforward : boolean = false;
+
+ var
+ { hack, which allows to use the current parsed }
+ { object type as function argument type }
+ testcurobject : byte;
+ curobjectname : stringid;
+
+ { reads a string, file type or a type id and returns a name and }
+ { tdef }
+ procedure single_type(var tt:ttype;isforwarddef:boolean);
+
+ procedure read_type(var tt:ttype;const name : stringid;parseprocvardir:boolean);
+
+ { reads a type definition }
+ { to a appropriating tdef, s gets the name of }
+ { the type to allow name mangling }
+ procedure id_type(var tt : ttype;isforwarddef:boolean);
+
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globals,tokens,verbose,
+ systems,
+ { target }
+ paramgr,
+ { symtable }
+ symconst,symbase,symdef,symsym,symtable,
+ defutil,defcmp,
+ { pass 1 }
+ node,
+ nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
+ { parser }
+ scanner,
+ pbase,pexpr,pdecsub,pdecvar,pdecobj;
+
+
+ procedure id_type(var tt : ttype;isforwarddef:boolean);
+ { reads a type definition }
+ { to a appropriating tdef, s gets the name of }
+ { the type to allow name mangling }
+ var
+ is_unit_specific : boolean;
+ pos : tfileposinfo;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ s,sorg : stringid;
+ begin
+ s:=pattern;
+ sorg:=orgpattern;
+ pos:=akttokenpos;
+ { classes can be used also in classes }
+ if (curobjectname=pattern) and is_class_or_interface(aktobjectdef) then
+ begin
+ tt.setdef(aktobjectdef);
+ consume(_ID);
+ exit;
+ end;
+ { objects can be parameters }
+ if (testcurobject=2) and (curobjectname=pattern) then
+ begin
+ tt.setdef(aktobjectdef);
+ consume(_ID);
+ exit;
+ end;
+ { try to load the symbol to see if it's a unitsym. Use the
+ special searchsym_type that ignores records,objects and
+ parameters }
+ is_unit_specific:=false;
+ searchsym_type(s,srsym,srsymtable);
+ consume(_ID);
+ if assigned(srsym) and
+ (srsym.typ=unitsym) then
+ begin
+ is_unit_specific:=true;
+ consume(_POINT);
+ if not(srsym.owner.symtabletype in [staticsymtable,globalsymtable]) then
+ internalerror(200501155);
+ { only allow unit.symbol access if the name was
+ found in the current module }
+ if srsym.owner.iscurrentunit then
+ begin
+ srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
+ pos:=akttokenpos;
+ s:=pattern;
+ end
+ else
+ srsym:=nil;
+ consume(_ID);
+ end;
+ { Types are first defined with an error def before assigning
+ the real type so check if it's an errordef. if so then
+ give an error. Only check for typesyms in the current symbol
+ table as forwarddef are not resolved directly }
+ if assigned(srsym) and
+ (srsym.typ=typesym) and
+ (srsym.owner=symtablestack) and
+ (ttypesym(srsym).restype.def.deftype=errordef) then
+ begin
+ Message1(type_e_type_is_not_completly_defined,ttypesym(srsym).realname);
+ tt:=generrortype;
+ exit;
+ end;
+ { are we parsing a possible forward def ? }
+ if isforwarddef and
+ not(is_unit_specific) then
+ begin
+ tt.setdef(tforwarddef.create(s,pos));
+ exit;
+ end;
+ { unknown sym ? }
+ if not assigned(srsym) then
+ begin
+ Message1(sym_e_id_not_found,sorg);
+ tt:=generrortype;
+ exit;
+ end;
+ { type sym ? }
+ if (srsym.typ<>typesym) then
+ begin
+ Message(type_e_type_id_expected);
+ tt:=generrortype;
+ exit;
+ end;
+ { Give an error when referring to an errordef }
+ if (ttypesym(srsym).restype.def.deftype=errordef) then
+ begin
+ Message(sym_e_error_in_type_def);
+ tt:=generrortype;
+ exit;
+ end;
+ { Use the definitions for current unit, because
+ they can be refered from the parameters and symbols are not
+ loaded at that time. Only write the definition when the
+ symbol is the real owner of the definition (not a redefine) }
+ if (ttypesym(srsym).owner.symtabletype in [staticsymtable,globalsymtable]) and
+ ttypesym(srsym).owner.iscurrentunit and
+ (
+ (ttypesym(srsym).restype.def.typesym=nil) or
+ (srsym=ttypesym(srsym).restype.def.typesym)
+ ) then
+ tt.setdef(ttypesym(srsym).restype.def)
+ else
+ tt.setsym(srsym);
+ end;
+
+
+ procedure single_type(var tt:ttype;isforwarddef:boolean);
+ var
+ t2 : ttype;
+ begin
+ case token of
+ _STRING:
+ string_dec(tt);
+ _FILE:
+ begin
+ consume(_FILE);
+ if token=_OF then
+ begin
+ consume(_OF);
+ single_type(t2,false);
+ tt.setdef(tfiledef.createtyped(t2));
+ end
+ else
+ tt:=cfiletype;
+ end;
+ _ID:
+ id_type(tt,isforwarddef);
+ else
+ begin
+ message(type_e_type_id_expected);
+ tt:=generrortype;
+ end;
+ end;
+ end;
+
+ { reads a record declaration }
+ function record_dec : tdef;
+
+ var
+ symtable : tsymtable;
+ storetypecanbeforward : boolean;
+ old_object_option : tsymoptions;
+ begin
+ { create recdef }
+ symtable:=trecordsymtable.create(aktpackrecords);
+ record_dec:=trecorddef.create(symtable);
+ { update symtable stack }
+ symtable.next:=symtablestack;
+ symtablestack:=symtable;
+ { parse record }
+ consume(_RECORD);
+ old_object_option:=current_object_option;
+ current_object_option:=[sp_public];
+ storetypecanbeforward:=typecanbeforward;
+ { for tp7 don't allow forward types }
+ if m_tp7 in aktmodeswitches then
+ typecanbeforward:=false;
+ read_var_decs([vd_record]);
+ consume(_END);
+ typecanbeforward:=storetypecanbeforward;
+ current_object_option:=old_object_option;
+ { make the record size aligned }
+ trecordsymtable(symtablestack).addalignmentpadding;
+ { restore symtable stack }
+ symtablestack:=symtable.next;
+ end;
+
+
+ { reads a type definition and returns a pointer to it }
+ procedure read_type(var tt : ttype;const name : stringid;parseprocvardir:boolean);
+ var
+ pt : tnode;
+ tt2 : ttype;
+ aktenumdef : tenumdef;
+ ap : tarraydef;
+ s : stringid;
+ l,v : TConstExprInt;
+ oldaktpackrecords : longint;
+ defpos,storepos : tfileposinfo;
+
+ procedure expr_type;
+ var
+ pt1,pt2 : tnode;
+ lv,hv : TConstExprInt;
+ begin
+ { use of current parsed object ? }
+ if (token=_ID) and (testcurobject=2) and (curobjectname=pattern) then
+ begin
+ consume(_ID);
+ tt.setdef(aktobjectdef);
+ exit;
+ end;
+ { classes can be used also in classes }
+ if (curobjectname=pattern) and is_class_or_interface(aktobjectdef) then
+ begin
+ tt.setdef(aktobjectdef);
+ consume(_ID);
+ exit;
+ end;
+ { we can't accept a equal in type }
+ pt1:=comp_expr(not(ignore_equal));
+ if (token=_POINTPOINT) then
+ begin
+ consume(_POINTPOINT);
+ { get high value of range }
+ pt2:=comp_expr(not(ignore_equal));
+ { make both the same type or give an error. This is not
+ done when both are integer values, because typecasting
+ between -3200..3200 will result in a signed-unsigned
+ conflict and give a range check error (PFV) }
+ if not(is_integer(pt1.resulttype.def) and is_integer(pt2.resulttype.def)) then
+ inserttypeconv(pt1,pt2.resulttype);
+ { both must be evaluated to constants now }
+ if (pt1.nodetype=ordconstn) and
+ (pt2.nodetype=ordconstn) then
+ begin
+ lv:=tordconstnode(pt1).value;
+ hv:=tordconstnode(pt2).value;
+ { Check bounds }
+ if hv<lv then
+ Message(parser_e_upper_lower_than_lower)
+ else
+ begin
+ { All checks passed, create the new def }
+ case pt1.resulttype.def.deftype of
+ enumdef :
+ tt.setdef(tenumdef.create_subrange(tenumdef(pt1.resulttype.def),lv,hv));
+ orddef :
+ begin
+ if is_char(pt1.resulttype.def) then
+ tt.setdef(torddef.create(uchar,lv,hv))
+ else
+ if is_boolean(pt1.resulttype.def) then
+ tt.setdef(torddef.create(bool8bit,l,hv))
+ else
+ tt.setdef(torddef.create(range_to_basetype(lv,hv),lv,hv));
+ end;
+ end;
+ end;
+ end
+ else
+ Message(sym_e_error_in_type_def);
+ pt2.free;
+ end
+ else
+ begin
+ { a simple type renaming }
+ if (pt1.nodetype=typen) then
+ tt:=ttypenode(pt1).resulttype
+ else
+ Message(sym_e_error_in_type_def);
+ end;
+ pt1.free;
+ end;
+
+ procedure array_dec;
+ var
+ lowval,
+ highval : aint;
+ arraytype : ttype;
+ ht : ttype;
+
+ procedure setdefdecl(const t:ttype);
+ begin
+ case t.def.deftype of
+ enumdef :
+ begin
+ lowval:=tenumdef(t.def).min;
+ highval:=tenumdef(t.def).max;
+ if (m_fpc in aktmodeswitches) and
+ (tenumdef(t.def).has_jumps) then
+ Message(type_e_array_index_enums_with_assign_not_possible);
+ arraytype:=t;
+ end;
+ orddef :
+ begin
+ if torddef(t.def).typ in [uchar,
+ u8bit,u16bit,
+ s8bit,s16bit,s32bit,
+{$ifdef cpu64bit}
+ u32bit,s64bit,
+{$endif cpu64bit}
+ bool8bit,bool16bit,bool32bit,
+ uwidechar] then
+ begin
+ lowval:=torddef(t.def).low;
+ highval:=torddef(t.def).high;
+ arraytype:=t;
+ end
+ else
+ Message1(parser_e_type_cant_be_used_in_array_index,t.def.gettypename);
+ end;
+ else
+ Message(sym_e_error_in_type_def);
+ end;
+ end;
+
+ begin
+ consume(_ARRAY);
+ { open array? }
+ if token=_LECKKLAMMER then
+ begin
+ consume(_LECKKLAMMER);
+ { defaults }
+ arraytype:=generrortype;
+ lowval:=low(aint);
+ highval:=high(aint);
+ tt.reset;
+ repeat
+ { read the expression and check it, check apart if the
+ declaration is an enum declaration because that needs to
+ be parsed by readtype (PFV) }
+ if token=_LKLAMMER then
+ begin
+ read_type(ht,'',true);
+ setdefdecl(ht);
+ end
+ else
+ begin
+ pt:=expr;
+ if pt.nodetype=typen then
+ setdefdecl(pt.resulttype)
+ else
+ begin
+ if (pt.nodetype=rangen) then
+ begin
+ if (trangenode(pt).left.nodetype=ordconstn) and
+ (trangenode(pt).right.nodetype=ordconstn) then
+ begin
+ { make both the same type or give an error. This is not
+ done when both are integer values, because typecasting
+ between -3200..3200 will result in a signed-unsigned
+ conflict and give a range check error (PFV) }
+ if not(is_integer(trangenode(pt).left.resulttype.def) and is_integer(trangenode(pt).left.resulttype.def)) then
+ inserttypeconv(trangenode(pt).left,trangenode(pt).right.resulttype);
+ lowval:=tordconstnode(trangenode(pt).left).value;
+ highval:=tordconstnode(trangenode(pt).right).value;
+ if highval<lowval then
+ begin
+ Message(parser_e_array_lower_less_than_upper_bound);
+ highval:=lowval;
+ end;
+ if is_integer(trangenode(pt).left.resulttype.def) then
+ range_to_type(lowval,highval,arraytype)
+ else
+ arraytype:=trangenode(pt).left.resulttype;
+ end
+ else
+ Message(type_e_cant_eval_constant_expr);
+ end
+ else
+ Message(sym_e_error_in_type_def)
+ end;
+ pt.free;
+ end;
+
+ { create arraydef }
+ if not assigned(tt.def) then
+ begin
+ ap:=tarraydef.create(lowval,highval,arraytype);
+ tt.setdef(ap);
+ end
+ else
+ begin
+ ap.elementtype.setdef(tarraydef.create(lowval,highval,arraytype));
+ ap:=tarraydef(ap.elementtype.def);
+ end;
+
+ if token=_COMMA then
+ consume(_COMMA)
+ else
+ break;
+ until false;
+ consume(_RECKKLAMMER);
+ end
+ else
+ begin
+ ap:=tarraydef.create(0,-1,s32inttype);
+ ap.IsDynamicArray:=true;
+ tt.setdef(ap);
+ end;
+ consume(_OF);
+ read_type(tt2,'',true);
+ { if no error, set element type }
+ if assigned(ap) then
+ ap.setelementtype(tt2);
+ end;
+
+ var
+ p : tnode;
+ pd : tabstractprocdef;
+ is_func,
+ enumdupmsg : boolean;
+ newtype : ttypesym;
+ oldlocalswitches : tlocalswitches;
+ begin
+ tt.reset;
+ case token of
+ _STRING,_FILE:
+ begin
+ single_type(tt,false);
+ end;
+ _LKLAMMER:
+ begin
+ consume(_LKLAMMER);
+ { allow negativ value_str }
+ l:=-1;
+ enumdupmsg:=false;
+ aktenumdef:=tenumdef.create;
+ repeat
+ s:=orgpattern;
+ defpos:=akttokenpos;
+ consume(_ID);
+ { only allow assigning of specific numbers under fpc mode }
+ if not(m_tp7 in aktmodeswitches) and
+ (
+ { in fpc mode also allow := to be compatible
+ with previous 1.0.x versions }
+ ((m_fpc in aktmodeswitches) and
+ try_to_consume(_ASSIGNMENT)) or
+ try_to_consume(_EQUAL)
+ ) then
+ begin
+ oldlocalswitches:=aktlocalswitches;
+ include(aktlocalswitches,cs_allow_enum_calc);
+ p:=comp_expr(true);
+ aktlocalswitches:=oldlocalswitches;
+ if (p.nodetype=ordconstn) then
+ begin
+ { we expect an integer or an enum of the
+ same type }
+ if is_integer(p.resulttype.def) or
+ is_char(p.resulttype.def) or
+ equal_defs(p.resulttype.def,aktenumdef) then
+ v:=tordconstnode(p).value
+ else
+ IncompatibleTypes(p.resulttype.def,s32inttype.def);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ { please leave that a note, allows type save }
+ { declarations in the win32 units ! }
+ if (v<=l) and (not enumdupmsg) then
+ begin
+ Message(parser_n_duplicate_enum);
+ enumdupmsg:=true;
+ end;
+ l:=v;
+ end
+ else
+ inc(l);
+ storepos:=akttokenpos;
+ akttokenpos:=defpos;
+ constsymtable.insert(tenumsym.create(s,aktenumdef,l));
+ akttokenpos:=storepos;
+ until not try_to_consume(_COMMA);
+ tt.setdef(aktenumdef);
+ consume(_RKLAMMER);
+ end;
+ _ARRAY:
+ begin
+ array_dec;
+ end;
+ _SET:
+ begin
+ consume(_SET);
+ consume(_OF);
+ read_type(tt2,'',true);
+ if assigned(tt2.def) then
+ begin
+ case tt2.def.deftype of
+ { don't forget that min can be negativ PM }
+ enumdef :
+ if tenumdef(tt2.def).min>=0 then
+ // !! tt.setdef(tsetdef.create(tt2,tenumdef(tt2.def).min,tenumdef(tt2.def).max))
+ tt.setdef(tsetdef.create(tt2,tenumdef(tt2.def).max))
+ else
+ Message(sym_e_ill_type_decl_set);
+ orddef :
+ begin
+ case torddef(tt2.def).typ of
+ uchar :
+ //!!! tt.setdef(tsetdef.create(tt2,0,255));
+ tt.setdef(tsetdef.create(tt2,255));
+ u8bit,u16bit,u32bit,
+ s8bit,s16bit,s32bit :
+ begin
+ if (torddef(tt2.def).low>=0) then
+ // !! tt.setdef(tsetdef.create(tt2,torddef(tt2.def).low,torddef(tt2.def).high))
+ tt.setdef(tsetdef.create(tt2,torddef(tt2.def).high))
+ else
+ Message(sym_e_ill_type_decl_set);
+ end;
+ else
+ Message(sym_e_ill_type_decl_set);
+ end;
+ end;
+ else
+ Message(sym_e_ill_type_decl_set);
+ end;
+ end
+ else
+ tt:=generrortype;
+ end;
+ _CARET:
+ begin
+ consume(_CARET);
+ single_type(tt2,typecanbeforward);
+ tt.setdef(tpointerdef.create(tt2));
+ end;
+ _RECORD:
+ begin
+ tt.setdef(record_dec);
+ end;
+ _PACKED:
+ begin
+ consume(_PACKED);
+ if token=_ARRAY then
+ array_dec
+ else
+ begin
+ oldaktpackrecords:=aktpackrecords;
+ aktpackrecords:=1;
+ if token in [_CLASS,_OBJECT] then
+ tt.setdef(object_dec(name,nil))
+ else
+ tt.setdef(record_dec);
+ aktpackrecords:=oldaktpackrecords;
+ end;
+ end;
+ _CLASS,
+ _CPPCLASS,
+ _INTERFACE,
+ _OBJECT:
+ begin
+ tt.setdef(object_dec(name,nil));
+ end;
+ _PROCEDURE,
+ _FUNCTION:
+ begin
+ is_func:=(token=_FUNCTION);
+ consume(token);
+ pd:=tprocvardef.create(normal_function_level);
+ if token=_LKLAMMER then
+ parse_parameter_dec(pd);
+ if is_func then
+ begin
+ consume(_COLON);
+ single_type(pd.rettype,false);
+ end;
+ if token=_OF then
+ begin
+ consume(_OF);
+ consume(_OBJECT);
+ include(pd.procoptions,po_methodpointer);
+ end;
+ tt.def:=pd;
+ { possible proc directives }
+ if parseprocvardir then
+ begin
+ if check_proc_directive(true) then
+ begin
+ newtype:=ttypesym.create('unnamed',tt);
+ parse_var_proc_directives(tsym(newtype));
+ newtype.restype.def:=nil;
+ tt.def.typesym:=nil;
+ newtype.free;
+ end;
+ { Add implicit hidden parameters and function result }
+ handle_calling_convention(pd);
+ end;
+ end;
+ else
+ expr_type;
+ end;
+ if tt.def=nil then
+ tt:=generrortype;
+ end;
+
+end.
diff --git a/compiler/raatt.pas b/compiler/raatt.pas
new file mode 100644
index 0000000000..2e70b9c04a
--- /dev/null
+++ b/compiler/raatt.pas
@@ -0,0 +1,1534 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the GAS styled inline assembler.
+
+ 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 raatt;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,
+ { aasm }
+ cpubase,cpuinfo,aasmbase,aasmtai,aasmcpu,
+ { assembler reader }
+ rabase,
+ rasm,
+ rautils,
+ { symtable }
+ symconst,
+ { cg }
+ cgbase;
+
+ type
+ tasmtoken = (
+ AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
+ AS_REALNUM,AS_COMMA,AS_LPAREN,
+ AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
+ AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
+ AS_HASH,AS_LSBRACKET,AS_RSBRACKET,AS_LBRACKET,AS_RBRACKET,
+ {------------------ Assembler directives --------------------}
+ AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,
+ AS_ALIGN,AS_BALIGN,AS_P2ALIGN,AS_ASCII,
+ AS_ASCIIZ,AS_LCOMM,AS_COMM,AS_SINGLE,AS_DOUBLE,AS_EXTENDED,
+ AS_DATA,AS_TEXT,AS_END,
+ {------------------ Assembler Operators --------------------}
+ AS_TYPE,AS_SIZEOF,AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR,AS_AT,
+ AS_LO,AS_HI);
+
+ tasmkeyword = string[10];
+
+ const
+ { These tokens should be modified accordingly to the modifications }
+ { in the different enumerations. }
+ firstdirective = AS_DB;
+ lastdirective = AS_END;
+
+ token2str : array[tasmtoken] of tasmkeyword=(
+ '','Label','LLabel','string','integer',
+ 'float',',','(',
+ ')',':','.','+','-','*',
+ ';','identifier','register','opcode','/','$',
+ '#','{','}','[',']',
+ '.byte','.word','.long','.quad','.globl',
+ '.align','.balign','.p2align','.ascii',
+ '.asciz','.lcomm','.comm','.single','.double','.tfloat',
+ '.data','.text','END',
+ 'TYPE','SIZEOF','%','<<','>>','!','&','|','^','~','@','lo','hi');
+
+ type
+ tattreader = class(tasmreader)
+ actasmtoken : tasmtoken;
+ prevasmtoken : tasmtoken;
+ procedure SetupTables;
+ procedure BuildConstant(constsize: byte);
+ procedure BuildConstantOperand(oper : toperand);
+ procedure BuildRealConstant(typ : tfloattype);
+ procedure BuildStringConstant(asciiz: boolean);
+ procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint);
+ procedure BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
+ function BuildConstExpression(allowref,betweenbracket:boolean): aint;
+ function Assemble: tlinkedlist;override;
+ procedure handleopcode;virtual;abstract;
+ function is_asmopcode(const s: string) : boolean;virtual;abstract;
+ Function is_asmdirective(const s: string):boolean;
+ function is_register(const s:string):boolean;virtual;
+ function is_locallabel(const s: string):boolean;
+ procedure GetToken;
+ function consume(t : tasmtoken):boolean;
+ procedure RecoverConsume(allowcomma:boolean);
+ procedure handlepercent;virtual;
+ end;
+ tcattreader = class of tattreader;
+
+ var
+ cattreader : tcattreader;
+
+ implementation
+
+ uses
+ { globals }
+ verbose,systems,
+ { input }
+ scanner,
+ { symtable }
+ symbase,symtype,symsym,symtable,
+{$ifdef x86}
+ rax86,
+{$endif x86}
+ itcpugas,
+ procinfo;
+
+
+ procedure tattreader.SetupTables;
+ { creates uppercased symbol tables for speed access }
+ var
+ i : tasmop;
+ str2opentry: tstr2opentry;
+ Begin
+ { opcodes }
+ iasmops:=TDictionary.Create;
+ iasmops.delete_doubles:=true;
+ for i:=firstop to lastop do
+ begin
+ str2opentry:=tstr2opentry.createname(upper(gas_op2str[i]));
+ str2opentry.op:=i;
+ iasmops.insert(str2opentry);
+ end;
+ end;
+
+
+ function tattreader.is_asmdirective(const s: string):boolean;
+ var
+ i : tasmtoken;
+ hs : string;
+ Begin
+ { GNU as is also not casesensitive with this }
+ hs:=lower(s);
+ for i:=firstdirective to lastdirective do
+ if hs=token2str[i] then
+ begin
+ actasmtoken:=i;
+ is_asmdirective:=true;
+ exit;
+ end;
+ is_asmdirective:=false;
+ end;
+
+
+ function tattreader.is_register(const s:string):boolean;
+ begin
+ is_register:=false;
+ actasmregister:=gas_regnum_search(lower(s));
+ if actasmregister<>NR_NO then
+ begin
+ is_register:=true;
+ actasmtoken:=AS_REGISTER;
+ end;
+ end;
+
+
+ function tattreader.is_locallabel(const s: string):boolean;
+ begin
+ is_locallabel:=(length(s)>=2) and (s[1]='.') and (s[2]='L');
+ end;
+
+
+ procedure tattreader.handlepercent;
+ begin
+ c:=current_scanner.asmgetchar;
+ actasmtoken:=AS_MOD;
+ end;
+
+
+ procedure tattreader.GetToken;
+ var
+ len : longint;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ { save old token and reset new token }
+ prevasmtoken:=actasmtoken;
+ actasmtoken:=AS_NONE;
+ { reset }
+ actasmpattern:='';
+ { while space and tab , continue scan... }
+ while c in [' ',#9] do
+ c:=current_scanner.asmgetchar;
+ { get token pos }
+{$ifdef arm}
+ if not (c in [#10,#13,';']) then
+ current_scanner.gettokenpos;
+{$else arm}
+ if not (c in [#10,#13,'{',';']) then
+ current_scanner.gettokenpos;
+{$endif arm}
+
+ { Local Label, Label, Directive, Prefix or Opcode }
+{$ifdef arm}
+ if firsttoken and not(c in [#10,#13,';']) then
+{$else arm}
+ if firsttoken and not(c in [#10,#13,'{',';']) then
+{$endif arm}
+ begin
+ firsttoken:=FALSE;
+ len:=0;
+ { directive or local label }
+ if c = '.' then
+ begin
+ inc(len);
+ actasmpattern[len]:=c;
+ { Let us point to the next character }
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ { this is a local label... }
+ if (c=':') and is_locallabel(actasmpattern) then
+ Begin
+ { local variables are case sensitive }
+ actasmtoken:=AS_LLABEL;
+ c:=current_scanner.asmgetchar;
+ firsttoken:=true;
+ exit;
+ end
+ { must be a directive }
+ else
+ Begin
+ { directives are case sensitive!! }
+ if is_asmdirective(actasmpattern) then
+ exit;
+ Message1(asmr_e_not_directive_or_local_symbol,actasmpattern);
+ end;
+ end;
+ { only opcodes and global labels are allowed now. }
+ while c in ['A'..'Z','a'..'z','0'..'9','_'] do
+ begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ { Label ? }
+ if c = ':' then
+ begin
+ actasmtoken:=AS_LABEL;
+ { let us point to the next character }
+ c:=current_scanner.asmgetchar;
+ firsttoken:=true;
+ exit;
+ end;
+{$ifdef POWERPC}
+ { some PowerPC instructions can have the postfix -, + or .
+ this code could be moved to is_asmopcode but I think
+ it's better to ifdef it here (FK)
+ }
+ case c of
+ '.', '-', '+':
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ end
+ end;
+{$endif POWERPC}
+{$ifdef POWERPC64}
+ { some PowerPC instructions can have the postfix -, + or .
+ this code could be moved to is_asmopcode but I think
+ it's better to ifdef it here (FK)
+ }
+ case c of
+ '.', '-', '+':
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ end
+ end;
+{$endif POWERPC64}
+ { Opcode ? }
+ If is_asmopcode(upper(actasmpattern)) then
+ Begin
+ uppervar(actasmpattern);
+ exit;
+ end;
+ { End of assemblerblock ? }
+ if upper(actasmpattern) = 'END' then
+ begin
+ actasmtoken:=AS_END;
+ exit;
+ end;
+ message1(asmr_e_unknown_opcode,actasmpattern);
+ actasmtoken:=AS_NONE;
+ end
+ else { else firsttoken }
+ { Here we must handle all possible cases }
+ begin
+ case c of
+ '.' : { possiblities : - local label reference , such as in jmp @local1 }
+ { - field of object/record }
+ { - directive. }
+ begin
+ if (prevasmtoken in [AS_ID,AS_RPAREN]) then
+ begin
+ c:=current_scanner.asmgetchar;
+ actasmtoken:=AS_DOT;
+ exit;
+ end;
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ if is_asmdirective(actasmpattern) then
+ exit;
+ { local label references and directives }
+ { are case sensitive }
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ { identifier, register, prefix or directive }
+ '_','A'..'Z','a'..'z':
+ begin
+ len:=0;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ uppervar(actasmpattern);
+{$ifdef x86}
+ { only x86 architectures have instruction prefixes }
+
+ { Opcode, can only be when the previous was a prefix }
+ If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
+ Begin
+ uppervar(actasmpattern);
+ exit;
+ end;
+{$endif x86}
+ { check for end which is a reserved word unlike the opcodes }
+ if actasmpattern = 'END' then
+ Begin
+ actasmtoken:=AS_END;
+ exit;
+ end;
+ if actasmpattern = 'TYPE' then
+ Begin
+ actasmtoken:=AS_TYPE;
+ exit;
+ end;
+ if actasmpattern = 'SIZEOF' then
+ Begin
+ actasmtoken:=AS_SIZEOF;
+ exit;
+ end;
+ if is_register(actasmpattern) then
+ begin
+ actasmtoken:=AS_REGISTER;
+ exit;
+ end;
+ { if next is a '.' and this is a unitsym then we also need to
+ parse the identifier }
+ if (c='.') then
+ begin
+ searchsym(actasmpattern,srsym,srsymtable);
+ if assigned(srsym) and
+ (srsym.typ=unitsym) and
+ (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
+ srsym.owner.iscurrentunit then
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ actasmpattern:=actasmpattern + upcase(c);
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ end;
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ '%' : { register or modulo }
+ handlepercent;
+
+ '1'..'9': { integer number }
+ begin
+ len:=0;
+ while c in ['0'..'9'] do
+ Begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ actasmpattern:=tostr(ParseVal(actasmpattern,10));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ '0' : { octal,hexa,real or binary number. }
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ case upcase(c) of
+ 'B': { binary }
+ Begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0','1'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern:=tostr(ParseVal(actasmpattern,2));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ 'D': { real }
+ Begin
+ c:=current_scanner.asmgetchar;
+ { get ridd of the 0d }
+ if (c in ['+','-']) then
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ end
+ else
+ actasmpattern:='';
+ while c in ['0'..'9'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ if c='.' then
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ while c in ['0'..'9'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ if upcase(c) = 'E' then
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ if (c in ['+','-']) then
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ while c in ['0'..'9'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ actasmtoken:=AS_REALNUM;
+ exit;
+ end
+ else
+ begin
+ Message1(asmr_e_invalid_float_const,actasmpattern+c);
+ actasmtoken:=AS_NONE;
+ end;
+ end;
+ 'X': { hexadecimal }
+ Begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0'..'9','a'..'f','A'..'F'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern:=tostr(ParseVal(actasmpattern,16));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ '1'..'7': { octal }
+ begin
+ actasmpattern:=actasmpattern + c;
+ while c in ['0'..'7'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern:=tostr(ParseVal(actasmpattern,8));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ else { octal number zero value...}
+ Begin
+ actasmpattern:=tostr(ParseVal(actasmpattern,8));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ end; { end case }
+ end;
+
+ '&' :
+ begin
+ c:=current_scanner.asmgetchar;
+ actasmtoken:=AS_AND;
+ end;
+
+ '''' : { char }
+ begin
+ current_scanner.in_asm_string:=true;
+ actasmpattern:='';
+ repeat
+ c:=current_scanner.asmgetchar;
+ case c of
+ '\' :
+ begin
+ { copy also the next char so \" is parsed correctly }
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ actasmpattern:=actasmpattern+c;
+ end;
+ '''' :
+ begin
+ c:=current_scanner.asmgetchar;
+ break;
+ end;
+ #10,#13:
+ Message(scan_f_string_exceeds_line);
+ else
+ actasmpattern:=actasmpattern+c;
+ end;
+ until false;
+ actasmpattern:=EscapeToPascal(actasmpattern);
+ actasmtoken:=AS_STRING;
+ current_scanner.in_asm_string:=false;
+ exit;
+ end;
+
+ '"' : { string }
+ begin
+ current_scanner.in_asm_string:=true;
+ actasmpattern:='';
+ repeat
+ c:=current_scanner.asmgetchar;
+ case c of
+ '\' :
+ begin
+ { copy also the next char so \" is parsed correctly }
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ actasmpattern:=actasmpattern+c;
+ end;
+ '"' :
+ begin
+ c:=current_scanner.asmgetchar;
+ break;
+ end;
+ #10,#13:
+ Message(scan_f_string_exceeds_line);
+ else
+ actasmpattern:=actasmpattern+c;
+ end;
+ until false;
+ actasmpattern:=EscapeToPascal(actasmpattern);
+ actasmtoken:=AS_STRING;
+ current_scanner.in_asm_string:=false;
+ exit;
+ end;
+
+ '$' :
+ begin
+ actasmtoken:=AS_DOLLAR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '#' :
+ begin
+ actasmtoken:=AS_HASH;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '[' :
+ begin
+ actasmtoken:=AS_LBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ']' :
+ begin
+ actasmtoken:=AS_RBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+{$ifdef arm}
+ // the arm assembler uses { ... } for register sets
+ '{' :
+ begin
+ actasmtoken:=AS_LSBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '}' :
+ begin
+ actasmtoken:=AS_RSBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+{$endif arm}
+
+ ',' :
+ begin
+ actasmtoken:=AS_COMMA;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '<' :
+ begin
+ actasmtoken:=AS_SHL;
+ c:=current_scanner.asmgetchar;
+ if c = '<' then
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '>' :
+ begin
+ actasmtoken:=AS_SHL;
+ c:=current_scanner.asmgetchar;
+ if c = '>' then
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '|' :
+ begin
+ actasmtoken:=AS_OR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '^' :
+ begin
+ actasmtoken:=AS_XOR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+
+ '(' :
+ begin
+ actasmtoken:=AS_LPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ')' :
+ begin
+ actasmtoken:=AS_RPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ':' :
+ begin
+ actasmtoken:=AS_COLON;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '+' :
+ begin
+ actasmtoken:=AS_PLUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '-' :
+ begin
+ actasmtoken:=AS_MINUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '*' :
+ begin
+ actasmtoken:=AS_STAR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '/' :
+ begin
+ actasmtoken:=AS_SLASH;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '!' :
+ begin
+ actasmtoken:=AS_NOT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '@' :
+ begin
+ actasmtoken:=AS_AT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+{$ifndef arm}
+ '{',
+{$endif arm}
+ #13,#10,';' :
+ begin
+ { the comment is read by asmgetchar }
+ c:=current_scanner.asmgetchar;
+ firsttoken:=TRUE;
+ actasmtoken:=AS_SEPARATOR;
+ exit;
+ end;
+
+ else
+ current_scanner.illegal_char(c);
+ end;
+ end;
+ end;
+
+
+ function tattreader.consume(t : tasmtoken):boolean;
+ begin
+ Consume:=true;
+ if t<>actasmtoken then
+ begin
+ Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
+ Consume:=false;
+ end;
+ repeat
+ gettoken;
+ until actasmtoken<>AS_NONE;
+ end;
+
+
+ procedure tattreader.RecoverConsume(allowcomma:boolean);
+ begin
+ While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
+ begin
+ if allowcomma and (actasmtoken=AS_COMMA) then
+ break;
+ Consume(actasmtoken);
+ end;
+ end;
+
+
+ Procedure tattreader.BuildConstant(constsize: byte);
+ var
+ asmsymtyp : TAsmSymType;
+ asmsym,
+ expr: string;
+ value : aint;
+ Begin
+ Repeat
+ Case actasmtoken of
+ AS_STRING:
+ Begin
+ expr:=actasmpattern;
+ if length(expr) > 1 then
+ Message(asmr_e_string_not_allowed_as_const);
+ Consume(AS_STRING);
+ Case actasmtoken of
+ AS_COMMA: Consume(AS_COMMA);
+ AS_END,
+ AS_SEPARATOR: ;
+ else
+ Message(asmr_e_invalid_string_expression);
+ end; { end case }
+ ConcatString(curlist,expr);
+ end;
+ AS_INTNUM,
+ AS_PLUS,
+ AS_MINUS,
+ AS_LPAREN,
+ AS_TYPE,
+ AS_SIZEOF,
+ AS_NOT,
+ AS_ID :
+ Begin
+ BuildConstSymbolExpression(false,false,false,value,asmsym,asmsymtyp);
+ if asmsym<>'' then
+ begin
+ if constsize<>sizeof(aint) then
+ Message(asmr_w_32bit_const_for_address);
+ ConcatConstSymbol(curlist,asmsym,asmsymtyp,value)
+ end
+ else
+ ConcatConstant(curlist,value,constsize);
+ end;
+ AS_COMMA:
+ Consume(AS_COMMA);
+ AS_END,
+ AS_SEPARATOR:
+ break;
+ else
+ begin
+ Message(asmr_e_syn_constant);
+ RecoverConsume(false);
+ end
+ end; { end case }
+ Until false;
+ end;
+
+
+ Procedure tattreader.BuildRealConstant(typ : tfloattype);
+ var
+ expr : string;
+ r : bestreal;
+ code : integer;
+ negativ : boolean;
+ errorflag: boolean;
+ Begin
+ errorflag:=FALSE;
+ Repeat
+ negativ:=false;
+ expr:='';
+ if actasmtoken=AS_PLUS then
+ Consume(AS_PLUS)
+ else
+ if actasmtoken=AS_MINUS then
+ begin
+ negativ:=true;
+ consume(AS_MINUS);
+ end;
+ Case actasmtoken of
+ AS_INTNUM:
+ Begin
+ expr:=actasmpattern;
+ Consume(AS_INTNUM);
+ if negativ then
+ expr:='-'+expr;
+ val(expr,r,code);
+ if code<>0 then
+ Begin
+ r:=0;
+ Message(asmr_e_invalid_float_expr);
+ End;
+ ConcatRealConstant(curlist,r,typ);
+ end;
+ AS_REALNUM:
+ Begin
+ expr:=actasmpattern;
+ Consume(AS_REALNUM);
+ { in ATT syntax you have 0d in front of the real }
+ { should this be forced ? yes i think so, as to }
+ { conform to gas as much as possible. }
+ if (expr[1]='0') and (upper(expr[2])='D') then
+ Delete(expr,1,2);
+ if negativ then
+ expr:='-'+expr;
+ val(expr,r,code);
+ if code<>0 then
+ Begin
+ r:=0;
+ Message(asmr_e_invalid_float_expr);
+ End;
+ ConcatRealConstant(curlist,r,typ);
+ end;
+ AS_COMMA:
+ begin
+ Consume(AS_COMMA);
+ end;
+ AS_END,
+ AS_SEPARATOR:
+ begin
+ break;
+ end;
+ else
+ Begin
+ Consume(actasmtoken);
+ if not errorflag then
+ Message(asmr_e_invalid_float_expr);
+ errorflag:=TRUE;
+ end;
+ end;
+ Until false;
+ end;
+
+
+ Procedure tattreader.BuildStringConstant(asciiz: boolean);
+ var
+ expr: string;
+ errorflag : boolean;
+ Begin
+ errorflag:=FALSE;
+ Repeat
+ Case actasmtoken of
+ AS_STRING:
+ Begin
+ expr:=actasmpattern;
+ if asciiz then
+ expr:=expr+#0;
+ ConcatPasString(curlist,expr);
+ Consume(AS_STRING);
+ end;
+ AS_COMMA:
+ begin
+ Consume(AS_COMMA);
+ end;
+ AS_END,
+ AS_SEPARATOR:
+ begin
+ break;
+ end;
+ else
+ Begin
+ Consume(actasmtoken);
+ if not errorflag then
+ Message(asmr_e_invalid_string_expression);
+ errorflag:=TRUE;
+ end;
+ end;
+ Until false;
+ end;
+
+
+ Function tattreader.Assemble: tlinkedlist;
+ Var
+ hl : tasmlabel;
+ commname : string;
+ lasTSec : TAsmSectionType;
+ l1,l2 : longint;
+ Begin
+ Message1(asmr_d_start_reading,'GNU AS');
+ firsttoken:=TRUE;
+ { sets up all opcode and register tables in uppercase }
+ if not _asmsorted then
+ Begin
+ SetupTables;
+ _asmsorted:=TRUE;
+ end;
+ curlist:=TAAsmoutput.Create;
+ lasTSec:=sec_code;
+ { setup label linked list }
+ LocalLabelList:=TLocalLabelList.Create;
+ { start tokenizer }
+ c:=current_scanner.asmgetcharstart;
+ gettoken;
+ { main loop }
+ repeat
+ case actasmtoken of
+ AS_LLABEL:
+ Begin
+ if CreateLocalLabel(actasmpattern,hl,true) then
+ ConcatLabel(curlist,hl);
+ Consume(AS_LLABEL);
+ end;
+
+ AS_LABEL:
+ Begin
+ if SearchLabel(upper(actasmpattern),hl,true) then
+ ConcatLabel(curlist,hl)
+ else
+ Message1(asmr_e_unknown_label_identifier,actasmpattern);
+ Consume(AS_LABEL);
+ end;
+
+ AS_DW:
+ Begin
+ Consume(AS_DW);
+ BuildConstant(2);
+ end;
+
+ AS_DATA:
+ Begin
+ new_section(curList,sec_data,lower(current_procinfo.procdef.mangledname),0);
+ lasTSec:=sec_data;
+ Consume(AS_DATA);
+ end;
+
+ AS_TEXT:
+ Begin
+ new_section(curList,sec_code,lower(current_procinfo.procdef.mangledname),0);
+ lasTSec:=sec_code;
+ Consume(AS_TEXT);
+ end;
+
+ AS_DB:
+ Begin
+ Consume(AS_DB);
+ BuildConstant(1);
+ end;
+
+ AS_DD:
+ Begin
+ Consume(AS_DD);
+ BuildConstant(4);
+ end;
+
+ AS_DQ:
+ Begin
+ Consume(AS_DQ);
+{$ifdef cpu64bit}
+ BuildConstant(8);
+{$else cpu64bit}
+ BuildRealConstant(s64comp);
+{$endif cpu64bit}
+ end;
+
+ AS_SINGLE:
+ Begin
+ Consume(AS_SINGLE);
+ BuildRealConstant(s32real);
+ end;
+
+ AS_DOUBLE:
+ Begin
+ Consume(AS_DOUBLE);
+ BuildRealConstant(s64real);
+ end;
+
+ AS_EXTENDED:
+ Begin
+ Consume(AS_EXTENDED);
+ BuildRealConstant(s80real);
+ end;
+
+ AS_GLOBAL:
+ Begin
+ Consume(AS_GLOBAL);
+ if actasmtoken=AS_ID then
+ ConcatPublic(curlist,actasmpattern);
+ Consume(AS_ID);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_ALIGN:
+ Begin
+ Consume(AS_ALIGN);
+ l1:=BuildConstExpression(false,false);
+ if (target_info.system in [system_i386_GO32V2]) then
+ begin
+ l2:=1;
+ if (l1>=0) and (l1<=16) then
+ while (l1>0) do
+ begin
+ l2:=2*l2;
+ dec(l1);
+ end;
+ l1:=l2;
+ end;
+ ConcatAlign(curlist,l1);
+ Message(asmr_n_align_is_target_specific);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_BALIGN:
+ Begin
+ Consume(AS_BALIGN);
+ ConcatAlign(curlist,BuildConstExpression(false,false));
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_P2ALIGN:
+ Begin
+ Consume(AS_P2ALIGN);
+ l1:=BuildConstExpression(false,false);
+ l2:=1;
+ if (l1>=0) and (l1<=16) then
+ while (l1>0) do
+ begin
+ l2:=2*l2;
+ dec(l1);
+ end;
+ l1:=l2;
+ ConcatAlign(curlist,l1);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_ASCIIZ:
+ Begin
+ Consume(AS_ASCIIZ);
+ BuildStringConstant(TRUE);
+ end;
+
+ AS_ASCII:
+ Begin
+ Consume(AS_ASCII);
+ BuildStringConstant(FALSE);
+ end;
+
+ AS_LCOMM:
+ Begin
+ Consume(AS_LCOMM);
+ commname:=actasmpattern;
+ Consume(AS_ID);
+ Consume(AS_COMMA);
+ curList.concat(Tai_datablock.Create(commname,BuildConstExpression(false,false)));
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_COMM:
+ Begin
+ Consume(AS_COMM);
+ commname:=actasmpattern;
+ Consume(AS_ID);
+ Consume(AS_COMMA);
+ curList.concat(Tai_datablock.Create_global(commname,BuildConstExpression(false,false)));
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_OPCODE:
+ Begin
+ HandleOpCode;
+ end;
+
+ AS_SEPARATOR:
+ Begin
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_END:
+ begin
+ break; { end assembly block }
+ end;
+
+ else
+ Begin
+ Message(asmr_e_syntax_error);
+ RecoverConsume(false);
+ end;
+ end;
+ until false;
+ { Check LocalLabelList }
+ LocalLabelList.CheckEmitted;
+ LocalLabelList.Free;
+ { are we back in the code section? }
+ if lasTSec<>sec_code then
+ begin
+ Message(asmr_w_assembler_code_not_returned_to_text);
+ new_section(curList,sec_code,lower(current_procinfo.procdef.mangledname),0);
+ end;
+ { Return the list in an asmnode }
+ assemble:=curlist;
+ Message1(asmr_d_finish_reading,'GNU AS');
+ end;
+
+
+{*****************************************************************************
+ Parsing Helpers
+*****************************************************************************}
+
+ Procedure tattreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint);
+ { Description: This routine builds up a record offset after a AS_DOT }
+ { token is encountered. }
+ { On entry actasmtoken should be equal to AS_DOT }
+ var
+ s : string;
+ Begin
+ offset:=0;
+ size:=0;
+ s:=expr;
+ while (actasmtoken=AS_DOT) do
+ begin
+ Consume(AS_DOT);
+ if actasmtoken=AS_ID then
+ s:=s+'.'+actasmpattern;
+ if not Consume(AS_ID) then
+ begin
+ RecoverConsume(true);
+ break;
+ end;
+ end;
+ if not GetRecordOffsetSize(s,offset,size) then
+ Message(asmr_e_building_record_offset);
+ end;
+
+
+ procedure tattreader.BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
+ var
+ hssymtyp : TAsmSymType;
+ hs,tempstr,expr : string;
+ parenlevel : longint;
+ l,k : aint;
+ errorflag : boolean;
+ prevtok : tasmtoken;
+ sym : tsym;
+ srsymtable : tsymtable;
+ hl : tasmlabel;
+ Begin
+ asmsym:='';
+ asmsymtyp:=AT_DATA;
+ value:=0;
+ errorflag:=FALSE;
+ tempstr:='';
+ expr:='';
+ parenlevel:=0;
+ Repeat
+ Case actasmtoken of
+ AS_LPAREN:
+ Begin
+ { Exit if ref? }
+ if allowref and (prevasmtoken in [AS_INTNUM,AS_ID]) then
+ break;
+ Consume(AS_LPAREN);
+ expr:=expr + '(';
+ inc(parenlevel);
+ end;
+ AS_RBRACKET:
+ begin
+ if betweenbracket then
+ break;
+ { write error only once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag:=TRUE;
+ end;
+ AS_RPAREN:
+ Begin
+ { end of ref ? }
+ if (parenlevel=0) and betweenbracket then
+ break;
+ Consume(AS_RPAREN);
+ expr:=expr + ')';
+ dec(parenlevel);
+ end;
+ AS_SHL:
+ Begin
+ Consume(AS_SHL);
+ expr:=expr + '<';
+ end;
+ AS_SHR:
+ Begin
+ Consume(AS_SHR);
+ expr:=expr + '>';
+ end;
+ AS_SLASH:
+ Begin
+ Consume(AS_SLASH);
+ expr:=expr + '/';
+ end;
+ AS_MOD:
+ Begin
+ Consume(AS_MOD);
+ expr:=expr + '%';
+ end;
+ AS_STAR:
+ Begin
+ Consume(AS_STAR);
+ expr:=expr + '*';
+ end;
+ AS_PLUS:
+ Begin
+ Consume(AS_PLUS);
+ expr:=expr + '+';
+ end;
+ AS_MINUS:
+ Begin
+ Consume(AS_MINUS);
+ expr:=expr + '-';
+ end;
+ AS_AND:
+ Begin
+ Consume(AS_AND);
+ expr:=expr + '&';
+ end;
+ AS_NOT:
+ Begin
+ Consume(AS_NOT);
+ expr:=expr + '~';
+ end;
+ AS_XOR:
+ Begin
+ Consume(AS_XOR);
+ expr:=expr + '^';
+ end;
+ AS_OR:
+ Begin
+ Consume(AS_OR);
+ expr:=expr + '|';
+ end;
+ AS_INTNUM:
+ Begin
+ expr:=expr + actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_DOLLAR:
+ begin
+ Consume(AS_DOLLAR);
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_dollar_without_identifier);
+ end;
+ AS_STRING:
+ Begin
+ l:=0;
+ case Length(actasmpattern) of
+ 1 :
+ l:=ord(actasmpattern[1]);
+ 2 :
+ l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
+ 3 :
+ l:=ord(actasmpattern[3]) +
+ Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
+ 4 :
+ l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
+ Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
+ else
+ Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
+ end;
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ Consume(AS_STRING);
+ end;
+ AS_SIZEOF,
+ AS_TYPE:
+ begin
+ l:=0;
+ Consume(actasmtoken);
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_type_without_identifier)
+ else
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ if actasmtoken=AS_DOT then
+ BuildRecordOffsetSize(tempstr,k,l)
+ else
+ begin
+ searchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ l:=tabstractvarsym(sym).getsize;
+ typedconstsym :
+ l:=ttypedconstsym(sym).getsize;
+ typesym :
+ l:=ttypesym(sym).restype.def.size;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ end;
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end;
+ AS_ID:
+ Begin
+ hs:='';
+ hssymtyp:=AT_DATA;
+ tempstr:=actasmpattern;
+ prevtok:=prevasmtoken;
+ consume(AS_ID);
+ if SearchIConstant(tempstr,l) then
+ begin
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end
+ else
+ begin
+ if is_locallabel(tempstr) then
+ begin
+ CreateLocalLabel(tempstr,hl,false);
+ hs:=hl.name;
+ hssymtyp:=AT_LABEL;
+ end
+ else
+ if SearchLabel(tempstr,hl,false) then
+ begin
+ hs:=hl.name;
+ hssymtyp:=AT_FUNCTION;
+ end
+ else
+ begin
+ searchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ globalvarsym :
+ hs:=tglobalvarsym(sym).mangledname;
+ localvarsym,
+ paravarsym :
+ Message(asmr_e_no_local_or_para_allowed);
+ typedconstsym :
+ hs:=ttypedconstsym(sym).mangledname;
+ procsym :
+ with Tprocsym(sym) do
+ begin
+ if procdef_count>1 then
+ message(asmr_w_calling_overload_func);
+ hs:=first_procdef.mangledname;
+ hssymtyp:=AT_FUNCTION;
+ end;
+ typesym :
+ begin
+ if not(ttypesym(sym).restype.def.deftype in [recorddef,objectdef]) then
+ Message(asmr_e_wrong_sym_type);
+ end;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ { symbol found? }
+ if hs<>'' then
+ begin
+ if needofs and (prevtok<>AS_DOLLAR) then
+ Message(asmr_e_need_dollar);
+ if asmsym='' then
+ begin
+ asmsym:=hs;
+ asmsymtyp:=hssymtyp;
+ end
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ if (expr='') or (expr[length(expr)]='+') then
+ begin
+ { don't remove the + if there could be a record field }
+ if actasmtoken<>AS_DOT then
+ delete(expr,length(expr),1);
+ end
+ else
+ Message(asmr_e_only_add_relocatable_symbol);
+ end;
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k);
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end
+ else
+ begin
+ if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
+ delete(expr,length(expr),1);
+ end;
+ end;
+ { check if there are wrong operator used like / or mod etc. }
+ if (hs<>'') and
+ not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,
+ AS_LPAREN,AS_RPAREN,AS_RBRACKET,AS_END]) then
+ Message(asmr_e_only_add_relocatable_symbol);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA:
+ break;
+ else
+ Begin
+ { write error only once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag:=TRUE;
+ end;
+ end;
+ Until false;
+ { calculate expression }
+ if not ErrorFlag then
+ value:=CalculateExpression(expr)
+ else
+ value:=0;
+ end;
+
+
+ function tattreader.BuildConstExpression(allowref,betweenbracket:boolean): aint;
+ var
+ l : aint;
+ hs : string;
+ hssymtyp : TAsmSymType;
+ begin
+ BuildConstSymbolExpression(allowref,betweenbracket,false,l,hs,hssymtyp);
+ if hs<>'' then
+ Message(asmr_e_relocatable_symbol_not_allowed);
+ BuildConstExpression:=l;
+ end;
+
+
+ Procedure tattreader.BuildConstantOperand(oper : toperand);
+ var
+ l : aint;
+ tempstr : string;
+ tempsymtyp : TAsmSymType;
+ begin
+ BuildConstSymbolExpression(false,false,true,l,tempstr,tempsymtyp);
+ if tempstr<>'' then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symofs:=l;
+ oper.opr.symbol:=objectlibrary.newasmsymbol(tempstr,AB_EXTERNAL,tempsymtyp);
+ end
+ else
+ begin
+ oper.opr.typ:=OPR_CONSTANT;
+ oper.opr.val:=l;
+ end;
+ end;
+
+end.
diff --git a/compiler/rabase.pas b/compiler/rabase.pas
new file mode 100644
index 0000000000..4cca4b3660
--- /dev/null
+++ b/compiler/rabase.pas
@@ -0,0 +1,105 @@
+{
+ Copyright (c) 1998-2003 by Peter Vreman, Florian Klaempfl and Carl Eric Codere
+
+ Basic stuff for assembler readers
+
+ 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 rabase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ systems;
+
+ type
+ tbaseasmreader = class
+ constructor create;virtual;
+ { the real return type is taasmoutput, but this would introduce too much unit circles }
+ function Assemble: tlinkedlist;virtual;abstract;
+ end;
+ tcbaseasmreader = class of tbaseasmreader;
+
+ pasmmodeinfo = ^tasmmodeinfo;
+ tasmmodeinfo = record
+ id : tasmmode;
+ idtxt : string[12];
+ casmreader : tcbaseasmreader;
+ end;
+
+ var
+ asmmodeinfos : array[tasmmode] of pasmmodeinfo;
+
+ function SetAsmReadMode(const s:string;var t:tasmmode):boolean;
+ procedure RegisterAsmMode(const r:tasmmodeinfo);
+
+ implementation
+
+ uses
+ cutils;
+
+
+ procedure RegisterAsmmode(const r:tasmmodeinfo);
+ var
+ t : tasmmode;
+ begin
+ t:=r.id;
+ if assigned(asmmodeinfos[t]) then
+ writeln('Warning: Asmmode is already registered!')
+ else
+ Getmem(asmmodeinfos[t],sizeof(tasmmodeinfo));
+ asmmodeinfos[t]^:=r;
+ end;
+
+
+ function SetAsmReadMode(const s:string;var t:tasmmode):boolean;
+ var
+ hs : string;
+ ht : tasmmode;
+ begin
+ result:=false;
+ { this should be case insensitive !! PM }
+ hs:=upper(s);
+ for ht:=low(tasmmode) to high(tasmmode) do
+ if assigned(asmmodeinfos[ht]) and
+ (asmmodeinfos[ht]^.idtxt=hs) then
+ begin
+ t:=asmmodeinfos[ht]^.id;
+ result:=true;
+ end;
+ end;
+
+
+ constructor tbaseasmreader.create;
+ begin
+ inherited create;
+ end;
+
+var
+ asmmode : tasmmode;
+
+finalization
+ for asmmode:=low(tasmmode) to high(tasmmode) do
+ if assigned(asmmodeinfos[asmmode]) then
+ begin
+ freemem(asmmodeinfos[asmmode],sizeof(tasmmodeinfo));
+ asmmodeinfos[asmmode]:=nil;
+ end;
+end.
diff --git a/compiler/rasm.pas b/compiler/rasm.pas
new file mode 100644
index 0000000000..fa515e41c5
--- /dev/null
+++ b/compiler/rasm.pas
@@ -0,0 +1,68 @@
+{
+ Copyright (c) 1998-2003 by Peter Vreman, Florian Klaempfl and Carl Eric Codere
+
+ Basic stuff for assembler readers
+
+ 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 rasm;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ rabase,
+ aasmtai,
+ systems,
+ cpubase,
+ cgbase;
+
+ type
+ tasmreader = class(tbaseasmreader)
+ firsttoken : boolean;
+ _asmsorted : boolean;
+ curlist : TAAsmoutput;
+ c : char;
+ actasmpattern : string;
+ actopcode : tasmop;
+ actasmregister : tregister;
+ actcondition : tasmcond;
+ iasmops : tdictionary;
+ constructor create;override;
+ destructor destroy;override;
+ end;
+
+ implementation
+
+ constructor tasmreader.create;
+ begin
+ inherited create;
+ firsttoken:=true;
+ end;
+
+
+ destructor tasmreader.destroy;
+ begin
+ if assigned(iasmops) then
+ iasmops.Free;
+ inherited destroy;
+ end;
+
+
+end.
diff --git a/compiler/rautils.pas b/compiler/rautils.pas
new file mode 100644
index 0000000000..6f3d57a4ab
--- /dev/null
+++ b/compiler/rautils.pas
@@ -0,0 +1,1556 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ This unit implements some support routines for assembler parsing
+ independent of the processor
+
+ 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 RAUtils;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Uses
+ cutils,cclasses,
+ globtype,aasmbase,aasmtai,cpubase,cpuinfo,cgbase,cgutils,
+ symconst,symbase,symtype,symdef,symsym;
+
+Const
+ RPNMax = 10; { I think you only need 4, but just to be safe }
+ OpMax = 25;
+
+{---------------------------------------------------------------------
+ Local Label Management
+---------------------------------------------------------------------}
+
+Type
+ { Each local label has this structure associated with it }
+ TLocalLabel = class(TNamedIndexItem)
+ Emitted : boolean;
+ constructor Create(const n:string);
+ function Gettasmlabel:tasmlabel;
+ private
+ lab : tasmlabel;
+ end;
+
+ TLocalLabelList = class(TDictionary)
+ procedure CheckEmitted;
+ end;
+
+var
+ LocalLabelList : TLocalLabelList;
+
+function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
+Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
+
+
+{---------------------------------------------------------------------
+ Instruction management
+---------------------------------------------------------------------}
+
+type
+ TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,OPR_LOCAL,
+ OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP);
+
+ TOprRec = record
+ case typ:TOprType of
+ OPR_NONE : ();
+ OPR_CONSTANT : (val:aint);
+ OPR_SYMBOL : (symbol:tasmsymbol;symofs:aint);
+ OPR_REFERENCE : (ref:treference);
+ OPR_LOCAL : (localsym:tabstractnormalvarsym;localsymofs:aint;localindexreg:tregister;localscale:byte;localgetoffset,localforceref:boolean);
+ OPR_REGISTER : (reg:tregister);
+{$ifdef m68k}
+ OPR_REGLIST : (regset : tcpuregisterset);
+{$endif m68k}
+{$ifdef powerpc}
+ OPR_COND : (cond : tasmcond);
+{$endif powerpc}
+{$ifdef POWERPC64}
+ OPR_COND : (cond : tasmcond);
+{$endif POWERPC64}
+{$ifdef arm}
+ OPR_REGSET : (regset : tcpuregisterset);
+ OPR_SHIFTEROP : (shifterop : tshifterop);
+{$endif arm}
+ end;
+
+ TOperand = class
+ typesize : aint;
+ hastype, { if the operand has typecasted variable }
+ hasvar : boolean; { if the operand is loaded with a variable }
+ size : TCGSize;
+ opr : TOprRec;
+ constructor create;virtual;
+ destructor destroy;override;
+ Procedure SetSize(_size:longint;force:boolean);virtual;
+ Procedure SetCorrectSize(opcode:tasmop);virtual;
+ Function SetupResult:boolean;virtual;
+ Function SetupSelf:boolean;
+ Function SetupOldEBP:boolean;
+ Function SetupVar(const s:string;GetOffset : boolean): Boolean;
+ Procedure InitRef;
+ end;
+ TCOperand = class of TOperand;
+
+ TInstruction = class
+ opcode : tasmop;
+ condition : tasmcond;
+ ops : byte;
+ labeled : boolean;
+ operands : array[1..max_operands] of toperand;
+ constructor create(optype : tcoperand);virtual;
+ destructor destroy;override;
+ { converts the instruction to an instruction how it's used by the assembler writer
+ and concats it to the passed list, the newly created item is returned }
+ function ConcatInstruction(p:TAAsmoutput) : tai;virtual;
+ Procedure Swapoperands;
+ end;
+
+ tstr2opentry = class(Tnamedindexitem)
+ op: TAsmOp;
+ end;
+
+ {---------------------------------------------------------------------}
+ { Expression parser types }
+ {---------------------------------------------------------------------}
+
+ TExprOperator = record
+ ch: char; { operator }
+ is_prefix: boolean; { was it a prefix, possible prefixes are +,- and not }
+ end;
+
+ {**********************************************************************}
+ { The following operators are supported: }
+ { '+' : addition }
+ { '-' : subtraction }
+ { '*' : multiplication }
+ { '/' : modulo division }
+ { '^' : exclusive or }
+ { '<' : shift left }
+ { '>' : shift right }
+ { '&' : bitwise and }
+ { '|' : bitwise or }
+ { '~' : bitwise complement }
+ { '%' : modulo division }
+ { nnn: longint numbers }
+ { ( and ) parenthesis }
+ {**********************************************************************}
+
+ TExprParse = class
+ public
+ Constructor create;
+ Destructor Destroy;override;
+ Function Evaluate(Expr: String): aint;
+ Function Priority(_Operator: Char): aint;
+ private
+ RPNStack : Array[1..RPNMax] of aint; { Stack For RPN calculator }
+ RPNTop : aint;
+ OpStack : Array[1..OpMax] of TExprOperator; { Operator stack For conversion }
+ OpTop : aint;
+ Procedure RPNPush(Num: aint);
+ Function RPNPop: aint;
+ Procedure RPNCalc(const token: String; prefix: boolean);
+ Procedure OpPush(_Operator: char; prefix: boolean);
+ { In reality returns TExprOperaotr }
+ Procedure OpPop(var _Operator:TExprOperator);
+ end;
+
+ { Evaluate an expression string to a aint }
+ Function CalculateExpression(const expression: string): aint;
+
+ {---------------------------------------------------------------------}
+ { String routines }
+ {---------------------------------------------------------------------}
+
+Function ParseVal(const S:String;base:byte):aint;
+Function PadZero(Var s: String; n: byte): Boolean;
+Function EscapeToPascal(const s:string): string;
+
+{---------------------------------------------------------------------
+ Symbol helper routines
+---------------------------------------------------------------------}
+
+procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:tsymtable);
+Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint):boolean;
+Function SearchType(const hs:string;var size:aint): Boolean;
+Function SearchRecordType(const s:string): boolean;
+Function SearchIConstant(const s:string; var l:aint): boolean;
+
+
+{---------------------------------------------------------------------
+ Instruction generation routines
+---------------------------------------------------------------------}
+
+ Procedure ConcatPasString(p : TAAsmoutput;s:string);
+ Procedure ConcatLabel(p: TAAsmoutput;var l : tasmlabel);
+ Procedure ConcatConstant(p : TAAsmoutput;value: aint; constsize:byte);
+ Procedure ConcatConstSymbol(p : TAAsmoutput;const sym:string;symtyp:tasmsymtype;l:aint);
+ Procedure ConcatRealConstant(p : TAAsmoutput;value: bestreal; real_typ : tfloattype);
+ Procedure ConcatString(p : TAAsmoutput;s:string);
+ procedure ConcatAlign(p:TAAsmoutput;l:aint);
+ Procedure ConcatPublic(p:TAAsmoutput;const s : string);
+ Procedure ConcatLocal(p:TAAsmoutput;const s : string);
+
+
+Implementation
+
+uses
+ strings,
+ defutil,systems,verbose,globals,
+ symtable,paramgr,
+ aasmcpu,
+ procinfo;
+
+{*************************************************************************
+ TExprParse
+*************************************************************************}
+
+Constructor TExprParse.create;
+Begin
+end;
+
+
+Procedure TExprParse.RPNPush(Num : aint);
+{ Add an operand to the top of the RPN stack }
+begin
+ if RPNTop < RPNMax then
+ begin
+ Inc(RPNTop);
+ RPNStack[RPNTop]:=Num;
+ end
+ else
+ Message(asmr_e_expr_illegal);
+end;
+
+
+Function TExprParse.RPNPop : aint;
+{ Get the operand at the top of the RPN stack }
+begin
+ if RPNTop > 0 then
+ begin
+ RPNPop:=RPNStack[RPNTop];
+ Dec(RPNTop);
+ end
+ else
+ Message(asmr_e_expr_illegal);
+end;
+
+
+Procedure TExprParse.RPNCalc(const Token : String; prefix:boolean); { RPN Calculator }
+Var
+ Temp : aint;
+ n1,n2 : aint;
+ LocalError : Integer;
+begin
+ { Handle operators }
+ if (Length(Token) = 1) and (Token[1] in ['+', '-', '*', '/','&','|','%','^','~','<','>']) then
+ Case Token[1] of
+ '+' :
+ Begin
+ if not prefix then
+ RPNPush(RPNPop + RPNPop);
+ end;
+ '-' :
+ Begin
+ if prefix then
+ RPNPush(-(RPNPop))
+ else
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 - n1);
+ end;
+ end;
+ '*' : RPNPush(RPNPop * RPNPop);
+ '&' :
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 and n1);
+ end;
+ '|' :
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 or n1);
+ end;
+ '~' : RPNPush(NOT RPNPop);
+ '<' :
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 SHL n1);
+ end;
+ '>' :
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 SHR n1);
+ end;
+ '%' :
+ begin
+ Temp:=RPNPop;
+ if Temp <> 0 then
+ RPNPush(RPNPop mod Temp)
+ else
+ begin
+ Message(asmr_e_expr_zero_divide);
+ { push 1 for error recovery }
+ RPNPush(1);
+ end;
+ end;
+ '^' : RPNPush(RPNPop XOR RPNPop);
+ '/' :
+ begin
+ Temp:=RPNPop;
+ if Temp <> 0 then
+ RPNPush(RPNPop div Temp)
+ else
+ begin
+ Message(asmr_e_expr_zero_divide);
+ { push 1 for error recovery }
+ RPNPush(1);
+ end;
+ end;
+ end
+ else
+ begin
+ { Convert String to number and add to stack }
+ Val(Token, Temp, LocalError);
+ if LocalError = 0 then
+ RPNPush(Temp)
+ else
+ begin
+ Message(asmr_e_expr_illegal);
+ { push 1 for error recovery }
+ RPNPush(1);
+ end;
+ end;
+end;
+
+
+Procedure TExprParse.OpPush(_Operator : char;prefix: boolean);
+{ Add an operator onto top of the stack }
+begin
+ if OpTop < OpMax then
+ begin
+ Inc(OpTop);
+ OpStack[OpTop].ch:=_Operator;
+ OpStack[OpTop].is_prefix:=prefix;
+ end
+ else
+ Message(asmr_e_expr_illegal);
+end;
+
+
+Procedure TExprParse.OpPop(var _Operator:TExprOperator);
+{ Get operator at the top of the stack }
+begin
+ if OpTop > 0 then
+ begin
+ _Operator:=OpStack[OpTop];
+ Dec(OpTop);
+ end
+ else
+ Message(asmr_e_expr_illegal);
+end;
+
+
+Function TExprParse.Priority(_Operator : Char) : aint;
+{ Return priority of operator }
+{ The greater the priority, the higher the precedence }
+begin
+ Case _Operator OF
+ '(' :
+ Priority:=0;
+ '+', '-' :
+ Priority:=1;
+ '*', '/','%','<','>' :
+ Priority:=2;
+ '|','&','^','~' :
+ Priority:=0;
+ else
+ Message(asmr_e_expr_illegal);
+ end;
+end;
+
+
+Function TExprParse.Evaluate(Expr : String):aint;
+Var
+ I : longint;
+ Token : String;
+ opr : TExprOperator;
+begin
+ Evaluate:=0;
+ { Reset stacks }
+ OpTop :=0;
+ RPNTop:=0;
+ Token :='';
+ { nothing to do ? }
+ if Expr='' then
+ exit;
+ For I:=1 to Length(Expr) DO
+ begin
+ if Expr[I] in ['0'..'9'] then
+ begin { Build multi-digit numbers }
+ Token:=Token + Expr[I];
+ if I = Length(Expr) then { Send last one to calculator }
+ RPNCalc(Token,false);
+ end
+ else
+ if Expr[I] in ['+', '-', '*', '/', '(', ')','^','&','|','%','~','<','>'] then
+ begin
+ if Token <> '' then
+ begin { Send last built number to calc. }
+ RPNCalc(Token,false);
+ Token:='';
+ end;
+
+ Case Expr[I] OF
+ '(' : OpPush('(',false);
+ ')' : begin
+ While (OpTop>0) and (OpStack[OpTop].ch <> '(') DO
+ Begin
+ OpPop(opr);
+ RPNCalc(opr.ch,opr.is_prefix);
+ end;
+ OpPop(opr); { Pop off and ignore the '(' }
+ end;
+ '+','-','~' : Begin
+ { workaround for -2147483648 }
+ if (expr[I]='-') and (expr[i+1] in ['0'..'9']) then
+ begin
+ token:='-';
+ expr[i]:='+';
+ end;
+ { if start of expression then surely a prefix }
+ { or if previous char was also an operator }
+ if (I = 1) or (not (Expr[I-1] in ['0'..'9','(',')'])) then
+ OpPush(Expr[I],true)
+ else
+ Begin
+ { Evaluate all higher priority operators }
+ While (OpTop > 0) AND (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
+ Begin
+ OpPop(opr);
+ RPNCalc(opr.ch,opr.is_prefix);
+ end;
+ OpPush(Expr[I],false);
+ End;
+ end;
+ '*', '/',
+ '^','|','&',
+ '%','<','>' : begin
+ While (OpTop > 0) and (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
+ Begin
+ OpPop(opr);
+ RPNCalc(opr.ch,opr.is_prefix);
+ end;
+ OpPush(Expr[I],false);
+ end;
+ end; { Case }
+ end
+ else
+ Message(asmr_e_expr_illegal); { Handle bad input error }
+ end;
+
+{ Pop off the remaining operators }
+ While OpTop > 0 do
+ Begin
+ OpPop(opr);
+ RPNCalc(opr.ch,opr.is_prefix);
+ end;
+
+{ The result is stored on the top of the stack }
+ Evaluate:=RPNPop;
+end;
+
+
+Destructor TExprParse.Destroy;
+Begin
+end;
+
+
+Function CalculateExpression(const expression: string): aint;
+var
+ expr: TExprParse;
+Begin
+ expr:=TExprParse.create;
+ CalculateExpression:=expr.Evaluate(expression);
+ expr.Free;
+end;
+
+
+{*************************************************************************}
+{ String conversions/utils }
+{*************************************************************************}
+
+Function EscapeToPascal(const s:string): string;
+{ converts a C styled string - which contains escape }
+{ characters to a pascal style string. }
+var
+ i,len : aint;
+ hs : string;
+ temp : string;
+ c : char;
+Begin
+ hs:='';
+ len:=0;
+ i:=0;
+ while (i<length(s)) and (len<255) do
+ begin
+ Inc(i);
+ if (s[i]='\') and (i<length(s)) then
+ Begin
+ inc(i);
+ case s[i] of
+ '\' :
+ c:='\';
+ 'b':
+ c:=#8;
+ 'f':
+ c:=#12;
+ 'n':
+ c:=#10;
+ 'r':
+ c:=#13;
+ 't':
+ c:=#9;
+ '"':
+ c:='"';
+ '0'..'7':
+ Begin
+ temp:=s[i];
+ temp:=temp+s[i+1];
+ temp:=temp+s[i+2];
+ inc(i,2);
+ c:=chr(ParseVal(temp,8));
+ end;
+ 'x':
+ Begin
+ temp:=s[i+1];
+ temp:=temp+s[i+2];
+ inc(i,2);
+ c:=chr(ParseVal(temp,16));
+ end;
+ else
+ Begin
+ Message1(asmr_e_escape_seq_ignored,s[i]);
+ c:=s[i];
+ end;
+ end;
+ end
+ else
+ c:=s[i];
+ inc(len);
+ hs[len]:=c;
+ end;
+ hs[0]:=chr(len);
+ EscapeToPascal:=hs;
+end;
+
+
+Function ParseVal(const S:String;base:byte):aint;
+{ Converts a decimal string to aint }
+var
+ code : integer;
+ errmsg : word;
+ prefix : string[2];
+Begin
+ case base of
+ 2 :
+ begin
+ errmsg:=asmr_e_error_converting_binary;
+ prefix:='%';
+ end;
+ 8 :
+ begin
+ errmsg:=asmr_e_error_converting_octal;
+ prefix:='&';
+ end;
+ 10 :
+ begin
+ errmsg:=asmr_e_error_converting_decimal;
+ prefix:='';
+ end;
+ 16 :
+ begin
+ errmsg:=asmr_e_error_converting_hexadecimal;
+ prefix:='$';
+ end;
+ else
+ internalerror(200501202);
+ end;
+ val(prefix+s,result,code);
+ if code<>0 then
+ begin
+ val(prefix+s,aword(result),code);
+ if code<>0 then
+ begin
+ Message1(errmsg,s);
+ result:=0;
+ end;
+ end;
+end;
+
+
+Function PadZero(Var s: String; n: byte): Boolean;
+Begin
+ PadZero:=TRUE;
+ { Do some error checking first }
+ if Length(s) = n then
+ exit
+ else
+ if Length(s) > n then
+ Begin
+ PadZero:=FALSE;
+ delete(s,n+1,length(s));
+ exit;
+ end
+ else
+ PadZero:=TRUE;
+ { Fill it up with the specified character }
+ fillchar(s[length(s)+1],n-1,#0);
+ s[0]:=chr(n);
+end;
+
+
+{****************************************************************************
+ TOperand
+****************************************************************************}
+
+constructor TOperand.Create;
+begin
+ size:=OS_NO;
+ hastype:=false;
+ hasvar:=false;
+ FillChar(Opr,sizeof(Opr),0);
+end;
+
+
+destructor TOperand.destroy;
+begin
+end;
+
+
+Procedure TOperand.SetSize(_size:longint;force:boolean);
+begin
+ if force or
+ ((size = OS_NO) and (_size<=16)) then
+ Begin
+ case _size of
+ 1 : size:=OS_8;
+ 2 : size:=OS_16{ could be S_IS};
+ 4 : size:=OS_32{ could be S_IL or S_FS};
+ 8 : size:=OS_64{ could be S_D or S_FL};
+ 10 : size:=OS_F80;
+ 16 : size:=OS_128;
+ end;
+ end;
+end;
+
+
+Procedure TOperand.SetCorrectSize(opcode:tasmop);
+begin
+end;
+
+
+function TOperand.SetupResult:boolean;
+
+begin
+ SetupResult:=false;
+ { replace by correct offset. }
+ with current_procinfo.procdef do
+ if (not is_void(rettype.def)) then
+ begin
+ if (m_tp7 in aktmodeswitches) and
+ (not paramanager.ret_in_param(rettype.def,proccalloption)) then
+ begin
+ message(asmr_e_cannot_use_RESULT_here);
+ exit;
+ end;
+ SetupResult:=setupvar('result',false)
+ end
+ else
+ message(asmr_e_void_function);
+end;
+
+
+Function TOperand.SetupSelf:boolean;
+Begin
+ SetupSelf:=false;
+ if assigned(current_procinfo.procdef._class) then
+ SetupSelf:=setupvar('self',false)
+ else
+ Message(asmr_e_cannot_use_SELF_outside_a_method);
+end;
+
+
+Function TOperand.SetupOldEBP:boolean;
+Begin
+ SetupOldEBP:=false;
+ if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
+ SetupOldEBP:=setupvar('parentframe',false)
+ else
+ Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
+end;
+
+
+Function TOperand.SetupVar(const s:string;GetOffset : boolean): Boolean;
+
+ function symtable_has_localvarsyms(st:tsymtable):boolean;
+ var
+ sym : tsym;
+ begin
+ result:=false;
+ sym:=tsym(st.symindex.first);
+ while assigned(sym) do
+ begin
+ if sym.typ=localvarsym then
+ begin
+ result:=true;
+ exit;
+ end;
+ sym:=tsym(sym.indexnext);
+ end;
+ end;
+
+ procedure setconst(l:aint);
+ begin
+ { We return the address of the field, just like Delphi/TP }
+ case opr.typ of
+ OPR_NONE :
+ begin
+ opr.typ:=OPR_CONSTANT;
+ opr.val:=l;
+ end;
+ OPR_CONSTANT :
+ inc(opr.val,l);
+ OPR_REFERENCE :
+ inc(opr.ref.offset,l);
+ OPR_LOCAL :
+ inc(opr.localsymofs,l);
+ else
+ Message(asmr_e_invalid_operand_type);
+ end;
+ end;
+
+
+{ search and sets up the correct fields in the Instr record }
+{ for the NON-constant identifier passed to the routine. }
+{ if not found returns FALSE. }
+var
+ sym : tsym;
+ srsymtable : tsymtable;
+ harrdef : tarraydef;
+ indexreg : tregister;
+ l : aint;
+ plist : psymlistitem;
+Begin
+ SetupVar:=false;
+ asmsearchsym(s,sym,srsymtable);
+ if sym = nil then
+ exit;
+ if sym.typ=absolutevarsym then
+ begin
+ if (tabsolutevarsym(sym).abstyp=tovar) then
+ begin
+ { Only support simple loads }
+ plist:=tabsolutevarsym(sym).ref.firstsym;
+ if assigned(plist) and
+ (plist^.sltype=sl_load) then
+ sym:=plist^.sym
+ else
+ begin
+ Message(asmr_e_unsupported_symbol_type);
+ exit;
+ end;
+ end
+ else
+ begin
+ Message(asmr_e_unsupported_symbol_type);
+ exit;
+ end;
+ end;
+ case sym.typ of
+ fieldvarsym :
+ begin
+ setconst(tfieldvarsym(sym).fieldoffset);
+ hasvar:=true;
+ SetupVar:=true;
+ end;
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ { we always assume in asm statements that }
+ { that the variable is valid. }
+ tabstractvarsym(sym).varstate:=vs_used;
+ inc(tabstractvarsym(sym).refs);
+ { variable can't be placed in a register }
+ tabstractvarsym(sym).varregable:=vr_none;
+ case sym.owner.symtabletype of
+ globalsymtable,
+ staticsymtable :
+ begin
+ initref;
+ opr.ref.symbol:=objectlibrary.newasmsymbol(tglobalvarsym(sym).mangledname,AB_EXTERNAL,AT_DATA);
+ end;
+ parasymtable,
+ localsymtable :
+ begin
+ if opr.typ=OPR_REFERENCE then
+ begin
+ indexreg:=opr.ref.base;
+ if opr.ref.index<>NR_NO then
+ begin
+ if indexreg=NR_NO then
+ indexreg:=opr.ref.index
+ else
+ Message(asmr_e_multiple_index);
+ end;
+ end
+ else
+ indexreg:=NR_NO;
+ opr.typ:=OPR_LOCAL;
+ if assigned(current_procinfo.parent) and
+ not(po_inline in current_procinfo.procdef.procoptions) and
+ (sym.owner<>current_procinfo.procdef.localst) and
+ (sym.owner<>current_procinfo.procdef.parast) and
+ (current_procinfo.procdef.localst.symtablelevel>normal_function_level) and
+ symtable_has_localvarsyms(current_procinfo.procdef.localst) then
+ message1(asmr_e_local_para_unreachable,s);
+ opr.localsym:=tabstractnormalvarsym(sym);
+ opr.localsymofs:=0;
+ opr.localindexreg:=indexreg;
+ opr.localscale:=0;
+ opr.localgetoffset:=GetOffset;
+ if paramanager.push_addr_param(tabstractvarsym(sym).varspez,tabstractvarsym(sym).vartype.def,current_procinfo.procdef.proccalloption) then
+ SetSize(sizeof(aint),false);
+ end;
+ end;
+ case tabstractvarsym(sym).vartype.def.deftype of
+ orddef,
+ enumdef,
+ pointerdef,
+ arraydef,
+ floatdef :
+ SetSize(tabstractvarsym(sym).getsize,false);
+ (* makes no sense when using sse instructions (FK)
+ arraydef :
+ begin
+ { for arrays try to get the element size, take care of
+ multiple indexes }
+ harrdef:=tarraydef(tabstractvarsym(sym).vartype.def);
+ while assigned(harrdef.elementtype.def) and
+ (harrdef.elementtype.def.deftype=arraydef) do
+ harrdef:=tarraydef(harrdef.elementtype.def);
+ SetSize(harrdef.elesize,false);
+ end;
+ *)
+ end;
+ hasvar:=true;
+ SetupVar:=true;
+ Exit;
+ end;
+ typedconstsym :
+ begin
+ initref;
+ opr.ref.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(sym).mangledname,AB_EXTERNAL,AT_DATA);
+ case ttypedconstsym(sym).typedconsttype.def.deftype of
+ orddef,
+ enumdef,
+ pointerdef,
+ floatdef :
+ SetSize(ttypedconstsym(sym).getsize,false);
+ arraydef :
+ begin
+ { for arrays try to get the element size, take care of
+ multiple indexes }
+ harrdef:=tarraydef(ttypedconstsym(sym).typedconsttype.def);
+ while assigned(harrdef.elementtype.def) and
+ (harrdef.elementtype.def.deftype=arraydef) do
+ harrdef:=tarraydef(harrdef.elementtype.def);
+ SetSize(harrdef.elesize,false);
+ end;
+ end;
+ hasvar:=true;
+ SetupVar:=true;
+ Exit;
+ end;
+ constsym :
+ begin
+ if tconstsym(sym).consttyp=constord then
+ begin
+ setconst(tconstsym(sym).value.valueord);
+ SetupVar:=true;
+ Exit;
+ end;
+ end;
+ typesym :
+ begin
+ if ttypesym(sym).restype.def.deftype in [recorddef,objectdef] then
+ begin
+ setconst(0);
+ SetupVar:=TRUE;
+ Exit;
+ end;
+ end;
+ procsym :
+ begin
+ if opr.typ<>OPR_NONE then
+ Message(asmr_e_invalid_operand_type);
+ if Tprocsym(sym).procdef_count>1 then
+ Message(asmr_w_calling_overload_func);
+ l:=opr.ref.offset;
+ opr.typ:=OPR_SYMBOL;
+ opr.symbol:=objectlibrary.newasmsymbol(tprocsym(sym).first_procdef.mangledname,AB_EXTERNAL,AT_FUNCTION);
+ opr.symofs:=l;
+ hasvar:=true;
+ SetupVar:=TRUE;
+ Exit;
+ end;
+ else
+ begin
+ Message(asmr_e_unsupported_symbol_type);
+ exit;
+ end;
+ end;
+end;
+
+
+procedure TOperand.InitRef;
+{*********************************************************************}
+{ Description: This routine first check if the opcode is of }
+{ type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
+{ If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
+{ the operand type to OPR_REFERENCE, as well as setting up the ref }
+{ to point to the default segment. }
+{*********************************************************************}
+var
+ l : aint;
+ hsymofs : aint;
+ hsymbol : tasmsymbol;
+ reg : tregister;
+Begin
+ case opr.typ of
+ OPR_REFERENCE :
+ exit;
+ OPR_CONSTANT :
+ begin
+ l:=opr.val;
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ opr.Ref.Offset:=l;
+ end;
+ OPR_NONE :
+ begin
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ end;
+ OPR_REGISTER :
+ begin
+ reg:=opr.reg;
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ opr.Ref.base:=reg;
+ end;
+ OPR_SYMBOL :
+ begin
+ hsymbol:=opr.symbol;
+ hsymofs:=opr.symofs;
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ opr.ref.symbol:=hsymbol;
+ opr.ref.offset:=hsymofs;
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_operand_type);
+ { Recover }
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ end;
+ end;
+end;
+
+
+{****************************************************************************
+ TInstruction
+****************************************************************************}
+
+constructor TInstruction.create(optype : tcoperand);
+ var
+ i : longint;
+ Begin
+ { these field are set to 0 anyways by the constructor helper (FK)
+ Opcode:=A_NONE;
+ Condition:=C_NONE;
+ Ops:=0;
+ }
+ for i:=1 to max_operands do
+ Operands[i]:=optype.create;
+ Labeled:=false;
+ end;
+
+
+destructor TInstruction.destroy;
+var
+ i : longint;
+Begin
+ for i:=1 to max_operands do
+ Operands[i].free;
+end;
+
+
+ Procedure TInstruction.Swapoperands;
+ Var
+ p : toperand;
+ Begin
+ case Ops of
+ 2 :
+ begin
+ p:=Operands[1];
+ Operands[1]:=Operands[2];
+ Operands[2]:=p;
+ end;
+ 3 :
+ begin
+ p:=Operands[1];
+ Operands[1]:=Operands[3];
+ Operands[3]:=p;
+ end;
+ end;
+ end;
+
+
+ function TInstruction.ConcatInstruction(p:TAAsmoutput) : tai;
+ var
+ ai : taicpu;
+ i : longint;
+ begin
+ ai:=taicpu.op_none(opcode);
+ ai.Ops:=Ops;
+ ai.Allocate_oper(Ops);
+ for i:=1 to Ops do
+ with operands[i].opr do
+ begin
+ case typ of
+ OPR_CONSTANT :
+ ai.loadconst(i-1,val);
+ OPR_REGISTER:
+ ai.loadreg(i-1,reg);
+ OPR_SYMBOL:
+ ai.loadsymbol(i-1,symbol,symofs);
+ OPR_LOCAL :
+ ai.loadlocal(i-1,localsym,localsymofs,localindexreg,
+ localscale,localgetoffset,localforceref);
+ OPR_REFERENCE:
+ ai.loadref(i-1,ref);
+{$ifdef ARM}
+ OPR_REGSET:
+ ai.loadregset(i-1,regset);
+ OPR_SHIFTEROP:
+ ai.loadshifterop(i-1,shifterop);
+{$endif ARM}
+ else
+ internalerror(200501051);
+ end;
+ end;
+ ai.SetCondition(condition);
+ { Concat the opcode or give an error }
+ if assigned(ai) then
+ p.concat(ai)
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ result:=ai;
+ end;
+
+
+{***************************************************************************
+ TLocalLabel
+***************************************************************************}
+
+constructor TLocalLabel.create(const n:string);
+begin
+ inherited CreateName(n);
+ lab:=nil;
+ emitted:=false;
+end;
+
+
+function TLocalLabel.Gettasmlabel:tasmlabel;
+begin
+ if not assigned(lab) then
+ begin
+ objectlibrary.getjumplabel(lab);
+ { this label is forced to be used so it's always written }
+ lab.increfs;
+ end;
+ Gettasmlabel:=lab;
+end;
+
+
+{***************************************************************************
+ TLocalLabelList
+***************************************************************************}
+
+procedure LocalLabelEmitted(p:tnamedindexitem;arg:pointer);
+begin
+ if not TLocalLabel(p).emitted then
+ Message1(asmr_e_unknown_label_identifier,p.name);
+end;
+
+procedure TLocalLabelList.CheckEmitted;
+begin
+ ForEach_Static(@LocalLabelEmitted,nil)
+end;
+
+
+function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
+var
+ lab : TLocalLabel;
+Begin
+ CreateLocalLabel:=true;
+{ Check if it already is defined }
+ lab:=TLocalLabel(LocalLabellist.Search(s));
+ if not assigned(lab) then
+ begin
+ lab:=TLocalLabel.Create(s);
+ LocalLabellist.Insert(lab);
+ end;
+{ set emitted flag and check for dup syms }
+ if emit then
+ begin
+ if lab.Emitted then
+ begin
+ Message1(asmr_e_dup_local_sym,lab.Name);
+ CreateLocalLabel:=false;
+ end;
+ lab.Emitted:=true;
+ end;
+ hl:=lab.Gettasmlabel;
+end;
+
+
+{****************************************************************************
+ Symbol table helper routines
+****************************************************************************}
+
+procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:tsymtable);
+var
+ i : integer;
+begin
+ i:=pos('.',s);
+ { allow unit.identifier }
+ if i>0 then
+ begin
+ searchsym(Copy(s,1,i-1),srsym,srsymtable);
+ if assigned(srsym) then
+ begin
+ if (srsym.typ=unitsym) and
+ (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
+ srsym.owner.iscurrentunit then
+ srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,Copy(s,i+1,255))
+ else
+ srsym:=nil;
+ end;
+ end
+ else
+ searchsym(s,srsym,srsymtable);
+end;
+
+
+Function SearchType(const hs:string;var size:aint): Boolean;
+var
+ srsym : tsym;
+ srsymtable : tsymtable;
+begin
+ result:=false;
+ size:=0;
+ asmsearchsym(hs,srsym,srsymtable);
+ if assigned(srsym) and
+ (srsym.typ=typesym) then
+ begin
+ size:=ttypesym(srsym).restype.def.size;
+ result:=true;
+ end;
+end;
+
+
+
+Function SearchRecordType(const s:string): boolean;
+var
+ srsym : tsym;
+ srsymtable : tsymtable;
+Begin
+ SearchRecordType:=false;
+{ Check the constants in symtable }
+ asmsearchsym(s,srsym,srsymtable);
+ if srsym <> nil then
+ Begin
+ case srsym.typ of
+ typesym :
+ begin
+ if ttypesym(srsym).restype.def.deftype in [recorddef,objectdef] then
+ begin
+ SearchRecordType:=true;
+ exit;
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+Function SearchIConstant(const s:string; var l:aint): boolean;
+{**********************************************************************}
+{ Description: Searches for a CONSTANT of name s in either the local }
+{ symbol list, then in the global symbol list, and returns the value }
+{ of that constant in l. Returns TRUE if successfull, if not found, }
+{ or if the constant is not of correct type, then returns FALSE }
+{ Remarks: Also handle TRUE and FALSE returning in those cases 1 and 0 }
+{ respectively. }
+{**********************************************************************}
+var
+ srsym : tsym;
+ srsymtable : tsymtable;
+Begin
+ SearchIConstant:=false;
+{ check for TRUE or FALSE reserved words first }
+ if s = 'TRUE' then
+ Begin
+ SearchIConstant:=TRUE;
+ l:=1;
+ exit;
+ end;
+ if s = 'FALSE' then
+ Begin
+ SearchIConstant:=TRUE;
+ l:=0;
+ exit;
+ end;
+{ Check the constants in symtable }
+ asmsearchsym(s,srsym,srsymtable);
+ if srsym <> nil then
+ Begin
+ case srsym.typ of
+ constsym :
+ begin
+ if tconstsym(srsym).consttyp=constord then
+ Begin
+ l:=tconstsym(srsym).value.valueord;
+ SearchIConstant:=TRUE;
+ exit;
+ end;
+ end;
+ enumsym:
+ Begin
+ l:=tenumsym(srsym).value;
+ SearchIConstant:=TRUE;
+ exit;
+ end;
+ end;
+ end;
+end;
+
+
+Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint):boolean;
+{ search and returns the offset and size of records/objects of the base }
+{ with field name setup in field. }
+{ returns FALSE if not found. }
+{ used when base is a variable or a typed constant name. }
+var
+ st : tsymtable;
+ harrdef : tarraydef;
+ sym : tsym;
+ srsymtable : tsymtable;
+ i : longint;
+ base : string;
+Begin
+ GetRecordOffsetSize:=FALSE;
+ Offset:=0;
+ Size:=0;
+ i:=pos('.',s);
+ if i=0 then
+ i:=255;
+ base:=Copy(s,1,i-1);
+ delete(s,1,i);
+ if base='SELF' then
+ st:=current_procinfo.procdef._class.symtable
+ else
+ begin
+ asmsearchsym(base,sym,srsymtable);
+ st:=nil;
+ { we can start with a var,type,typedconst }
+ if assigned(sym) then
+ case sym.typ of
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ st:=Tabstractvarsym(sym).vartype.def.getsymtable(gs_record);
+ typesym :
+ st:=Ttypesym(sym).restype.def.getsymtable(gs_record);
+ typedconstsym :
+ st:=Ttypedconstsym(sym).typedconsttype.def.getsymtable(gs_record);
+ end
+ else
+ s:='';
+ end;
+ { now walk all recordsymtables }
+ while assigned(st) and (s<>'') do
+ begin
+ { load next field in base }
+ i:=pos('.',s);
+ if i=0 then
+ i:=255;
+ base:=Copy(s,1,i-1);
+ delete(s,1,i);
+ if st.symtabletype=objectsymtable then
+ sym:=search_class_member(tobjectdef(st.defowner),base)
+ else
+ sym:=tsym(st.search(base));
+ if not assigned(sym) then
+ begin
+ GetRecordOffsetSize:=false;
+ exit;
+ end;
+ st:=nil;
+ case sym.typ of
+ fieldvarsym :
+ with Tfieldvarsym(sym) do
+ begin
+ inc(Offset,fieldoffset);
+ size:=getsize;
+ with vartype do
+ case def.deftype of
+ arraydef :
+ begin
+ { for arrays try to get the element size, take care of
+ multiple indexes }
+ harrdef:=tarraydef(def);
+ while assigned(harrdef.elementtype.def) and
+ (harrdef.elementtype.def.deftype=arraydef) do
+ harrdef:=tarraydef(harrdef.elementtype.def);
+ size:=harrdef.elesize;
+ end;
+ recorddef :
+ st:=trecorddef(def).symtable;
+ objectdef :
+ st:=tobjectdef(def).symtable;
+ end;
+ end;
+ end;
+ end;
+ { Support Field.Type as typecasting }
+ if (st=nil) and (s<>'') then
+ begin
+ asmsearchsym(s,sym,srsymtable);
+ if assigned(sym) and (sym.typ=typesym) then
+ begin
+ size:=ttypesym(sym).restype.def.size;
+ s:=''
+ end;
+ end;
+ GetRecordOffsetSize:=(s='');
+end;
+
+
+Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
+var
+ sym : tsym;
+ srsymtable : tsymtable;
+ hs : string;
+Begin
+ hl:=nil;
+ SearchLabel:=false;
+{ Check for pascal labels, which are case insensetive }
+ hs:=upper(s);
+ asmsearchsym(hs,sym,srsymtable);
+ if sym=nil then
+ exit;
+ case sym.typ of
+ labelsym :
+ begin
+ if not(assigned(tlabelsym(sym).asmblocklabel)) then
+ objectlibrary.getjumplabel(tlabelsym(sym).asmblocklabel);
+ hl:=tlabelsym(sym).asmblocklabel;
+ if emit then
+ tlabelsym(sym).defined:=true
+ else
+ tlabelsym(sym).used:=true;
+ SearchLabel:=true;
+ end;
+ end;
+end;
+
+
+ {*************************************************************************}
+ { Instruction Generation Utilities }
+ {*************************************************************************}
+
+
+ Procedure ConcatString(p : TAAsmoutput;s:string);
+ {*********************************************************************}
+ { PROCEDURE ConcatString(s:string); }
+ { Description: This routine adds the character chain pointed to in }
+ { s to the instruction linked list. }
+ {*********************************************************************}
+ Var
+ pc: PChar;
+ Begin
+ getmem(pc,length(s)+1);
+ p.concat(Tai_string.Create_pchar(strpcopy(pc,s),length(s)));
+ end;
+
+ Procedure ConcatPasString(p : TAAsmoutput;s:string);
+ {*********************************************************************}
+ { PROCEDURE ConcatPasString(s:string); }
+ { Description: This routine adds the character chain pointed to in }
+ { s to the instruction linked list, contrary to ConcatString it }
+ { uses a pascal style string, so it conserves null characters. }
+ {*********************************************************************}
+ Begin
+ p.concat(Tai_string.Create(s));
+ end;
+
+
+Procedure ConcatConstant(p: TAAsmoutput; value: aint; constsize:byte);
+{*********************************************************************}
+{ PROCEDURE ConcatConstant(value: aint; maxvalue: aint); }
+{ Description: This routine adds the value constant to the current }
+{ instruction linked list. }
+{ maxvalue -> indicates the size of the data to initialize: }
+{ $ff -> create a byte node. }
+{ $ffff -> create a word node. }
+{ $ffffffff -> create a dword node. }
+{*********************************************************************}
+var
+ rangelo,rangehi : int64;
+Begin
+ case constsize of
+ 1 :
+ begin
+ p.concat(Tai_const.Create_8bit(byte(value)));
+ rangelo:=low(shortint);
+ rangehi:=high(byte);
+ end;
+ 2 :
+ begin
+ p.concat(Tai_const.Create_16bit(word(value)));
+ rangelo:=low(smallint);
+ rangehi:=high(word);
+ end;
+ 4 :
+ begin
+ p.concat(Tai_const.Create_32bit(longint(value)));
+ rangelo:=low(longint);
+ rangehi:=high(cardinal);
+ end;
+ 8 :
+ begin
+ p.concat(Tai_const.Create_64bit(int64(value)));
+ rangelo:=0;
+ rangehi:=0;
+ end;
+ else
+ internalerror(200405011);
+ end;
+ { check for out of bounds }
+ if (rangelo<>0) and
+ ((value>rangehi) or (value<rangelo)) then
+ Message(asmr_e_constant_out_of_bounds);
+end;
+
+
+ Procedure ConcatConstSymbol(p : TAAsmoutput;const sym:string;symtyp:tasmsymtype;l:aint);
+ begin
+ p.concat(Tai_const.Createname(sym,symtyp,l));
+ end;
+
+
+ Procedure ConcatRealConstant(p : TAAsmoutput;value: bestreal; real_typ : tfloattype);
+ {***********************************************************************}
+ { PROCEDURE ConcatRealConstant(value: bestreal; real_typ : tfloattype); }
+ { Description: This routine adds the value constant to the current }
+ { instruction linked list. }
+ { real_typ -> indicates the type of the real data to initialize: }
+ { s32real -> create a single node. }
+ { s64real -> create a double node. }
+ { s80real -> create an extended node. }
+ { s64bit -> create a comp node. }
+ { f32bit -> create a fixed node. (not used normally) }
+ {***********************************************************************}
+ Begin
+ case real_typ of
+ s32real : p.concat(Tai_real_32bit.Create(value));
+ s64real :
+{$ifdef ARM}
+ if aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11] then
+ p.concat(Tai_real_64bit.Create_hiloswapped(value))
+ else
+{$endif ARM}
+ p.concat(Tai_real_64bit.Create(value));
+ s80real : p.concat(Tai_real_80bit.Create(value));
+ s64comp : p.concat(Tai_comp_64bit.Create(trunc(value)));
+ end;
+ end;
+
+ Procedure ConcatLabel(p: TAAsmoutput;var l : tasmlabel);
+ {*********************************************************************}
+ { PROCEDURE ConcatLabel }
+ { Description: This routine either emits a label or a labeled }
+ { instruction to the linked list of instructions. }
+ {*********************************************************************}
+ begin
+ p.concat(Tai_label.Create(l));
+ end;
+
+ procedure ConcatAlign(p:TAAsmoutput;l:aint);
+ {*********************************************************************}
+ { PROCEDURE ConcatPublic }
+ { Description: This routine emits an global definition to the }
+ { linked list of instructions.(used by AT&T styled asm) }
+ {*********************************************************************}
+ begin
+ p.concat(Tai_align.Create(l));
+ end;
+
+ procedure ConcatPublic(p:TAAsmoutput;const s : string);
+ {*********************************************************************}
+ { PROCEDURE ConcatPublic }
+ { Description: This routine emits an global definition to the }
+ { linked list of instructions.(used by AT&T styled asm) }
+ {*********************************************************************}
+ begin
+ p.concat(Tai_symbol.Createname_global(s,AT_LABEL,0));
+ end;
+
+ procedure ConcatLocal(p:TAAsmoutput;const s : string);
+ {*********************************************************************}
+ { PROCEDURE ConcatLocal }
+ { Description: This routine emits an local definition to the }
+ { linked list of instructions. }
+ {*********************************************************************}
+ begin
+ p.concat(Tai_symbol.Createname(s,AT_LABEL,0));
+ end;
+
+
+end.
diff --git a/compiler/regvars.pas b/compiler/regvars.pas
new file mode 100644
index 0000000000..4b19de49f3
--- /dev/null
+++ b/compiler/regvars.pas
@@ -0,0 +1,666 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Jonas Maebe
+
+ This unit handles register variable allocation
+
+ 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 regvars;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmbase,aasmtai,aasmcpu,
+ node,
+ symsym,
+ cpubase, cgbase, tgobj;
+
+{$ifdef OLDREGVARS}
+ procedure assign_regvars(p: tnode);
+ procedure load_regvars(asml: TAAsmoutput; p: tnode);
+ procedure cleanup_regvars(asml: TAAsmoutput);
+ procedure store_regvar(asml: TAAsmoutput; reg: tregister);
+ procedure load_regvar(asml: TAAsmoutput; vsym: tvarsym);
+ procedure load_regvar_reg(asml: TAAsmoutput; reg: tregister);
+ procedure load_all_regvars(asml: TAAsmoutput);
+ procedure free_regvars(list: taasmoutput);
+{ procedure translate_regvars(list: taasmoutput); }
+{$endif OLDREGVARS}
+
+{$ifdef i386}
+(*
+ procedure sync_regvars_other(list1, list2: taasmoutput; const regvarsloaded1,
+ regvarsloaded2: regvarother_booleanarray);
+ procedure sync_regvars_int(list1, list2: taasmoutput; const regvarsloaded1,
+ regvarsloaded2: Tsuperregisterset);
+*)
+{$endif i386}
+
+implementation
+
+ uses
+ globtype,systems,comphook,
+ cutils,cclasses,verbose,globals,
+ psub,
+ symconst,symbase,symtype,symdef,paramgr,defutil,
+ cpuinfo,cgobj,procinfo;
+
+{$ifdef OLDREGVARS}
+ procedure searchregvars(p : tnamedindexitem;arg:pointer);
+ var
+ i,j,k : longint;
+ parasym : boolean;
+ begin
+ parasym:=pboolean(arg)^;
+ if (tsym(p).typ=varsym) and ((tvarsym(p).varregable <> vr_none) or
+ ((tvarsym(p).varspez in [vs_var,vs_const,vs_out]) and
+ paramanager.push_addr_param(tvarsym(p).varspez,tvarsym(p).vartype.def,current_procinfo.procdef.proccalloption))) and
+ not tvarsym(p).vartype.def.needs_inittable then
+ begin
+ j:=tvarsym(p).refs;
+ { walk through all momentary register variables }
+ for i:=1 to maxvarregs do
+ begin
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ if ((regvars[i]=nil) or (j>regvars_refs[i])) and (j>0) then
+ begin
+ for k:=maxvarregs-1 downto i do
+ begin
+ regvars[k+1]:=regvars[k];
+ regvars_para[k+1]:=regvars_para[k];
+ regvars_refs[k+1]:=regvars_refs[k];
+ end;
+ { calc the new refs
+ tvarsym(p).refs:=j; }
+ regvars[i]:=tsym(p);
+ regvars_para[i]:=parasym;
+ regvars_refs[i]:=j;
+ break;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure searchfpuregvars(p : tnamedindexitem;arg:pointer);
+ var
+ i,j,k : longint;
+ parasym : boolean;
+ begin
+ parasym:=pboolean(arg)^;
+ if (tsym(p).typ=varsym) and (tvarsym(p).varregable <> vr_none) then
+ begin
+ j:=tvarsym(p).refs;
+ { parameter get a less value }
+ { walk through all momentary register variables }
+ for i:=1 to maxfpuvarregs do
+ begin
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ if ((fpuregvars[i]=nil) or (j>fpuregvars_refs[i])) and (j>0) then
+ begin
+ for k:=maxfpuvarregs-1 downto i do
+ begin
+ fpuregvars[k+1]:=fpuregvars[k];
+ fpuregvars_para[k+1]:=fpuregvars_para[k];
+ fpuregvars_refs[k+1]:=fpuregvars_refs[k];
+ end;
+ { calc the new refs
+ tvarsym(p).refs:=j; }
+ fpuregvars[i]:=tsym(p);
+ fpuregvars_para[i]:=parasym;
+ fpuregvars_refs[i]:=j;
+ break;
+ end;
+ end;
+ end;
+ end;
+
+ procedure assign_regvars(p: tnode);
+ { register variables }
+ var
+{$ifndef i386}
+ hp: tparaitem;
+{$endif i386}
+ regvarinfo: pregvarinfo;
+ i: longint;
+ parasym : boolean;
+ siz : tcgsize;
+ begin
+ { max. optimizations }
+ { only if no asm is used }
+ { and no try statement }
+ if (cs_regvars in aktglobalswitches) and
+ { we have to store regvars back to memory in this case (the nested }
+ { procedures can access the variables of the parent) }
+ (tcgprocinfo(current_procinfo).nestedprocs.count = 0) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) then
+ begin
+ new(regvarinfo);
+ fillchar(regvarinfo^,sizeof(regvarinfo^),0);
+ current_procinfo.procdef.regvarinfo := regvarinfo;
+ if (p.registersint<maxvarregs) then
+ begin
+ parasym:=false;
+ symtablestack.foreach_static(searchregvars,@parasym);
+ { copy parameter into a register ? }
+ parasym:=true;
+ symtablestack.next.foreach_static(searchregvars,@parasym);
+ { hold needed registers free }
+ for i:=maxvarregs downto maxvarregs-p.registersint+1 do
+ begin
+ regvarinfo^.regvars[i]:=nil;
+ regvarinfo^.regvars_para[i] := false;
+ end;
+ { now assign register }
+ for i:=1 to maxvarregs-p.registersint do
+ begin
+ if assigned(regvarinfo^.regvars[i]) and
+ { currently we assume we can use registers for all }
+ { regvars if procedure does no call }
+ (not(pi_do_call in current_procinfo.flags) or
+ { otherwise, demand some (arbitrary) minimum usage }
+ (tvarsym(regvarinfo^.regvars[i]).refs > 100)) then
+ begin
+ { register is no longer available for }
+ { expressions }
+ { search the register which is the most }
+ { unused }
+
+ { call by reference/const ? }
+ if paramanager.push_addr_param(tvarsym(regvarinfo^.regvars[i]).varspez,tvarsym(regvarinfo^.regvars[i]).vartype.def,current_procinfo.procdef.proccalloption) then
+ siz:=OS_32
+ else
+ if (tvarsym(regvarinfo^.regvars[i]).vartype.def.deftype in [orddef,enumdef]) and
+ (tvarsym(regvarinfo^.regvars[i]).vartype.def.size=1) then
+ siz:=OS_8
+ else
+ if (tvarsym(regvarinfo^.regvars[i]).vartype.def.deftype in [orddef,enumdef]) and
+ (tvarsym(regvarinfo^.regvars[i]).vartype.def.size=2) then
+ siz:=OS_16
+ else
+ siz:=OS_32;
+
+ { allocate a register for this regvar }
+ tvarsym(regvarinfo^.regvars[i]).localloc.register:=cg.getintregister(exprasmlist,siz);
+ tvarsym(regvarinfo^.regvars[i]).localloc.loc:=LOC_REGISTER;
+ { and make sure it can't be freed }
+{ rg.makeregvarint(getsupreg(regvarinfo^.regvars[i].localloc.register));}
+ end
+ else
+ begin
+ regvarinfo^.regvars[i] := nil;
+ regvarinfo^.regvars_para[i] := false;
+ end;
+ end;
+ end;
+ if ((p.registersfpu+1)<maxfpuvarregs) then
+ begin
+ parasym:=false;
+ symtablestack.foreach_static(searchfpuregvars,@parasym);
+{$ifndef i386}
+ { this code should be never enabled because }
+ { 1. the caller loads parameters into registers }
+ { 2. (later) the CSE loads a parameter into a }
+ { register, if necessary }
+ { (FK) }
+ { copy parameter into a register ? }
+ parasym:=true;
+ symtablestack.next.foreach_static(searchregvars,@parasym);
+{$endif i386}
+ { hold needed registers free }
+
+ { in non leaf procedures we must be very careful }
+ { with assigning registers }
+{$ifdef i386}
+ if aktmaxfpuregisters=-1 then
+ begin
+ if (pi_do_call in current_procinfo.flags) then
+ begin
+ for i:=maxfpuvarregs downto 2 do
+ regvarinfo^.fpuregvars[i]:=nil;
+ end
+ else
+{$endif i386}
+ begin
+ for i:=maxfpuvarregs downto maxfpuvarregs-p.registersfpu do
+ regvarinfo^.fpuregvars[i]:=nil;
+ end;
+{$ifdef i386}
+ end
+ else
+ begin
+ for i:=aktmaxfpuregisters+1 to maxfpuvarregs do
+ regvarinfo^.fpuregvars[i]:=nil;
+ end;
+{$endif i386}
+ { now assign register }
+ for i:=1 to maxfpuvarregs do
+ begin
+ if assigned(regvarinfo^.fpuregvars[i]) then
+ begin
+{$ifdef i386}
+ { reserve place on the FPU stack }
+ {$error fixme x86 fpuregvars}
+{ regvarinfo^.fpuregvars[i].localloc.register:=trgcpu(rg).correct_fpuregister(NR_ST0,i);}
+{$else i386}
+{$ifdef x86_64}
+{$endif x86_64}
+ begin
+ tvarsym(regvarinfo^.fpuregvars[i]).localloc.register:=cg.getfpuregister(exprasmlist,OS_F64);
+ tvarsym(regvarinfo^.fpuregvars[i]).localloc.loc:=LOC_FPUREGISTER;
+{ rg.makeregvarother(regvarinfo^.fpuregvars[i].localloc.register);}
+ end;
+{$endif i386}
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+
+ procedure store_regvar(asml: TAAsmoutput; reg: tregister);
+ var
+ i: longint;
+ cgsize : tcgsize;
+ r : tregister;
+ hr: treference;
+ regvarinfo: pregvarinfo;
+ vsym: tvarsym;
+ regidx : tregisterindex;
+ supreg : tsuperregister;
+ begin
+{$ifdef i386}
+ regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
+ if not assigned(regvarinfo) then
+ exit;
+ if getregtype(reg)=R_INTREGISTER then
+ begin
+ supreg:=getsupreg(reg);
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) and
+ (getsupreg(tvarsym(regvarinfo^.regvars[i]).localloc.register)=supreg) then
+ begin
+ {$warning fixme regvar_loaded_int}
+(* if supreg in rg.regvar_loaded_int then
+ begin
+ vsym := tvarsym(regvarinfo^.regvars[i]);
+ { we only have to store the regvar back to memory if it's }
+ { possible that it's been modified (JM) }
+ if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
+ begin
+{$warning FIXME Check vsym.localloc for regvars}
+// reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
+ cgsize:=def_cgsize(vsym.vartype.def);
+ cg.a_load_reg_ref(asml,cgsize,cgsize,vsym.localloc.register,hr);
+ end;
+ asml.concat(tai_regalloc.dealloc(vsym.localloc.register));
+ exclude(rg.regvar_loaded_int,supreg);
+ end;
+*)
+ break;
+ end;
+ end
+ else
+ begin
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) then
+ begin
+ {$warning fixme regvars}
+(*
+ r:=rg.makeregsize(regvarinfo^.regvars[i].localloc.register,OS_INT);
+ if (r = reg) then
+ begin
+ regidx:=findreg_by_number(r);
+ if rg.regvar_loaded_other[regidx] then
+ begin
+ vsym := tvarsym(regvarinfo^.regvars[i]);
+ { we only have to store the regvar back to memory if it's }
+ { possible that it's been modified (JM) }
+ if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
+ begin
+{$warning FIXME Check vsym.localloc for regvars}
+// reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
+ cgsize:=def_cgsize(vsym.vartype.def);
+ cg.a_load_reg_ref(asml,cgsize,cgsize,vsym.localloc.register,hr);
+ end;
+ asml.concat(tai_regalloc.dealloc(vsym.localloc.register));
+ rg.regvar_loaded_other[regidx] := false;
+ end;
+ break;
+ end;
+*)
+ end;
+ end;
+{$endif i386}
+ end;
+
+ procedure load_regvar(asml: TAAsmoutput; vsym: tvarsym);
+ var
+ hr: treference;
+ opsize: tcgsize;
+ r,
+ reg : tregister;
+ regidx : tregisterindex;
+ begin
+{$ifndef i386}
+ exit;
+{$endif i386}
+ reg:=vsym.localloc.register;
+ {$warning fixme regvars}
+(*
+ if getregtype(reg)=R_INTREGISTER then
+ begin
+
+ if not(getsupreg(reg) in rg.regvar_loaded_int) then
+ begin
+ asml.concat(tai_regalloc.alloc(reg));
+{$warning FIXME Check vsym.localloc for regvars}
+// reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
+ if paramanager.push_addr_param(vsym.varspez,vsym.vartype.def,current_procinfo.procdef.proccalloption) then
+ opsize := OS_ADDR
+ else
+ opsize := def_cgsize(vsym.vartype.def);
+ cg.a_load_ref_reg(asml,opsize,opsize,hr,reg);
+ include(rg.regvar_loaded_int,getsupreg(reg));
+ end;
+ end
+ else
+ begin
+ r:=rg.makeregsize(reg,OS_INT);
+ regidx:=findreg_by_number(r);
+ if not rg.regvar_loaded_other[regidx] then
+ begin
+ asml.concat(tai_regalloc.alloc(reg));
+{$warning FIXME Check vsym.localloc for regvars}
+// reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
+ if paramanager.push_addr_param(vsym.varspez,vsym.vartype.def,current_procinfo.procdef.proccalloption) then
+ opsize := OS_ADDR
+ else
+ opsize := def_cgsize(vsym.vartype.def);
+ cg.a_load_ref_reg(asml,opsize,opsize,hr,reg);
+ rg.regvar_loaded_other[regidx] := true;
+ end;
+ end;
+*)
+ end;
+
+ procedure load_regvar_reg(asml: TAAsmoutput; reg: tregister);
+ var
+ i: longint;
+ regvarinfo: pregvarinfo;
+ reg_spare : tregister;
+ supreg : tsuperregister;
+ begin
+{
+ regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
+ if not assigned(regvarinfo) then
+ exit;
+ if getregtype(reg)=R_INTREGISTER then
+ begin
+ supreg:=getsupreg(reg);
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) and
+ (getsupreg(regvarinfo^.regvars[i].localloc.register) = supreg) then
+ load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
+ end
+ else
+ begin
+ reg_spare := cg.makeregsize(reg,OS_INT);
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) and
+ (cg.makeregsize(regvarinfo^.regvars[i].localloc.register,OS_INT) = reg_spare) then
+ load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
+ end;
+}
+ end;
+
+ procedure load_all_regvars(asml: TAAsmoutput);
+{
+ var
+ i: longint;
+ regvarinfo: pregvarinfo;
+}
+ begin
+{
+ regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
+ if not assigned(regvarinfo) then
+ exit;
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) then
+ load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
+}
+ end;
+
+
+ procedure load_regvars(asml: TAAsmoutput; p: tnode);
+ var
+ i: longint;
+ regvarinfo: pregvarinfo;
+ begin
+ if (cs_regvars in aktglobalswitches) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) then
+ begin
+ regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
+ { can happen when inlining assembler procedures (JM) }
+ if not assigned(regvarinfo) then
+ exit;
+ for i:=1 to maxfpuvarregs do
+ begin
+ if assigned(regvarinfo^.fpuregvars[i]) then
+ begin
+{$ifdef i386}
+ { reserve place on the FPU stack }
+ {$warning fixme fpustack}
+(*
+ regvarinfo^.fpuregvars[i].localloc.register:=trgcpu(rg).correct_fpuregister(NR_ST0,i-1);
+*)
+ asml.concat(Taicpu.op_none(A_FLDZ,S_NO));
+{$endif i386}
+ end;
+ end;
+{$ifdef i386}
+ if assigned(p) then
+ if cs_asm_source in aktglobalswitches then
+ asml.insert(tai_comment.Create(strpnew(tostr(p.registersfpu)+
+ ' registers on FPU stack used by temp. expressions')));
+{$endif i386}
+{
+ for i:=1 to maxfpuvarregs do
+ begin
+ if assigned(regvarinfo^.fpuregvars[i]) then
+ begin
+ if cs_asm_source in aktglobalswitches then
+ asml.insert(tai_comment.Create(strpnew(regvarinfo^.fpuregvars[i].name+
+ ' with weight '+tostr(regvarinfo^.fpuregvars[i].refs)+' assigned to register '+
+ std_regname(regvarinfo^.fpuregvars[i].localloc.register))));
+ if (status.verbosity and v_debug)=v_debug then
+ Message3(cg_d_register_weight,std_regname(regvarinfo^.fpuregvars[i].localloc.register),
+ tostr(regvarinfo^.fpuregvars[i].refs),regvarinfo^.fpuregvars[i].name);
+ end;
+ end;
+ if cs_asm_source in aktglobalswitches then
+ asml.insert(tai_comment.Create(strpnew('Register variable assignment:')));
+}
+ end;
+ end;
+
+{$ifdef i386}
+(*
+ procedure sync_regvars_other(list1, list2: taasmoutput; const regvarsloaded1,
+ regvarsloaded2: regvarother_booleanarray);
+ var
+ counter: tregisterindex;
+ begin
+ for counter := low(rg.regvar_loaded_other) to high(rg.regvar_loaded_other) do
+ begin
+ rg.regvar_loaded_other[counter] := regvarsloaded1[counter] and
+ regvarsloaded2[counter];
+ if regvarsloaded1[counter] xor regvarsloaded2[counter] then
+ if regvarsloaded1[counter] then
+ load_regvar_reg(list2,counter)
+ else
+ load_regvar_reg(list1,counter);
+ end;
+ end;
+
+
+ procedure sync_regvars_int(list1, list2: taasmoutput; const regvarsloaded1,
+ regvarsloaded2: Tsuperregisterset);
+ var
+ i : longint;
+ r : tregister;
+ begin
+ for i:=1 to maxvarregs do
+ begin
+ r:=newreg(R_INTREGISTER,varregs[i],R_SUBWHOLE);
+ if (varregs[i] in regvarsloaded1) and
+ not(varregs[i] in regvarsloaded2) then
+ load_regvar_reg(list2,r)
+ else
+ if (varregs[i] in regvarsloaded2) and
+ not(varregs[i] in regvarsloaded1) then
+ load_regvar_reg(list1,r);
+ end;
+ end;
+*)
+{$endif i386}
+
+
+ procedure cleanup_regvars(asml: TAAsmoutput);
+ var
+ i: longint;
+ reg : tregister;
+ regidx : tregisterindex;
+ begin
+ { can happen when inlining assembler procedures (JM) }
+ if not assigned(current_procinfo.procdef.regvarinfo) then
+ exit;
+ if (cs_regvars in aktglobalswitches) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) then
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ begin
+{$ifdef i386}
+ for i:=1 to maxfpuvarregs do
+ if assigned(fpuregvars[i]) then
+ { ... and clean it up }
+ asml.concat(Taicpu.op_reg(A_FSTP,S_NO,NR_ST0));
+{$endif i386}
+(*
+ for i := 1 to maxvarregs do
+ begin
+ if assigned(regvars[i]) then
+ begin
+ reg:=regvars[i].localloc.register;
+ if getregtype(reg)=R_INTREGISTER then
+ begin
+ end
+ else
+ begin
+ reg:=cg.makeregsize(reg,OS_INT);
+ regidx:=findreg_by_number(reg);
+ {$warning fixme regvar dealloc}
+{
+ if (rg.regvar_loaded_other[regidx]) then
+ asml.concat(tai_regalloc.dealloc(reg));
+}
+ end;
+ end;
+ end;
+*)
+ end;
+ end;
+
+{
+
+ Note: this one can't really be "fixed": register colouring happens after
+ stabs generation. It could still be useful to generate the "var X is
+ assigned to register Y with weight ZZZ" messages though
+
+ procedure translate_regvars(list: taasmoutput);
+ var
+ i: longint;
+ r: tregister;
+ begin
+ if not assigned(current_procinfo.procdef.regvarinfo) then
+ exit;
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ begin
+ for i := 1 to maxvarregs do
+ if assigned(regvars[i]) then
+ begin
+ cg.rg[R_INTREGISTER].translate_register(tvarsym(regvars[i]).localloc.register);
+ r:=tvarsym(regvars[i]).localloc.register;
+ if cs_asm_source in aktglobalswitches then
+ list.insert(tai_comment.Create(strpnew(tvarsym(regvars[i]).name+
+ ' with weight '+tostr(tvarsym(regvars[i]).refs)+' assigned to register '+
+ std_regname(r))));
+ Message3(cg_d_register_weight,std_regname(r),
+ tostr(tvarsym(regvars[i]).refs),tvarsym(regvars[i]).name);
+ end;
+ for i := 1 to maxfpuvarregs do
+ if assigned(fpuregvars[i]) then
+ begin
+ cg.rg[R_FPUREGISTER].translate_register(tvarsym(regvars[i]).localloc.register);
+ r:=tvarsym(fpuregvars[i]).localloc.register;
+ if cs_asm_source in aktglobalswitches then
+ list.insert(tai_comment.Create(strpnew(tvarsym(fpuregvars[i]).name+
+ ' with weight '+tostr(tvarsym(fpuregvars[i]).refs)+' assigned to register '+
+ std_regname(r))));
+ Message3(cg_d_register_weight,std_regname(r),
+ tostr(tvarsym(fpuregvars[i]).refs),tvarsym(fpuregvars[i]).name);
+ end;
+ end;
+ end;
+}
+
+ procedure free_regvars(list: taasmoutput);
+ var
+ i: longint;
+ reg: tregister;
+ size: tcgsize;
+ begin
+ if not assigned(current_procinfo.procdef.regvarinfo) then
+ exit;
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ begin
+ for i := 1 to maxvarregs do
+ if assigned(regvars[i]) then
+ begin
+ reg:=cg.makeregsize(list,tvarsym(regvars[i]).localloc.register,OS_INT);
+ cg.a_load_reg_reg(list,OS_INT,OS_INT,reg,reg);
+ end;
+ for i := 1 to maxfpuvarregs do
+ if assigned(fpuregvars[i]) then
+ begin
+ reg:=tvarsym(fpuregvars[i]).localloc.register;
+ size:=reg_cgsize(reg);
+ cg.a_loadfpu_reg_reg(list,size,reg,reg);
+ end;
+ end;
+ end;
+
+
+{$endif OLDREGVARS}
+
+
+end.
diff --git a/compiler/rgbase.pas b/compiler/rgbase.pas
new file mode 100644
index 0000000000..a3224781ce
--- /dev/null
+++ b/compiler/rgbase.pas
@@ -0,0 +1,80 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Helper routines for register allocator
+
+ 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 rgbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpuBase,cgBase;
+
+ type
+ TRegNameTable = array[tregisterindex] of string[7];
+ TRegisterIndexTable = array[tregisterindex] of tregisterindex;
+
+ function findreg_by_number_table(r:Tregister;const regnumber_index:TRegisterIndexTable):tregisterindex;
+ function findreg_by_name_table(const s:string;const regname_table:TRegNameTable;const regname_index:TRegisterIndexTable):byte;
+
+
+implementation
+
+ function findreg_by_name_table(const s:string;const regname_table:TRegNameTable;const regname_index:TRegisterIndexTable):byte;
+ var
+ i,p,q : tregisterindex;
+ begin
+ p:=Low(tregisterindex);
+ q:=high(tregisterindex);
+ repeat
+ i:=(p+q) shr 1;
+ if s>regname_table[regname_index[i]] then
+ p:=i+1
+ else
+ q:=i;
+ until p=q;
+ if regname_table[regname_index[p]]=s then
+ result:=regname_index[p]
+ else
+ result:=0;
+ end;
+
+
+ function findreg_by_number_table(r:Tregister;const regnumber_index:TRegisterIndexTable):tregisterindex;
+ var
+ i,p,q : longint;
+ begin
+ p:=Low(tregisterindex);
+ q:=high(tregisterindex);
+ repeat
+ i:=(p+q) shr 1;
+ if r>regnumber_table[regnumber_index[i]] then
+ p:=i+1
+ else
+ q:=i;
+ until p=q;
+ if regnumber_table[regnumber_index[p]]=r then
+ result:=regnumber_index[p]
+ else
+ result:=0;
+ end;
+
+end.
diff --git a/compiler/rgobj.pas b/compiler/rgobj.pas
new file mode 100644
index 0000000000..05be21b3c2
--- /dev/null
+++ b/compiler/rgobj.pas
@@ -0,0 +1,2022 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the base class for the register allocator
+
+ 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.
+ ****************************************************************************
+}
+
+{$i fpcdefs.inc}
+
+{ Allow duplicate allocations, can be used to get the .s file written }
+{ $define ALLOWDUPREG}
+
+
+unit rgobj;
+
+ interface
+
+ uses
+ cutils, cpubase,
+ aasmbase,aasmtai,aasmcpu,
+ cclasses,globtype,cgbase,cgutils,
+ cpuinfo
+ ;
+
+ type
+ {
+ The interference bitmap contains of 2 layers:
+ layer 1 - 256*256 blocks with pointers to layer 2 blocks
+ layer 2 - blocks of 32*256 (32 bytes = 256 bits)
+ }
+ Tinterferencebitmap2 = array[byte] of set of byte;
+ Pinterferencebitmap2 = ^Tinterferencebitmap2;
+ Tinterferencebitmap1 = array[byte] of Pinterferencebitmap2;
+ pinterferencebitmap1 = ^tinterferencebitmap1;
+
+ Tinterferencebitmap=class
+ private
+ maxx1,
+ maxy1 : byte;
+ fbitmap : pinterferencebitmap1;
+ function getbitmap(x,y:tsuperregister):boolean;
+ procedure setbitmap(x,y:tsuperregister;b:boolean);
+ public
+ constructor create;
+ destructor destroy;override;
+ property bitmap[x,y:tsuperregister]:boolean read getbitmap write setbitmap;default;
+ end;
+
+ Tmovelistheader=record
+ count,
+ maxcount,
+ sorted_until : cardinal;
+ end;
+
+ Tmovelist=record
+ header : Tmovelistheader;
+ data : array[tsuperregister] of Tlinkedlistitem;
+ end;
+ Pmovelist=^Tmovelist;
+
+ {In the register allocator we keep track of move instructions.
+ These instructions are moved between five linked lists. There
+ is also a linked list per register to keep track about the moves
+ it is associated with. Because we need to determine quickly in
+ which of the five lists it is we add anu enumeradtion to each
+ move instruction.}
+
+ Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
+ ms_worklist_moves,ms_active_moves);
+ Tmoveins=class(Tlinkedlistitem)
+ moveset:Tmoveset;
+ x,y:Tsuperregister;
+ end;
+
+ Treginfoflag=(ri_coalesced,ri_selected);
+ Treginfoflagset=set of Treginfoflag;
+
+ Treginfo=record
+ live_start,
+ live_end : Tai;
+ subreg : tsubregister;
+ alias : Tsuperregister;
+ { The register allocator assigns each register a colour }
+ colour : Tsuperregister;
+ movelist : Pmovelist;
+ adjlist : Psuperregisterworklist;
+ degree : TSuperregister;
+ flags : Treginfoflagset;
+ end;
+ Preginfo=^TReginfo;
+
+ tspillreginfo = record
+ spillreg : tregister;
+ orgreg : tsuperregister;
+ tempreg : tregister;
+ regread,regwritten, mustbespilled: boolean;
+ end;
+ tspillregsinfo = array[0..2] of tspillreginfo;
+
+ {#------------------------------------------------------------------
+
+ This class implements the default register allocator. It is used by the
+ code generator to allocate and free registers which might be valid
+ across nodes. It also contains utility routines related to registers.
+
+ Some of the methods in this class should be overriden
+ by cpu-specific implementations.
+
+ --------------------------------------------------------------------}
+ trgobj=class
+ preserved_by_proc : tcpuregisterset;
+ used_in_proc : tcpuregisterset;
+
+ constructor create(Aregtype:Tregistertype;
+ Adefaultsub:Tsubregister;
+ const Ausable:array of tsuperregister;
+ Afirst_imaginary:Tsuperregister;
+ Apreserved_by_proc:Tcpuregisterset);
+ destructor destroy;override;
+
+ {# Allocate a register. An internalerror will be generated if there is
+ no more free registers which can be allocated.}
+ function getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;virtual;
+ {# Get the register specified.}
+ procedure getcpuregister(list:Taasmoutput;r:Tregister);virtual;
+ procedure ungetcpuregister(list:Taasmoutput;r:Tregister);virtual;
+ {# Get multiple registers specified.}
+ procedure alloccpuregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;
+ {# Free multiple registers specified.}
+ procedure dealloccpuregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;
+ function uses_registers:boolean;virtual;
+ procedure add_reg_instruction(instr:Tai;r:tregister);
+ procedure add_move_instruction(instr:Taicpu);
+ {# Do the register allocation.}
+ procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
+ { Adds an interference edge.
+ don't move this to the protected section, the arm cg requires to access this (FK) }
+ procedure add_edge(u,v:Tsuperregister);
+ protected
+ regtype : Tregistertype;
+ { default subregister used }
+ defaultsub : tsubregister;
+ live_registers:Tsuperregisterworklist;
+ { can be overriden to add cpu specific interferences }
+ procedure add_cpu_interferences(p : tai);virtual;
+ procedure add_constraints(reg:Tregister);virtual;
+ function getregisterinline(list:Taasmoutput;subreg:Tsubregister):Tregister;
+ procedure ungetregisterinline(list:Taasmoutput;r:Tregister);
+ function get_spill_subreg(r : tregister) : tsubregister;virtual;
+ function do_spill_replace(list:Taasmoutput;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;virtual;
+ procedure do_spill_read(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);virtual;
+ procedure do_spill_written(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);virtual;
+
+ function instr_spill_register(list:Taasmoutput;
+ instr:taicpu;
+ const r:Tsuperregisterset;
+ const spilltemplist:Tspill_temp_list): boolean;virtual;
+ private
+ {# First imaginary register.}
+ first_imaginary : Tsuperregister;
+ {# Highest register allocated until now.}
+ reginfo : PReginfo;
+ maxreginfo,
+ maxreginfoinc,
+ maxreg : Tsuperregister;
+ usable_registers_cnt : word;
+ usable_registers : array[0..maxcpuregister-1] of tsuperregister;
+ ibitmap : Tinterferencebitmap;
+ spillednodes,
+ simplifyworklist,
+ freezeworklist,
+ spillworklist,
+ coalescednodes,
+ selectstack : tsuperregisterworklist;
+ worklist_moves,
+ active_moves,
+ frozen_moves,
+ coalesced_moves,
+ constrained_moves : Tlinkedlist;
+{$ifdef EXTDEBUG}
+ procedure writegraph(loopidx:longint);
+{$endif EXTDEBUG}
+ {# Disposes of the reginfo array.}
+ procedure dispose_reginfo;
+ {# Prepare the register colouring.}
+ procedure prepare_colouring;
+ {# Clean up after register colouring.}
+ procedure epilogue_colouring;
+ {# Colour the registers; that is do the register allocation.}
+ procedure colour_registers;
+ procedure insert_regalloc_info(list:Taasmoutput;u:tsuperregister);
+ procedure insert_regalloc_info_all(list:Taasmoutput);
+ procedure generate_interference_graph(list:Taasmoutput;headertai:tai);
+ procedure translate_registers(list:Taasmoutput);
+ function spill_registers(list:Taasmoutput;headertai:tai):boolean;virtual;
+ function getnewreg(subreg:tsubregister):tsuperregister;
+ procedure add_edges_used(u:Tsuperregister);
+ procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
+ function move_related(n:Tsuperregister):boolean;
+ procedure make_work_list;
+ procedure sort_simplify_worklist;
+ procedure enable_moves(n:Tsuperregister);
+ procedure decrement_degree(m:Tsuperregister);
+ procedure simplify;
+ function get_alias(n:Tsuperregister):Tsuperregister;
+ procedure add_worklist(u:Tsuperregister);
+ function adjacent_ok(u,v:Tsuperregister):boolean;
+ function conservative(u,v:Tsuperregister):boolean;
+ procedure combine(u,v:Tsuperregister);
+ procedure coalesce;
+ procedure freeze_moves(u:Tsuperregister);
+ procedure freeze;
+ procedure select_spill;
+ procedure assign_colours;
+ procedure clear_interferences(u:Tsuperregister);
+ end;
+
+ const
+ first_reg = 0;
+ last_reg = high(tsuperregister)-1;
+ maxspillingcounter = 20;
+
+
+ implementation
+
+ uses
+ systems,
+ globals,verbose,tgobj,procinfo;
+
+
+ procedure sort_movelist(ml:Pmovelist);
+
+ {Ok, sorting pointers is silly, but it does the job to make Trgobj.combine
+ faster.}
+
+ var h,i,p:word;
+ t:Tlinkedlistitem;
+
+ begin
+ with ml^ do
+ begin
+ if header.count<2 then
+ exit;
+ p:=1;
+ while 2*p<header.count do
+ p:=2*p;
+ while p<>0 do
+ begin
+ for h:=p to header.count-1 do
+ begin
+ i:=h;
+ t:=data[i];
+ repeat
+ if ptrint(data[i-p])<=ptrint(t) then
+ break;
+ data[i]:=data[i-p];
+ dec(i,p);
+ until i<p;
+ data[i]:=t;
+ end;
+ p:=p shr 1;
+ end;
+ header.sorted_until:=header.count-1;
+ end;
+ end;
+
+{******************************************************************************
+ tinterferencebitmap
+******************************************************************************}
+
+ constructor tinterferencebitmap.create;
+ begin
+ inherited create;
+ maxx1:=1;
+ getmem(fbitmap,sizeof(tinterferencebitmap1)*2);
+ fillchar(fbitmap^,sizeof(tinterferencebitmap1)*2,0);
+ end;
+
+
+ destructor tinterferencebitmap.destroy;
+
+ var i,j:byte;
+
+ begin
+ for i:=0 to maxx1 do
+ for j:=0 to maxy1 do
+ if assigned(fbitmap[i,j]) then
+ dispose(fbitmap[i,j]);
+ freemem(fbitmap);
+ end;
+
+
+ function tinterferencebitmap.getbitmap(x,y:tsuperregister):boolean;
+ var
+ page : pinterferencebitmap2;
+ begin
+ result:=false;
+ if (x shr 8>maxx1) then
+ exit;
+ page:=fbitmap[x shr 8,y shr 8];
+ result:=assigned(page) and
+ ((x and $ff) in page^[y and $ff]);
+ end;
+
+
+ procedure tinterferencebitmap.setbitmap(x,y:tsuperregister;b:boolean);
+ var
+ x1,y1 : byte;
+ begin
+ x1:=x shr 8;
+ y1:=y shr 8;
+ if x1>maxx1 then
+ begin
+ reallocmem(fbitmap,sizeof(tinterferencebitmap1)*(x1+1));
+ fillchar(fbitmap[maxx1+1],sizeof(tinterferencebitmap1)*(x1-maxx1),0);
+ maxx1:=x1;
+ end;
+ if not assigned(fbitmap[x1,y1]) then
+ begin
+ if y1>maxy1 then
+ maxy1:=y1;
+ new(fbitmap[x1,y1]);
+ fillchar(fbitmap[x1,y1]^,sizeof(tinterferencebitmap2),0);
+ end;
+ if b then
+ include(fbitmap[x1,y1]^[y and $ff],(x and $ff))
+ else
+ exclude(fbitmap[x1,y1]^[y and $ff],(x and $ff));
+ end;
+
+
+{******************************************************************************
+ trgobj
+******************************************************************************}
+
+ constructor trgobj.create(Aregtype:Tregistertype;
+ Adefaultsub:Tsubregister;
+ const Ausable:array of tsuperregister;
+ Afirst_imaginary:Tsuperregister;
+ Apreserved_by_proc:Tcpuregisterset);
+ var
+ i : Tsuperregister;
+ begin
+ { empty super register sets can cause very strange problems }
+ if high(Ausable)=0 then
+ internalerror(200210181);
+ first_imaginary:=Afirst_imaginary;
+ maxreg:=Afirst_imaginary;
+ regtype:=Aregtype;
+ defaultsub:=Adefaultsub;
+ preserved_by_proc:=Apreserved_by_proc;
+ used_in_proc:=[];
+ live_registers.init;
+ { Get reginfo for CPU registers }
+ maxreginfo:=first_imaginary;
+ maxreginfoinc:=16;
+ worklist_moves:=Tlinkedlist.create;
+ reginfo:=allocmem(first_imaginary*sizeof(treginfo));
+ for i:=0 to first_imaginary-1 do
+ begin
+ reginfo[i].degree:=high(tsuperregister);
+ reginfo[i].alias:=RS_INVALID;
+ end;
+ { Usable registers }
+ fillchar(usable_registers,sizeof(usable_registers),0);
+ for i:=low(Ausable) to high(Ausable) do
+ usable_registers[i]:=Ausable[i];
+ usable_registers_cnt:=high(Ausable)+1;
+ { Initialize Worklists }
+ spillednodes.init;
+ simplifyworklist.init;
+ freezeworklist.init;
+ spillworklist.init;
+ coalescednodes.init;
+ selectstack.init;
+ end;
+
+ destructor trgobj.destroy;
+
+ begin
+ spillednodes.done;
+ simplifyworklist.done;
+ freezeworklist.done;
+ spillworklist.done;
+ coalescednodes.done;
+ selectstack.done;
+ live_registers.done;
+ worklist_moves.free;
+ dispose_reginfo;
+ end;
+
+ procedure Trgobj.dispose_reginfo;
+
+ var i:Tsuperregister;
+
+ begin
+ if reginfo<>nil then
+ begin
+ for i:=0 to maxreg-1 do
+ with reginfo[i] do
+ begin
+ if adjlist<>nil then
+ dispose(adjlist,done);
+ if movelist<>nil then
+ dispose(movelist);
+ end;
+ freemem(reginfo);
+ reginfo:=nil;
+ end;
+ end;
+
+ function trgobj.getnewreg(subreg:tsubregister):tsuperregister;
+ var
+ oldmaxreginfo : tsuperregister;
+ begin
+ result:=maxreg;
+ inc(maxreg);
+ if maxreg>=last_reg then
+ Message(parser_f_too_complex_proc);
+ if maxreg>=maxreginfo then
+ begin
+ oldmaxreginfo:=maxreginfo;
+ { Prevent overflow }
+ if maxreginfoinc>last_reg-maxreginfo then
+ maxreginfo:=last_reg
+ else
+ begin
+ inc(maxreginfo,maxreginfoinc);
+ if maxreginfoinc<256 then
+ maxreginfoinc:=maxreginfoinc*2;
+ end;
+ reallocmem(reginfo,maxreginfo*sizeof(treginfo));
+ { Do we really need it to clear it ? At least for 1.0.x (PFV) }
+ fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
+ end;
+ reginfo[result].subreg:=subreg;
+ end;
+
+
+ function trgobj.getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;
+ begin
+ {$ifdef EXTDEBUG}
+ if reginfo=nil then
+ InternalError(2004020901);
+ {$endif EXTDEBUG}
+ if defaultsub=R_SUBNONE then
+ result:=newreg(regtype,getnewreg(R_SUBNONE),R_SUBNONE)
+ else
+ result:=newreg(regtype,getnewreg(subreg),subreg);
+ end;
+
+
+ function trgobj.uses_registers:boolean;
+ begin
+ result:=(maxreg>first_imaginary);
+ end;
+
+
+ procedure trgobj.ungetcpuregister(list:Taasmoutput;r:Tregister);
+ begin
+ if (getsupreg(r)>=first_imaginary) then
+ InternalError(2004020901);
+ list.concat(Tai_regalloc.dealloc(r,nil));
+ end;
+
+
+ procedure trgobj.getcpuregister(list:Taasmoutput;r:Tregister);
+ var
+ supreg:Tsuperregister;
+ begin
+ supreg:=getsupreg(r);
+ if supreg>=first_imaginary then
+ internalerror(2003121503);
+ include(used_in_proc,supreg);
+ list.concat(Tai_regalloc.alloc(r,nil));
+ end;
+
+
+ procedure trgobj.alloccpuregisters(list:Taasmoutput;r:Tcpuregisterset);
+
+ var i:Tsuperregister;
+
+ begin
+ for i:=0 to first_imaginary-1 do
+ if i in r then
+ getcpuregister(list,newreg(regtype,i,defaultsub));
+ end;
+
+
+ procedure trgobj.dealloccpuregisters(list:Taasmoutput;r:Tcpuregisterset);
+
+ var i:Tsuperregister;
+
+ begin
+ for i:=0 to first_imaginary-1 do
+ if i in r then
+ ungetcpuregister(list,newreg(regtype,i,defaultsub));
+ end;
+
+
+ procedure trgobj.do_register_allocation(list:Taasmoutput;headertai:tai);
+ var
+ spillingcounter:byte;
+ endspill:boolean;
+ begin
+ { Insert regalloc info for imaginary registers }
+ insert_regalloc_info_all(list);
+ ibitmap:=tinterferencebitmap.create;
+ generate_interference_graph(list,headertai);
+ { Don't do the real allocation when -sr is passed }
+ if (cs_no_regalloc in aktglobalswitches) then
+ exit;
+ {Do register allocation.}
+ spillingcounter:=0;
+ repeat
+ prepare_colouring;
+ colour_registers;
+ epilogue_colouring;
+ endspill:=true;
+ if spillednodes.length<>0 then
+ begin
+ inc(spillingcounter);
+ if spillingcounter>maxspillingcounter then
+ begin
+{$ifdef EXTDEBUG}
+ { Only exit here so the .s file is still generated. Assembling
+ the file will still trigger an error }
+ exit;
+{$else}
+ internalerror(200309041);
+{$endif}
+ end;
+ endspill:=not spill_registers(list,headertai);
+ end;
+ until endspill;
+ ibitmap.free;
+ translate_registers(list);
+ dispose_reginfo;
+ end;
+
+
+ procedure trgobj.add_constraints(reg:Tregister);
+
+ begin
+ end;
+
+
+ procedure trgobj.add_edge(u,v:Tsuperregister);
+
+ {This procedure will add an edge to the virtual interference graph.}
+
+ procedure addadj(u,v:Tsuperregister);
+
+ begin
+ with reginfo[u] do
+ begin
+ if adjlist=nil then
+ new(adjlist,init);
+ adjlist^.add(v);
+ end;
+ end;
+
+ begin
+ if (u<>v) and not(ibitmap[v,u]) then
+ begin
+ ibitmap[v,u]:=true;
+ ibitmap[u,v]:=true;
+ {Precoloured nodes are not stored in the interference graph.}
+ if (u>=first_imaginary) then
+ addadj(u,v);
+ if (v>=first_imaginary) then
+ addadj(v,u);
+ end;
+ end;
+
+
+ procedure trgobj.add_edges_used(u:Tsuperregister);
+
+ var i:word;
+
+ begin
+ with live_registers do
+ if length>0 then
+ for i:=0 to length-1 do
+ add_edge(u,get_alias(buf^[i]));
+ end;
+
+{$ifdef EXTDEBUG}
+ procedure trgobj.writegraph(loopidx:longint);
+
+ {This procedure writes out the current interference graph in the
+ register allocator.}
+
+
+ var f:text;
+ i,j:Tsuperregister;
+
+ begin
+ assign(f,'igraph'+tostr(loopidx));
+ rewrite(f);
+ writeln(f,'Interference graph');
+ writeln(f);
+ write(f,' ');
+ for i:=0 to 15 do
+ for j:=0 to 15 do
+ write(f,hexstr(i,1));
+ writeln(f);
+ write(f,' ');
+ for i:=0 to 15 do
+ write(f,'0123456789ABCDEF');
+ writeln(f);
+ for i:=0 to maxreg-1 do
+ begin
+ write(f,hexstr(i,2):4);
+ for j:=0 to maxreg-1 do
+ if ibitmap[i,j] then
+ write(f,'*')
+ else
+ write(f,'-');
+ writeln(f);
+ end;
+ close(f);
+ end;
+{$endif EXTDEBUG}
+
+ procedure trgobj.add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
+ begin
+ with reginfo[u] do
+ begin
+ if movelist=nil then
+ begin
+ getmem(movelist,sizeof(tmovelistheader)+60*sizeof(pointer));
+ movelist^.header.maxcount:=60;
+ movelist^.header.count:=0;
+ movelist^.header.sorted_until:=0;
+ end
+ else
+ begin
+ if movelist^.header.count>=movelist^.header.maxcount then
+ begin
+ movelist^.header.maxcount:=movelist^.header.maxcount*2;
+ reallocmem(movelist,sizeof(tmovelistheader)+movelist^.header.maxcount*sizeof(pointer));
+ end;
+ end;
+ movelist^.data[movelist^.header.count]:=data;
+ inc(movelist^.header.count);
+ end;
+ end;
+
+
+ procedure trgobj.add_reg_instruction(instr:Tai;r:tregister);
+ var
+ supreg : tsuperregister;
+ begin
+ supreg:=getsupreg(r);
+{$ifdef extdebug}
+ if supreg>=maxreginfo then
+ internalerror(200411061);
+{$endif extdebug}
+ if supreg>=first_imaginary then
+ with reginfo[supreg] do
+ begin
+ if not assigned(live_start) then
+ live_start:=instr;
+ live_end:=instr;
+ end;
+ end;
+
+
+ procedure trgobj.add_move_instruction(instr:Taicpu);
+
+ {This procedure notifies a certain as a move instruction so the
+ register allocator can try to eliminate it.}
+
+ var i:Tmoveins;
+ ssupreg,dsupreg:Tsuperregister;
+
+ begin
+ {$ifdef extdebug}
+ if (instr.oper[O_MOV_SOURCE]^.typ<>top_reg) or
+ (instr.oper[O_MOV_DEST]^.typ<>top_reg) then
+ internalerror(200311291);
+ {$endif}
+ i:=Tmoveins.create;
+ i.moveset:=ms_worklist_moves;
+ worklist_moves.insert(i);
+ ssupreg:=getsupreg(instr.oper[O_MOV_SOURCE]^.reg);
+ add_to_movelist(ssupreg,i);
+ dsupreg:=getsupreg(instr.oper[O_MOV_DEST]^.reg);
+ if ssupreg<>dsupreg then
+ {Avoid adding the same move instruction twice to a single register.}
+ add_to_movelist(dsupreg,i);
+ i.x:=ssupreg;
+ i.y:=dsupreg;
+ end;
+
+ function trgobj.move_related(n:Tsuperregister):boolean;
+
+ var i:cardinal;
+
+ begin
+ move_related:=false;
+ with reginfo[n] do
+ if movelist<>nil then
+ with movelist^ do
+ for i:=0 to header.count-1 do
+ if Tmoveins(data[i]).moveset in [ms_worklist_moves,ms_active_moves] then
+ begin
+ move_related:=true;
+ break;
+ end;
+ end;
+
+ procedure Trgobj.sort_simplify_worklist;
+
+ {Sorts the simplifyworklist by the number of interferences the
+ registers in it cause. This allows simplify to execute in
+ constant time.}
+
+ var p,h,i,leni,lent:word;
+ t:Tsuperregister;
+ adji,adjt:Psuperregisterworklist;
+
+ begin
+ with simplifyworklist do
+ begin
+ if length<2 then
+ exit;
+ p:=1;
+ while 2*p<length do
+ p:=2*p;
+ while p<>0 do
+ begin
+ for h:=p to length-1 do
+ begin
+ i:=h;
+ t:=buf^[i];
+ adjt:=reginfo[buf^[i]].adjlist;
+ lent:=0;
+ if adjt<>nil then
+ lent:=adjt^.length;
+ repeat
+ adji:=reginfo[buf^[i-p]].adjlist;
+ leni:=0;
+ if adji<>nil then
+ leni:=adji^.length;
+ if leni<=lent then
+ break;
+ buf^[i]:=buf^[i-p];
+ dec(i,p)
+ until i<p;
+ buf^[i]:=t;
+ end;
+ p:=p shr 1;
+ end;
+ end;
+ end;
+
+ procedure trgobj.make_work_list;
+
+ var n:Tsuperregister;
+
+ begin
+ {If we have 7 cpu registers, and the degree of a node is 7, we cannot
+ assign it to any of the registers, thus it is significant.}
+ for n:=first_imaginary to maxreg-1 do
+ with reginfo[n] do
+ begin
+ if adjlist=nil then
+ degree:=0
+ else
+ degree:=adjlist^.length;
+ if degree>=usable_registers_cnt then
+ spillworklist.add(n)
+ else if move_related(n) then
+ freezeworklist.add(n)
+ else
+ simplifyworklist.add(n);
+ end;
+ sort_simplify_worklist;
+ end;
+
+
+ procedure trgobj.prepare_colouring;
+ begin
+ make_work_list;
+ active_moves:=Tlinkedlist.create;
+ frozen_moves:=Tlinkedlist.create;
+ coalesced_moves:=Tlinkedlist.create;
+ constrained_moves:=Tlinkedlist.create;
+ selectstack.clear;
+ end;
+
+ procedure trgobj.enable_moves(n:Tsuperregister);
+
+ var m:Tlinkedlistitem;
+ i:cardinal;
+
+ begin
+ with reginfo[n] do
+ if movelist<>nil then
+ for i:=0 to movelist^.header.count-1 do
+ begin
+ m:=movelist^.data[i];
+ if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
+ if Tmoveins(m).moveset=ms_active_moves then
+ begin
+ {Move m from the set active_moves to the set worklist_moves.}
+ active_moves.remove(m);
+ Tmoveins(m).moveset:=ms_worklist_moves;
+ worklist_moves.concat(m);
+ end;
+ end;
+ end;
+
+ procedure Trgobj.decrement_degree(m:Tsuperregister);
+
+ var adj : Psuperregisterworklist;
+ n : tsuperregister;
+ d,i : word;
+
+ begin
+ with reginfo[m] do
+ begin
+ d:=degree;
+ if d=0 then
+ internalerror(200312151);
+ dec(degree);
+ if d=usable_registers_cnt then
+ begin
+ {Enable moves for m.}
+ enable_moves(m);
+ {Enable moves for adjacent.}
+ adj:=adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if reginfo[n].flags*[ri_selected,ri_coalesced]<>[] then
+ enable_moves(n);
+ end;
+ {Remove the node from the spillworklist.}
+ if not spillworklist.delete(m) then
+ internalerror(200310145);
+
+ if move_related(m) then
+ freezeworklist.add(m)
+ else
+ simplifyworklist.add(m);
+ end;
+ end;
+ end;
+
+ procedure trgobj.simplify;
+
+ var adj : Psuperregisterworklist;
+ m,n : Tsuperregister;
+ i : word;
+ begin
+ {We take the element with the least interferences out of the
+ simplifyworklist. Since the simplifyworklist is now sorted, we
+ no longer need to search, but we can simply take the first element.}
+ m:=simplifyworklist.get;
+
+ {Push it on the selectstack.}
+ selectstack.add(m);
+ with reginfo[m] do
+ begin
+ include(flags,ri_selected);
+ adj:=adjlist;
+ end;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if (n>=first_imaginary) and
+ (reginfo[n].flags*[ri_selected,ri_coalesced]=[]) then
+ decrement_degree(n);
+ end;
+ end;
+
+ function trgobj.get_alias(n:Tsuperregister):Tsuperregister;
+
+ begin
+ while ri_coalesced in reginfo[n].flags do
+ n:=reginfo[n].alias;
+ get_alias:=n;
+ end;
+
+ procedure trgobj.add_worklist(u:Tsuperregister);
+ begin
+ if (u>=first_imaginary) and
+ (not move_related(u)) and
+ (reginfo[u].degree<usable_registers_cnt) then
+ begin
+ if not freezeworklist.delete(u) then
+ internalerror(200308161); {must be found}
+ simplifyworklist.add(u);
+ end;
+ end;
+
+
+ function trgobj.adjacent_ok(u,v:Tsuperregister):boolean;
+
+ {Check wether u and v should be coalesced. u is precoloured.}
+
+ function ok(t,r:Tsuperregister):boolean;
+
+ begin
+ ok:=(t<first_imaginary) or
+ (reginfo[t].degree<usable_registers_cnt) or
+ ibitmap[r,t];
+ end;
+
+ var adj : Psuperregisterworklist;
+ i : word;
+ n : tsuperregister;
+
+ begin
+ with reginfo[v] do
+ begin
+ adjacent_ok:=true;
+ adj:=adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if (flags*[ri_coalesced,ri_selected]=[]) and not ok(n,u) then
+ begin
+ adjacent_ok:=false;
+ break;
+ end;
+ end;
+ end;
+ end;
+
+ function trgobj.conservative(u,v:Tsuperregister):boolean;
+
+ var adj : Psuperregisterworklist;
+ done : Tsuperregisterset; {To prevent that we count nodes twice.}
+ i,k:word;
+ n : tsuperregister;
+
+ begin
+ k:=0;
+ supregset_reset(done,false,maxreg);
+ with reginfo[u] do
+ begin
+ adj:=adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if flags*[ri_coalesced,ri_selected]=[] then
+ begin
+ supregset_include(done,n);
+ if reginfo[n].degree>=usable_registers_cnt then
+ inc(k);
+ end;
+ end;
+ end;
+ adj:=reginfo[v].adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if not supregset_in(done,n) and
+ (reginfo[n].degree>=usable_registers_cnt) and
+ (reginfo[u].flags*[ri_coalesced,ri_selected]=[]) then
+ inc(k);
+ end;
+ conservative:=(k<usable_registers_cnt);
+ end;
+
+
+ procedure trgobj.combine(u,v:Tsuperregister);
+
+ var adj : Psuperregisterworklist;
+ i,n,p,q:cardinal;
+ t : tsuperregister;
+ searched:Tlinkedlistitem;
+
+ label l1;
+
+ begin
+ if not freezeworklist.delete(v) then
+ spillworklist.delete(v);
+ coalescednodes.add(v);
+ include(reginfo[v].flags,ri_coalesced);
+ reginfo[v].alias:=u;
+
+ {Combine both movelists. Since the movelists are sets, only add
+ elements that are not already present. The movelists cannot be
+ empty by definition; nodes are only coalesced if there is a move
+ between them. To prevent quadratic time blowup (movelists of
+ especially machine registers can get very large because of moves
+ generated during calls) we need to go into disgusting complexity.
+
+ (See webtbs/tw2242 for an example that stresses this.)
+
+ We want to sort the movelist to be able to search logarithmically.
+ Unfortunately, sorting the movelist every time before searching
+ is counter-productive, since the movelist usually grows with a few
+ items at a time. Therefore, we split the movelist into a sorted
+ and an unsorted part and search through both. If the unsorted part
+ becomes too large, we sort.}
+ if assigned(reginfo[u].movelist) then
+ begin
+ {We have to weigh the cost of sorting the list against searching
+ the cost of the unsorted part. I use factor of 8 here; if the
+ number of items is less than 8 times the numer of unsorted items,
+ we'll sort the list.}
+ with reginfo[u].movelist^ do
+ if header.count<8*(header.count-header.sorted_until) then
+ sort_movelist(reginfo[u].movelist);
+
+ if assigned(reginfo[v].movelist) then
+ begin
+ for n:=0 to reginfo[v].movelist^.header.count-1 do
+ begin
+ {Binary search the sorted part of the list.}
+ searched:=reginfo[v].movelist^.data[n];
+ p:=0;
+ q:=reginfo[u].movelist^.header.sorted_until;
+ i:=0;
+ if q<>0 then
+ repeat
+ i:=(p+q) shr 1;
+ if ptrint(searched)>ptrint(reginfo[u].movelist^.data[i]) then
+ p:=i+1
+ else
+ q:=i;
+ until p=q;
+ with reginfo[u].movelist^ do
+ if searched<>data[i] then
+ begin
+ {Linear search the unsorted part of the list.}
+ for i:=header.sorted_until+1 to header.count-1 do
+ if searched=data[i] then
+ goto l1;
+ {Not found -> add}
+ add_to_movelist(u,searched);
+ l1:
+ end;
+ end;
+ end;
+ end;
+
+ enable_moves(v);
+
+ adj:=reginfo[v].adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ t:=adj^.buf^[i-1];
+ with reginfo[t] do
+ if not(ri_coalesced in flags) then
+ begin
+ {t has a connection to v. Since we are adding v to u, we
+ need to connect t to u. However, beware if t was already
+ connected to u...}
+ if (ibitmap[t,u]) and not (ri_selected in flags) then
+ {... because in that case, we are actually removing an edge
+ and the degree of t decreases.}
+ decrement_degree(t)
+ else
+ begin
+ add_edge(t,u);
+ {We have added an edge to t and u. So their degree increases.
+ However, v is added to u. That means its neighbours will
+ no longer point to v, but to u instead. Therefore, only the
+ degree of u increases.}
+ if (u>=first_imaginary) and not (ri_selected in flags) then
+ inc(reginfo[u].degree);
+ end;
+ end;
+ end;
+ if (reginfo[u].degree>=usable_registers_cnt) and freezeworklist.delete(u) then
+ spillworklist.add(u);
+ end;
+
+
+ procedure trgobj.coalesce;
+
+ var m:Tmoveins;
+ x,y,u,v:Tsuperregister;
+
+ begin
+ m:=Tmoveins(worklist_moves.getfirst);
+ x:=get_alias(m.x);
+ y:=get_alias(m.y);
+ if (y<first_imaginary) then
+ begin
+ u:=y;
+ v:=x;
+ end
+ else
+ begin
+ u:=x;
+ v:=y;
+ end;
+ if (u=v) then
+ begin
+ m.moveset:=ms_coalesced_moves; {Already coalesced.}
+ coalesced_moves.insert(m);
+ add_worklist(u);
+ end
+ {Do u and v interfere? In that case the move is constrained. Two
+ precoloured nodes interfere allways. If v is precoloured, by the above
+ code u is precoloured, thus interference...}
+ else if (v<first_imaginary) or ibitmap[u,v] then
+ begin
+ m.moveset:=ms_constrained_moves; {Cannot coalesce yet...}
+ constrained_moves.insert(m);
+ add_worklist(u);
+ add_worklist(v);
+ end
+ {Next test: is it possible and a good idea to coalesce??}
+ else if ((u<first_imaginary) and adjacent_ok(u,v)) or
+ ((u>=first_imaginary) and conservative(u,v)) then
+ begin
+ m.moveset:=ms_coalesced_moves; {Move coalesced!}
+ coalesced_moves.insert(m);
+ combine(u,v);
+ add_worklist(u);
+ end
+ else
+ begin
+ m.moveset:=ms_active_moves;
+ active_moves.insert(m);
+ end;
+ end;
+
+ procedure trgobj.freeze_moves(u:Tsuperregister);
+
+ var i:cardinal;
+ m:Tlinkedlistitem;
+ v,x,y:Tsuperregister;
+
+ begin
+ if reginfo[u].movelist<>nil then
+ for i:=0 to reginfo[u].movelist^.header.count-1 do
+ begin
+ m:=reginfo[u].movelist^.data[i];
+ if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
+ begin
+ x:=Tmoveins(m).x;
+ y:=Tmoveins(m).y;
+ if get_alias(y)=get_alias(u) then
+ v:=get_alias(x)
+ else
+ v:=get_alias(y);
+ {Move m from active_moves/worklist_moves to frozen_moves.}
+ if Tmoveins(m).moveset=ms_active_moves then
+ active_moves.remove(m)
+ else
+ worklist_moves.remove(m);
+ Tmoveins(m).moveset:=ms_frozen_moves;
+ frozen_moves.insert(m);
+
+ if (v>=first_imaginary) and not(move_related(v)) and
+ (reginfo[v].degree<usable_registers_cnt) then
+ begin
+ freezeworklist.delete(v);
+ simplifyworklist.add(v);
+ end;
+ end;
+ end;
+ end;
+
+ procedure trgobj.freeze;
+
+ var n:Tsuperregister;
+
+ begin
+ { We need to take a random element out of the freezeworklist. We take
+ the last element. Dirty code! }
+ n:=freezeworklist.get;
+ {Add it to the simplifyworklist.}
+ simplifyworklist.add(n);
+ freeze_moves(n);
+ end;
+
+ procedure trgobj.select_spill;
+
+ var
+ n : tsuperregister;
+ adj : psuperregisterworklist;
+ max,p,i:word;
+
+ begin
+ { We must look for the element with the most interferences in the
+ spillworklist. This is required because those registers are creating
+ the most conflicts and keeping them in a register will not reduce the
+ complexity and even can cause the help registers for the spilling code
+ to get too much conflicts with the result that the spilling code
+ will never converge (PFV) }
+ max:=0;
+ p:=0;
+ with spillworklist do
+ begin
+ {Safe: This procedure is only called if length<>0}
+ for i:=0 to length-1 do
+ begin
+ adj:=reginfo[buf^[i]].adjlist;
+ if assigned(adj) and (adj^.length>max) then
+ begin
+ p:=i;
+ max:=adj^.length;
+ end;
+ end;
+ n:=buf^[p];
+ deleteidx(p);
+ end;
+
+ simplifyworklist.add(n);
+ freeze_moves(n);
+ end;
+
+ procedure trgobj.assign_colours;
+
+ {Assign_colours assigns the actual colours to the registers.}
+
+ var adj : Psuperregisterworklist;
+ i,j,k : word;
+ n,a,c : Tsuperregister;
+ colourednodes : Tsuperregisterset;
+ adj_colours:set of 0..255;
+ found : boolean;
+
+ begin
+ spillednodes.clear;
+ {Reset colours}
+ for n:=0 to maxreg-1 do
+ reginfo[n].colour:=n;
+ {Colour the cpu registers...}
+ supregset_reset(colourednodes,false,maxreg);
+ for n:=0 to first_imaginary-1 do
+ supregset_include(colourednodes,n);
+ {Now colour the imaginary registers on the select-stack.}
+ for i:=selectstack.length downto 1 do
+ begin
+ n:=selectstack.buf^[i-1];
+ {Create a list of colours that we cannot assign to n.}
+ adj_colours:=[];
+ adj:=reginfo[n].adjlist;
+ if adj<>nil then
+ for j:=0 to adj^.length-1 do
+ begin
+ a:=get_alias(adj^.buf^[j]);
+ if supregset_in(colourednodes,a) and (reginfo[a].colour<=255) then
+ include(adj_colours,reginfo[a].colour);
+ end;
+ if regtype=R_INTREGISTER then
+ include(adj_colours,RS_STACK_POINTER_REG);
+ {Assume a spill by default...}
+ found:=false;
+ {Search for a colour not in this list.}
+ for k:=0 to usable_registers_cnt-1 do
+ begin
+ c:=usable_registers[k];
+ if not(c in adj_colours) then
+ begin
+ reginfo[n].colour:=c;
+ found:=true;
+ supregset_include(colourednodes,n);
+ include(used_in_proc,c);
+ break;
+ end;
+ end;
+ if not found then
+ spillednodes.add(n);
+ end;
+ {Finally colour the nodes that were coalesced.}
+ for i:=1 to coalescednodes.length do
+ begin
+ n:=coalescednodes.buf^[i-1];
+ k:=get_alias(n);
+ reginfo[n].colour:=reginfo[k].colour;
+ if reginfo[k].colour<maxcpuregister then
+ include(used_in_proc,reginfo[k].colour);
+ end;
+ end;
+
+ procedure trgobj.colour_registers;
+
+ begin
+ repeat
+ if simplifyworklist.length<>0 then
+ simplify
+ else if not(worklist_moves.empty) then
+ coalesce
+ else if freezeworklist.length<>0 then
+ freeze
+ else if spillworklist.length<>0 then
+ select_spill;
+ until (simplifyworklist.length=0) and
+ worklist_moves.empty and
+ (freezeworklist.length=0) and
+ (spillworklist.length=0);
+ assign_colours;
+ end;
+
+ procedure trgobj.epilogue_colouring;
+ var
+ i : Tsuperregister;
+ begin
+ worklist_moves.clear;
+ active_moves.destroy;
+ active_moves:=nil;
+ frozen_moves.destroy;
+ frozen_moves:=nil;
+ coalesced_moves.destroy;
+ coalesced_moves:=nil;
+ constrained_moves.destroy;
+ constrained_moves:=nil;
+ for i:=0 to maxreg-1 do
+ with reginfo[i] do
+ if movelist<>nil then
+ begin
+ dispose(movelist);
+ movelist:=nil;
+ end;
+ end;
+
+
+ procedure trgobj.clear_interferences(u:Tsuperregister);
+
+ {Remove node u from the interference graph and remove all collected
+ move instructions it is associated with.}
+
+ var i : word;
+ v : Tsuperregister;
+ adj,adj2 : Psuperregisterworklist;
+
+ begin
+ adj:=reginfo[u].adjlist;
+ if adj<>nil then
+ begin
+ for i:=1 to adj^.length do
+ begin
+ v:=adj^.buf^[i-1];
+ {Remove (u,v) and (v,u) from bitmap.}
+ ibitmap[u,v]:=false;
+ ibitmap[v,u]:=false;
+ {Remove (v,u) from adjacency list.}
+ adj2:=reginfo[v].adjlist;
+ if adj2<>nil then
+ begin
+ adj2^.delete(u);
+ if adj2^.length=0 then
+ begin
+ dispose(adj2,done);
+ reginfo[v].adjlist:=nil;
+ end;
+ end;
+ end;
+ {Remove ( u,* ) from adjacency list.}
+ dispose(adj,done);
+ reginfo[u].adjlist:=nil;
+ end;
+ end;
+
+
+ function trgobj.getregisterinline(list:Taasmoutput;subreg:Tsubregister):Tregister;
+ var
+ p : Tsuperregister;
+ begin
+ p:=getnewreg(subreg);
+ live_registers.add(p);
+ result:=newreg(regtype,p,subreg);
+ add_edges_used(p);
+ add_constraints(result);
+ end;
+
+
+ procedure trgobj.ungetregisterinline(list:Taasmoutput;r:Tregister);
+ var
+ supreg:Tsuperregister;
+ begin
+ supreg:=getsupreg(r);
+ live_registers.delete(supreg);
+ insert_regalloc_info(list,supreg);
+ end;
+
+
+ procedure trgobj.insert_regalloc_info(list:Taasmoutput;u:tsuperregister);
+ var
+ p : tai;
+ r : tregister;
+ palloc,
+ pdealloc : tai_regalloc;
+ begin
+ { Insert regallocs for all imaginary registers }
+ with reginfo[u] do
+ begin
+ r:=newreg(regtype,u,subreg);
+ if assigned(live_start) then
+ begin
+ { Generate regalloc and bind it to an instruction, this
+ is needed to find all live registers belonging to an
+ instruction during the spilling }
+ if live_start.typ=ait_instruction then
+ palloc:=tai_regalloc.alloc(r,live_start)
+ else
+ palloc:=tai_regalloc.alloc(r,nil);
+ if live_end.typ=ait_instruction then
+ pdealloc:=tai_regalloc.dealloc(r,live_end)
+ else
+ pdealloc:=tai_regalloc.dealloc(r,nil);
+ { Insert live start allocation before the instruction/reg_a_sync }
+ list.insertbefore(palloc,live_start);
+ { Insert live end deallocation before reg allocations
+ to reduce conflicts }
+ p:=live_end;
+ while assigned(p) and
+ assigned(p.previous) and
+ (tai(p.previous).typ=ait_regalloc) and
+ (tai_regalloc(p.previous).ratype=ra_alloc) and
+ (tai_regalloc(p.previous).reg<>r) do
+ p:=tai(p.previous);
+ { , but add release after a reg_a_sync }
+ if assigned(p) and
+ (p.typ=ait_regalloc) and
+ (tai_regalloc(p).ratype=ra_sync) then
+ p:=tai(p.next);
+ if assigned(p) then
+ list.insertbefore(pdealloc,p)
+ else
+ list.concat(pdealloc);
+ end
+{$ifdef EXTDEBUG}
+ else
+ Comment(V_Warning,'Register '+std_regname(r)+' not used');
+{$endif EXTDEBUG}
+ end;
+ end;
+
+
+ procedure trgobj.insert_regalloc_info_all(list:Taasmoutput);
+ var
+ supreg : tsuperregister;
+ begin
+ { Insert regallocs for all imaginary registers }
+ for supreg:=first_imaginary to maxreg-1 do
+ insert_regalloc_info(list,supreg);
+ end;
+
+
+ procedure trgobj.add_cpu_interferences(p : tai);
+ begin
+ end;
+
+
+ procedure trgobj.generate_interference_graph(list:Taasmoutput;headertai:tai);
+ var
+ p : tai;
+{$ifdef EXTDEBUG}
+ i : integer;
+{$endif EXTDEBUG}
+ supreg : tsuperregister;
+ begin
+ { All allocations are available. Now we can generate the
+ interference graph. Walk through all instructions, we can
+ start with the headertai, because before the header tai is
+ only symbols. }
+ live_registers.clear;
+ p:=headertai;
+ while assigned(p) do
+ begin
+ if p.typ=ait_regalloc then
+ with Tai_regalloc(p) do
+ begin
+ if (getregtype(reg)=regtype) then
+ begin
+ supreg:=getsupreg(reg);
+ case ratype of
+ ra_alloc :
+ begin
+ live_registers.add(supreg);
+ add_edges_used(supreg);
+ end;
+ ra_dealloc :
+ begin
+ live_registers.delete(supreg);
+ add_edges_used(supreg);
+ end;
+ end;
+ { constraints needs always to be updated }
+ add_constraints(reg);
+ end;
+ end;
+ add_cpu_interferences(p);
+ p:=Tai(p.next);
+ end;
+
+{$ifdef EXTDEBUG}
+ if live_registers.length>0 then
+ begin
+ for i:=0 to live_registers.length-1 do
+ begin
+ { Only report for imaginary registers }
+ if live_registers.buf^[i]>=first_imaginary then
+ Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf^[i],defaultsub))+' not released');
+ end;
+ end;
+{$endif}
+ end;
+
+
+ procedure Trgobj.translate_registers(list:taasmoutput);
+ var
+ hp,p,q:Tai;
+ i:shortint;
+{$ifdef arm}
+ so:pshifterop;
+{$endif arm}
+
+
+ begin
+ { Leave when no imaginary registers are used }
+ if maxreg<=first_imaginary then
+ exit;
+ p:=Tai(list.first);
+ while assigned(p) do
+ begin
+ case p.typ of
+ ait_regalloc:
+ with Tai_regalloc(p) do
+ begin
+ if (getregtype(reg)=regtype) then
+ begin
+ { Only alloc/dealloc is needed for the optimizer, remove
+ other regalloc }
+ if not(ratype in [ra_alloc,ra_dealloc]) then
+ begin
+ q:=Tai(next);
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end
+ else
+ begin
+ setsupreg(reg,reginfo[getsupreg(reg)].colour);
+ {
+ Remove sequences of release and
+ allocation of the same register like. Other combinations
+ of release/allocate need to stay in the list.
+
+ # Register X released
+ # Register X allocated
+ }
+ if assigned(previous) and
+ (ratype=ra_alloc) and
+ (Tai(previous).typ=ait_regalloc) and
+ (Tai_regalloc(previous).reg=reg) and
+ (Tai_regalloc(previous).ratype=ra_dealloc) then
+ begin
+ q:=Tai(next);
+ hp:=tai(previous);
+ list.remove(hp);
+ hp.free;
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end;
+ end;
+ end;
+ end;
+ ait_instruction:
+ with Taicpu(p) do
+ begin
+ aktfilepos:=fileinfo;
+ for i:=0 to ops-1 do
+ with oper[i]^ do
+ case typ of
+ Top_reg:
+ if (getregtype(reg)=regtype) then
+ setsupreg(reg,reginfo[getsupreg(reg)].colour);
+ Top_ref:
+ begin
+ if regtype=R_INTREGISTER then
+ with ref^ do
+ begin
+ if base<>NR_NO then
+ setsupreg(base,reginfo[getsupreg(base)].colour);
+ if index<>NR_NO then
+ setsupreg(index,reginfo[getsupreg(index)].colour);
+ end;
+ end;
+{$ifdef arm}
+ Top_shifterop:
+ begin
+ if regtype=R_INTREGISTER then
+ begin
+ so:=shifterop;
+ if so^.rs<>NR_NO then
+ setsupreg(so^.rs,reginfo[getsupreg(so^.rs)].colour);
+ end;
+ end;
+{$endif arm}
+ end;
+
+ { Maybe the operation can be removed when
+ it is a move and both arguments are the same }
+ if is_same_reg_move(regtype) then
+ begin
+ q:=Tai(p.next);
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end;
+ end;
+ end;
+ p:=Tai(p.next);
+ end;
+ aktfilepos:=current_procinfo.exitpos;
+ end;
+
+
+ function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
+ { Returns true if any help registers have been used }
+ var
+ i : word;
+ t : tsuperregister;
+ p,q : Tai;
+ regs_to_spill_set:Tsuperregisterset;
+ spill_temps : ^Tspill_temp_list;
+ supreg : tsuperregister;
+ templist : taasmoutput;
+ begin
+ spill_registers:=false;
+ live_registers.clear;
+ for i:=first_imaginary to maxreg-1 do
+ exclude(reginfo[i].flags,ri_selected);
+ spill_temps:=allocmem(sizeof(treference)*maxreg);
+ supregset_reset(regs_to_spill_set,false,$ffff);
+ { Allocate temps and insert in front of the list }
+ templist:=taasmoutput.create;
+ {Safe: this procedure is only called if there are spilled nodes.}
+ with spillednodes do
+ for i:=0 to length-1 do
+ begin
+ t:=buf^[i];
+ {Alternative representation.}
+ supregset_include(regs_to_spill_set,t);
+ {Clear all interferences of the spilled register.}
+ clear_interferences(t);
+ {Get a temp for the spilled register, the size must at least equal a complete register,
+ take also care of the fact that subreg can be larger than a single register like doubles
+ that occupy 2 registers }
+ tg.gettemp(templist,
+ max(tcgsize2size[reg_cgsize(newreg(regtype,t,R_SUBWHOLE))],
+ tcgsize2size[reg_cgsize(newreg(regtype,t,reginfo[t].subreg))]),
+ tt_noreuse,spill_temps^[t]);
+ end;
+ list.insertlistafter(headertai,templist);
+ templist.free;
+ { Walk through all instructions, we can start with the headertai,
+ because before the header tai is only symbols }
+ p:=headertai;
+ while assigned(p) do
+ begin
+ case p.typ of
+ ait_regalloc:
+ with Tai_regalloc(p) do
+ begin
+ if (getregtype(reg)=regtype) then
+ begin
+ {A register allocation of a spilled register can be removed.}
+ supreg:=getsupreg(reg);
+ if supregset_in(regs_to_spill_set,supreg) then
+ begin
+ q:=Tai(p.next);
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end
+ else
+ begin
+ case ratype of
+ ra_alloc :
+ live_registers.add(supreg);
+ ra_dealloc :
+ live_registers.delete(supreg);
+ end;
+ end;
+ end;
+ end;
+ ait_instruction:
+ with Taicpu(p) do
+ begin
+ aktfilepos:=fileinfo;
+ if instr_spill_register(list,taicpu(p),regs_to_spill_set,spill_temps^) then
+ spill_registers:=true;
+ end;
+ end;
+ p:=Tai(p.next);
+ end;
+ aktfilepos:=current_procinfo.exitpos;
+ {Safe: this procedure is only called if there are spilled nodes.}
+ with spillednodes do
+ for i:=0 to length-1 do
+ tg.ungettemp(list,spill_temps^[buf^[i]]);
+ freemem(spill_temps);
+ end;
+
+
+ function trgobj.do_spill_replace(list:Taasmoutput;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
+ begin
+ result:=false;
+ end;
+
+
+ procedure Trgobj.do_spill_read(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);
+ begin
+ list.insertafter(spilling_create_load(spilltemp,tempreg),pos);
+ end;
+
+
+ procedure Trgobj.do_spill_written(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);
+ begin
+ list.insertafter(spilling_create_store(tempreg,spilltemp),pos);
+ end;
+
+
+ function trgobj.get_spill_subreg(r : tregister) : tsubregister;
+ begin
+ result:=defaultsub;
+ end;
+
+
+ function trgobj.instr_spill_register(list:Taasmoutput;
+ instr:taicpu;
+ const r:Tsuperregisterset;
+ const spilltemplist:Tspill_temp_list): boolean;
+ var
+ counter, regindex: longint;
+ regs: tspillregsinfo;
+ spilled: boolean;
+
+ procedure addreginfo(reg: tregister; operation: topertype);
+ var
+ i, tmpindex: longint;
+ supreg : tsuperregister;
+ begin
+ tmpindex := regindex;
+ supreg:=getsupreg(reg);
+ { did we already encounter this register? }
+ for i := 0 to pred(regindex) do
+ if (regs[i].orgreg = supreg) then
+ begin
+ tmpindex := i;
+ break;
+ end;
+ if tmpindex > high(regs) then
+ internalerror(2003120301);
+ regs[tmpindex].orgreg := supreg;
+ regs[tmpindex].spillreg:=reg;
+ if supregset_in(r,supreg) then
+ begin
+ { add/update info on this register }
+ regs[tmpindex].mustbespilled := true;
+ case operation of
+ operand_read:
+ regs[tmpindex].regread := true;
+ operand_write:
+ regs[tmpindex].regwritten := true;
+ operand_readwrite:
+ begin
+ regs[tmpindex].regread := true;
+ regs[tmpindex].regwritten := true;
+ end;
+ end;
+ spilled := true;
+ end;
+ inc(regindex,ord(regindex=tmpindex));
+ end;
+
+
+ procedure tryreplacereg(var reg: tregister);
+ var
+ i: longint;
+ supreg: tsuperregister;
+ begin
+ supreg:=getsupreg(reg);
+ for i:=0 to pred(regindex) do
+ if (regs[i].mustbespilled) and
+ (regs[i].orgreg=supreg) then
+ begin
+ { Only replace supreg }
+ setsupreg(reg,getsupreg(regs[i].tempreg));
+ break;
+ end;
+ end;
+
+ var
+ loadpos,
+ storepos : tai;
+ oldlive_registers : tsuperregisterworklist;
+ begin
+ result := false;
+ fillchar(regs,sizeof(regs),0);
+ for counter := low(regs) to high(regs) do
+ regs[counter].orgreg := RS_INVALID;
+ spilled := false;
+ regindex := 0;
+
+ { check whether and if so which and how (read/written) this instructions contains
+ registers that must be spilled }
+ for counter := 0 to instr.ops-1 do
+ with instr.oper[counter]^ do
+ begin
+ case typ of
+ top_reg:
+ begin
+ if (getregtype(reg) = regtype) then
+ addreginfo(reg,instr.spilling_get_operation_type(counter));
+ end;
+ top_ref:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ with ref^ do
+ begin
+ if (base <> NR_NO) then
+ addreginfo(base,instr.spilling_get_operation_type_ref(counter,base));
+ if (index <> NR_NO) then
+ addreginfo(index,instr.spilling_get_operation_type_ref(counter,index));
+ end;
+ end;
+{$ifdef ARM}
+ top_shifterop:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ if shifterop^.rs<>NR_NO then
+ addreginfo(shifterop^.rs,operand_read);
+ end;
+{$endif ARM}
+ end;
+ end;
+
+ { if no spilling for this instruction we can leave }
+ if not spilled then
+ exit;
+
+{$ifdef x86}
+ { Try replacing the register with the spilltemp. This is usefull only
+ for the i386,x86_64 that support memory locations for several instructions }
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled then
+ begin
+ if do_spill_replace(list,instr,orgreg,spilltemplist[orgreg]) then
+ mustbespilled:=false;
+ end;
+ end;
+{$endif x86}
+
+ {
+ There are registers that need are spilled. We generate the
+ following code for it. The used positions where code need
+ to be inserted are marked using #. Note that code is always inserted
+ before the positions using pos.previous. This way the position is always
+ the same since pos doesn't change, but pos.previous is modified everytime
+ new code is inserted.
+
+ [
+ - reg_allocs load spills
+ - load spills
+ ]
+ [#loadpos
+ - reg_deallocs
+ - reg_allocs
+ ]
+ [
+ - reg_deallocs for load-only spills
+ - reg_allocs for store-only spills
+ ]
+ [#instr
+ - original instruction
+ ]
+ [
+ - store spills
+ - reg_deallocs store spills
+ ]
+ [#storepos
+ ]
+ }
+
+ result := true;
+ oldlive_registers.copyfrom(live_registers);
+
+ { Process all tai_regallocs belonging to this instruction, ignore explicit
+ inserted regallocs. These can happend for example in i386:
+ mov ref,ireg26
+ <regdealloc ireg26, instr=taicpu of lea>
+ <regalloc edi, insrt=nil>
+ lea [ireg26+ireg17],edi
+ All released registers are also added to the live_registers because
+ they can't be used during the spilling }
+ loadpos:=tai(instr.previous);
+ while assigned(loadpos) and
+ (loadpos.typ=ait_regalloc) and
+ ((tai_regalloc(loadpos).instr=nil) or
+ (tai_regalloc(loadpos).instr=instr)) do
+ begin
+ { Only add deallocs belonging to the instruction. Explicit inserted deallocs
+ belong to the previous instruction and not the current instruction }
+ if (tai_regalloc(loadpos).instr=instr) and
+ (tai_regalloc(loadpos).ratype=ra_dealloc) then
+ live_registers.add(getsupreg(tai_regalloc(loadpos).reg));
+ loadpos:=tai(loadpos.previous);
+ end;
+ loadpos:=tai(loadpos.next);
+
+ { Load the spilled registers }
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled and regread then
+ begin
+ tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
+ do_spill_read(list,tai(loadpos.previous),spilltemplist[orgreg],tempreg);
+ end;
+ end;
+
+ { Release temp registers of read-only registers, and add reference of the instruction
+ to the reginfo }
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled and regread and (not regwritten) then
+ begin
+ { The original instruction will be the next that uses this register }
+ add_reg_instruction(instr,tempreg);
+ ungetregisterinline(list,tempreg);
+ end;
+ end;
+
+ { Allocate temp registers of write-only registers, and add reference of the instruction
+ to the reginfo }
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled and regwritten then
+ begin
+ { When the register is also loaded there is already a register assigned }
+ if (not regread) then
+ tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
+ { The original instruction will be the next that uses this register, this
+ also needs to be done for read-write registers }
+ add_reg_instruction(instr,tempreg);
+ end;
+ end;
+
+ { store the spilled registers }
+ storepos:=tai(instr.next);
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled and regwritten then
+ begin
+ do_spill_written(list,tai(storepos.previous),spilltemplist[orgreg],tempreg);
+ ungetregisterinline(list,tempreg);
+ end;
+ end;
+
+ { now all spilling code is generated we can restore the live registers. This
+ must be done after the store because the store can need an extra register
+ that also needs to conflict with the registers of the instruction }
+ live_registers.done;
+ live_registers:=oldlive_registers;
+
+ { substitute registers }
+ for counter:=0 to instr.ops-1 do
+ with instr.oper[counter]^ do
+ begin
+ case typ of
+ top_reg:
+ begin
+ if (getregtype(reg) = regtype) then
+ tryreplacereg(reg);
+ end;
+ top_ref:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ begin
+ tryreplacereg(ref^.base);
+ tryreplacereg(ref^.index);
+ end;
+ end;
+{$ifdef ARM}
+ top_shifterop:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ tryreplacereg(shifterop^.rs);
+ end;
+{$endif ARM}
+ end;
+ end;
+ end;
+
+end.
diff --git a/compiler/scandir.pas b/compiler/scandir.pas
new file mode 100644
index 0000000000..3d3805b0eb
--- /dev/null
+++ b/compiler/scandir.pas
@@ -0,0 +1,1209 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements directive parsing for the scanner
+
+ 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 scandir;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+ procedure InitScannerDirectives;
+
+implementation
+
+ uses
+ cutils,
+ globtype,globals,systems,widestr,
+ verbose,comphook,ppu,
+ scanner,switches,
+ fmodule,
+ symtable,
+ rabase;
+
+ const
+ localswitchesstackmax = 20;
+
+ var
+ localswitchesstack: array[0..localswitchesstackmax] of tlocalswitches;
+ localswitchesstackpos: Integer;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure do_delphiswitch(sw:char);
+ var
+ state : char;
+ begin
+ { c contains the next char, a + or - would be fine }
+ state:=current_scanner.readstate;
+ if state in ['-','+'] then
+ HandleSwitch(sw,state);
+ end;
+
+
+ procedure do_setverbose(flag:char);
+ var
+ state : char;
+ begin
+ { support ON/OFF }
+ state:=current_scanner.ReadState;
+ SetVerbosity(flag+state);
+ end;
+
+
+ procedure do_moduleswitch(sw:tmoduleswitch);
+ var
+ state : char;
+ begin
+ state:=current_scanner.readstate;
+ if (sw<>cs_modulenone) and (state in ['-','+']) then
+ begin
+ if state='-' then
+ exclude(aktmoduleswitches,sw)
+ else
+ include(aktmoduleswitches,sw);
+ end;
+ end;
+
+
+ procedure do_localswitch(sw:tlocalswitch);
+ var
+ state : char;
+ begin
+ state:=current_scanner.readstate;
+ if (sw<>cs_localnone) and (state in ['-','+']) then
+ begin
+ if not localswitcheschanged then
+ nextaktlocalswitches:=aktlocalswitches;
+ if state='-' then
+ exclude(nextaktlocalswitches,sw)
+ else
+ include(nextaktlocalswitches,sw);
+ localswitcheschanged:=true;
+ end;
+ end;
+
+ procedure do_localswitchdefault(sw:tlocalswitch);
+ var
+ state : char;
+ begin
+ state:=current_scanner.readstatedefault;
+ if (sw<>cs_localnone) and (state in ['-','+','*']) then
+ begin
+ if not localswitcheschanged then
+ nextaktlocalswitches:=aktlocalswitches;
+ if state='-' then
+ exclude(nextaktlocalswitches,sw)
+ else
+ if state='+' then
+ include(nextaktlocalswitches,sw)
+ else
+ begin
+ if sw in initlocalswitches then
+ include(nextaktlocalswitches,sw)
+ else
+ exclude(nextaktlocalswitches,sw);
+ end;
+ localswitcheschanged:=true;
+ end;
+ end;
+
+
+ procedure do_message(w:integer);
+ begin
+ current_scanner.skipspace;
+ Message1(w,current_scanner.readcomment);
+ end;
+
+{*****************************************************************************
+ Directive Callbacks
+*****************************************************************************}
+
+ procedure dir_align;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['0'..'9']) then
+ begin
+ { Support also the ON and OFF as switch }
+ hs:=current_scanner.readid;
+ if (hs='ON') then
+ aktpackrecords:=4
+ else if (hs='OFF') then
+ aktpackrecords:=1
+ else if m_mac in aktmodeswitches then
+ begin
+ { Support switches used in Apples Universal Interfaces}
+ if (hs='MAC68K') then
+ aktpackrecords:=2
+ else if (hs='POWER') then
+ aktpackrecords:=4
+ else if (hs='RESET') then
+ aktpackrecords:=0
+ else
+ Message1(scan_e_illegal_pack_records,hs);
+ end
+ else
+ Message1(scan_e_illegal_pack_records,hs);
+ end
+ else
+ begin
+ case current_scanner.readval of
+ 1 : aktpackrecords:=1;
+ 2 : aktpackrecords:=2;
+ 4 : aktpackrecords:=4;
+ 8 : aktpackrecords:=8;
+ 16 : aktpackrecords:=16;
+ 32 : aktpackrecords:=32;
+ else
+ Message1(scan_e_illegal_pack_records,hs);
+ end;
+ end;
+ end;
+
+ procedure dir_a1;
+ begin
+ aktpackrecords:=1;
+ end;
+
+ procedure dir_a2;
+ begin
+ aktpackrecords:=2;
+ end;
+
+ procedure dir_a4;
+ begin
+ aktpackrecords:=4;
+ end;
+
+ procedure dir_a8;
+ begin
+ aktpackrecords:=8;
+ end;
+
+ procedure dir_asmmode;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ s:=current_scanner.readid;
+ If Inside_asm_statement then
+ Message1(scan_w_no_asm_reader_switch_inside_asm,s);
+ if s='DEFAULT' then
+ aktasmmode:=initasmmode
+ else
+ if not SetAsmReadMode(s,aktasmmode) then
+ Message1(scan_e_illegal_asmmode_specifier,s);
+ end;
+
+{$ifdef m68k}
+ procedure dir_appid;
+ begin
+ if target_info.system<>system_m68k_palmos then
+ Message(scan_w_appid_not_support);
+ { change description global var in all cases }
+ { it not used but in win32 and os2 }
+ current_scanner.skipspace;
+ palmos_applicationid:=current_scanner.readcomment;
+ end;
+
+ procedure dir_appname;
+ begin
+ if target_info.system<>system_m68k_palmos then
+ Message(scan_w_appname_not_support);
+ { change description global var in all cases }
+ { it not used but in win32 and os2 }
+ current_scanner.skipspace;
+ palmos_applicationname:=current_scanner.readcomment;
+ end;
+{$endif m68k}
+
+ procedure dir_apptype;
+ var
+ hs : string;
+ begin
+ if not (target_info.system in system_all_windows + [system_i386_os2,
+ system_i386_emx, system_powerpc_macos]) then
+ Message(scan_w_app_type_not_support);
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ if hs='GUI' then
+ apptype:=app_gui
+ else if hs='CONSOLE' then
+ apptype:=app_cui
+ else if (hs='NATIVE') and (target_info.system in system_windows) then
+ apptype:=app_native
+ else if (hs='FS') and (target_info.system in [system_i386_os2,
+ system_i386_emx]) then
+ apptype:=app_fs
+ else if (hs='TOOL') and (target_info.system in [system_powerpc_macos]) then
+ apptype:=app_tool
+ else
+ Message1(scan_w_unsupported_app_type,hs);
+ end;
+ end;
+
+
+ procedure dir_calling;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ if not SetAktProcCall(hs,false) then
+ Message1(parser_w_unknown_proc_directive_ignored,hs);
+ end;
+
+
+ procedure dir_checkpointer;
+ begin
+ do_localswitchdefault(cs_checkpointer);
+ end;
+
+
+ procedure dir_objectchecks;
+ begin
+ do_localswitch(cs_check_object);
+ end;
+
+
+ procedure dir_assertions;
+ begin
+ do_delphiswitch('C');
+ end;
+
+ procedure dir_booleval;
+ begin
+ do_delphiswitch('B');
+ end;
+
+ procedure dir_debuginfo;
+ begin
+ do_delphiswitch('D');
+ end;
+
+ procedure dir_description;
+ begin
+ if not (target_info.system in [system_i386_os2,system_i386_emx,
+ system_i386_win32,system_i386_netware,system_i386_wdosx,system_i386_netwlibc]) then
+ Message(scan_w_description_not_support);
+ { change description global var in all cases }
+ { it not used but in win32, os2 and netware }
+ current_scanner.skipspace;
+ description:=current_scanner.readcomment;
+ DescriptionSetExplicity:=true;
+ end;
+
+ procedure dir_screenname; {ad}
+ begin
+ if not (target_info.system in [system_i386_netware,system_i386_netwlibc]) then
+ {Message(scan_w_decription_not_support);}
+ comment (V_Warning,'Screenname only supported for target netware');
+ current_scanner.skipspace;
+ nwscreenname:=current_scanner.readcomment;
+ end;
+
+ procedure dir_threadname; {ad}
+ begin
+ if not (target_info.system in [system_i386_netware,system_i386_netwlibc]) then
+ {Message(scan_w_decription_not_support);}
+ comment (V_Warning,'Threadname only supported for target netware');
+ current_scanner.skipspace;
+ nwthreadname:=current_scanner.readcomment;
+ end;
+
+ procedure dir_copyright; {ad}
+ begin
+ if not (target_info.system in [system_i386_netware,system_i386_netwlibc]) then
+ {Message(scan_w_decription_not_support);}
+ comment (V_Warning,'Copyright only supported for target netware');
+ current_scanner.skipspace;
+ nwcopyright:=current_scanner.readcomment;
+ end;
+
+ procedure dir_error;
+ begin
+ do_message(scan_e_user_defined);
+ end;
+
+ procedure dir_extendedsyntax;
+ begin
+ do_delphiswitch('X');
+ end;
+
+ procedure dir_fatal;
+ begin
+ do_message(scan_f_user_defined);
+ end;
+
+ procedure dir_fputype;
+ begin
+ current_scanner.skipspace;
+ { current_scanner.undef_macro('FPU'+fputypestr[aktfputype]); }
+ if not(SetFPUType(upper(current_scanner.readcomment),false)) then
+ comment(V_Error,'Illegal FPU type');
+ { current_scanner.def_macro('FPU'+fputypestr[aktfputype]); }
+ end;
+
+ procedure dir_goto;
+ begin
+ do_moduleswitch(cs_support_goto);
+ end;
+
+ procedure dir_hint;
+ begin
+ do_message(scan_h_user_defined);
+ end;
+
+ procedure dir_hints;
+ begin
+ do_setverbose('H');
+ end;
+
+ procedure dir_implicitexceptions;
+ begin
+ do_moduleswitch(cs_implicit_exceptions);
+ end;
+
+ procedure dir_includepath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_module.localincludesearchpath.AddPath(current_scanner.readcomment,false);
+ end;
+ end;
+
+ procedure dir_info;
+ begin
+ do_message(scan_i_user_defined);
+ end;
+
+ procedure dir_inline;
+ begin
+ do_moduleswitch(cs_support_inline);
+ end;
+
+ procedure dir_interfaces;
+ var
+ hs : string;
+ begin
+ {corba/com/default}
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ if (hs='CORBA') then
+ aktinterfacetype:=it_interfacecorba
+ else if (hs='COM') then
+ aktinterfacetype:=it_interfacecom
+ else if (hs='DEFAULT') then
+ aktinterfacetype:=initinterfacetype
+ else
+ Message(scan_e_invalid_interface_type);
+ end;
+
+ procedure dir_iochecks;
+ begin
+ do_delphiswitch('I');
+ end;
+
+ procedure dir_libexport;
+ begin
+ {not implemented}
+ end;
+
+ procedure dir_librarypath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_module.locallibrarysearchpath.AddPath(current_scanner.readcomment,false);
+ end;
+ end;
+
+ procedure dir_link;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if scanner.c = '''' then
+ begin
+ s:= current_scanner.readquotedstring;
+ current_scanner.readcomment
+ end
+ else
+ s:= trimspace(current_scanner.readcomment);
+ s:=AddExtension(FixFileName(s),target_info.objext);
+ current_module.linkotherofiles.add(s,link_allways);
+ end;
+
+ procedure dir_linklib;
+ type
+ tLinkMode=(lm_shared,lm_static);
+ var
+ s : string;
+ quote : char;
+ libext,
+ libname,
+ linkmodestr : string;
+ p : longint;
+ linkMode : tLinkMode;
+ begin
+ current_scanner.skipspace;
+ if scanner.c = '''' then
+ begin
+ libname:= current_scanner.readquotedstring;
+ s:= current_scanner.readcomment;
+ p:=pos(',',s);
+ end
+ else
+ begin
+ s:= current_scanner.readcomment;
+ p:=pos(',',s);
+ if p=0 then
+ libname:=TrimSpace(s)
+ else
+ libname:=TrimSpace(copy(s,1,p-1));
+ end;
+ if p=0 then
+ linkmodeStr:=''
+ else
+ linkmodeStr:=Upper(TrimSpace(copy(s,p+1,255)));
+
+
+ if (libname='') or (libname='''''') or (libname='""') then
+ exit;
+ { create library name }
+ if libname[1] in ['''','"'] then
+ begin
+ quote:=libname[1];
+ Delete(libname,1,1);
+ p:=pos(quote,libname);
+ if p>0 then
+ Delete(libname,p,1);
+ end;
+ libname:=FixFileName(libname);
+
+ { get linkmode, default is to check the extension for
+ the static library, otherwise shared linking is assumed }
+ linkmode:=lm_shared;
+ if linkModeStr='' then
+ begin
+ libext:=SplitExtension(libname);
+ if libext=target_info.staticClibext then
+ linkMode:=lm_static;
+ end
+ else if linkModeStr='STATIC' then
+ linkmode:=lm_static
+ else if (LinkModeStr='SHARED') or (LinkModeStr='') then
+ linkmode:=lm_shared
+ else
+ Comment(V_Error,'Wrong link mode specified: "'+Linkmodestr+'"');
+
+ { add to the list of other libraries }
+ if linkMode=lm_static then
+ current_module.linkOtherStaticLibs.add(libname,link_allways)
+ else
+ current_module.linkOtherSharedLibs.add(libname,link_allways);
+ end;
+
+ procedure dir_localsymbols;
+ begin
+ do_delphiswitch('L');
+ end;
+
+ procedure dir_longstrings;
+ begin
+ do_delphiswitch('H');
+ end;
+
+ procedure dir_macro;
+ begin
+ do_moduleswitch(cs_support_macro);
+ end;
+
+ procedure dir_maxfpuregisters;
+ var
+ l : integer;
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['0'..'9']) then
+ begin
+ hs:=current_scanner.readid;
+ if (hs='NORMAL') or (hs='DEFAULT') then
+ aktmaxfpuregisters:=-1
+ else
+ Message(scan_e_invalid_maxfpureg_value);
+ end
+ else
+ begin
+ l:=current_scanner.readval;
+ case l of
+ 0..8:
+ aktmaxfpuregisters:=l;
+ else
+ Message(scan_e_invalid_maxfpureg_value);
+ end;
+ end;
+ end;
+
+ procedure dir_memory;
+ var
+ l : longint;
+ begin
+ current_scanner.skipspace;
+ l:=current_scanner.readval;
+ if l>1024 then
+ stacksize:=l;
+ if c=',' then
+ begin
+ current_scanner.readchar;
+ current_scanner.skipspace;
+ l:=current_scanner.readval;
+ if l>1024 then
+ heapsize:=l;
+ end;
+ end;
+
+
+ procedure dir_message;
+ var
+ hs : string;
+ w : longint;
+ begin
+ w:=0;
+ current_scanner.skipspace;
+ { Message level specified? }
+ if c='''' then
+ w:=scan_n_user_defined
+ else
+ begin
+ hs:=current_scanner.readid;
+ if (hs='WARN') or (hs='WARNING') then
+ w:=scan_w_user_defined
+ else
+ if (hs='ERROR') then
+ w:=scan_e_user_defined
+ else
+ if (hs='FATAL') then
+ w:=scan_f_user_defined
+ else
+ if (hs='HINT') then
+ w:=scan_h_user_defined
+ else
+ if (hs='NOTE') then
+ w:=scan_n_user_defined
+ else
+ Message1(scan_w_illegal_directive,hs);
+ end;
+ { Only print message when there was no error }
+ if w<>0 then
+ begin
+ current_scanner.skipspace;
+ if c='''' then
+ hs:=current_scanner.readquotedstring
+ else
+ hs:=current_scanner.readcomment;
+ Message1(w,hs);
+ end
+ else
+ current_scanner.readcomment;
+ end;
+
+
+ procedure dir_mode;
+
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_scanner.readstring;
+ if not current_module.mode_switch_allowed and
+ not ((m_mac in aktmodeswitches) and (pattern='MACPAS')) then
+ Message1(scan_e_mode_switch_not_allowed,pattern)
+ else if SetCompileMode(pattern,false) then
+ ConsolidateMode
+ else
+ Message1(scan_w_illegal_switch,pattern)
+ end;
+ current_module.mode_switch_allowed:= false;
+ end;
+
+ procedure dir_mmx;
+ begin
+ do_localswitch(cs_mmx);
+ end;
+
+ procedure dir_note;
+ begin
+ do_message(scan_n_user_defined);
+ end;
+
+ procedure dir_notes;
+ begin
+ do_setverbose('N');
+ end;
+
+ procedure dir_objectpath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_module.localobjectsearchpath.AddPath(current_scanner.readcomment,false);
+ end;
+ end;
+
+ procedure dir_openstrings;
+ begin
+ do_delphiswitch('P');
+ end;
+
+ procedure dir_overflowchecks;
+ begin
+ do_delphiswitch('Q');
+ end;
+
+ procedure dir_packenum;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['0'..'9']) then
+ begin
+ hs:=current_scanner.readid;
+ if (hs='NORMAL') or (hs='DEFAULT') then
+ aktpackenum:=4
+ else
+ Message1(scan_e_illegal_pack_enum, hs);
+ end
+ else
+ begin
+ case current_scanner.readval of
+ 1 : aktpackenum:=1;
+ 2 : aktpackenum:=2;
+ 4 : aktpackenum:=4;
+ else
+ Message1(scan_e_illegal_pack_enum, pattern);
+ end;
+ end;
+ end;
+
+ procedure dir_packrecords;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['0'..'9']) then
+ begin
+ hs:=current_scanner.readid;
+ { C has the special recordalignmax of -1 }
+ if (hs='C') then
+ aktpackrecords:=-1
+ else
+ if (hs='NORMAL') or (hs='DEFAULT') then
+ aktpackrecords:=0
+ else
+ Message1(scan_e_illegal_pack_records,hs);
+ end
+ else
+ begin
+ case current_scanner.readval of
+ 1 : aktpackrecords:=1;
+ 2 : aktpackrecords:=2;
+ 4 : aktpackrecords:=4;
+ 8 : aktpackrecords:=8;
+ 16 : aktpackrecords:=16;
+ 32 : aktpackrecords:=32;
+ else
+ Message1(scan_e_illegal_pack_records,pattern);
+ end;
+ end;
+ end;
+
+{$ifdef testvarsets}
+ procedure dir_packset;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['1','2','4']) then
+ begin
+ hs:=current_scanner.readid;
+ if (hs='FIXED') or ((hs='DEFAULT') OR (hs='NORMAL')) then
+ aktsetalloc:=0 {Fixed mode, sets are 4 or 32 bytes}
+ else
+ Message(scan_w_only_packset);
+ end
+ else
+ begin
+ case current_scanner.readval of
+ 1 : aktsetalloc:=1;
+ 2 : aktsetalloc:=2;
+ 4 : aktsetalloc:=4;
+ else
+ Message(scan_w_only_packset);
+ end;
+ end;
+ end;
+{$ENDIF}
+
+ procedure dir_pop;
+
+ begin
+ if localswitchesstackpos < 1 then
+ Message(scan_e_too_many_pop);
+
+ if not localswitcheschanged then
+ nextaktlocalswitches:=aktlocalswitches;
+
+ Dec(localswitchesstackpos);
+ nextaktlocalswitches:= localswitchesstack[localswitchesstackpos];
+
+ localswitcheschanged:=true;
+ end;
+
+ procedure dir_profile;
+ begin
+ do_moduleswitch(cs_profile);
+ { defined/undefine FPC_PROFILE }
+ if cs_profile in aktmoduleswitches then
+ def_system_macro('FPC_PROFILE')
+ else
+ undef_system_macro('FPC_PROFILE');
+ end;
+
+ procedure dir_push;
+
+ begin
+ if localswitchesstackpos > localswitchesstackmax then
+ Message(scan_e_too_many_push);
+
+ if localswitcheschanged then
+ begin
+ aktlocalswitches:=nextaktlocalswitches;
+ localswitcheschanged:=false;
+ end;
+
+ localswitchesstack[localswitchesstackpos]:= aktlocalswitches;
+ Inc(localswitchesstackpos);
+ end;
+
+ procedure dir_rangechecks;
+ begin
+ do_delphiswitch('R');
+ end;
+
+ procedure dir_referenceinfo;
+ begin
+ do_delphiswitch('Y');
+ end;
+
+ procedure dir_resource;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if scanner.c = '''' then
+ begin
+ s:= current_scanner.readquotedstring;
+ current_scanner.readcomment
+ end
+ else
+ s:= trimspace(current_scanner.readcomment);
+
+ { replace * with current module name.
+ This should always be defined. }
+ if s[1]='*' then
+ if Assigned(Current_Module) then
+ begin
+ delete(S,1,1);
+ if m_delphi in aktmodeswitches then
+ insert(current_module.realmodulename^,S,1)
+ else
+ insert(lower(current_module.modulename^),S,1);
+ end;
+ s:=AddExtension(FixFileName(s),target_info.resext);
+ if target_info.res<>res_none then
+ begin
+ current_module.flags:=current_module.flags or uf_has_resourcefiles;
+ if (target_info.res = res_emxbind) and
+ not (Current_module.ResourceFiles.Empty) then
+ Message(scan_w_only_one_resourcefile_supported)
+ else
+ current_module.resourcefiles.insert(FixFileName(s));
+ end
+ else
+ Message(scan_e_resourcefiles_not_supported);
+ end;
+
+ procedure dir_saturation;
+ begin
+ do_localswitch(cs_mmx_saturation);
+ end;
+
+ procedure dir_smartlink;
+ begin
+ do_moduleswitch(cs_create_smart);
+ end;
+
+ procedure dir_stackframes;
+ begin
+ do_delphiswitch('W');
+ end;
+
+ procedure dir_static;
+ begin
+ do_moduleswitch(cs_static_keyword);
+ end;
+
+ procedure dir_stop;
+ begin
+ do_message(scan_f_user_defined);
+ end;
+
+{$ifdef powerpc}
+ procedure dir_syscall;
+ var
+ sctype : string;
+ begin
+ if not (target_info.system in [system_powerpc_morphos]) then
+ comment (V_Warning,'Syscall directive is useless on this target.');
+ current_scanner.skipspace;
+
+ sctype:=current_scanner.readid;
+ if (sctype='LEGACY') or (sctype='SYSV') or (sctype='SYSVBASE') or
+ (sctype='BASESYSV') or (sctype='R12BASE') then
+ syscall_convention:=sctype
+ else
+ comment (V_Warning,'Invalid Syscall directive ignored.');
+ end;
+{$endif}
+
+ procedure dir_typedaddress;
+ begin
+ do_delphiswitch('T');
+ end;
+
+ procedure dir_typeinfo;
+ begin
+ do_delphiswitch('M');
+ end;
+
+ procedure dir_unitpath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ with current_scanner,current_module,localunitsearchpath do
+ begin
+ skipspace;
+ AddPath(path^,readcomment,false);
+ end;
+ end;
+
+ procedure dir_varstringchecks;
+ begin
+ do_delphiswitch('V');
+ end;
+
+ procedure dir_version;
+ var
+ major, minor, revision : longint;
+ error : integer;
+ begin
+ if not (target_info.system in [system_i386_os2,system_i386_emx,
+ system_i386_win32,system_i386_netware,system_i386_wdosx,
+ system_i386_netwlibc]) then
+ begin
+ Message(scan_n_version_not_support);
+ exit;
+ end;
+ if (compile_level<>1) then
+ Message(scan_n_only_exe_version)
+ else
+ begin
+ { change description global var in all cases }
+ { it not used but in win32, os2 and netware }
+ current_scanner.skipspace;
+ { we should only accept Major.Minor format for win32 and os2 }
+ current_scanner.readnumber;
+ major:=0;
+ minor:=0;
+ revision:=0;
+ val(pattern,major,error);
+ if (error<>0) or (major > high(word)) or (major < 0) then
+ begin
+ Message1(scan_w_wrong_version_ignored,pattern);
+ exit;
+ end;
+ if c='.' then
+ begin
+ current_scanner.readchar;
+ current_scanner.readnumber;
+ val(pattern,minor,error);
+ if (error<>0) or (minor > high(word)) or (minor < 0) then
+ begin
+ Message1(scan_w_wrong_version_ignored,tostr(major)+'.'+pattern);
+ exit;
+ end;
+ if (c='.') and
+ (target_info.system in [system_i386_netware,system_i386_netwlibc]) then
+ begin
+ current_scanner.readchar;
+ current_scanner.readnumber;
+ val(pattern,revision,error);
+ if (error<>0) or (revision > high(word)) or (revision < 0) then
+ begin
+ Message1(scan_w_wrong_version_ignored,tostr(revision)+'.'+pattern);
+ exit;
+ end;
+ dllmajor:=word(major);
+ dllminor:=word(minor);
+ dllrevision:=word(revision);
+ dllversion:=tostr(major)+','+tostr(minor)+','+tostr(revision);
+ end
+ else
+ begin
+ dllmajor:=word(major);
+ dllminor:=word(minor);
+ dllversion:=tostr(major)+'.'+tostr(minor);
+ end;
+ end
+ else
+ dllversion:=tostr(major);
+ end;
+ end;
+
+ procedure dir_wait;
+ var
+ had_info : boolean;
+ begin
+ had_info:=(status.verbosity and V_Info)<>0;
+ { this message should allways appear !! }
+ status.verbosity:=status.verbosity or V_Info;
+ Message(scan_i_press_enter);
+ readln;
+ If not(had_info) then
+ status.verbosity:=status.verbosity and (not V_Info);
+ end;
+
+ procedure dir_warning;
+ begin
+ do_message(scan_w_user_defined);
+ end;
+
+ procedure dir_warnings;
+ begin
+ do_setverbose('W');
+ end;
+
+ procedure dir_writeableconst;
+ begin
+ do_delphiswitch('J');
+ end;
+
+ procedure dir_z1;
+ begin
+ aktpackenum:=1;
+ end;
+
+ procedure dir_z2;
+ begin
+ aktpackenum:=2;
+ end;
+
+ procedure dir_z4;
+ begin
+ aktpackenum:=4;
+ end;
+
+ procedure dir_externalsym;
+ begin
+ end;
+
+ procedure dir_nodefine;
+ begin
+ end;
+
+ procedure dir_hppemit;
+ begin
+ end;
+
+ procedure dir_weakpackageunit;
+ begin
+ end;
+
+ procedure dir_codealign;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ s:=current_scanner.readcomment;
+ UpdateAlignmentStr(s,aktalignment);
+ end;
+
+ procedure dir_codepage;
+ var
+ s : string;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ s:=current_scanner.readcomment;
+ if (upper(s)='UTF8') or (upper(s)='UTF-8') then
+ aktsourcecodepage:='utf8'
+ else if not(cpavailable(s)) then
+ Message1(option_code_page_not_available,s)
+ else
+ aktsourcecodepage:=s;
+ end;
+ end;
+
+ procedure dir_coperators;
+ begin
+ do_moduleswitch(cs_support_c_operators);
+ end;
+
+
+{****************************************************************************
+ Initialize Directives
+****************************************************************************}
+
+ procedure InitScannerDirectives;
+ begin
+ AddDirective('A1',directive_all, @dir_a1);
+ AddDirective('A2',directive_all, @dir_a2);
+ AddDirective('A4',directive_all, @dir_a4);
+ AddDirective('A8',directive_all, @dir_a8);
+ AddDirective('ALIGN',directive_all, @dir_align);
+{$ifdef m68k}
+ AddDirective('APPID',directive_all, @dir_appid);
+ AddDirective('APPNAME',directive_all, @dir_appname);
+{$endif m68k}
+ AddDirective('APPTYPE',directive_all, @dir_apptype);
+ AddDirective('ASMMODE',directive_all, @dir_asmmode);
+ AddDirective('ASSERTIONS',directive_all, @dir_assertions);
+ AddDirective('BOOLEVAL',directive_all, @dir_booleval);
+ AddDirective('CALLING',directive_all, @dir_calling);
+ AddDirective('CHECKPOINTER',directive_all, @dir_checkpointer);
+ AddDirective('CODEALIGN',directive_all, @dir_codealign);
+ AddDirective('CODEPAGE',directive_all, @dir_codepage);
+ AddDirective('COPERATORS',directive_all, @dir_coperators);
+ AddDirective('COPYRIGHT',directive_all, @dir_copyright);
+ AddDirective('D',directive_all, @dir_description);
+ AddDirective('DEBUGINFO',directive_all, @dir_debuginfo);
+ AddDirective('DESCRIPTION',directive_all, @dir_description);
+ AddDirective('ERROR',directive_all, @dir_error);
+ AddDirective('ERRORC',directive_mac, @dir_error);
+ AddDirective('EXTENDEDSYNTAX',directive_all, @dir_extendedsyntax);
+ AddDirective('EXTERNALSYM',directive_all, @dir_externalsym);
+ AddDirective('FATAL',directive_all, @dir_fatal);
+ AddDirective('FPUTYPE',directive_all, @dir_fputype);
+ AddDirective('GOTO',directive_all, @dir_goto);
+ AddDirective('HINT',directive_all, @dir_hint);
+ AddDirective('HINTS',directive_all, @dir_hints);
+ AddDirective('HPPEMIT',directive_all, @dir_hppemit);
+ AddDirective('IOCHECKS',directive_all, @dir_iochecks);
+ AddDirective('IMPLICITEXCEPTIONS',directive_all, @dir_implicitexceptions);
+ AddDirective('INCLUDEPATH',directive_all, @dir_includepath);
+ AddDirective('INFO',directive_all, @dir_info);
+ AddDirective('INLINE',directive_all, @dir_inline);
+ AddDirective('INTERFACES',directive_all, @dir_interfaces);
+ AddDirective('L',directive_all, @dir_link);
+ AddDirective('LIBEXPORT',directive_mac, @dir_libexport);
+ AddDirective('LIBRARYPATH',directive_all, @dir_librarypath);
+ AddDirective('LINK',directive_all, @dir_link);
+ AddDirective('LINKLIB',directive_all, @dir_linklib);
+ AddDirective('LOCALSYMBOLS',directive_all, @dir_localsymbols);
+ AddDirective('LONGSTRINGS',directive_all, @dir_longstrings);
+ AddDirective('M',directive_all, @dir_memory);
+ AddDirective('MACRO',directive_all, @dir_macro);
+ AddDirective('MAXFPUREGISTERS',directive_all, @dir_maxfpuregisters);
+ AddDirective('MEMORY',directive_all, @dir_memory);
+ AddDirective('MESSAGE',directive_all, @dir_message);
+ AddDirective('MINENUMSIZE',directive_all, @dir_packenum);
+ AddDirective('MMX',directive_all, @dir_mmx);
+ AddDirective('MODE',directive_all, @dir_mode);
+ AddDirective('NODEFINE',directive_all, @dir_nodefine);
+ AddDirective('NOTE',directive_all, @dir_note);
+ AddDirective('NOTES',directive_all, @dir_notes);
+ AddDirective('OBJECTCHECKS',directive_all, @dir_objectchecks);
+ AddDirective('OBJECTPATH',directive_all, @dir_objectpath);
+ AddDirective('OPENSTRINGS',directive_all, @dir_openstrings);
+ AddDirective('OVERFLOWCHECKS',directive_all, @dir_overflowchecks);
+ AddDirective('PACKENUM',directive_all, @dir_packenum);
+ AddDirective('PACKRECORDS',directive_all, @dir_packrecords);
+{$IFDEF TestVarsets}
+ AddDirective('PACKSET',directive_all, @dir_packset);
+{$ENDIF}
+ AddDirective('POP',directive_mac, @dir_pop);
+ AddDirective('PROFILE',directive_all, @dir_profile);
+ AddDirective('PUSH',directive_mac, @dir_push);
+ AddDirective('R',directive_all, @dir_resource);
+ AddDirective('RANGECHECKS',directive_all, @dir_rangechecks);
+ AddDirective('REFERENCEINFO',directive_all, @dir_referenceinfo);
+ AddDirective('RESOURCE',directive_all, @dir_resource);
+ AddDirective('SATURATION',directive_all, @dir_saturation);
+ AddDirective('SCREENNAME',directive_all, @dir_screenname);
+ AddDirective('SMARTLINK',directive_all, @dir_smartlink);
+ AddDirective('STACKFRAMES',directive_all, @dir_stackframes);
+ AddDirective('STATIC',directive_all, @dir_static);
+ AddDirective('STOP',directive_all, @dir_stop);
+{$ifdef powerpc}
+ AddDirective('SYSCALL',directive_all, @dir_syscall);
+{$endif powerpc}
+ AddDirective('THREADNAME',directive_all, @dir_threadname);
+ AddDirective('TYPEDADDRESS',directive_all, @dir_typedaddress);
+ AddDirective('TYPEINFO',directive_all, @dir_typeinfo);
+ AddDirective('UNITPATH',directive_all, @dir_unitpath);
+ AddDirective('VARSTRINGCHECKS',directive_all, @dir_varstringchecks);
+ AddDirective('VERSION',directive_all, @dir_version);
+ AddDirective('WAIT',directive_all, @dir_wait);
+ AddDirective('WARN',directive_all, @dir_warnings);
+ AddDirective('WARNING',directive_all, @dir_warning);
+ AddDirective('WARNINGS',directive_all, @dir_warnings);
+ AddDirective('WEAKPACKAGEUNIT',directive_all, @dir_weakpackageunit);
+ AddDirective('WRITEABLECONST',directive_all, @dir_writeableconst);
+ AddDirective('Z1',directive_all, @dir_z1);
+ AddDirective('Z2',directive_all, @dir_z2);
+ AddDirective('Z4',directive_all, @dir_z4);
+ end;
+
+begin
+ localswitchesstackpos:= 0;
+end.
diff --git a/compiler/scanner.pas b/compiler/scanner.pas
new file mode 100644
index 0000000000..81f8e521b4
--- /dev/null
+++ b/compiler/scanner.pas
@@ -0,0 +1,3760 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the scanner part and handling of the switches
+
+ 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 scanner;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,version,tokens,
+ verbose,comphook,
+ finput,
+ widestr;
+
+ const
+ max_include_nesting=32;
+ max_macro_nesting=16;
+ preprocbufsize=32*1024;
+
+
+ type
+ tcommentstyle = (comment_none,comment_tp,comment_oldtp,comment_delphi,comment_c);
+
+ tscannerfile = class;
+
+ preproctyp = (pp_ifdef,pp_ifndef,pp_if,pp_ifopt,pp_else,pp_elseif);
+
+ tpreprocstack = class
+ typ : preproctyp;
+ accept : boolean;
+ next : tpreprocstack;
+ name : stringid;
+ line_nb : longint;
+ owner : tscannerfile;
+ constructor Create(atyp:preproctyp;a:boolean;n:tpreprocstack);
+ end;
+
+ tdirectiveproc=procedure;
+
+ tdirectiveitem = class(TNamedIndexItem)
+ public
+ is_conditional : boolean;
+ proc : tdirectiveproc;
+ constructor Create(const n:string;p:tdirectiveproc);
+ constructor CreateCond(const n:string;p:tdirectiveproc);
+ end;
+
+ tcompile_time_predicate = function(var valuedescr: String) : Boolean;
+
+ tscannerfile = class
+ public
+ inputfile : tinputfile; { current inputfile list }
+ inputfilecount : longint;
+
+ inputbuffer, { input buffer }
+ inputpointer : pchar;
+ inputstart : longint;
+
+ line_no, { line }
+ lastlinepos : longint;
+
+ lasttokenpos : longint; { token }
+ lasttoken,
+ nexttoken : ttoken;
+
+ comment_level,
+ yylexcount : longint;
+ lastasmgetchar : char;
+ ignoredirectives : tstringlist; { ignore directives, used to give warnings only once }
+ preprocstack : tpreprocstack;
+ in_asm_string : boolean;
+
+ preproc_pattern : string;
+ preproc_token : ttoken;
+
+ constructor Create(const fn:string);
+ destructor Destroy;override;
+ { File buffer things }
+ function openinputfile:boolean;
+ procedure closeinputfile;
+ function tempopeninputfile:boolean;
+ procedure tempcloseinputfile;
+ procedure saveinputfile;
+ procedure restoreinputfile;
+ procedure firstfile;
+ procedure nextfile;
+ procedure addfile(hp:tinputfile);
+ procedure reload;
+ procedure insertmacro(const macname:string;p:pchar;len,line,fileindex:longint);
+ { Scanner things }
+ procedure gettokenpos;
+ procedure inc_comment_level;
+ procedure dec_comment_level;
+ procedure illegal_char(c:char);
+ procedure end_of_file;
+ procedure checkpreprocstack;
+ procedure poppreprocstack;
+ procedure ifpreprocstack(atyp : preproctyp;compile_time_predicate:tcompile_time_predicate;messid:longint);
+ procedure elseifpreprocstack(compile_time_predicate:tcompile_time_predicate);
+ procedure elsepreprocstack;
+ procedure handleconditional(p:tdirectiveitem);
+ procedure handledirectives;
+ procedure linebreak;
+ procedure readchar;
+ procedure readstring;
+ procedure readnumber;
+ function readid:string;
+ function readval:longint;
+ function readval_asstring:string;
+ function readcomment:string;
+ function readquotedstring:string;
+ function readstate:char;
+ function readstatedefault:char;
+ procedure skipspace;
+ procedure skipuntildirective;
+ procedure skipcomment;
+ procedure skipdelphicomment;
+ procedure skipoldtpcomment;
+ procedure readtoken;
+ function readpreproc:ttoken;
+ function asmgetcharstart : char;
+ function asmgetchar:char;
+ end;
+
+{$ifdef PREPROCWRITE}
+ tpreprocfile=class
+ f : text;
+ buf : pointer;
+ spacefound,
+ eolfound : boolean;
+ constructor create(const fn:string);
+ destructor destroy;
+ procedure Add(const s:string);
+ procedure AddSpace;
+ end;
+{$endif PREPROCWRITE}
+
+ var
+ { read strings }
+ c : char;
+ orgpattern,
+ pattern : string;
+ patternw : pcompilerwidestring;
+
+ { token }
+ token, { current token being parsed }
+ idtoken : ttoken; { holds the token if the pattern is a known word }
+
+ current_scanner : tscannerfile; { current scanner in use }
+
+ aktcommentstyle : tcommentstyle; { needed to use read_comment from directives }
+{$ifdef PREPROCWRITE}
+ preprocfile : tpreprocfile; { used with only preprocessing }
+{$endif PREPROCWRITE}
+
+ type
+ tdirectivemode = (directive_all, directive_turbo, directive_mac);
+
+ procedure AddDirective(const s:string; dm: tdirectivemode; p:tdirectiveproc);
+ procedure AddConditional(const s:string; dm: tdirectivemode; p:tdirectiveproc);
+
+ procedure InitScanner;
+ procedure DoneScanner;
+
+ {To be called when the language mode is finally determined}
+ procedure ConsolidateMode;
+ Function SetCompileMode(const s:string; changeInit: boolean):boolean;
+
+
+implementation
+
+ uses
+ dos,
+ cutils,
+ systems,
+ switches,
+ symbase,symtable,symtype,symsym,symconst,symdef,defutil,
+ fmodule;
+
+ var
+ { dictionaries with the supported directives }
+ turbo_scannerdirectives : tdictionary; { for other modes }
+ mac_scannerdirectives : tdictionary; { for mode mac }
+
+
+{*****************************************************************************
+ Helper routines
+*****************************************************************************}
+
+ const
+ { use any special name that is an invalid file name to avoid problems }
+ preprocstring : array [preproctyp] of string[7]
+ = ('$IFDEF','$IFNDEF','$IF','$IFOPT','$ELSE','$ELSEIF');
+
+
+ function is_keyword(const s:string):boolean;
+ var
+ low,high,mid : longint;
+ begin
+ if not (length(s) in [tokenlenmin..tokenlenmax]) or
+ not (s[1] in ['a'..'z','A'..'Z']) then
+ begin
+ is_keyword:=false;
+ exit;
+ end;
+ low:=ord(tokenidx^[length(s),s[1]].first);
+ high:=ord(tokenidx^[length(s),s[1]].last);
+ while low<high do
+ begin
+ mid:=(high+low+1) shr 1;
+ if pattern<tokeninfo^[ttoken(mid)].str then
+ high:=mid-1
+ else
+ low:=mid;
+ end;
+ is_keyword:=(pattern=tokeninfo^[ttoken(high)].str) and
+ (tokeninfo^[ttoken(high)].keyword in aktmodeswitches);
+ end;
+
+
+ {To be called when the language mode is finally determined}
+ procedure ConsolidateMode;
+
+ begin
+ if m_mac in aktmodeswitches then
+ if current_module.is_unit and not assigned(current_module.globalmacrosymtable) then
+ begin
+ current_module.globalmacrosymtable:= tmacrosymtable.create(true);
+ current_module.globalmacrosymtable.next:= current_module.localmacrosymtable;
+ macrosymtablestack:=current_module.globalmacrosymtable;
+ end;
+ end;
+
+
+ Function SetCompileMode(const s:string; changeInit: boolean):boolean;
+ var
+ b : boolean;
+ oldaktmodeswitches : tmodeswitches;
+ begin
+ oldaktmodeswitches:=aktmodeswitches;
+
+ b:=true;
+ if s='DEFAULT' then
+ aktmodeswitches:=initmodeswitches
+ else
+ if s='DELPHI' then
+ aktmodeswitches:=delphimodeswitches
+ else
+ if s='TP' then
+ aktmodeswitches:=tpmodeswitches
+ else
+ if s='FPC' then
+ aktmodeswitches:=fpcmodeswitches
+ else
+ if s='OBJFPC' then
+ aktmodeswitches:=objfpcmodeswitches
+ else
+ if s='GPC' then
+ aktmodeswitches:=gpcmodeswitches
+ else
+ if s='MACPAS' then
+ aktmodeswitches:=macmodeswitches
+ else
+ b:=false;
+
+ if b and changeInit then
+ initmodeswitches := aktmodeswitches;
+
+ if b then
+ begin
+ { turn ansistrings on by default ? }
+ if (m_delphi in aktmodeswitches) then
+ begin
+ include(aktlocalswitches,cs_ansistrings);
+ if changeinit then
+ include(initlocalswitches,cs_ansistrings);
+ end
+ else
+ begin
+ exclude(aktlocalswitches,cs_ansistrings);
+ if changeinit then
+ exclude(initlocalswitches,cs_ansistrings);
+ end;
+ { Default enum packing for delphi/tp7 }
+ if (m_tp7 in aktmodeswitches) or
+ (m_delphi in aktmodeswitches) or
+ (m_mac in aktmodeswitches) then
+ aktpackenum:=1
+ else
+ aktpackenum:=4;
+ if changeinit then
+ initpackenum:=aktpackenum;
+{$ifdef i386}
+ { Default to intel assembler for delphi/tp7 on i386 }
+ if (m_delphi in aktmodeswitches) or
+ (m_tp7 in aktmodeswitches) then
+ aktasmmode:=asmmode_i386_intel;
+ if changeinit then
+ initasmmode:=aktasmmode;
+{$endif i386}
+
+ { Undefine old symbol }
+ if (m_delphi in oldaktmodeswitches) then
+ undef_system_macro('FPC_DELPHI')
+ else if (m_tp7 in oldaktmodeswitches) then
+ undef_system_macro('FPC_TP')
+ else if (m_objfpc in oldaktmodeswitches) then
+ undef_system_macro('FPC_OBJFPC')
+ else if (m_gpc in oldaktmodeswitches) then
+ undef_system_macro('FPC_GPC')
+ else if (m_mac in oldaktmodeswitches) then
+ undef_system_macro('FPC_MACPAS');
+
+ { define new symbol in delphi,objfpc,tp,gpc,macpas mode }
+ if (m_delphi in aktmodeswitches) then
+ def_system_macro('FPC_DELPHI')
+ else if (m_tp7 in aktmodeswitches) then
+ def_system_macro('FPC_TP')
+ else if (m_objfpc in aktmodeswitches) then
+ def_system_macro('FPC_OBJFPC')
+ else if (m_gpc in aktmodeswitches) then
+ def_system_macro('FPC_GPC')
+ else if (m_mac in aktmodeswitches) then
+ def_system_macro('FPC_MACPAS');
+ end;
+
+ SetCompileMode:=b;
+ end;
+
+
+{*****************************************************************************
+ Conditional Directives
+*****************************************************************************}
+
+ procedure dir_else;
+ begin
+ current_scanner.elsepreprocstack;
+ end;
+
+
+ procedure dir_endif;
+ begin
+ current_scanner.poppreprocstack;
+ end;
+
+ function isdef(var valuedescr: String): Boolean;
+ var
+ hs : string;
+ mac : tmacro;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ valuedescr:= hs;
+ if hs='' then
+ Message(scan_e_error_in_preproc_expr);
+ mac:=tmacro(search_macro(hs));
+ if assigned(mac) then
+ mac.is_used:=true;
+ isdef:= assigned(mac) and mac.defined;
+ end;
+
+ procedure dir_ifdef;
+ begin
+ current_scanner.ifpreprocstack(pp_ifdef,@isdef,scan_c_ifdef_found);
+ end;
+
+ function isnotdef(var valuedescr: String): Boolean;
+ var
+ hs : string;
+ mac : tmacro;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ valuedescr:= hs;
+ if hs='' then
+ Message(scan_e_error_in_preproc_expr);
+ mac:=tmacro(search_macro(hs));
+ if assigned(mac) then
+ mac.is_used:=true;
+ isnotdef:= not (assigned(mac) and mac.defined);
+ end;
+
+ procedure dir_ifndef;
+ begin
+ current_scanner.ifpreprocstack(pp_ifndef,@isnotdef,scan_c_ifndef_found);
+ end;
+
+ function opt_check(var valuedescr: String): Boolean;
+ var
+ hs : string;
+ state : char;
+ begin
+ opt_check:= false;
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ valuedescr:= hs;
+ if (length(hs)>1) then
+ Message1(scan_w_illegal_switch,hs)
+ else
+ begin
+ state:=current_scanner.ReadState;
+ if state in ['-','+'] then
+ opt_check:=CheckSwitch(hs[1],state)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end;
+ end;
+
+ procedure dir_ifopt;
+ begin
+ current_scanner.ifpreprocstack(pp_ifopt,@opt_check,scan_c_ifopt_found);
+ end;
+
+ procedure dir_libprefix;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if c <> '''' then
+ Message2(scan_f_syn_expected, '''', c);
+ s := current_scanner.readquotedstring;
+ stringdispose(outputprefix);
+ outputprefix := stringdup(s);
+ with current_module do
+ setfilename(paramfn^, paramallowoutput);
+ end;
+
+ procedure dir_libsuffix;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if c <> '''' then
+ Message2(scan_f_syn_expected, '''', c);
+ s := current_scanner.readquotedstring;
+ stringdispose(outputsuffix);
+ outputsuffix := stringdup(s);
+ with current_module do
+ setfilename(paramfn^, paramallowoutput);
+ end;
+
+ procedure dir_extension;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if c <> '''' then
+ Message2(scan_f_syn_expected, '''', c);
+ s := current_scanner.readquotedstring;
+ outputextension := '.'+s;
+ with current_module do
+ setfilename(paramfn^, paramallowoutput);
+ end;
+
+{
+Compile time expression type check
+----------------------------------
+Each subexpression returns its type to the caller, which then can
+do type check. Since data types of compile time expressions is
+not well defined, the type system does a best effort. The drawback is
+that some errors might not be detected.
+
+Instead of returning a particular data type, a set of possible data types
+are returned. This way ambigouos types can be handled. For instance a
+value of 1 can be both a boolean and and integer.
+
+Booleans
+--------
+
+The following forms of boolean values are supported:
+* C coded, that is 0 is false, non-zero is true.
+* TRUE/FALSE for mac style compile time variables
+
+Thus boolean mac compile time variables are always stored as TRUE/FALSE.
+When a compile time expression is evaluated, they are then translated
+to C coded booleans (0/1), to simplify for the expression evaluator.
+
+Note that this scheme then also of support mac compile time variables which
+are 0/1 but with a boolean meaning.
+
+The TRUE/FALSE format is new from 22 august 2005, but the above scheme
+means that units which is not recompiled, and thus stores
+compile time variables as the old format (0/1), continue to work.
+
+}
+
+ type
+ {Compile time expression types}
+ TCTEType = (ctetBoolean, ctetInteger, ctetString, ctetSet);
+ TCTETypeSet = set of TCTEType;
+
+ const
+ cteTypeNames : array[TCTEType] of string[10] = (
+ 'BOOLEAN','INTEGER','STRING','SET');
+
+ {Subset of types which can be elements in sets.}
+ setElementTypes = [ctetBoolean, ctetInteger, ctetString];
+
+
+ function GetCTETypeName(t: TCTETypeSet): String;
+ var
+ i: TCTEType;
+ begin
+ result:= '';
+ for i:= Low(TCTEType) to High(TCTEType) do
+ if i in t then
+ if result = '' then
+ result:= cteTypeNames[i]
+ else
+ result:= result + ' or ' + cteTypeNames[i];
+ end;
+
+ procedure CTEError(actType, desiredExprType: TCTETypeSet; place: String);
+
+ begin
+ Message3(scan_e_compile_time_typeerror,
+ GetCTETypeName(desiredExprType),
+ GetCTETypeName(actType),
+ place
+ );
+ end;
+
+ function parse_compiler_expr(var compileExprType: TCTETypeSet):string;
+
+ function read_expr(var exprType: TCTETypeSet) : string; forward;
+
+ procedure preproc_consume(t : ttoken);
+ begin
+ if t<>current_scanner.preproc_token then
+ Message(scan_e_preproc_syntax_error);
+ current_scanner.preproc_token:=current_scanner.readpreproc;
+ end;
+
+ function preproc_substitutedtoken(var macroType: TCTETypeSet): string;
+ { Currently this parses identifiers as well as numbers.
+ The result from this procedure can either be that the token
+ itself is a value, or that it is a compile time variable/macro,
+ which then is substituted for another value (for macros
+ recursivelly substituted).}
+
+ var
+ hs: string;
+ mac : tmacro;
+ macrocount,
+ len : integer;
+ numres : longint;
+ w: word;
+ begin
+ result := current_scanner.preproc_pattern;
+ mac:= nil;
+ { Substitue macros and compiler variables with their content/value.
+ For real macros also do recursive substitution. }
+ macrocount:=0;
+ repeat
+ mac:=tmacro(search_macro(result));
+
+ inc(macrocount);
+ if macrocount>max_macro_nesting then
+ begin
+ Message(scan_w_macro_too_deep);
+ break;
+ end;
+
+ if assigned(mac) and mac.defined then
+ if assigned(mac.buftext) then
+ begin
+ if mac.buflen>255 then
+ begin
+ len:=255;
+ Message(scan_w_macro_cut_after_255_chars);
+ end
+ else
+ len:=mac.buflen;
+ hs[0]:=char(len);
+ move(mac.buftext^,hs[1],len);
+ result:=upcase(hs);
+ mac.is_used:=true;
+ end
+ else
+ begin
+ Message1(scan_e_error_macro_lacks_value, result);
+ break;
+ end
+ else
+ begin
+ break;
+ end;
+
+ if mac.is_compiler_var then
+ break;
+ until false;
+
+ { At this point, result do contain the value. Do some decoding and
+ determine the type.}
+ val(result,numres,w);
+ if (w=0) then {It is an integer}
+ begin
+ if (numres = 0) or (numres = 1) then
+ macroType := [ctetInteger, ctetBoolean]
+ else
+ macroType := [ctetInteger];
+ end
+ else if assigned(mac) and (m_mac in aktmodeswitches) and (result='FALSE') then
+ begin
+ result:= '0';
+ macroType:= [ctetBoolean];
+ end
+ else if assigned(mac) and (m_mac in aktmodeswitches) and (result='TRUE') then
+ begin
+ result:= '1';
+ macroType:= [ctetBoolean];
+ end
+ else if (m_mac in aktmodeswitches) and
+ (not assigned(mac) or not mac.defined) and
+ (macrocount = 1) then
+ begin
+ {Errors in mode mac is issued here. For non macpas modes there is
+ more liberty, but the error will eventually be caught at a later stage.}
+ Message1(scan_e_error_macro_undefined, result);
+ macroType:= [ctetString]; {Just to have something}
+ end
+ else
+ macroType:= [ctetString];
+ end;
+
+ function read_factor(var factorType: TCTETypeSet) : string;
+ var
+ hs : string;
+ mac: tmacro;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ l : longint;
+ w : integer;
+ hasKlammer: Boolean;
+ setElemType : TCTETypeSet;
+
+ begin
+ if current_scanner.preproc_token=_ID then
+ begin
+ if current_scanner.preproc_pattern='DEFINED' then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ hasKlammer:= true;
+ end
+ else if (m_mac in aktmodeswitches) then
+ hasKlammer:= false
+ else
+ Message(scan_e_error_in_preproc_expr);
+
+ if current_scanner.preproc_token =_ID then
+ begin
+ hs := current_scanner.preproc_pattern;
+ mac := tmacro(search_macro(hs));
+ if assigned(mac) and mac.defined then
+ begin
+ hs := '1';
+ mac.is_used:=true;
+ end
+ else
+ hs := '0';
+ read_factor := hs;
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+
+ if hasKlammer then
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='UNDEFINED') then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_ID then
+ begin
+ hs := current_scanner.preproc_pattern;
+ mac := tmacro(search_macro(hs));
+ if assigned(mac) then
+ begin
+ hs := '0';
+ mac.is_used:=true;
+ end
+ else
+ hs := '1';
+ read_factor := hs;
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='OPTION') then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+
+ if not (current_scanner.preproc_token = _ID) then
+ Message(scan_e_error_in_preproc_expr);
+
+ hs:=current_scanner.preproc_pattern;
+ if (length(hs) > 1) then
+ {This is allowed in Metrowerks Pascal}
+ Message(scan_e_error_in_preproc_expr)
+ else
+ begin
+ if CheckSwitch(hs[1],'+') then
+ read_factor := '1'
+ else
+ read_factor := '0';
+ end;
+
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if current_scanner.preproc_pattern='SIZEOF' then
+ begin
+ factorType:= [ctetInteger];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
+ begin
+ l:=0;
+ case srsym.typ of
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ l:=tabstractvarsym(srsym).getsize;
+ typedconstsym :
+ l:=ttypedconstsym(srsym).getsize;
+ typesym:
+ l:=ttypesym(srsym).restype.def.size;
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end;
+ str(l,read_factor);
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ else
+ Message1(sym_e_id_not_found,current_scanner.preproc_pattern);
+
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if current_scanner.preproc_pattern='DECLARED' then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ if current_scanner.preproc_token =_ID then
+ begin
+ hs := upper(current_scanner.preproc_pattern);
+ if searchsym(hs,srsym,srsymtable) then
+ hs := '1'
+ else
+ hs := '0';
+ read_factor := hs;
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if current_scanner.preproc_pattern='NOT' then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ hs:=read_factor(factorType);
+ if not (ctetBoolean in factorType) then
+ CTEError(factorType, [ctetBoolean], 'NOT');
+ val(hs,l,w);
+ if l<>0 then
+ read_factor:='0'
+ else
+ read_factor:='1';
+ end
+ else
+ if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='TRUE') then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ read_factor:='1';
+ end
+ else
+ if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='FALSE') then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ read_factor:='0';
+ end
+ else
+ begin
+ hs:=preproc_substitutedtoken(factorType);
+
+ { Default is to return the original symbol }
+ read_factor:=hs;
+ if (m_delphi in aktmodeswitches) and (ctetString in factorType) then
+ if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
+ begin
+ case srsym.typ of
+ constsym :
+ begin
+ with tconstsym(srsym) do
+ begin
+ case consttyp of
+ constord :
+ begin
+ case consttype.def.deftype of
+ orddef:
+ begin
+ if is_integer(consttype.def) then
+ begin
+ read_factor:=tostr(value.valueord);
+ factorType:= [ctetInteger];
+ end
+ else if is_boolean(consttype.def) then
+ begin
+ read_factor:=tostr(value.valueord);
+ factorType:= [ctetBoolean];
+ end
+ else if is_char(consttype.def) then
+ begin
+ read_factor:=chr(value.valueord);
+ factorType:= [ctetString];
+ end
+ end;
+ enumdef:
+ begin
+ read_factor:=tostr(value.valueord);
+ factorType:= [ctetInteger];
+ end;
+ end;
+ end;
+ conststring :
+ begin
+ read_factor := upper(pchar(value.valueptr));
+ factorType:= [ctetString];
+ end;
+ constset :
+ begin
+ hs:=',';
+ for l:=0 to 255 do
+ if l in pconstset(tconstsym(srsym).value.valueptr)^ then
+ hs:=hs+tostr(l)+',';
+ read_factor := hs;
+ factorType:= [ctetSet];
+ end;
+ end;
+ end;
+ end;
+ enumsym :
+ begin
+ read_factor:=tostr(tenumsym(srsym).value);
+ factorType:= [ctetInteger];
+ end;
+ end;
+ end;
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ end
+ else if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ read_factor:=read_expr(factorType);
+ preproc_consume(_RKLAMMER);
+ end
+ else if current_scanner.preproc_token = _LECKKLAMMER then
+ begin
+ preproc_consume(_LECKKLAMMER);
+ read_factor := ',';
+ while current_scanner.preproc_token = _ID do
+ begin
+ read_factor := read_factor+read_factor(setElemType)+',';
+ if current_scanner.preproc_token = _COMMA then
+ preproc_consume(_COMMA);
+ end;
+ // TODO Add check of setElemType
+ preproc_consume(_RECKKLAMMER);
+ factorType:= [ctetSet];
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end;
+
+ function read_term(var termType: TCTETypeSet) : string;
+ var
+ hs1,hs2 : string;
+ l1,l2 : longint;
+ w : integer;
+ termType2: TCTETypeSet;
+ begin
+ hs1:=read_factor(termType);
+ repeat
+ if (current_scanner.preproc_token<>_ID) then
+ break;
+ if current_scanner.preproc_pattern<>'AND' then
+ break;
+
+ {Check if first expr is boolean. Must be done here, after we know
+ it is an AND expression.}
+ if not (ctetBoolean in termType) then
+ CTEError(termType, [ctetBoolean], 'AND');
+ termType:= [ctetBoolean];
+
+ preproc_consume(_ID);
+ hs2:=read_factor(termType2);
+
+ if not (ctetBoolean in termType2) then
+ CTEError(termType2, [ctetBoolean], 'AND');
+
+ val(hs1,l1,w);
+ val(hs2,l2,w);
+ if (l1<>0) and (l2<>0) then
+ hs1:='1'
+ else
+ hs1:='0';
+ until false;
+ read_term:=hs1;
+ end;
+
+
+ function read_simple_expr(var simpleExprType: TCTETypeSet) : string;
+ var
+ hs1,hs2 : string;
+ l1,l2 : longint;
+ w : integer;
+ simpleExprType2: TCTETypeSet;
+ begin
+ hs1:=read_term(simpleExprType);
+ repeat
+ if (current_scanner.preproc_token<>_ID) then
+ break;
+ if current_scanner.preproc_pattern<>'OR' then
+ break;
+
+ {Check if first expr is boolean. Must be done here, after we know
+ it is an OR expression.}
+ if not (ctetBoolean in simpleExprType) then
+ CTEError(simpleExprType, [ctetBoolean], 'OR');
+ simpleExprType:= [ctetBoolean];
+
+ preproc_consume(_ID);
+ hs2:=read_term(simpleExprType2);
+
+ if not (ctetBoolean in simpleExprType2) then
+ CTEError(simpleExprType2, [ctetBoolean], 'OR');
+
+ val(hs1,l1,w);
+ val(hs2,l2,w);
+ if (l1<>0) or (l2<>0) then
+ hs1:='1'
+ else
+ hs1:='0';
+ until false;
+ read_simple_expr:=hs1;
+ end;
+
+ function read_expr(var exprType: TCTETypeSet) : string;
+ var
+ hs1,hs2 : string;
+ b : boolean;
+ op : ttoken;
+ w : integer;
+ l1,l2 : longint;
+ exprType2: TCTETypeSet;
+ begin
+ hs1:=read_simple_expr(exprType);
+ op:=current_scanner.preproc_token;
+ if (op = _ID) and (current_scanner.preproc_pattern = 'IN') then
+ op := _IN;
+ if not (op in [_IN,_EQUAL,_UNEQUAL,_LT,_GT,_LTE,_GTE]) then
+ begin
+ read_expr:=hs1;
+ exit;
+ end;
+
+ if (op = _IN) then
+ preproc_consume(_ID)
+ else
+ preproc_consume(op);
+ hs2:=read_simple_expr(exprType2);
+
+ if op = _IN then
+ begin
+ if exprType2 <> [ctetSet] then
+ CTEError(exprType2, [ctetSet], 'IN');
+ if exprType = [ctetSet] then
+ CTEError(exprType, setElementTypes, 'IN');
+
+ if is_number(hs1) and is_number(hs2) then
+ Message(scan_e_preproc_syntax_error)
+ else if hs2[1] = ',' then
+ b:=pos(','+hs1+',', hs2) > 0 { TODO For integer sets, perhaps check for numeric equivalence so that 0 = 00 }
+ else
+ Message(scan_e_preproc_syntax_error);
+ end
+ else
+ begin
+ if (exprType * exprType2) = [] then
+ CTEError(exprType2, exprType, tokeninfo^[op].str);
+
+ if is_number(hs1) and is_number(hs2) then
+ begin
+ val(hs1,l1,w);
+ val(hs2,l2,w);
+ case op of
+ _EQUAL :
+ b:=l1=l2;
+ _UNEQUAL :
+ b:=l1<>l2;
+ _LT :
+ b:=l1<l2;
+ _GT :
+ b:=l1>l2;
+ _GTE :
+ b:=l1>=l2;
+ _LTE :
+ b:=l1<=l2;
+ end;
+ end
+ else
+ begin
+ case op of
+ _EQUAL :
+ b:=hs1=hs2;
+ _UNEQUAL :
+ b:=hs1<>hs2;
+ _LT :
+ b:=hs1<hs2;
+ _GT :
+ b:=hs1>hs2;
+ _GTE :
+ b:=hs1>=hs2;
+ _LTE :
+ b:=hs1<=hs2;
+ end;
+ end;
+ end;
+
+ if b then
+ read_expr:='1'
+ else
+ read_expr:='0';
+ exprType:= [ctetBoolean];
+ end;
+ begin
+ current_scanner.skipspace;
+ { start preproc expression scanner }
+ current_scanner.preproc_token:=current_scanner.readpreproc;
+ parse_compiler_expr:=read_expr(compileExprType);
+ end;
+
+ function boolean_compile_time_expr(var valuedescr: String): Boolean;
+ var
+ hs : string;
+ exprType: TCTETypeSet;
+ begin
+ hs:=parse_compiler_expr(exprType);
+ if (exprType * [ctetBoolean]) = [] then
+ CTEError(exprType, [ctetBoolean], 'IF or ELSEIF');
+ boolean_compile_time_expr:= hs <> '0';
+ valuedescr:= hs;
+ end;
+
+ procedure dir_if;
+ begin
+ current_scanner.ifpreprocstack(pp_if,@boolean_compile_time_expr, scan_c_if_found);
+ end;
+
+ procedure dir_elseif;
+ begin
+ current_scanner.elseifpreprocstack(@boolean_compile_time_expr);
+ end;
+
+ procedure dir_define_impl(macstyle: boolean);
+ var
+ hs : string;
+ bracketcount : longint;
+ mac : tmacro;
+ macropos : longint;
+ macrobuffer : pmacrobuffer;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ mac:=tmacro(search_macro(hs));
+ if not assigned(mac) or (mac.owner <> macrosymtablestack) then
+ begin
+ mac:=tmacro.create(hs);
+ mac.defined:=true;
+ Message1(parser_c_macro_defined,mac.name);
+ macrosymtablestack.insert(mac);
+ end
+ else
+ begin
+ Message1(parser_c_macro_defined,mac.name);
+ mac.defined:=true;
+ mac.is_compiler_var:=false;
+ { delete old definition }
+ if assigned(mac.buftext) then
+ begin
+ freemem(mac.buftext,mac.buflen);
+ mac.buftext:=nil;
+ end;
+ end;
+ mac.is_used:=true;
+ if (cs_support_macro in aktmoduleswitches) then
+ begin
+ { !!!!!! handle macro params, need we this? }
+ current_scanner.skipspace;
+
+ if not macstyle then
+ begin
+ { may be a macro? }
+ if c <> ':' then
+ exit;
+ current_scanner.readchar;
+ if c <> '=' then
+ exit;
+ current_scanner.readchar;
+ current_scanner.skipspace;
+ end;
+
+ { key words are never substituted }
+ if is_keyword(hs) then
+ Message(scan_e_keyword_cant_be_a_macro);
+
+ new(macrobuffer);
+ macropos:=0;
+ { parse macro, brackets are counted so it's possible
+ to have a $ifdef etc. in the macro }
+ bracketcount:=0;
+ repeat
+ case c of
+ '}' :
+ if (bracketcount=0) then
+ break
+ else
+ dec(bracketcount);
+ '{' :
+ inc(bracketcount);
+ #10,#13 :
+ current_scanner.linebreak;
+ #26 :
+ current_scanner.end_of_file;
+ end;
+ macrobuffer^[macropos]:=c;
+ inc(macropos);
+ if macropos>=maxmacrolen then
+ Message(scan_f_macro_buffer_overflow);
+ current_scanner.readchar;
+ until false;
+
+ { free buffer of macro ?}
+ if assigned(mac.buftext) then
+ freemem(mac.buftext,mac.buflen);
+ { get new mem }
+ getmem(mac.buftext,macropos);
+ mac.buflen:=macropos;
+ { copy the text }
+ move(macrobuffer^,mac.buftext^,macropos);
+ dispose(macrobuffer);
+ end
+ else
+ begin
+ { check if there is an assignment, then we need to give a
+ warning }
+ current_scanner.skipspace;
+ if c=':' then
+ begin
+ current_scanner.readchar;
+ if c='=' then
+ Message(scan_w_macro_support_turned_off);
+ end;
+ end;
+ end;
+
+ procedure dir_define;
+ begin
+ dir_define_impl(false);
+ end;
+
+ procedure dir_definec;
+ begin
+ dir_define_impl(true);
+ end;
+
+ procedure dir_setc;
+ var
+ hs : string;
+ mac : tmacro;
+ exprType: TCTETypeSet;
+ l : longint;
+ w : integer;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ mac:=tmacro(search_macro(hs));
+ if not assigned(mac) or (mac.owner <> macrosymtablestack) then
+ begin
+ mac:=tmacro.create(hs);
+ mac.defined:=true;
+ mac.is_compiler_var:=true;
+ Message1(parser_c_macro_defined,mac.name);
+ macrosymtablestack.insert(mac);
+ end
+ else
+ begin
+ mac.defined:=true;
+ mac.is_compiler_var:=true;
+ { delete old definition }
+ if assigned(mac.buftext) then
+ begin
+ freemem(mac.buftext,mac.buflen);
+ mac.buftext:=nil;
+ end;
+ end;
+ mac.is_used:=true;
+
+
+ { key words are never substituted }
+ if is_keyword(hs) then
+ Message(scan_e_keyword_cant_be_a_macro);
+ { !!!!!! handle macro params, need we this? }
+ current_scanner.skipspace;
+ { may be a macro? }
+
+ { assignment can be both := and = }
+ if c=':' then
+ current_scanner.readchar;
+
+ if c='=' then
+ begin
+ current_scanner.readchar;
+ hs:= parse_compiler_expr(exprType);
+ if (exprType * [ctetBoolean, ctetInteger]) = [] then
+ CTEError(exprType, [ctetBoolean, ctetInteger], 'SETC');
+
+ if length(hs) <> 0 then
+ begin
+ {If we are absolutely shure it is boolean, translate
+ to TRUE/FALSE to increase possibility to do future type check}
+ if exprType = [ctetBoolean] then
+ begin
+ val(hs,l,w);
+ if l<>0 then
+ hs:='TRUE'
+ else
+ hs:='FALSE';
+ end;
+ Message2(parser_c_macro_set_to,mac.name,hs);
+ { free buffer of macro ?}
+ if assigned(mac.buftext) then
+ freemem(mac.buftext,mac.buflen);
+ { get new mem }
+ getmem(mac.buftext,length(hs));
+ mac.buflen:=length(hs);
+ { copy the text }
+ move(hs[1],mac.buftext^,mac.buflen);
+ end
+ else
+ Message(scan_e_preproc_syntax_error);
+ end
+ else
+ Message(scan_e_preproc_syntax_error);
+ end;
+
+
+ procedure dir_undef;
+ var
+ hs : string;
+ mac : tmacro;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ mac:=tmacro(search_macro(hs));
+ if not assigned(mac) or (mac.owner <> macrosymtablestack) then
+ begin
+ mac:=tmacro.create(hs);
+ Message1(parser_c_macro_undefined,mac.name);
+ mac.defined:=false;
+ macrosymtablestack.insert(mac);
+ end
+ else
+ begin
+ Message1(parser_c_macro_undefined,mac.name);
+ mac.defined:=false;
+ mac.is_compiler_var:=false;
+ { delete old definition }
+ if assigned(mac.buftext) then
+ begin
+ freemem(mac.buftext,mac.buflen);
+ mac.buftext:=nil;
+ end;
+ end;
+ mac.is_used:=true;
+ end;
+
+ procedure dir_include;
+
+ function findincludefile(const path,name,ext:string;var foundfile:string):boolean;
+ var
+ found : boolean;
+ hpath : string;
+
+ begin
+ (* look for the include file
+ If path was specified as part of {$I } then
+ 1. specified path (expanded with path of inputfile if relative)
+ else
+ 1. path of current inputfile,current dir
+ 2. local includepath
+ 3. global includepath *)
+ found:=false;
+ foundfile:='';
+ hpath:='';
+ if path<>'' then
+ begin
+ if not path_absolute(path) then
+ hpath:=current_scanner.inputfile.path^+path
+ else
+ hpath:=path;
+ found:=FindFile(name+ext, hpath,foundfile);
+ end
+ else
+ begin
+ hpath:=current_scanner.inputfile.path^+';'+CurDirRelPath(source_info);
+ found:=FindFile(name+ext, hpath,foundfile);
+ if not found then
+ found:=current_module.localincludesearchpath.FindFile(name+ext,foundfile);
+ if not found then
+ found:=includesearchpath.FindFile(name+ext,foundfile);
+ end;
+ findincludefile:=found;
+ end;
+
+
+ var
+ args,
+ foundfile,
+ hs : string;
+ path : dirstr;
+ name : namestr;
+ ext : extstr;
+ hp : tinputfile;
+ found : boolean;
+ begin
+ current_scanner.skipspace;
+ args:=current_scanner.readcomment;
+ hs:=GetToken(args,' ');
+ if hs='' then
+ exit;
+ if (hs[1]='%') then
+ begin
+ { case insensitive }
+ hs:=upper(hs);
+ { remove %'s }
+ Delete(hs,1,1);
+ if hs[length(hs)]='%' then
+ Delete(hs,length(hs),1);
+ { save old }
+ path:=hs;
+ { first check for internal macros }
+ if hs='TIME' then
+ hs:=gettimestr
+ else
+ if hs='DATE' then
+ hs:=getdatestr
+ else
+ if hs='FILE' then
+ hs:=current_module.sourcefiles.get_file_name(aktfilepos.fileindex)
+ else
+ if hs='LINE' then
+ hs:=tostr(aktfilepos.line)
+ else
+ if hs='FPCVERSION' then
+ hs:=version_string
+ else
+ if hs='FPCTARGET' then
+ hs:=target_cpu_string
+ else
+ if hs='FPCTARGETCPU' then
+ hs:=target_cpu_string
+ else
+ if hs='FPCTARGETOS' then
+ hs:=target_info.shortname
+ else
+ hs:=getenv(hs);
+ if hs='' then
+ Message1(scan_w_include_env_not_found,path);
+ { make it a stringconst }
+ hs:=''''+hs+'''';
+ current_scanner.insertmacro(path,@hs[1],length(hs),
+ current_scanner.line_no,current_scanner.inputfile.ref_index);
+ end
+ else
+ begin
+ hs:=FixFileName(hs);
+ fsplit(hs,path,name,ext);
+ { try to find the file }
+ found:=findincludefile(path,name,ext,foundfile);
+ if (ext='') then
+ begin
+ { try default extensions .inc , .pp and .pas }
+ if (not found) then
+ found:=findincludefile(path,name,'.inc',foundfile);
+ if (not found) then
+ found:=findincludefile(path,name,sourceext,foundfile);
+ if (not found) then
+ found:=findincludefile(path,name,pasext,foundfile);
+ end;
+ if current_scanner.inputfilecount<max_include_nesting then
+ begin
+ inc(current_scanner.inputfilecount);
+ { we need to reread the current char }
+ dec(current_scanner.inputpointer);
+ { shutdown current file }
+ current_scanner.tempcloseinputfile;
+ { load new file }
+ hp:=do_openinputfile(foundfile);
+ current_scanner.addfile(hp);
+ current_module.sourcefiles.register_file(hp);
+ if (not found) then
+ Message1(scan_f_cannot_open_includefile,hs);
+ if (not current_scanner.openinputfile) then
+ Message1(scan_f_cannot_open_includefile,hs);
+ Message1(scan_t_start_include_file,current_scanner.inputfile.path^+current_scanner.inputfile.name^);
+ current_scanner.reload;
+ end
+ else
+ Message(scan_f_include_deep_ten);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Preprocessor writting
+*****************************************************************************}
+
+{$ifdef PREPROCWRITE}
+ constructor tpreprocfile.create(const fn:string);
+ begin
+ { open outputfile }
+ assign(f,fn);
+ {$I-}
+ rewrite(f);
+ {$I+}
+ if ioresult<>0 then
+ Comment(V_Fatal,'can''t create file '+fn);
+ getmem(buf,preprocbufsize);
+ settextbuf(f,buf^,preprocbufsize);
+ { reset }
+ eolfound:=false;
+ spacefound:=false;
+ end;
+
+
+ destructor tpreprocfile.destroy;
+ begin
+ close(f);
+ freemem(buf,preprocbufsize);
+ end;
+
+
+ procedure tpreprocfile.add(const s:string);
+ begin
+ write(f,s);
+ end;
+
+ procedure tpreprocfile.addspace;
+ begin
+ if eolfound then
+ begin
+ writeln(f,'');
+ eolfound:=false;
+ spacefound:=false;
+ end
+ else
+ if spacefound then
+ begin
+ write(f,' ');
+ spacefound:=false;
+ end;
+ end;
+{$endif PREPROCWRITE}
+
+
+{*****************************************************************************
+ TPreProcStack
+*****************************************************************************}
+
+ constructor tpreprocstack.create(atyp : preproctyp;a:boolean;n:tpreprocstack);
+ begin
+ accept:=a;
+ typ:=atyp;
+ next:=n;
+ end;
+
+
+{*****************************************************************************
+ TDirectiveItem
+*****************************************************************************}
+
+ constructor TDirectiveItem.Create(const n:string;p:tdirectiveproc);
+ begin
+ inherited CreateName(n);
+ is_conditional:=false;
+ proc:=p;
+ end;
+
+
+ constructor TDirectiveItem.CreateCond(const n:string;p:tdirectiveproc);
+ begin
+ inherited CreateName(n);
+ is_conditional:=true;
+ proc:=p;
+ end;
+
+{****************************************************************************
+ TSCANNERFILE
+ ****************************************************************************}
+
+ constructor tscannerfile.create(const fn:string);
+ begin
+ inputfile:=do_openinputfile(fn);
+ if assigned(current_module) then
+ current_module.sourcefiles.register_file(inputfile);
+ { reset localinput }
+ inputbuffer:=nil;
+ inputpointer:=nil;
+ inputstart:=0;
+ { reset scanner }
+ preprocstack:=nil;
+ comment_level:=0;
+ yylexcount:=0;
+ block_type:=bt_general;
+ line_no:=0;
+ lastlinepos:=0;
+ lasttokenpos:=0;
+ lasttoken:=NOTOKEN;
+ nexttoken:=NOTOKEN;
+ lastasmgetchar:=#0;
+ ignoredirectives:=TStringList.Create;
+ in_asm_string:=false;
+ end;
+
+
+ procedure tscannerfile.firstfile;
+ begin
+ { load block }
+ if not openinputfile then
+ Message1(scan_f_cannot_open_input,inputfile.name^);
+ reload;
+ end;
+
+
+ destructor tscannerfile.destroy;
+ begin
+ if assigned(current_module) and
+ (current_module.state=ms_compiled) and
+ (status.errorcount=0) then
+ checkpreprocstack
+ else
+ begin
+ while assigned(preprocstack) do
+ poppreprocstack;
+ end;
+ if not inputfile.closed then
+ closeinputfile;
+ ignoredirectives.free;
+ end;
+
+
+ function tscannerfile.openinputfile:boolean;
+ begin
+ openinputfile:=inputfile.open;
+ { load buffer }
+ inputbuffer:=inputfile.buf;
+ inputpointer:=inputfile.buf;
+ inputstart:=inputfile.bufstart;
+ { line }
+ line_no:=0;
+ lastlinepos:=0;
+ lasttokenpos:=0;
+ end;
+
+
+ procedure tscannerfile.closeinputfile;
+ begin
+ inputfile.close;
+ { reset buffer }
+ inputbuffer:=nil;
+ inputpointer:=nil;
+ inputstart:=0;
+ { reset line }
+ line_no:=0;
+ lastlinepos:=0;
+ lasttokenpos:=0;
+ end;
+
+
+ function tscannerfile.tempopeninputfile:boolean;
+ begin
+ if inputfile.is_macro then
+ exit;
+ tempopeninputfile:=inputfile.tempopen;
+ { reload buffer }
+ inputbuffer:=inputfile.buf;
+ inputpointer:=inputfile.buf;
+ inputstart:=inputfile.bufstart;
+ end;
+
+
+ procedure tscannerfile.tempcloseinputfile;
+ begin
+ if inputfile.closed or inputfile.is_macro then
+ exit;
+ inputfile.setpos(inputstart+(inputpointer-inputbuffer));
+ inputfile.tempclose;
+ { reset buffer }
+ inputbuffer:=nil;
+ inputpointer:=nil;
+ inputstart:=0;
+ end;
+
+
+ procedure tscannerfile.saveinputfile;
+ begin
+ inputfile.saveinputpointer:=inputpointer;
+ inputfile.savelastlinepos:=lastlinepos;
+ inputfile.saveline_no:=line_no;
+ end;
+
+
+ procedure tscannerfile.restoreinputfile;
+ begin
+ inputpointer:=inputfile.saveinputpointer;
+ lastlinepos:=inputfile.savelastlinepos;
+ line_no:=inputfile.saveline_no;
+ if not inputfile.is_macro then
+ parser_current_file:=inputfile.name^;
+ end;
+
+
+ procedure tscannerfile.nextfile;
+ var
+ to_dispose : tinputfile;
+ begin
+ if assigned(inputfile.next) then
+ begin
+ if inputfile.is_macro then
+ to_dispose:=inputfile
+ else
+ begin
+ to_dispose:=nil;
+ dec(inputfilecount);
+ end;
+ { we can allways close the file, no ? }
+ inputfile.close;
+ inputfile:=inputfile.next;
+ if assigned(to_dispose) then
+ to_dispose.free;
+ restoreinputfile;
+ end;
+ end;
+
+
+ procedure tscannerfile.addfile(hp:tinputfile);
+ begin
+ saveinputfile;
+ { add to list }
+ hp.next:=inputfile;
+ inputfile:=hp;
+ { load new inputfile }
+ restoreinputfile;
+ end;
+
+
+ procedure tscannerfile.reload;
+ begin
+ with inputfile do
+ begin
+ { when nothing more to read then leave immediatly, so we
+ don't change the aktfilepos and leave it point to the last
+ char }
+ if (c=#26) and (not assigned(next)) then
+ exit;
+ repeat
+ { still more to read?, then change the #0 to a space so its seen
+ as a seperator, this can't be used for macro's which can change
+ the place of the #0 in the buffer with tempopen }
+ if (c=#0) and (bufsize>0) and
+ not(inputfile.is_macro) and
+ (inputpointer-inputbuffer<bufsize) then
+ begin
+ c:=' ';
+ inc(inputpointer);
+ exit;
+ end;
+ { can we read more from this file ? }
+ if (c<>#26) and (not endoffile) then
+ begin
+ readbuf;
+ inputpointer:=buf;
+ inputbuffer:=buf;
+ inputstart:=bufstart;
+ { first line? }
+ if line_no=0 then
+ begin
+ c:=inputpointer^;
+ { eat utf-8 signature? }
+ if (ord(inputpointer^)=$ef) and
+ (ord((inputpointer+1)^)=$bb) and
+ (ord((inputpointer+2)^)=$bf) then
+ begin
+ inc(inputpointer,3);
+ message(scan_c_switching_to_utf8);
+ aktsourcecodepage:='utf8';
+ end;
+
+ line_no:=1;
+ if cs_asm_source in aktglobalswitches then
+ inputfile.setline(line_no,bufstart);
+ end;
+ end
+ else
+ begin
+ { load eof position in tokenpos/aktfilepos }
+ gettokenpos;
+ { close file }
+ closeinputfile;
+ { no next module, than EOF }
+ if not assigned(inputfile.next) then
+ begin
+ c:=#26;
+ exit;
+ end;
+ { load next file and reopen it }
+ nextfile;
+ tempopeninputfile;
+ { status }
+ Message1(scan_t_back_in,inputfile.name^);
+ end;
+ { load next char }
+ c:=inputpointer^;
+ inc(inputpointer);
+ until c<>#0; { if also end, then reload again }
+ end;
+ end;
+
+
+ procedure tscannerfile.insertmacro(const macname:string;p:pchar;len,line,fileindex:longint);
+ var
+ hp : tinputfile;
+ begin
+ { save old postion }
+ dec(inputpointer);
+ tempcloseinputfile;
+ { create macro 'file' }
+ { use special name to dispose after !! }
+ hp:=do_openinputfile('_Macro_.'+macname);
+ addfile(hp);
+ with inputfile do
+ begin
+ setmacro(p,len);
+ { local buffer }
+ inputbuffer:=buf;
+ inputpointer:=buf;
+ inputstart:=bufstart;
+ ref_index:=fileindex;
+ end;
+ { reset line }
+ line_no:=line;
+ lastlinepos:=0;
+ lasttokenpos:=0;
+ { load new c }
+ c:=inputpointer^;
+ inc(inputpointer);
+ end;
+
+
+ procedure tscannerfile.gettokenpos;
+ { load the values of tokenpos and lasttokenpos }
+ begin
+ lasttokenpos:=inputstart+(inputpointer-inputbuffer);
+ akttokenpos.line:=line_no;
+ akttokenpos.column:=lasttokenpos-lastlinepos;
+ akttokenpos.fileindex:=inputfile.ref_index;
+ aktfilepos:=akttokenpos;
+ end;
+
+
+ procedure tscannerfile.inc_comment_level;
+ var
+ oldaktfilepos : tfileposinfo;
+ begin
+ if (m_nested_comment in aktmodeswitches) then
+ inc(comment_level)
+ else
+ comment_level:=1;
+ if (comment_level>1) then
+ begin
+ oldaktfilepos:=aktfilepos;
+ gettokenpos; { update for warning }
+ Message1(scan_w_comment_level,tostr(comment_level));
+ aktfilepos:=oldaktfilepos;
+ end;
+ end;
+
+
+ procedure tscannerfile.dec_comment_level;
+ begin
+ if (m_nested_comment in aktmodeswitches) then
+ dec(comment_level)
+ else
+ comment_level:=0;
+ end;
+
+
+ procedure tscannerfile.linebreak;
+ var
+ cur : char;
+ oldtokenpos,
+ oldaktfilepos : tfileposinfo;
+ begin
+ with inputfile do
+ begin
+ if (byte(inputpointer^)=0) and not(endoffile) then
+ begin
+ cur:=c;
+ reload;
+ if byte(cur)+byte(c)<>23 then
+ dec(inputpointer);
+ end
+ else
+ begin
+ { Support all combination of #10 and #13 as line break }
+ if (byte(inputpointer^)+byte(c)=23) then
+ inc(inputpointer);
+ end;
+ { Always return #10 as line break }
+ c:=#10;
+ { increase line counters }
+ lastlinepos:=bufstart+(inputpointer-inputbuffer);
+ inc(line_no);
+ { update linebuffer }
+ if cs_asm_source in aktglobalswitches then
+ inputfile.setline(line_no,lastlinepos);
+ { update for status and call the show status routine,
+ but don't touch aktfilepos ! }
+ oldaktfilepos:=aktfilepos;
+ oldtokenpos:=akttokenpos;
+ gettokenpos; { update for v_status }
+ inc(status.compiledlines);
+ ShowStatus;
+ aktfilepos:=oldaktfilepos;
+ akttokenpos:=oldtokenpos;
+ end;
+ end;
+
+
+ procedure tscannerfile.illegal_char(c:char);
+ var
+ s : string;
+ begin
+ if c in [#32..#255] then
+ s:=''''+c+''''
+ else
+ s:='#'+tostr(ord(c));
+ Message2(scan_f_illegal_char,s,'$'+hexstr(ord(c),2));
+ end;
+
+
+ procedure tscannerfile.end_of_file;
+ begin
+ checkpreprocstack;
+ Message(scan_f_end_of_file);
+ end;
+
+ {-------------------------------------------
+ IF Conditional Handling
+ -------------------------------------------}
+
+ procedure tscannerfile.checkpreprocstack;
+ begin
+ { check for missing ifdefs }
+ while assigned(preprocstack) do
+ begin
+ Message4(scan_e_endif_expected,preprocstring[preprocstack.typ],preprocstack.name,
+ preprocstack.owner.inputfile.name^,tostr(preprocstack.line_nb));
+ poppreprocstack;
+ end;
+ end;
+
+
+ procedure tscannerfile.poppreprocstack;
+ var
+ hp : tpreprocstack;
+ begin
+ if assigned(preprocstack) then
+ begin
+ Message1(scan_c_endif_found,preprocstack.name);
+ hp:=preprocstack.next;
+ preprocstack.free;
+ preprocstack:=hp;
+ end
+ else
+ Message(scan_e_endif_without_if);
+ end;
+
+
+ procedure tscannerfile.ifpreprocstack(atyp : preproctyp;compile_time_predicate:tcompile_time_predicate;messid:longint);
+ var
+ condition: Boolean;
+ valuedescr: String;
+ begin
+ if (preprocstack=nil) or preprocstack.accept then
+ condition:= compile_time_predicate(valuedescr)
+ else
+ begin
+ condition:= false;
+ valuedescr:= '';
+ end;
+ preprocstack:=tpreprocstack.create(atyp, condition, preprocstack);
+ preprocstack.name:=valuedescr;
+ preprocstack.line_nb:=line_no;
+ preprocstack.owner:=self;
+ if preprocstack.accept then
+ Message2(messid,preprocstack.name,'accepted')
+ else
+ Message2(messid,preprocstack.name,'rejected');
+ end;
+
+ procedure tscannerfile.elsepreprocstack;
+ begin
+ if assigned(preprocstack) and
+ (preprocstack.typ<>pp_else) then
+ begin
+ if (preprocstack.typ=pp_elseif) then
+ preprocstack.accept:=false
+ else
+ if (not(assigned(preprocstack.next)) or (preprocstack.next.accept)) then
+ preprocstack.accept:=not preprocstack.accept;
+ preprocstack.typ:=pp_else;
+ preprocstack.line_nb:=line_no;
+ if preprocstack.accept then
+ Message2(scan_c_else_found,preprocstack.name,'accepted')
+ else
+ Message2(scan_c_else_found,preprocstack.name,'rejected');
+ end
+ else
+ Message(scan_e_endif_without_if);
+ end;
+
+ procedure tscannerfile.elseifpreprocstack(compile_time_predicate:tcompile_time_predicate);
+ var
+ valuedescr: String;
+ begin
+ if assigned(preprocstack) and
+ (preprocstack.typ in [pp_if,pp_elseif]) then
+ begin
+ { when the branch is accepted we use pp_elseif so we know that
+ all the next branches need to be rejected. when this branch is still
+ not accepted then leave it at pp_if }
+ if (preprocstack.typ=pp_elseif) then
+ preprocstack.accept:=false
+ else if (preprocstack.typ=pp_if) and preprocstack.accept then
+ begin
+ preprocstack.accept:=false;
+ preprocstack.typ:=pp_elseif;
+ end
+ else if (not(assigned(preprocstack.next)) or (preprocstack.next.accept))
+ and compile_time_predicate(valuedescr) then
+ begin
+ preprocstack.name:=valuedescr;
+ preprocstack.accept:=true;
+ preprocstack.typ:=pp_elseif;
+ end;
+
+ preprocstack.line_nb:=line_no;
+ if preprocstack.accept then
+ Message2(scan_c_else_found,preprocstack.name,'accepted')
+ else
+ Message2(scan_c_else_found,preprocstack.name,'rejected');
+ end
+ else
+ Message(scan_e_endif_without_if);
+ end;
+
+
+ procedure tscannerfile.handleconditional(p:tdirectiveitem);
+ var
+ oldaktfilepos : tfileposinfo;
+ begin
+ oldaktfilepos:=aktfilepos;
+ repeat
+ current_scanner.gettokenpos;
+ p.proc();
+ { accept the text ? }
+ if (current_scanner.preprocstack=nil) or current_scanner.preprocstack.accept then
+ break
+ else
+ begin
+ current_scanner.gettokenpos;
+ Message(scan_c_skipping_until);
+ repeat
+ current_scanner.skipuntildirective;
+ if not (m_mac in aktmodeswitches) then
+ p:=tdirectiveitem(turbo_scannerdirectives.search(current_scanner.readid))
+ else
+ p:=tdirectiveitem(mac_scannerdirectives.search(current_scanner.readid));
+ until assigned(p) and (p.is_conditional);
+ current_scanner.gettokenpos;
+ Message1(scan_d_handling_switch,'$'+p.name);
+ end;
+ until false;
+ aktfilepos:=oldaktfilepos;
+ end;
+
+
+ procedure tscannerfile.handledirectives;
+ var
+ t : tdirectiveitem;
+ hs : string;
+ begin
+ gettokenpos;
+ readchar; {Remove the $}
+ hs:=readid;
+{$ifdef PREPROCWRITE}
+ if parapreprocess then
+ begin
+ t:=Get_Directive(hs);
+ if not(is_conditional(t) or (t=_DIR_DEFINE) or (t=_DIR_UNDEF)) then
+ begin
+ preprocfile^.AddSpace;
+ preprocfile^.Add('{$'+hs+current_scanner.readcomment+'}');
+ exit;
+ end;
+ end;
+{$endif PREPROCWRITE}
+ { skip this directive? }
+ if (ignoredirectives.find(hs)<>nil) then
+ begin
+ if (comment_level>0) then
+ readcomment;
+ { we've read the whole comment }
+ aktcommentstyle:=comment_none;
+ exit;
+ end;
+ if hs='' then
+ begin
+ Message1(scan_w_illegal_switch,'$'+hs);
+ end;
+ { Check for compiler switches }
+ while (length(hs)=1) and (c in ['-','+']) do
+ begin
+ HandleSwitch(hs[1],c);
+ current_scanner.readchar; {Remove + or -}
+ if c=',' then
+ begin
+ current_scanner.readchar; {Remove , }
+ { read next switch, support $v+,$+}
+ hs:=current_scanner.readid;
+ if (hs='') then
+ begin
+ if (c='$') and (m_fpc in aktmodeswitches) then
+ begin
+ current_scanner.readchar; { skip $ }
+ hs:=current_scanner.readid;
+ end;
+ if (hs='') then
+ Message1(scan_w_illegal_directive,'$'+c);
+ end
+ else
+ Message1(scan_d_handling_switch,'$'+hs);
+ end
+ else
+ hs:='';
+ end;
+ { directives may follow switches after a , }
+ if hs<>'' then
+ begin
+ if not (m_mac in aktmodeswitches) then
+ t:=tdirectiveitem(turbo_scannerdirectives.search(hs))
+ else
+ t:=tdirectiveitem(mac_scannerdirectives.search(hs));
+
+ if assigned(t) then
+ begin
+ if t.is_conditional then
+ handleconditional(t)
+ else
+ begin
+ Message1(scan_d_handling_switch,'$'+hs);
+ t.proc();
+ end;
+ end
+ else
+ begin
+ current_scanner.ignoredirectives.insert(hs);
+ Message1(scan_w_illegal_directive,'$'+hs);
+ end;
+ { conditionals already read the comment }
+ if (current_scanner.comment_level>0) then
+ current_scanner.readcomment;
+ { we've read the whole comment }
+ aktcommentstyle:=comment_none;
+ end;
+ end;
+
+
+ procedure tscannerfile.readchar;
+ begin
+ c:=inputpointer^;
+ if c=#0 then
+ reload
+ else
+ inc(inputpointer);
+ end;
+
+
+ procedure tscannerfile.readstring;
+ var
+ i : longint;
+ err : boolean;
+ begin
+ err:=false;
+ i:=0;
+ repeat
+ case c of
+ '_',
+ '0'..'9',
+ 'A'..'Z' :
+ begin
+ if i<255 then
+ begin
+ inc(i);
+ orgpattern[i]:=c;
+ pattern[i]:=c;
+ end
+ else
+ begin
+ if not err then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ err:=true;
+ end;
+ end;
+ c:=inputpointer^;
+ inc(inputpointer);
+ end;
+ 'a'..'z' :
+ begin
+ if i<255 then
+ begin
+ inc(i);
+ orgpattern[i]:=c;
+ pattern[i]:=chr(ord(c)-32)
+ end
+ else
+ begin
+ if not err then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ err:=true;
+ end;
+ end;
+ c:=inputpointer^;
+ inc(inputpointer);
+ end;
+ #0 :
+ reload;
+ else
+ break;
+ end;
+ until false;
+ orgpattern[0]:=chr(i);
+ pattern[0]:=chr(i);
+ end;
+
+
+ procedure tscannerfile.readnumber;
+ var
+ base,
+ i : longint;
+ begin
+ case c of
+ '%' :
+ begin
+ readchar;
+ base:=2;
+ pattern[1]:='%';
+ i:=1;
+ end;
+ '&' :
+ begin
+ readchar;
+ base:=8;
+ pattern[1]:='&';
+ i:=1;
+ end;
+ '$' :
+ begin
+ readchar;
+ base:=16;
+ pattern[1]:='$';
+ i:=1;
+ end;
+ else
+ begin
+ base:=10;
+ i:=0;
+ end;
+ end;
+ while ((base>=10) and (c in ['0'..'9'])) or
+ ((base=16) and (c in ['A'..'F','a'..'f'])) or
+ ((base=8) and (c in ['0'..'7'])) or
+ ((base=2) and (c in ['0'..'1'])) do
+ begin
+ if i<255 then
+ begin
+ inc(i);
+ pattern[i]:=c;
+ end;
+ readchar;
+ end;
+ pattern[0]:=chr(i);
+ end;
+
+
+ function tscannerfile.readid:string;
+ begin
+ readstring;
+ readid:=pattern;
+ end;
+
+
+ function tscannerfile.readval:longint;
+ var
+ l : longint;
+ w : integer;
+ begin
+ readnumber;
+ val(pattern,l,w);
+ readval:=l;
+ end;
+
+
+ function tscannerfile.readval_asstring:string;
+ begin
+ readnumber;
+ readval_asstring:=pattern;
+ end;
+
+
+ function tscannerfile.readcomment:string;
+ var
+ i : longint;
+ begin
+ i:=0;
+ repeat
+ case c of
+ '{' :
+ begin
+ if aktcommentstyle=comment_tp then
+ inc_comment_level;
+ end;
+ '}' :
+ begin
+ if aktcommentstyle=comment_tp then
+ begin
+ readchar;
+ dec_comment_level;
+ if comment_level=0 then
+ break
+ else
+ continue;
+ end;
+ end;
+ '*' :
+ begin
+ if aktcommentstyle=comment_oldtp then
+ begin
+ readchar;
+ if c=')' then
+ begin
+ readchar;
+ dec_comment_level;
+ break;
+ end
+ else
+ { Add both characters !!}
+ if (i<255) then
+ begin
+ inc(i);
+ readcomment[i]:='*';
+ if (i<255) then
+ begin
+ inc(i);
+ readcomment[i]:='*';
+ end;
+ end;
+ end
+ else
+ { Not old TP comment, so add...}
+ begin
+ if (i<255) then
+ begin
+ inc(i);
+ readcomment[i]:='*';
+ end;
+ end;
+ end;
+ #10,#13 :
+ linebreak;
+ #26 :
+ end_of_file;
+ else
+ begin
+ if (i<255) then
+ begin
+ inc(i);
+ readcomment[i]:=c;
+ end;
+ end;
+ end;
+ readchar;
+ until false;
+ readcomment[0]:=chr(i);
+ end;
+
+
+ function tscannerfile.readquotedstring:string;
+ var
+ i : longint;
+ msgwritten : boolean;
+ begin
+ i:=0;
+ msgwritten:=false;
+ if (c='''') then
+ begin
+ repeat
+ readchar;
+ case c of
+ #26 :
+ end_of_file;
+ #10,#13 :
+ Message(scan_f_string_exceeds_line);
+ '''' :
+ begin
+ readchar;
+ if c<>'''' then
+ break;
+ end;
+ end;
+ if i<255 then
+ begin
+ inc(i);
+ result[i]:=c;
+ end
+ else
+ begin
+ if not msgwritten then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ msgwritten:=true;
+ end;
+ end;
+ until false;
+ end;
+ result[0]:=chr(i);
+ end;
+
+
+ function tscannerfile.readstate:char;
+ var
+ state : char;
+ begin
+ state:=' ';
+ if c=' ' then
+ begin
+ current_scanner.skipspace;
+ current_scanner.readid;
+ if pattern='ON' then
+ state:='+'
+ else
+ if pattern='OFF' then
+ state:='-';
+ end
+ else
+ state:=c;
+ if not (state in ['+','-']) then
+ Message(scan_e_wrong_switch_toggle);
+ readstate:=state;
+ end;
+
+
+ function tscannerfile.readstatedefault:char;
+ var
+ state : char;
+ begin
+ state:=' ';
+ if c=' ' then
+ begin
+ current_scanner.skipspace;
+ current_scanner.readid;
+ if pattern='ON' then
+ state:='+'
+ else
+ if pattern='OFF' then
+ state:='-'
+ else
+ if pattern='DEFAULT' then
+ state:='*';
+ end
+ else
+ state:=c;
+ if not (state in ['+','-','*']) then
+ Message(scan_e_wrong_switch_toggle_default);
+ readstatedefault:=state;
+ end;
+
+
+ procedure tscannerfile.skipspace;
+ begin
+ repeat
+ case c of
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ break;
+ continue;
+ end;
+ #10,
+ #13 :
+ linebreak;
+ #9,#11,#12,' ' :
+ ;
+ else
+ break;
+ end;
+ readchar;
+ until false;
+ end;
+
+
+ procedure tscannerfile.skipuntildirective;
+ var
+ found : longint;
+ next_char_loaded : boolean;
+ begin
+ found:=0;
+ next_char_loaded:=false;
+ repeat
+ case c of
+ #10,
+ #13 :
+ linebreak;
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ end_of_file;
+ continue;
+ end;
+ '{' :
+ begin
+ if (aktcommentstyle in [comment_tp,comment_none]) then
+ begin
+ aktcommentstyle:=comment_tp;
+ if (comment_level=0) then
+ found:=1;
+ inc_comment_level;
+ end;
+ end;
+ '*' :
+ begin
+ if (aktcommentstyle=comment_oldtp) then
+ begin
+ readchar;
+ if c=')' then
+ begin
+ dec_comment_level;
+ found:=0;
+ aktcommentstyle:=comment_none;
+ end
+ else
+ next_char_loaded:=true;
+ end
+ else
+ found := 0;
+ end;
+ '}' :
+ begin
+ if (aktcommentstyle=comment_tp) then
+ begin
+ dec_comment_level;
+ if (comment_level=0) then
+ aktcommentstyle:=comment_none;
+ found:=0;
+ end;
+ end;
+ '$' :
+ begin
+ if found=1 then
+ found:=2;
+ end;
+ '''' :
+ if (aktcommentstyle=comment_none) then
+ begin
+ repeat
+ readchar;
+ case c of
+ #26 :
+ end_of_file;
+ #10,#13 :
+ break;
+ '''' :
+ begin
+ readchar;
+ if c<>'''' then
+ begin
+ next_char_loaded:=true;
+ break;
+ end;
+ end;
+ end;
+ until false;
+ end;
+ '(' :
+ begin
+ if (aktcommentstyle=comment_none) then
+ begin
+ readchar;
+ if c='*' then
+ begin
+ readchar;
+ if c='$' then
+ begin
+ found:=2;
+ inc_comment_level;
+ aktcommentstyle:=comment_oldtp;
+ end
+ else
+ begin
+ skipoldtpcomment;
+ next_char_loaded:=true;
+ end;
+ end
+ else
+ next_char_loaded:=true;
+ end
+ else
+ found:=0;
+ end;
+ '/' :
+ begin
+ if (aktcommentstyle=comment_none) then
+ begin
+ readchar;
+ if c='/' then
+ skipdelphicomment;
+ next_char_loaded:=true;
+ end
+ else
+ found:=0;
+ end;
+ else
+ found:=0;
+ end;
+ if next_char_loaded then
+ next_char_loaded:=false
+ else
+ readchar;
+ until (found=2);
+ end;
+
+
+{****************************************************************************
+ Comment Handling
+****************************************************************************}
+
+ procedure tscannerfile.skipcomment;
+ begin
+ aktcommentstyle:=comment_tp;
+ readchar;
+ inc_comment_level;
+ { handle compiler switches }
+ if (c='$') then
+ handledirectives;
+ { handle_switches can dec comment_level, }
+ while (comment_level>0) do
+ begin
+ case c of
+ '{' :
+ inc_comment_level;
+ '}' :
+ dec_comment_level;
+ #10,#13 :
+ linebreak;
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ end_of_file;
+ continue;
+ end;
+ end;
+ readchar;
+ end;
+ aktcommentstyle:=comment_none;
+ end;
+
+
+ procedure tscannerfile.skipdelphicomment;
+ begin
+ aktcommentstyle:=comment_delphi;
+ inc_comment_level;
+ readchar;
+ { this is not supported }
+ if c='$' then
+ Message(scan_w_wrong_styled_switch);
+ { skip comment }
+ while not (c in [#10,#13,#26]) do
+ readchar;
+ dec_comment_level;
+ aktcommentstyle:=comment_none;
+ end;
+
+
+ procedure tscannerfile.skipoldtpcomment;
+ var
+ found : longint;
+ begin
+ aktcommentstyle:=comment_oldtp;
+ inc_comment_level;
+ { only load a char if last already processed,
+ was cause of bug1634 PM }
+ if c=#0 then
+ readchar;
+ { this is now supported }
+ if (c='$') then
+ handledirectives;
+ { skip comment }
+ while (comment_level>0) do
+ begin
+ found:=0;
+ repeat
+ case c of
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ end_of_file;
+ continue;
+ end;
+ #10,#13 :
+ linebreak;
+ '*' :
+ begin
+ if found=3 then
+ found:=4
+ else
+ found:=1;
+ end;
+ ')' :
+ begin
+ if found in [1,4] then
+ begin
+ dec_comment_level;
+ if comment_level=0 then
+ found:=2
+ else
+ found:=0;
+ end;
+ end;
+ '(' :
+ begin
+ if found=4 then
+ inc_comment_level;
+ found:=3;
+ end;
+ else
+ begin
+ if found=4 then
+ inc_comment_level;
+ found:=0;
+ end;
+ end;
+ readchar;
+ until (found=2);
+ end;
+ aktcommentstyle:=comment_none;
+ end;
+
+
+
+{****************************************************************************
+ Token Scanner
+****************************************************************************}
+
+ procedure tscannerfile.readtoken;
+ var
+ code : integer;
+ len,
+ low,high,mid : longint;
+ w : word;
+ m : longint;
+ mac : tmacro;
+ asciinr : string[6];
+ msgwritten,
+ iswidestring : boolean;
+ label
+ exit_label;
+ begin
+ if localswitcheschanged then
+ begin
+ aktlocalswitches:=nextaktlocalswitches;
+ localswitcheschanged:=false;
+ end;
+ { was there already a token read, then return that token }
+ if nexttoken<>NOTOKEN then
+ begin
+ token:=nexttoken;
+ nexttoken:=NOTOKEN;
+ goto exit_label;
+ end;
+
+ { Skip all spaces and comments }
+ repeat
+ case c of
+ '{' :
+ skipcomment;
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ break;
+ end;
+ ' ',#9..#13 :
+ begin
+{$ifdef PREPROCWRITE}
+ if parapreprocess then
+ begin
+ if c=#10 then
+ preprocfile.eolfound:=true
+ else
+ preprocfile.spacefound:=true;
+ end;
+{$endif PREPROCWRITE}
+ skipspace;
+ end
+ else
+ break;
+ end;
+ until false;
+
+ { Save current token position, for EOF its already loaded }
+ if c<>#26 then
+ gettokenpos;
+
+ { Check first for a identifier/keyword, this is 20+% faster (PFV) }
+ if c in ['A'..'Z','a'..'z','_'] then
+ begin
+ readstring;
+ token:=_ID;
+ idtoken:=_ID;
+ { keyword or any other known token,
+ pattern is always uppercased }
+ if (pattern[1]<>'_') and (length(pattern) in [tokenlenmin..tokenlenmax]) then
+ begin
+ low:=ord(tokenidx^[length(pattern),pattern[1]].first);
+ high:=ord(tokenidx^[length(pattern),pattern[1]].last);
+ while low<high do
+ begin
+ mid:=(high+low+1) shr 1;
+ if pattern<tokeninfo^[ttoken(mid)].str then
+ high:=mid-1
+ else
+ low:=mid;
+ end;
+ with tokeninfo^[ttoken(high)] do
+ if pattern=str then
+ begin
+ if keyword in aktmodeswitches then
+ if op=NOTOKEN then
+ token:=ttoken(high)
+ else
+ token:=op;
+ idtoken:=ttoken(high);
+ end;
+ end;
+ { Only process identifiers and not keywords }
+ if token=_ID then
+ begin
+ { this takes some time ... }
+ if (cs_support_macro in aktmoduleswitches) then
+ begin
+ mac:=tmacro(search_macro(pattern));
+ if assigned(mac) and (not mac.is_compiler_var) and (assigned(mac.buftext)) then
+ begin
+ if yylexcount<max_macro_nesting then
+ begin
+ mac.is_used:=true;
+ inc(yylexcount);
+ insertmacro(pattern,mac.buftext,mac.buflen,
+ mac.fileinfo.line,mac.fileinfo.fileindex);
+ { handle empty macros }
+ if c=#0 then
+ reload;
+ readtoken;
+ { that's all folks }
+ dec(yylexcount);
+ exit;
+ end
+ else
+ Message(scan_w_macro_too_deep);
+ end;
+ end;
+ end;
+ { return token }
+ goto exit_label;
+ end
+ else
+ begin
+ idtoken:=_NOID;
+ case c of
+
+ '$' :
+ begin
+ readnumber;
+ token:=_INTCONST;
+ goto exit_label;
+ end;
+
+ '%' :
+ begin
+ if not(m_fpc in aktmodeswitches) then
+ Illegal_Char(c)
+ else
+ begin
+ readnumber;
+ token:=_INTCONST;
+ goto exit_label;
+ end;
+ end;
+
+ '&' :
+ begin
+ if m_fpc in aktmodeswitches then
+ begin
+ readnumber;
+ token:=_INTCONST;
+ goto exit_label;
+ end
+ else if m_mac in aktmodeswitches then
+ begin
+ readchar;
+ token:=_AMPERSAND;
+ goto exit_label;
+ end
+ else
+ Illegal_Char(c);
+ end;
+
+ '0'..'9' :
+ begin
+ readnumber;
+ if (c in ['.','e','E']) then
+ begin
+ { first check for a . }
+ if c='.' then
+ begin
+ readchar;
+ { is it a .. from a range? }
+ case c of
+ '.' :
+ begin
+ readchar;
+ token:=_INTCONST;
+ nexttoken:=_POINTPOINT;
+ goto exit_label;
+ end;
+ ')' :
+ begin
+ readchar;
+ token:=_INTCONST;
+ nexttoken:=_RECKKLAMMER;
+ goto exit_label;
+ end;
+ end;
+ { insert the number after the . }
+ pattern:=pattern+'.';
+ while c in ['0'..'9'] do
+ begin
+ pattern:=pattern+c;
+ readchar;
+ end;
+ end;
+ { E can also follow after a point is scanned }
+ if c in ['e','E'] then
+ begin
+ pattern:=pattern+'E';
+ readchar;
+ if c in ['-','+'] then
+ begin
+ pattern:=pattern+c;
+ readchar;
+ end;
+ if not(c in ['0'..'9']) then
+ Illegal_Char(c);
+ while c in ['0'..'9'] do
+ begin
+ pattern:=pattern+c;
+ readchar;
+ end;
+ end;
+ token:=_REALNUMBER;
+ goto exit_label;
+ end;
+ token:=_INTCONST;
+ goto exit_label;
+ end;
+
+ ';' :
+ begin
+ readchar;
+ token:=_SEMICOLON;
+ goto exit_label;
+ end;
+
+ '[' :
+ begin
+ readchar;
+ token:=_LECKKLAMMER;
+ goto exit_label;
+ end;
+
+ ']' :
+ begin
+ readchar;
+ token:=_RECKKLAMMER;
+ goto exit_label;
+ end;
+
+ '(' :
+ begin
+ readchar;
+ case c of
+ '*' :
+ begin
+ c:=#0;{Signal skipoldtpcomment to reload a char }
+ skipoldtpcomment;
+ readtoken;
+ exit;
+ end;
+ '.' :
+ begin
+ readchar;
+ token:=_LECKKLAMMER;
+ goto exit_label;
+ end;
+ end;
+ token:=_LKLAMMER;
+ goto exit_label;
+ end;
+
+ ')' :
+ begin
+ readchar;
+ token:=_RKLAMMER;
+ goto exit_label;
+ end;
+
+ '+' :
+ begin
+ readchar;
+ if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
+ begin
+ readchar;
+ token:=_PLUSASN;
+ goto exit_label;
+ end;
+ token:=_PLUS;
+ goto exit_label;
+ end;
+
+ '-' :
+ begin
+ readchar;
+ if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
+ begin
+ readchar;
+ token:=_MINUSASN;
+ goto exit_label;
+ end;
+ token:=_MINUS;
+ goto exit_label;
+ end;
+
+ ':' :
+ begin
+ readchar;
+ if c='=' then
+ begin
+ readchar;
+ token:=_ASSIGNMENT;
+ goto exit_label;
+ end;
+ token:=_COLON;
+ goto exit_label;
+ end;
+
+ '*' :
+ begin
+ readchar;
+ if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
+ begin
+ readchar;
+ token:=_STARASN;
+ end
+ else
+ if c='*' then
+ begin
+ readchar;
+ token:=_STARSTAR;
+ end
+ else
+ token:=_STAR;
+ goto exit_label;
+ end;
+
+ '/' :
+ begin
+ readchar;
+ case c of
+ '=' :
+ begin
+ if (cs_support_c_operators in aktmoduleswitches) then
+ begin
+ readchar;
+ token:=_SLASHASN;
+ goto exit_label;
+ end;
+ end;
+ '/' :
+ begin
+ skipdelphicomment;
+ readtoken;
+ exit;
+ end;
+ end;
+ token:=_SLASH;
+ goto exit_label;
+ end;
+
+ '|' :
+ if m_mac in aktmodeswitches then
+ begin
+ readchar;
+ token:=_PIPE;
+ goto exit_label;
+ end
+ else
+ Illegal_Char(c);
+
+ '=' :
+ begin
+ readchar;
+ token:=_EQUAL;
+ goto exit_label;
+ end;
+
+ '.' :
+ begin
+ readchar;
+ case c of
+ '.' :
+ begin
+ readchar;
+ case c of
+ '.' :
+ begin
+ readchar;
+ token:=_POINTPOINTPOINT;
+ goto exit_label;
+ end;
+ else
+ begin
+ token:=_POINTPOINT;
+ goto exit_label;
+ end;
+ end;
+ end;
+ ')' :
+ begin
+ readchar;
+ token:=_RECKKLAMMER;
+ goto exit_label;
+ end;
+ end;
+ token:=_POINT;
+ goto exit_label;
+ end;
+
+ '@' :
+ begin
+ readchar;
+ token:=_KLAMMERAFFE;
+ goto exit_label;
+ end;
+
+ ',' :
+ begin
+ readchar;
+ token:=_COMMA;
+ goto exit_label;
+ end;
+
+ '''','#','^' :
+ begin
+ len:=0;
+ msgwritten:=false;
+ pattern:='';
+ iswidestring:=false;
+ if c='^' then
+ begin
+ readchar;
+ c:=upcase(c);
+ if (block_type=bt_type) or
+ (lasttoken=_ID) or (lasttoken=_NIL) or
+ (lasttoken=_RKLAMMER) or (lasttoken=_RECKKLAMMER) or (lasttoken=_CARET) then
+ begin
+ token:=_CARET;
+ goto exit_label;
+ end
+ else
+ begin
+ inc(len);
+ if c<#64 then
+ pattern[len]:=chr(ord(c)+64)
+ else
+ pattern[len]:=chr(ord(c)-64);
+ readchar;
+ end;
+ end;
+ repeat
+ case c of
+ '#' :
+ begin
+ readchar; { read # }
+ if c='$' then
+ begin
+ readchar; { read leading $ }
+ asciinr:='$';
+ while (upcase(c) in ['A'..'F','0'..'9']) and (length(asciinr)<6) do
+ begin
+ asciinr:=asciinr+c;
+ readchar;
+ end;
+ end
+ else
+ begin
+ asciinr:='';
+ while (c in ['0'..'9']) and (length(asciinr)<6) do
+ begin
+ asciinr:=asciinr+c;
+ readchar;
+ end;
+ end;
+ val(asciinr,m,code);
+ if (asciinr='') or (code<>0) then
+ Message(scan_e_illegal_char_const)
+ else if (m<0) or (m>255) or (length(asciinr)>3) then
+ begin
+ if (m>=0) and (m<=65535) then
+ begin
+ if not iswidestring then
+ begin
+ ascii2unicode(@pattern[1],len,patternw);
+ iswidestring:=true;
+ len:=0;
+ end;
+ concatwidestringchar(patternw,tcompilerwidechar(m));
+ end
+ else
+ Message(scan_e_illegal_char_const)
+ end
+ else if iswidestring then
+ concatwidestringchar(patternw,asciichar2unicode(char(m)))
+ else
+ begin
+ if len<255 then
+ begin
+ inc(len);
+ pattern[len]:=chr(m);
+ end
+ else
+ begin
+ if not msgwritten then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ msgwritten:=true;
+ end;
+ end;
+ end;
+ end;
+ '''' :
+ begin
+ repeat
+ readchar;
+ case c of
+ #26 :
+ end_of_file;
+ #10,#13 :
+ Message(scan_f_string_exceeds_line);
+ '''' :
+ begin
+ readchar;
+ if c<>'''' then
+ break;
+ end;
+ end;
+ { interpret as utf-8 string? }
+ if (ord(c)>=$80) and (aktsourcecodepage='utf8') then
+ begin
+ { convert existing string to an utf-8 string }
+ if not iswidestring then
+ begin
+ ascii2unicode(@pattern[1],len,patternw);
+ iswidestring:=true;
+ len:=0;
+ end;
+ { four or more chars aren't handled }
+ if (ord(c) and $f0)=$f0 then
+ message(scan_e_utf8_bigger_than_65535)
+ { three chars }
+ else if (ord(c) and $e0)=$e0 then
+ begin
+ w:=ord(c) and $f;
+ readchar;
+ if (ord(c) and $c0)<>$80 then
+ message(scan_e_utf8_malformed);
+ w:=(w shl 6) or (ord(c) and $3f);
+ readchar;
+ if (ord(c) and $c0)<>$80 then
+ message(scan_e_utf8_malformed);
+ w:=(w shl 6) or (ord(c) and $3f);
+ concatwidestringchar(patternw,w);
+ end
+ { two chars }
+ else if (ord(c) and $c0)<>0 then
+ begin
+ w:=ord(c) and $1f;
+ readchar;
+ if (ord(c) and $c0)<>$80 then
+ message(scan_e_utf8_malformed);
+ w:=(w shl 6) or (ord(c) and $3f);
+ concatwidestringchar(patternw,w);
+ end
+ { illegal }
+ else if (ord(c) and $80)<>0 then
+ message(scan_e_utf8_malformed)
+ else
+ concatwidestringchar(patternw,tcompilerwidechar(c))
+ end
+ else if iswidestring then
+ begin
+ if aktsourcecodepage='utf8' then
+ concatwidestringchar(patternw,ord(c))
+ else
+ concatwidestringchar(patternw,asciichar2unicode(c))
+ end
+ else
+ begin
+ if len<255 then
+ begin
+ inc(len);
+ pattern[len]:=c;
+ end
+ else
+ begin
+ if not msgwritten then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ msgwritten:=true;
+ end;
+ end;
+ end;
+ until false;
+ end;
+ '^' :
+ begin
+ readchar;
+ c:=upcase(c);
+ if c<#64 then
+ c:=chr(ord(c)+64)
+ else
+ c:=chr(ord(c)-64);
+
+ if iswidestring then
+ concatwidestringchar(patternw,asciichar2unicode(c))
+ else
+ begin
+ if len<255 then
+ begin
+ inc(len);
+ pattern[len]:=c;
+ end
+ else
+ begin
+ if not msgwritten then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ msgwritten:=true;
+ end;
+ end;
+ end;
+
+ readchar;
+ end;
+ else
+ break;
+ end;
+ until false;
+ { strings with length 1 become const chars }
+ if iswidestring then
+ begin
+ if patternw^.len=1 then
+ token:=_CWCHAR
+ else
+ token:=_CWSTRING;
+ end
+ else
+ begin
+ pattern[0]:=chr(len);
+ if len=1 then
+ token:=_CCHAR
+ else
+ token:=_CSTRING;
+ end;
+ goto exit_label;
+ end;
+
+ '>' :
+ begin
+ readchar;
+ case c of
+ '=' :
+ begin
+ readchar;
+ token:=_GTE;
+ goto exit_label;
+ end;
+ '>' :
+ begin
+ readchar;
+ token:=_OP_SHR;
+ goto exit_label;
+ end;
+ '<' :
+ begin { >< is for a symetric diff for sets }
+ readchar;
+ token:=_SYMDIF;
+ goto exit_label;
+ end;
+ end;
+ token:=_GT;
+ goto exit_label;
+ end;
+
+ '<' :
+ begin
+ readchar;
+ case c of
+ '>' :
+ begin
+ readchar;
+ token:=_UNEQUAL;
+ goto exit_label;
+ end;
+ '=' :
+ begin
+ readchar;
+ token:=_LTE;
+ goto exit_label;
+ end;
+ '<' :
+ begin
+ readchar;
+ token:=_OP_SHL;
+ goto exit_label;
+ end;
+ end;
+ token:=_LT;
+ goto exit_label;
+ end;
+
+ #26 :
+ begin
+ token:=_EOF;
+ checkpreprocstack;
+ goto exit_label;
+ end;
+ else
+ Illegal_Char(c);
+ end;
+ end;
+exit_label:
+ lasttoken:=token;
+ end;
+
+
+ function tscannerfile.readpreproc:ttoken;
+ begin
+ skipspace;
+ case c of
+ '_',
+ 'A'..'Z',
+ 'a'..'z' :
+ begin
+ current_scanner.preproc_pattern:=readid;
+ readpreproc:=_ID;
+ end;
+ '0'..'9' :
+ begin
+ current_scanner.preproc_pattern:=readval_asstring;
+ { realnumber? }
+ if c='.' then
+ begin
+ readchar;
+ while c in ['0'..'9'] do
+ begin
+ current_scanner.preproc_pattern:=current_scanner.preproc_pattern+c;
+ readchar;
+ end;
+ end;
+ readpreproc:=_ID;
+ end;
+ '$','%','&' :
+ begin
+ current_scanner.preproc_pattern:=readval_asstring;
+ readpreproc:=_ID;
+ end;
+ ',' :
+ begin
+ readchar;
+ readpreproc:=_COMMA;
+ end;
+ '}' :
+ begin
+ readpreproc:=_END;
+ end;
+ '(' :
+ begin
+ readchar;
+ readpreproc:=_LKLAMMER;
+ end;
+ ')' :
+ begin
+ readchar;
+ readpreproc:=_RKLAMMER;
+ end;
+ '[' :
+ begin
+ readchar;
+ readpreproc:=_LECKKLAMMER;
+ end;
+ ']' :
+ begin
+ readchar;
+ readpreproc:=_RECKKLAMMER;
+ end;
+ '+' :
+ begin
+ readchar;
+ readpreproc:=_PLUS;
+ end;
+ '-' :
+ begin
+ readchar;
+ readpreproc:=_MINUS;
+ end;
+ '*' :
+ begin
+ readchar;
+ readpreproc:=_STAR;
+ end;
+ '/' :
+ begin
+ readchar;
+ readpreproc:=_SLASH;
+ end;
+ '=' :
+ begin
+ readchar;
+ readpreproc:=_EQUAL;
+ end;
+ '>' :
+ begin
+ readchar;
+ if c='=' then
+ begin
+ readchar;
+ readpreproc:=_GTE;
+ end
+ else
+ readpreproc:=_GT;
+ end;
+ '<' :
+ begin
+ readchar;
+ case c of
+ '>' :
+ begin
+ readchar;
+ readpreproc:=_UNEQUAL;
+ end;
+ '=' :
+ begin
+ readchar;
+ readpreproc:=_LTE;
+ end;
+ else
+ readpreproc:=_LT;
+ end;
+ end;
+ #26 :
+ begin
+ readpreproc:=_EOF;
+ checkpreprocstack;
+ end;
+ else
+ Illegal_Char(c);
+ end;
+ end;
+
+
+ function tscannerfile.asmgetcharstart : char;
+ begin
+ { return first the character already
+ available in c }
+ lastasmgetchar:=c;
+ result:=asmgetchar;
+ end;
+
+
+ function tscannerfile.asmgetchar : char;
+ begin
+ if lastasmgetchar<>#0 then
+ begin
+ c:=lastasmgetchar;
+ lastasmgetchar:=#0;
+ end
+ else
+ readchar;
+ if in_asm_string then
+ begin
+ asmgetchar:=c;
+ exit;
+ end;
+ repeat
+ case c of
+{$ifndef arm}
+ // the { ... } is used in ARM assembler to define register sets, so we can't used
+ // it as comment, either (* ... *), /* ... */ or // ... should be used instead
+ '{' :
+ skipcomment;
+{$endif arm}
+ #10,#13 :
+ begin
+ linebreak;
+ asmgetchar:=c;
+ exit;
+ end;
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ end_of_file;
+ continue;
+ end;
+ '/' :
+ begin
+ readchar;
+ if c='/' then
+ skipdelphicomment
+ else
+ begin
+ asmgetchar:='/';
+ lastasmgetchar:=c;
+ exit;
+ end;
+ end;
+ '(' :
+ begin
+ readchar;
+ if c='*' then
+ begin
+ c:=#0;{Signal skipoldtpcomment to reload a char }
+ skipoldtpcomment;
+ end
+ else
+ begin
+ asmgetchar:='(';
+ lastasmgetchar:=c;
+ exit;
+ end;
+ end;
+ else
+ begin
+ asmgetchar:=c;
+ exit;
+ end;
+ end;
+ until false;
+ end;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure AddDirective(const s:string; dm: tdirectivemode; p:tdirectiveproc);
+ begin
+ if dm in [directive_all, directive_turbo] then
+ turbo_scannerdirectives.insert(tdirectiveitem.create(s,p));
+ if dm in [directive_all, directive_mac] then
+ mac_scannerdirectives.insert(tdirectiveitem.create(s,p));
+ end;
+
+ procedure AddConditional(const s:string; dm: tdirectivemode; p:tdirectiveproc);
+ begin
+ if dm in [directive_all, directive_turbo] then
+ turbo_scannerdirectives.insert(tdirectiveitem.createcond(s,p));
+ if dm in [directive_all, directive_mac] then
+ mac_scannerdirectives.insert(tdirectiveitem.createcond(s,p));
+ end;
+
+{*****************************************************************************
+ Initialization
+*****************************************************************************}
+
+ procedure InitScanner;
+ begin
+ InitWideString(patternw);
+ turbo_scannerdirectives:=TDictionary.Create;
+ mac_scannerdirectives:=TDictionary.Create;
+
+ { Common directives and conditionals }
+ AddDirective('I',directive_all, @dir_include);
+ AddDirective('DEFINE',directive_all, @dir_define);
+ AddDirective('UNDEF',directive_all, @dir_undef);
+
+ AddConditional('IF',directive_all, @dir_if);
+ AddConditional('IFDEF',directive_all, @dir_ifdef);
+ AddConditional('IFNDEF',directive_all, @dir_ifndef);
+ AddConditional('ELSE',directive_all, @dir_else);
+ AddConditional('ELSEIF',directive_all, @dir_elseif);
+ AddConditional('ENDIF',directive_all, @dir_endif);
+
+ { Directives and conditionals for all modes except mode macpas}
+ AddDirective('INCLUDE',directive_turbo, @dir_include);
+ AddDirective('LIBPREFIX',directive_turbo, @dir_libprefix);
+ AddDirective('LIBSUFFIX',directive_turbo, @dir_libsuffix);
+ AddDirective('EXTENSION',directive_turbo, @dir_extension);
+
+ AddConditional('IFEND',directive_turbo, @dir_endif);
+ AddConditional('IFOPT',directive_turbo, @dir_ifopt);
+
+ { Directives and conditionals for mode macpas: }
+ AddDirective('SETC',directive_mac, @dir_setc);
+ AddDirective('DEFINEC',directive_mac, @dir_definec);
+ AddDirective('UNDEFC',directive_mac, @dir_undef);
+
+ AddConditional('IFC',directive_mac, @dir_if);
+ AddConditional('ELSEC',directive_mac, @dir_else);
+ AddConditional('ELIFC',directive_mac, @dir_elseif);
+ AddConditional('ENDC',directive_mac, @dir_endif);
+ end;
+
+
+ procedure DoneScanner;
+ begin
+ turbo_scannerdirectives.Free;
+ mac_scannerdirectives.Free;
+ DoneWideString(patternw);
+ end;
+
+
+end.
diff --git a/compiler/script.pas b/compiler/script.pas
new file mode 100644
index 0000000000..1b9a05ad4e
--- /dev/null
+++ b/compiler/script.pas
@@ -0,0 +1,502 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit handles the writing of script files
+
+ 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 script;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses;
+
+type
+ TScript=class
+ fn : string[100];
+ data : TStringList;
+ executable : boolean;
+ constructor Create(const s:string);
+ constructor CreateExec(const s:string);
+ destructor Destroy;override;
+ procedure AddStart(const s:string);
+ procedure Add(const s:string);
+ Function Empty:boolean;
+ procedure WriteToDisk;virtual;
+ end;
+
+ TAsmScript = class (TScript)
+ Constructor Create(Const ScriptName : String); virtual;
+ Procedure AddAsmCommand (Const Command, Options,FileName : String);virtual;abstract;
+ Procedure AddLinkCommand (Const Command, Options, FileName : String);virtual;abstract;
+ Procedure AddDeleteCommand (Const FileName : String);virtual;abstract;
+ Procedure AddDeleteDirCommand (Const FileName : String);virtual;abstract;
+ end;
+
+ TAsmScriptDos = class (TAsmScript)
+ Constructor Create (Const ScriptName : String); override;
+ Procedure AddAsmCommand (Const Command, Options,FileName : String);override;
+ Procedure AddLinkCommand (Const Command, Options, FileName : String);override;
+ Procedure AddDeleteCommand (Const FileName : String);override;
+ Procedure AddDeleteDirCommand (Const FileName : String);override;
+ Procedure WriteToDisk;override;
+ end;
+
+ TAsmScriptAmiga = class (TAsmScript)
+ Constructor Create (Const ScriptName : String); override;
+ Procedure AddAsmCommand (Const Command, Options,FileName : String);override;
+ Procedure AddLinkCommand (Const Command, Options, FileName : String);override;
+ Procedure AddDeleteCommand (Const FileName : String);override;
+ Procedure AddDeleteDirCommand (Const FileName : String);override;
+ Procedure WriteToDisk;override;
+ end;
+
+ TAsmScriptUnix = class (TAsmScript)
+ Constructor Create (Const ScriptName : String);override;
+ Procedure AddAsmCommand (Const Command, Options,FileName : String);override;
+ Procedure AddLinkCommand (Const Command, Options, FileName : String);override;
+ Procedure AddDeleteCommand (Const FileName : String);override;
+ Procedure AddDeleteDirCommand (Const FileName : String);override;
+ Procedure WriteToDisk;override;
+ end;
+
+ TAsmScriptMPW = class (TAsmScript)
+ Constructor Create (Const ScriptName : String); override;
+ Procedure AddAsmCommand (Const Command, Options,FileName : String);override;
+ Procedure AddLinkCommand (Const Command, Options, FileName : String);override;
+ Procedure AddDeleteCommand (Const FileName : String);override;
+ Procedure AddDeleteDirCommand (Const FileName : String);override;
+ Procedure WriteToDisk;override;
+ end;
+
+ TLinkRes = Class (TScript)
+ procedure Add(const s:string);
+ procedure AddFileName(const s:string);
+ end;
+
+var
+ AsmRes : TAsmScript;
+
+Function ScriptFixFileName(const s:string):string;
+Procedure GenerateAsmRes(const st : string);
+
+
+implementation
+
+uses
+{$ifdef hasUnix}
+ {$ifdef havelinuxrtl10}
+ Linux,
+ {$else}
+ BaseUnix,
+ {$endif}
+{$endif}
+ cutils,
+ globtype,globals,systems,verbose;
+
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ Function ScriptFixFileName(const s:string):string;
+ begin
+ if cs_link_on_target in aktglobalswitches then
+ ScriptFixFileName:=TargetFixFileName(s)
+ else
+ ScriptFixFileName:=FixFileName(s);
+ end;
+
+{****************************************************************************
+ TScript
+****************************************************************************}
+
+constructor TScript.Create(const s:string);
+begin
+ fn:=FixFileName(s);
+ executable:=false;
+ data:=TStringList.Create;
+end;
+
+
+constructor TScript.CreateExec(const s:string);
+begin
+ fn:=FixFileName(s);
+ if cs_link_on_target in aktglobalswitches then
+ fn:=AddExtension(fn,target_info.scriptext)
+ else
+ fn:=AddExtension(fn,source_info.scriptext);
+ executable:=true;
+ data:=TStringList.Create;
+end;
+
+
+destructor TScript.Destroy;
+begin
+ data.Free;
+end;
+
+
+procedure TScript.AddStart(const s:string);
+begin
+ data.Insert(s);
+end;
+
+
+procedure TScript.Add(const s:string);
+begin
+ data.Concat(s);
+end;
+
+
+Function TScript.Empty:boolean;
+begin
+ Empty:=Data.Empty;
+end;
+
+procedure TScript.WriteToDisk;
+var
+ t : file;
+ i : longint;
+ s : string;
+ le: string[2];
+
+begin
+ Assign(t,fn);
+ if cs_link_on_target in aktglobalswitches then
+ le:= target_info.newline
+ else
+ le:= source_info.newline;
+
+ {$I-}
+ Rewrite(t,1);
+ if ioresult<>0 then
+ exit;
+ while not data.Empty do
+ begin
+ s:=data.GetFirst;
+ Blockwrite(t,s[1],length(s),i);
+ Blockwrite(t,le[1],length(le),i);
+ end;
+ Close(t);
+ {$I+}
+ i:=ioresult;
+{$ifdef hasUnix}
+ if executable then
+ {$ifdef havelinuxrtl10}ChMod{$else}fpchmod{$endif}(fn,493);
+{$endif}
+end;
+
+{****************************************************************************
+ Asm Response
+****************************************************************************}
+
+Constructor TAsmScript.Create (Const ScriptName : String);
+begin
+ Inherited CreateExec(ScriptName);
+end;
+
+
+{****************************************************************************
+ DOS Asm Response
+****************************************************************************}
+
+Constructor TAsmScriptDos.Create (Const ScriptName : String);
+begin
+ Inherited Create(ScriptName);
+end;
+
+
+Procedure TAsmScriptDos.AddAsmCommand (Const Command, Options,FileName : String);
+begin
+ if FileName<>'' then
+ begin
+ Add('SET THEFILE='+ScriptFixFileName(FileName));
+ Add('echo Assembling %THEFILE%');
+ end;
+ Add(maybequoted(command)+' '+Options);
+ Add('if errorlevel 1 goto asmend');
+end;
+
+
+Procedure TAsmScriptDos.AddLinkCommand (Const Command, Options, FileName : String);
+begin
+ if FileName<>'' then
+ begin
+ Add('SET THEFILE='+ScriptFixFileName(FileName));
+ Add('echo Linking %THEFILE%');
+ end;
+ Add(maybequoted(command)+' '+Options);
+ Add('if errorlevel 1 goto linkend');
+end;
+
+
+Procedure TAsmScriptDos.AddDeleteCommand (Const FileName : String);
+begin
+ Add('Del ' + MaybeQuoted (ScriptFixFileName (FileName)));
+end;
+
+
+Procedure TAsmScriptDos.AddDeleteDirCommand (Const FileName : String);
+begin
+ Add('Rmdir ' + MaybeQuoted (ScriptFixFileName (FileName)));
+end;
+
+
+Procedure TAsmScriptDos.WriteToDisk;
+Begin
+ AddStart('@echo off');
+ Add('goto end');
+ Add(':asmend');
+ Add('echo An error occured while assembling %THEFILE%');
+ Add('goto end');
+ Add(':linkend');
+ Add('echo An error occured while linking %THEFILE%');
+ Add(':end');
+ inherited WriteToDisk;
+end;
+
+{****************************************************************************
+ Amiga Asm Response
+****************************************************************************}
+
+Constructor TAsmScriptAmiga.Create (Const ScriptName : String);
+begin
+ Inherited Create(ScriptName);
+end;
+
+
+Procedure TAsmScriptAmiga.AddAsmCommand (Const Command, Options,FileName : String);
+begin
+ if FileName<>'' then
+ begin
+ Add('SET THEFILE '+ScriptFixFileName(FileName));
+ Add('echo Assembling $THEFILE');
+ end;
+ Add(maybequoted(command)+' '+Options);
+ { There is a problem here,
+ as allways return with a non zero error value PM }
+ Add('if error');
+ Add('why');
+ Add('skip asmend');
+ Add('endif');
+end;
+
+
+Procedure TAsmScriptAmiga.AddLinkCommand (Const Command, Options, FileName : String);
+begin
+ if FileName<>'' then
+ begin
+ Add('SET THEFILE '+ScriptFixFileName(FileName));
+ Add('echo Linking $THEFILE');
+ end;
+ Add(maybequoted(command)+' '+Options);
+ Add('if error');
+ Add('skip linkend');
+ Add('endif');
+end;
+
+
+Procedure TAsmScriptAmiga.AddDeleteCommand (Const FileName : String);
+begin
+ Add('Delete ' + MaybeQuoted (ScriptFixFileName(FileName)));
+end;
+
+
+Procedure TAsmScriptAmiga.AddDeleteDirCommand (Const FileName : String);
+begin
+ Add('Delete ' + MaybeQuoted (ScriptFixFileName(FileName)));
+end;
+
+
+Procedure TAsmScriptAmiga.WriteToDisk;
+Begin
+ Add('skip end');
+ Add('lab asmend');
+ Add('why');
+ Add('echo An error occured while assembling $THEFILE');
+ Add('skip end');
+ Add('lab linkend');
+ Add('why');
+ Add('echo An error occured while linking $THEFILE');
+ Add('lab end');
+ inherited WriteToDisk;
+end;
+
+
+{****************************************************************************
+ Unix Asm Response
+****************************************************************************}
+
+Constructor TAsmScriptUnix.Create (Const ScriptName : String);
+begin
+ Inherited Create(ScriptName);
+end;
+
+
+Procedure TAsmScriptUnix.AddAsmCommand (Const Command, Options,FileName : String);
+begin
+ if FileName<>'' then
+ Add('echo Assembling '+ScriptFixFileName(FileName));
+ Add(maybequoted(command)+' '+Options);
+ Add('if [ $? != 0 ]; then DoExitAsm '+ScriptFixFileName(FileName)+'; fi');
+end;
+
+
+Procedure TAsmScriptUnix.AddLinkCommand (Const Command, Options, FileName : String);
+begin
+ if FileName<>'' then
+ Add('echo Linking '+ScriptFixFileName(FileName));
+ Add(maybequoted(command)+' '+Options);
+ Add('if [ $? != 0 ]; then DoExitLink '+ScriptFixFileName(FileName)+'; fi');
+end;
+
+
+Procedure TAsmScriptUnix.AddDeleteCommand (Const FileName : String);
+begin
+ Add('rm ' + MaybeQuoted (ScriptFixFileName(FileName)));
+end;
+
+
+Procedure TAsmScriptUnix.AddDeleteDirCommand (Const FileName : String);
+begin
+ Add('rmdir ' + MaybeQuoted (ScriptFixFileName(FileName)));
+end;
+
+
+Procedure TAsmScriptUnix.WriteToDisk;
+Begin
+ AddStart('{ echo "An error occurred while linking $1"; exit 1; }');
+ AddStart('DoExitLink ()');
+ AddStart('{ echo "An error occurred while assembling $1"; exit 1; }');
+ AddStart('DoExitAsm ()');
+ {$ifdef BEOS}
+ AddStart('#!/boot/beos/bin/sh');
+ {$else}
+ AddStart('#!/bin/sh');
+ {$endif}
+ inherited WriteToDisk;
+end;
+
+
+{****************************************************************************
+ MPW (MacOS) Asm Response
+****************************************************************************}
+
+Constructor TAsmScriptMPW.Create (Const ScriptName : String);
+begin
+ Inherited Create(ScriptName);
+end;
+
+
+Procedure TAsmScriptMPW.AddAsmCommand (Const Command, Options,FileName : String);
+begin
+ if FileName<>'' then
+ Add('Echo Assembling '+ScriptFixFileName(FileName));
+ Add(maybequoted(command)+' '+Options);
+ Add('Exit If "{Status}" != 0');
+end;
+
+
+Procedure TAsmScriptMPW.AddLinkCommand (Const Command, Options, FileName : String);
+begin
+ if FileName<>'' then
+ Add('Echo Linking '+ScriptFixFileName(FileName));
+ Add(maybequoted(command)+' '+Options);
+ Add('Exit If "{Status}" != 0');
+
+ {Add resources}
+ if apptype = app_cui then {If SIOW}
+ begin
+ Add('Rez -append "{RIncludes}"SIOW.r -o '+ ScriptFixFileName(FileName));
+ Add('Exit If "{Status}" != 0');
+ end;
+end;
+
+
+Procedure TAsmScriptMPW.AddDeleteCommand (Const FileName : String);
+begin
+ Add('Delete ' + MaybeQuoted (ScriptFixFileName(FileName)));
+end;
+
+
+Procedure TAsmScriptMPW.AddDeleteDirCommand (Const FileName : String);
+begin
+ Add('Delete ' + MaybeQuoted (ScriptFixFileName (FileName)));
+end;
+
+
+Procedure TAsmScriptMPW.WriteToDisk;
+Begin
+ AddStart('# Script for assembling and linking a FreePascal program on MPW (MacOS)');
+ Add('Echo Done');
+ inherited WriteToDisk;
+end;
+
+
+
+Procedure GenerateAsmRes(const st : string);
+var
+ scripttyp : tscripttype;
+begin
+ if cs_link_on_target in aktglobalswitches then
+ scripttyp := target_info.script
+ else
+ scripttyp := source_info.script;
+ case scripttyp of
+ script_unix :
+ AsmRes:=TAsmScriptUnix.Create(st);
+ script_dos :
+ AsmRes:=TAsmScriptDos.Create(st);
+ script_amiga :
+ AsmRes:=TAsmScriptAmiga.Create(st);
+ script_mpw :
+ AsmRes:=TAsmScriptMPW.Create(st);
+ end;
+end;
+
+
+{****************************************************************************
+ Link Response
+****************************************************************************}
+
+procedure TLinkRes.Add(const s:string);
+begin
+ if s<>'' then
+ inherited Add(s);
+end;
+
+procedure TLinkRes.AddFileName(const s:string);
+begin
+ if s<>'' then
+ begin
+ if not(s[1] in ['a'..'z','A'..'Z','/','\','.','"']) then
+ begin
+ if cs_link_on_target in aktglobalswitches then
+ inherited Add('.'+target_info.DirSep+s)
+ else
+ inherited Add('.'+source_info.DirSep+s);
+ end
+ else
+ inherited Add(s);
+ end;
+end;
+
+end.
diff --git a/compiler/sparc/aasmcpu.pas b/compiler/sparc/aasmcpu.pas
new file mode 100644
index 0000000000..556e060d11
--- /dev/null
+++ b/compiler/sparc/aasmcpu.pas
@@ -0,0 +1,312 @@
+{
+ Copyright (c) 1999-2002 by Mazen Neifer
+
+ Contains the assembler object for the 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 aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,
+ globtype,globals,verbose,
+ aasmbase,aasmtai,
+ cgbase,cgutils,cpubase,cpuinfo;
+
+ 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)
+ 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_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: LongInt);
+ constructor op_const_reg(op:tasmop; _op1: LongInt; _op2: tregister);
+ constructor op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
+
+ 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;_op1:TRegister;_op2:aint;_op3:tregister);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ procedure loadbool(opidx:longint;_b:boolean);
+ { register allocation }
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+ function spilling_create_load(const ref:treference;r:tregister): tai;
+ function spilling_create_store(r:tregister; const ref:treference): tai;
+
+implementation
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+ procedure taicpu.loadbool(opidx:longint;_b:boolean);
+ begin
+ if opidx>=ops then
+ ops:=opidx+1;
+ with oper[opidx]^ do
+ begin
+ if typ=top_ref then
+ dispose(ref);
+ b:=_b;
+ typ:=top_bool;
+ end;
+ end;
+
+
+ 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_ref(op : tasmop;const _op1 : treference);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_op1 : LongInt);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(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_reg_const(op:tasmop; _op1: tregister; _op2: LongInt);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+ constructor taicpu.op_const_reg(op:tasmop; _op1: LongInt; _op2: tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ 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_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(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_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister);
+ begin
+ inherited create(op);
+ { only allowed to load the address }
+ if not(_op2.refaddr in [addr_lo,addr_hi]) then
+ internalerror(200305311);
+ ops:=3;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_const_reg(op:tasmop;_op1:TRegister;_op2:aint;_op3:tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ is_jmp:=op in [A_BA,A_Bxx];
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ is_jmp:=op in [A_BA,A_Bxx];
+ 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;
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ result:=(
+ ((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
+ ((regtype = R_FPUREGISTER) and (opcode in [A_FMOVS,A_FMOVD]))
+ ) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg);
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ if opnr=ops-1 then
+ result := operand_write
+ else
+ result := operand_read;
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister): tai;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_ref_reg(A_LD,ref,r);
+ R_FPUREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFS :
+ result:=taicpu.op_ref_reg(A_LDF,ref,r);
+ R_SUBFD :
+ result:=taicpu.op_ref_reg(A_LDD,ref,r);
+ else
+ internalerror(200401042);
+ end;
+ end
+ 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_ST,r,ref);
+ R_FPUREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFS :
+ result:=taicpu.op_reg_ref(A_STF,r,ref);
+ R_SUBFD :
+ result:=taicpu.op_reg_ref(A_STD,r,ref);
+ else
+ internalerror(200401042);
+ end;
+ end
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+begin
+ cai_cpu:=taicpu;
+ cai_align:=tai_align;
+end.
diff --git a/compiler/sparc/aoptcpu.pas b/compiler/sparc/aoptcpu.pas
new file mode 100644
index 0000000000..cb656af36e
--- /dev/null
+++ b/compiler/sparc/aoptcpu.pas
@@ -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.
diff --git a/compiler/sparc/aoptcpub.pas b/compiler/sparc/aoptcpub.pas
new file mode 100644
index 0000000000..b6954875a2
--- /dev/null
+++ b/compiler/sparc/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the sparc 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_BA;
+ aopt_condjmp = A_Bxx;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/compiler/sparc/aoptcpud.pas b/compiler/sparc/aoptcpud.pas
new file mode 100644
index 0000000000..cb8c5d319f
--- /dev/null
+++ b/compiler/sparc/aoptcpud.pas
@@ -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.
diff --git a/compiler/sparc/cgcpu.pas b/compiler/sparc/cgcpu.pas
new file mode 100644
index 0000000000..593f936d66
--- /dev/null
+++ b/compiler/sparc/cgcpu.pas
@@ -0,0 +1,1479 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the 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 cgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,parabase,
+ cgbase,cgutils,cgobj,cg64f32,
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,cpuinfo,
+ node,symconst,SymType,symdef,
+ rgcpu;
+
+ type
+ TCgSparc=class(tcg)
+ protected
+ function IsSimpleRef(const ref:treference):boolean;
+ public
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+ function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
+ { sparc special, needed by cg64 }
+ procedure make_simple_ref(list:taasmoutput;var ref: treference);
+ procedure handle_load_store(list:taasmoutput;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
+ procedure handle_reg_const_reg(list:taasmoutput;op:Tasmop;src:tregister;a:aint;dst:tregister);
+ { parameter }
+ procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aint;const paraloc:TCGPara);override;
+ procedure a_param_ref(list:TAasmOutput;sz:tcgsize;const r:TReference;const paraloc:TCGPara);override;
+ procedure a_paramaddr_ref(list:TAasmOutput;const r:TReference;const paraloc:TCGPara);override;
+ procedure a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const paraloc : TCGPara);override;
+ procedure a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
+ procedure a_call_name(list:TAasmOutput;const s:string);override;
+ procedure a_call_reg(list:TAasmOutput;Reg:TRegister);override;
+ { General purpose instructions }
+ procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;size:tcgsize;a:aint;reg:TRegister);override;
+ procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
+ procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aint;src, dst:tregister);override;
+ procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
+ procedure a_op_const_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op_reg_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+ { move instructions }
+ procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aint;reg:tregister);override;
+ procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aint;const ref:TReference);override;
+ procedure a_load_reg_ref(list:TAasmOutput;FromSize,ToSize:TCgSize;reg:TRegister;const ref:TReference);override;
+ procedure a_load_ref_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);override;
+ procedure a_load_reg_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;reg1,reg2:tregister);override;
+ procedure a_loadaddr_ref_reg(list:TAasmOutput;const ref:TReference;r:tregister);override;
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list:TAasmOutput;size:tcgsize;reg1, reg2:tregister);override;
+ procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);override;
+ procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);override;
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aint;reg:tregister;l:tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
+ procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override;
+ procedure a_jmp_name(list : taasmoutput;const s : string);override;
+ procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;}
+ procedure a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);override;
+ procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);override;
+ procedure g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);override;
+ procedure g_overflowCheck_loc(List:TAasmOutput;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
+ procedure g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);override;
+ procedure g_restore_standard_registers(list:taasmoutput);override;
+ procedure g_save_standard_registers(list : taasmoutput);override;
+ procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);override;
+ procedure g_concatcopy_unaligned(list : taasmoutput;const source,dest : treference;len : aint);override;
+ procedure g_concatcopy_move(list : taasmoutput;const source,dest : treference;len : aint);
+ procedure g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ end;
+
+ TCg64Sparc=class(tcg64f32)
+ private
+ procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
+ public
+ procedure a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);override;
+ procedure a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);override;
+ procedure a_param64_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);override;
+ procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);override;
+ procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);override;
+ procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
+ procedure a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
+ procedure a_op64_const_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op64_reg_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+ end;
+
+ const
+ TOpCG2AsmOp : array[topcg] of TAsmOp=(
+ A_NONE,A_ADD,A_AND,A_UDIV,A_SDIV,A_SMUL,A_UMUL,A_NEG,A_NOT,A_OR,A_SRA,A_SLL,A_SRL,A_SUB,A_XOR
+ );
+ TOpCG2AsmOpWithFlags : array[topcg] of TAsmOp=(
+ A_NONE,A_ADDcc,A_ANDcc,A_UDIVcc,A_SDIVcc,A_SMULcc,A_UMULcc,A_NEG,A_NOT,A_ORcc,A_SRA,A_SLL,A_SRL,A_SUBcc,A_XORcc
+ );
+ TOpCmp2AsmCond : array[topcmp] of TAsmCond=(C_NONE,
+ C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A
+ );
+
+
+implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ paramgr,fmodule,
+ tgobj,
+ procinfo,cpupi;
+
+
+ function TCgSparc.IsSimpleRef(const ref:treference):boolean;
+ begin
+ if (ref.base=NR_NO) and (ref.index<>NR_NO) then
+ InternalError(2002100804);
+ result :=not(assigned(ref.symbol))and
+ (((ref.index = NR_NO) and
+ (ref.offset >= simm13lo) and
+ (ref.offset <= simm13hi)) or
+ ((ref.index <> NR_NO) and
+ (ref.offset = 0)));
+ end;
+
+
+ procedure tcgsparc.make_simple_ref(list:taasmoutput;var ref: treference);
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+ begin
+ tmpreg:=NR_NO;
+ { Be sure to have a base register }
+ if (ref.base=NR_NO) then
+ begin
+ ref.base:=ref.index;
+ ref.index:=NR_NO;
+ end;
+ if (cs_create_pic in aktmoduleswitches) and
+ assigned(ref.symbol) then
+ begin
+ tmpreg:=GetIntRegister(list,OS_INT);
+ reference_reset(tmpref);
+ tmpref.symbol:=ref.symbol;
+ tmpref.refaddr:=addr_pic;
+ if not(pi_needs_got in current_procinfo.flags) then
+ internalerror(200501161);
+ tmpref.index:=current_procinfo.got;
+ list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
+ ref.symbol:=nil;
+ if (ref.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
+ ref.index:=tmpreg;
+ end
+ else
+ begin
+ if ref.base<>NR_NO then
+ ref.index:=tmpreg
+ else
+ ref.base:=tmpreg;
+ end;
+ end;
+ { When need to use SETHI, do it first }
+ if assigned(ref.symbol) or
+ (ref.offset<simm13lo) or
+ (ref.offset>simm13hi) then
+ begin
+ tmpreg:=GetIntRegister(list,OS_INT);
+ reference_reset(tmpref);
+ tmpref.symbol:=ref.symbol;
+ tmpref.offset:=ref.offset;
+ tmpref.refaddr:=addr_hi;
+ list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
+ if (ref.offset=0) and (ref.index=NR_NO) and
+ (ref.base=NR_NO) then
+ begin
+ ref.refaddr:=addr_lo;
+ end
+ else
+ begin
+ { Load the low part is left }
+ tmpref.refaddr:=addr_lo;
+ list.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
+ ref.offset:=0;
+ { symbol is loaded }
+ ref.symbol:=nil;
+ end;
+ if (ref.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
+ ref.index:=tmpreg;
+ end
+ else
+ begin
+ if ref.base<>NR_NO then
+ ref.index:=tmpreg
+ else
+ ref.base:=tmpreg;
+ end;
+ end;
+ if (ref.base<>NR_NO) then
+ begin
+ if (ref.index<>NR_NO) and
+ ((ref.offset<>0) or assigned(ref.symbol)) then
+ begin
+ if tmpreg=NR_NO then
+ tmpreg:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end;
+ end;
+
+
+ procedure tcgsparc.handle_load_store(list:taasmoutput;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
+ begin
+ make_simple_ref(list,ref);
+ if isstore then
+ list.concat(taicpu.op_reg_ref(op,reg,ref))
+ else
+ list.concat(taicpu.op_ref_reg(op,ref,reg));
+ end;
+
+
+ procedure tcgsparc.handle_reg_const_reg(list:taasmoutput;op:Tasmop;src:tregister;a:aint;dst:tregister);
+ var
+ tmpreg : tregister;
+ begin
+ if (a<simm13lo) or
+ (a>simm13hi) then
+ begin
+ tmpreg:=GetIntRegister(list,OS_INT);
+ a_load_const_reg(list,OS_INT,a,tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(op,src,tmpreg,dst));
+ end
+ else
+ list.concat(taicpu.op_reg_const_reg(op,src,a,dst));
+ end;
+
+
+{****************************************************************************
+ Assembler code
+****************************************************************************}
+
+ procedure Tcgsparc.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+
+ if (cs_create_pic in aktmoduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ begin
+ current_procinfo.got:=NR_L7;
+ rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
+ [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,
+ RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6],
+ first_int_imreg,[]);
+ end
+ else
+ rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
+ [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,
+ RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7],
+ first_int_imreg,[]);
+
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBFS,
+ [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
+ RS_F8,RS_F9,RS_F10,RS_F11,RS_F12,RS_F13,RS_F14,RS_F15,
+ RS_F16,RS_F17,RS_F18,RS_F19,RS_F20,RS_F21,RS_F22,RS_F23,
+ RS_F24,RS_F25,RS_F26,RS_F27,RS_F28,RS_F29,RS_F30,RS_F31],
+ first_fpu_imreg,[]);
+ end;
+
+
+ procedure Tcgsparc.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ function tcgsparc.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
+ begin
+ if size=OS_F64 then
+ result:=rg[R_FPUREGISTER].getregister(list,R_SUBFD)
+ else
+ result:=rg[R_FPUREGISTER].getregister(list,R_SUBFS);
+ end;
+
+
+ procedure TCgSparc.a_param_const(list:TAasmOutput;size:tcgsize;a:aint;const paraloc:TCGPara);
+ var
+ Ref:TReference;
+ begin
+ paraloc.check_simple_location;
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,size,a,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ { Code conventions need the parameters being allocated in %o6+92 }
+ with paraloc.location^.Reference do
+ begin
+ if (Index=NR_SP) and (Offset<Target_info.first_parm_offset) then
+ InternalError(2002081104);
+ reference_reset_base(ref,index,offset);
+ end;
+ a_load_const_ref(list,size,a,ref);
+ end;
+ else
+ InternalError(2002122200);
+ end;
+ end;
+
+
+ procedure TCgSparc.a_param_ref(list:TAasmOutput;sz:TCgSize;const r:TReference;const paraloc:TCGPara);
+ var
+ ref: treference;
+ tmpreg:TRegister;
+ begin
+ paraloc.check_simple_location;
+ with paraloc.location^ do
+ begin
+ case loc of
+ LOC_REGISTER,LOC_CREGISTER :
+ a_load_ref_reg(list,sz,sz,r,Register);
+ LOC_REFERENCE:
+ begin
+ { Code conventions need the parameters being allocated in %o6+92 }
+ with Reference do
+ begin
+ if (Index=NR_SP) and (Offset<Target_info.first_parm_offset) then
+ InternalError(2002081104);
+ reference_reset_base(ref,index,offset);
+ end;
+ tmpreg:=GetIntRegister(list,OS_INT);
+ a_load_ref_reg(list,sz,sz,r,tmpreg);
+ a_load_reg_ref(list,sz,sz,tmpreg,ref);
+ end;
+ else
+ internalerror(2002081103);
+ end;
+ end;
+ end;
+
+
+ procedure TCgSparc.a_paramaddr_ref(list:TAasmOutput;const r:TReference;const paraloc:TCGPara);
+ var
+ Ref:TReference;
+ TmpReg:TRegister;
+ begin
+ paraloc.check_simple_location;
+ with paraloc.location^ do
+ begin
+ case loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadaddr_ref_reg(list,r,register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref);
+ ref.base := reference.index;
+ ref.offset := reference.offset;
+ tmpreg:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+ end;
+
+
+ procedure tcgsparc.a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const paraloc : TCGPara);
+ var
+ href,href2 : treference;
+ hloc : pcgparalocation;
+ begin
+ href:=ref;
+ hloc:=paraloc.location;
+ while assigned(hloc) do
+ begin
+ case hloc^.loc of
+ LOC_REGISTER :
+ 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);
+ a_load_ref_ref(list,hloc^.size,hloc^.size,href,href2);
+ end;
+ else
+ internalerror(200408241);
+ end;
+ inc(href.offset,tcgsize2size[hloc^.size]);
+ hloc:=hloc^.next;
+ end;
+ end;
+
+
+ procedure tcgsparc.a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const paraloc : TCGPara);
+ var
+ href : treference;
+ begin
+ tg.GetTemp(list,TCGSize2Size[size],tt_normal,href);
+ a_loadfpu_reg_ref(list,size,r,href);
+ a_paramfpu_ref(list,size,href,paraloc);
+ tg.Ungettemp(list,href);
+ end;
+
+
+ procedure TCgSparc.a_call_name(list:TAasmOutput;const s:string);
+ begin
+ list.concat(taicpu.op_sym(A_CALL,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
+ { Delay slot }
+ list.concat(taicpu.op_none(A_NOP));
+ end;
+
+
+ procedure TCgSparc.a_call_reg(list:TAasmOutput;Reg:TRegister);
+ begin
+ list.concat(taicpu.op_reg(A_CALL,reg));
+ { Delay slot }
+ list.concat(taicpu.op_none(A_NOP));
+ end;
+
+
+ {********************** load instructions ********************}
+
+ procedure TCgSparc.a_load_const_reg(list : TAasmOutput;size : TCGSize;a : aint;reg : TRegister);
+ begin
+ { we don't use the set instruction here because it could be evalutated to two
+ instructions which would cause problems with the delay slot (FK) }
+ if (a=0) then
+ list.concat(taicpu.op_reg(A_CLR,reg))
+ { sethi allows to set the upper 22 bit, so we'll take full advantage of it }
+ else if (a and aint($1fff))=0 then
+ list.concat(taicpu.op_const_reg(A_SETHI,a shr 10,reg))
+ else if (a>=simm13lo) and (a<=simm13hi) then
+ list.concat(taicpu.op_const_reg(A_MOV,a,reg))
+ else
+ begin
+ list.concat(taicpu.op_const_reg(A_SETHI,a shr 10,reg));
+ list.concat(taicpu.op_reg_const_reg(A_OR,reg,a and aint($3ff),reg));
+ end;
+ end;
+
+
+ procedure TCgSparc.a_load_const_ref(list : TAasmOutput;size : tcgsize;a : aint;const ref : TReference);
+ begin
+ if a=0 then
+ a_load_reg_ref(list,size,size,NR_G0,ref)
+ else
+ inherited a_load_const_ref(list,size,a,ref);
+ end;
+
+
+ procedure TCgSparc.a_load_reg_ref(list:TAasmOutput;FromSize,ToSize:TCGSize;reg:tregister;const Ref:TReference);
+ var
+ op : tasmop;
+ begin
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ case fromsize of
+ { signed integer registers }
+ OS_8,
+ OS_S8:
+ Op:=A_STB;
+ OS_16,
+ OS_S16:
+ Op:=A_STH;
+ OS_32,
+ OS_S32:
+ Op:=A_ST;
+ else
+ InternalError(2002122100);
+ end;
+ handle_load_store(list,true,op,reg,ref);
+ end;
+
+
+ procedure TCgSparc.a_load_ref_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);
+ var
+ op : tasmop;
+ begin
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ case fromsize of
+ OS_S8:
+ Op:=A_LDSB;{Load Signed Byte}
+ OS_8:
+ Op:=A_LDUB;{Load Unsigned Byte}
+ OS_S16:
+ Op:=A_LDSH;{Load Signed Halfword}
+ OS_16:
+ Op:=A_LDUH;{Load Unsigned Halfword}
+ OS_S32,
+ OS_32:
+ Op:=A_LD;{Load Word}
+ OS_S64,
+ OS_64:
+ Op:=A_LDD;{Load a Long Word}
+ else
+ InternalError(2002122101);
+ end;
+ handle_load_store(list,false,op,reg,ref);
+ end;
+
+
+ procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);
+ var
+ instr : taicpu;
+ begin
+ if (tcgsize2size[tosize]<tcgsize2size[fromsize]) or
+ (
+ (tcgsize2size[tosize] = tcgsize2size[fromsize]) and
+ (tosize <> fromsize) and
+ not(fromsize in [OS_32,OS_S32])
+ ) then
+ begin
+ case tosize of
+ OS_8 :
+ a_op_const_reg_reg(list,OP_AND,tosize,$ff,reg1,reg2);
+ OS_16 :
+ a_op_const_reg_reg(list,OP_AND,tosize,$ffff,reg1,reg2);
+ OS_32,
+ OS_S32 :
+ begin
+ instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+ OS_S8 :
+ begin
+ list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,24,reg2));
+ list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,24,reg2));
+ end;
+ OS_S16 :
+ begin
+ list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
+ list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,16,reg2));
+ end;
+ else
+ internalerror(2002090901);
+ end;
+ end
+ else
+ begin
+ if reg1<>reg2 then
+ begin
+ { same size, only a register mov required }
+ instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+ end;
+ end;
+
+
+ procedure TCgSparc.a_loadaddr_ref_reg(list : TAasmOutput;const ref : TReference;r : tregister);
+ var
+ tmpref,href : treference;
+ hreg,tmpreg : tregister;
+ begin
+ href:=ref;
+ if (href.base=NR_NO) and (href.index<>NR_NO) then
+ internalerror(200306171);
+
+ if (cs_create_pic in aktmoduleswitches) and
+ assigned(href.symbol) then
+ begin
+ tmpreg:=GetIntRegister(list,OS_ADDR);
+ reference_reset(tmpref);
+ tmpref.symbol:=href.symbol;
+ tmpref.refaddr:=addr_pic;
+ if not(pi_needs_got in current_procinfo.flags) then
+ internalerror(200501161);
+ tmpref.base:=current_procinfo.got;
+ list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
+ href.symbol:=nil;
+ if (href.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,href.index,tmpreg));
+ href.index:=tmpreg;
+ end
+ else
+ begin
+ if href.base<>NR_NO then
+ href.index:=tmpreg
+ else
+ href.base:=tmpreg;
+ end;
+ end;
+
+ { At least big offset (need SETHI), maybe base and maybe index }
+ if assigned(href.symbol) or
+ (href.offset<simm13lo) or
+ (href.offset>simm13hi) then
+ begin
+ hreg:=GetAddressRegister(list);
+ reference_reset(tmpref);
+ tmpref.symbol := href.symbol;
+ tmpref.offset := href.offset;
+ tmpref.refaddr := addr_hi;
+ list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
+ { Only the low part is left }
+ tmpref.refaddr:=addr_lo;
+ list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
+ if href.base<>NR_NO then
+ begin
+ if href.index<>NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.base,hreg));
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.index,r));
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.base,r));
+ end
+ else
+ begin
+ if hreg<>r then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,hreg,r);
+ end;
+ end
+ else
+ { At least small offset, maybe base and maybe index }
+ if href.offset<>0 then
+ begin
+ if href.base<>NR_NO then
+ begin
+ if href.index<>NR_NO then
+ begin
+ hreg:=GetAddressRegister(list);
+ list.concat(taicpu.op_reg_const_reg(A_ADD,href.base,href.offset,hreg));
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.index,r));
+ end
+ else
+ list.concat(taicpu.op_reg_const_reg(A_ADD,href.base,href.offset,r));
+ end
+ else
+ list.concat(taicpu.op_const_reg(A_MOV,href.offset,r));
+ end
+ else
+ { Both base and index }
+ if href.index<>NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,href.base,href.index,r))
+ else
+ { Only base }
+ if href.base<>NR_NO then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r)
+ else
+ { only offset, can be generated by absolute }
+ a_load_const_reg(list,OS_ADDR,href.offset,r);
+ end;
+
+
+ procedure TCgSparc.a_loadfpu_reg_reg(list:TAasmOutput;size:tcgsize;reg1, reg2:tregister);
+ const
+ FpuMovInstr : Array[OS_F32..OS_F64] of TAsmOp =
+ (A_FMOVS,A_FMOVD);
+ var
+ instr : taicpu;
+ begin
+ if reg1<>reg2 then
+ begin
+ instr:=taicpu.op_reg_reg(fpumovinstr[size],reg1,reg2);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+ end;
+
+
+ procedure TCgSparc.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);
+ const
+ FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
+ (A_LDF,A_LDDF);
+ begin
+ handle_load_store(list,false,fpuloadinstr[size],reg,ref);
+ end;
+
+
+ procedure TCgSparc.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);
+ const
+ FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
+ (A_STF,A_STDF);
+ begin
+ handle_load_store(list,true,fpuloadinstr[size],reg,ref);
+ end;
+
+
+ procedure TCgSparc.a_op_const_reg(list:TAasmOutput;Op:TOpCG;size:tcgsize;a:aint;reg:TRegister);
+ begin
+ if Op in [OP_NEG,OP_NOT] then
+ internalerror(200306011);
+ if (a=0) then
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],reg,NR_G0,reg))
+ else
+ handle_reg_const_reg(list,TOpCG2AsmOp[op],reg,a,reg);
+ end;
+
+
+ procedure TCgSparc.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);
+ var
+ a : aint;
+ begin
+ Case Op of
+ OP_NEG :
+ list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],src,dst));
+ OP_NOT :
+ begin
+ case size of
+ OS_8 :
+ a:=aint($ffffff00);
+ OS_16 :
+ a:=aint($ffff0000);
+ else
+ a:=0;
+ end;
+ handle_reg_const_reg(list,A_XNOR,src,a,dst);
+ end;
+ else
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst));
+ end;
+ end;
+
+
+ procedure TCgSparc.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aint;src, dst:tregister);
+ var
+ power : longInt;
+ begin
+ case op of
+ OP_MUL,
+ OP_IMUL:
+ begin
+ if ispowerof2(a,power) then
+ begin
+ { can be done with a shift }
+ inherited a_op_const_reg_reg(list,op,size,a,src,dst);
+ exit;
+ end;
+ end;
+ OP_SUB,
+ OP_ADD :
+ begin
+ if (a=0) then
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ exit;
+ end;
+ end;
+ end;
+ handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
+ end;
+
+
+ procedure TCgSparc.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);
+ begin
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
+ end;
+
+
+ procedure tcgsparc.a_op_const_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ power : longInt;
+ tmpreg1,tmpreg2 : tregister;
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_SUB,
+ OP_ADD :
+ begin
+ if (a=0) then
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ exit;
+ end;
+ end;
+ end;
+ if setflags then
+ begin
+ handle_reg_const_reg(list,TOpCG2AsmOpWithFlags[op],src,a,dst);
+ case op of
+ OP_MUL:
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
+ list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end;
+ OP_IMUL:
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ tmpreg2:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
+ list.concat(taicpu.op_reg_const_reg(A_SRL,dst,31,tmpreg2));
+ list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end;
+ end;
+ end
+ else
+ handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst)
+ end;
+
+
+ procedure tcgsparc.a_op_reg_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ tmpreg1,tmpreg2 : tregister;
+ begin
+ ovloc.loc:=LOC_VOID;
+ if setflags then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOpWithFlags[op],src2,src1,dst));
+ case op of
+ OP_MUL:
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
+ list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end;
+ OP_IMUL:
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ tmpreg2:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
+ list.concat(taicpu.op_reg_const_reg(A_SRL,dst,31,tmpreg2));
+ list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end;
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst))
+ end;
+
+
+
+ {*************** compare instructructions ****************}
+
+ procedure TCgSparc.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aint;reg:tregister;l:tasmlabel);
+ begin
+ if (a=0) then
+ list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg,NR_G0,NR_G0))
+ else
+ handle_reg_const_reg(list,A_SUBcc,reg,a,NR_G0);
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure TCgSparc.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg2,reg1,NR_G0));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure TCgSparc.a_jmp_always(List:TAasmOutput;l:TAsmLabel);
+ begin
+ List.Concat(TAiCpu.op_sym(A_BA,objectlibrary.newasmsymbol(l.name,AB_EXTERNAL,AT_FUNCTION)));
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end;
+
+
+ procedure tcgsparc.a_jmp_name(list : taasmoutput;const s : string);
+ begin
+ List.Concat(TAiCpu.op_sym(A_BA,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end;
+
+
+ procedure TCgSparc.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:TAsmLabel);
+ var
+ ai:TAiCpu;
+ begin
+ ai:=TAiCpu.Op_sym(A_Bxx,l);
+ ai.SetCondition(TOpCmp2AsmCond[cond]);
+ list.Concat(ai);
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end;
+
+
+ procedure TCgSparc.a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);
+ var
+ ai : taicpu;
+ op : tasmop;
+ begin
+ if f in [F_FE,F_FNE,F_FG,F_FL,F_FGE,F_FLE] then
+ op:=A_FBxx
+ else
+ op:=A_Bxx;
+ ai := Taicpu.op_sym(op,l);
+ ai.SetCondition(flags_to_cond(f));
+ list.Concat(ai);
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end;
+
+
+ procedure TCgSparc.g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);
+ var
+ hl : tasmlabel;
+ begin
+ objectlibrary.getjumplabel(hl);
+ a_load_const_reg(list,size,1,reg);
+ a_jmp_flags(list,f,hl);
+ a_load_const_reg(list,size,0,reg);
+ a_label(list,hl);
+ end;
+
+
+ procedure tcgsparc.g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);
+ var
+ l : tlocation;
+ begin
+ l.loc:=LOC_VOID;
+ g_overflowCheck_loc(list,loc,def,l);
+ end;
+
+
+ procedure TCgSparc.g_overflowCheck_loc(List:TAasmOutput;const Loc:TLocation;def:TDef;ovloc : tlocation);
+ var
+ hl : tasmlabel;
+ ai:TAiCpu;
+ hflags : tresflags;
+ begin
+ if not(cs_check_overflow in aktlocalswitches) then
+ exit;
+ objectlibrary.getjumplabel(hl);
+ case ovloc.loc of
+ LOC_VOID:
+ begin
+ if not((def.deftype=pointerdef) or
+ ((def.deftype=orddef) and
+ (torddef(def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,bool8bit,bool16bit,bool32bit]))) then
+ begin
+ ai:=TAiCpu.Op_sym(A_Bxx,hl);
+ ai.SetCondition(C_NO);
+ list.Concat(ai);
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end
+ else
+ a_jmp_cond(list,OC_AE,hl);
+ end;
+ LOC_FLAGS:
+ begin
+ hflags:=ovloc.resflags;
+ inverse_flags(hflags);
+ cg.a_jmp_flags(list,hflags,hl);
+ end;
+ else
+ internalerror(200409281);
+ end;
+
+ a_call_name(list,'FPC_OVERFLOW');
+ a_label(list,hl);
+ end;
+
+ { *********** entry/exit code and address loading ************ }
+
+ procedure TCgSparc.g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);
+ begin
+ if nostackframe then
+ exit;
+ { Althogh the SPARC architecture require only word alignment, software
+ convention and the operating system require every stack frame to be double word
+ aligned }
+ LocalSize:=align(LocalSize,8);
+ { Execute the SAVE instruction to get a new register window and create a new
+ stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
+ before execution of the SAVE instrucion so it is the caller %i6, when the %i6
+ after execution of that instruction is the called function stack pointer}
+ { constant can be 13 bit signed, since it's negative, size can be max. 4096 }
+ if LocalSize>4096 then
+ begin
+ a_load_const_reg(list,OS_ADDR,-LocalSize,NR_G1);
+ list.concat(Taicpu.Op_reg_reg_reg(A_SAVE,NR_STACK_POINTER_REG,NR_G1,NR_STACK_POINTER_REG));
+ end
+ else
+ list.concat(Taicpu.Op_reg_const_reg(A_SAVE,NR_STACK_POINTER_REG,-LocalSize,NR_STACK_POINTER_REG));
+ if (cs_create_pic in aktmoduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ begin
+ current_procinfo.got:=NR_L7;
+ end;
+ end;
+
+
+ procedure TCgSparc.g_restore_standard_registers(list:taasmoutput);
+ begin
+ { The sparc port uses the sparc standard calling convetions so this function has no used }
+ end;
+
+
+ procedure TCgSparc.g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);
+ var
+ hr : treference;
+ begin
+ if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption) then
+ begin
+ reference_reset(hr);
+ hr.offset:=12;
+ hr.refaddr:=addr_full;
+ if nostackframe then
+ begin
+ hr.base:=NR_O7;
+ list.concat(taicpu.op_ref_reg(A_JMPL,hr,NR_G0));
+ list.concat(Taicpu.op_none(A_NOP))
+ end
+ else
+ begin
+ { We use trivial restore in the delay slot of the JMPL instruction, as we
+ already set result onto %i0 }
+ hr.base:=NR_I7;
+ list.concat(taicpu.op_ref_reg(A_JMPL,hr,NR_G0));
+ list.concat(Taicpu.op_none(A_RESTORE));
+ end;
+ end
+ else
+ begin
+ if nostackframe then
+ begin
+ { Here we need to use RETL instead of RET so it uses %o7 }
+ list.concat(Taicpu.op_none(A_RETL));
+ list.concat(Taicpu.op_none(A_NOP))
+ end
+ else
+ begin
+ { We use trivial restore in the delay slot of the JMPL instruction, as we
+ already set result onto %i0 }
+ list.concat(Taicpu.op_none(A_RET));
+ list.concat(Taicpu.op_none(A_RESTORE));
+ end;
+ end;
+ end;
+
+
+ procedure TCgSparc.g_save_standard_registers(list : taasmoutput);
+ begin
+ { The sparc port uses the sparc standard calling convetions so this function has no used }
+ end;
+
+
+ { ************* concatcopy ************ }
+
+ procedure tcgsparc.g_concatcopy_move(list : taasmoutput;const source,dest : treference;len : aint);
+ var
+ paraloc1,paraloc2,paraloc3 : TCGPara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ paramanager.allocparaloc(list,paraloc3);
+ a_param_const(list,OS_INT,len,paraloc3);
+ paramanager.allocparaloc(list,paraloc2);
+ a_paramaddr_ref(list,dest,paraloc2);
+ paramanager.allocparaloc(list,paraloc2);
+ a_paramaddr_ref(list,source,paraloc1);
+ paramanager.freeparaloc(list,paraloc3);
+ paramanager.freeparaloc(list,paraloc2);
+ 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');
+ dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+ end;
+
+
+ procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aint);
+ var
+ tmpreg1,
+ hreg,
+ countreg: TRegister;
+ src, dst: TReference;
+ lab: tasmlabel;
+ count, count2: aint;
+ begin
+ if len>high(longint) then
+ internalerror(2002072704);
+ { anybody wants to determine a good value here :)? }
+ if len>100 then
+ g_concatcopy_move(list,source,dest,len)
+ else
+ begin
+ reference_reset(src);
+ reference_reset(dst);
+ { load the address of source into src.base }
+ src.base:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,source,src.base);
+ { load the address of dest into dst.base }
+ dst.base:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,dest,dst.base);
+ { generate a loop }
+ count:=len div 4;
+ if count>4 then
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ countreg:=GetIntRegister(list,OS_INT);
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ 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.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_ref_reg(A_LD,src,tmpreg1));
+ list.concat(taicpu.op_reg_ref(A_ST,tmpreg1,dst));
+ list.concat(taicpu.op_reg_const_reg(A_ADD,src.base,4,src.base));
+ list.concat(taicpu.op_reg_const_reg(A_ADD,dst.base,4,dst.base));
+ list.concat(taicpu.op_reg_const_reg(A_SUBcc,countreg,1,countreg));
+ a_jmp_cond(list,OC_NE,lab);
+ list.concat(taicpu.op_none(A_NOP));
+ { keep the registers alive }
+ list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+ list.concat(taicpu.op_reg_reg(A_MOV,src.base,src.base));
+ list.concat(taicpu.op_reg_reg(A_MOV,dst.base,dst.base));
+ len := len mod 4;
+ end;
+ { unrolled loop }
+ count:=len div 4;
+ if count>0 then
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ for count2 := 1 to count do
+ begin
+ list.concat(taicpu.op_ref_reg(A_LD,src,tmpreg1));
+ list.concat(taicpu.op_reg_ref(A_ST,tmpreg1,dst));
+ inc(src.offset,4);
+ inc(dst.offset,4);
+ end;
+ len := len mod 4;
+ end;
+ if (len and 4) <> 0 then
+ begin
+ hreg:=GetIntRegister(list,OS_INT);
+ a_load_ref_reg(list,OS_32,OS_32,src,hreg);
+ a_load_reg_ref(list,OS_32,OS_32,hreg,dst);
+ inc(src.offset,4);
+ inc(dst.offset,4);
+ end;
+ { copy the leftovers }
+ if (len and 2) <> 0 then
+ begin
+ hreg:=GetIntRegister(list,OS_INT);
+ a_load_ref_reg(list,OS_16,OS_16,src,hreg);
+ a_load_reg_ref(list,OS_16,OS_16,hreg,dst);
+ inc(src.offset,2);
+ inc(dst.offset,2);
+ end;
+ if (len and 1) <> 0 then
+ begin
+ hreg:=GetIntRegister(list,OS_INT);
+ a_load_ref_reg(list,OS_8,OS_8,src,hreg);
+ a_load_reg_ref(list,OS_8,OS_8,hreg,dst);
+ end;
+ end;
+ end;
+
+
+ procedure tcgsparc.g_concatcopy_unaligned(list : taasmoutput;const source,dest : treference;len : aint);
+ var
+ src, dst: TReference;
+ tmpreg1,
+ countreg: TRegister;
+ i : aint;
+ lab: tasmlabel;
+ begin
+ if len>31 then
+ g_concatcopy_move(list,source,dest,len)
+ else
+ begin
+ reference_reset(src);
+ reference_reset(dst);
+ { load the address of source into src.base }
+ src.base:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,source,src.base);
+ { load the address of dest into dst.base }
+ dst.base:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,dest,dst.base);
+ { generate a loop }
+ if len>4 then
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ countreg:=GetIntRegister(list,OS_INT);
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ 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.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_ref_reg(A_LDUB,src,tmpreg1));
+ list.concat(taicpu.op_reg_ref(A_STB,tmpreg1,dst));
+ list.concat(taicpu.op_reg_const_reg(A_ADD,src.base,1,src.base));
+ list.concat(taicpu.op_reg_const_reg(A_ADD,dst.base,1,dst.base));
+ list.concat(taicpu.op_reg_const_reg(A_SUBcc,countreg,1,countreg));
+ a_jmp_cond(list,OC_NE,lab);
+ list.concat(taicpu.op_none(A_NOP));
+ { keep the registers alive }
+ list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+ list.concat(taicpu.op_reg_reg(A_MOV,src.base,src.base));
+ list.concat(taicpu.op_reg_reg(A_MOV,dst.base,dst.base));
+ end
+ else
+ begin
+ { unrolled loop }
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ for i:=1 to len do
+ begin
+ list.concat(taicpu.op_ref_reg(A_LDUB,src,tmpreg1));
+ list.concat(taicpu.op_reg_ref(A_STB,tmpreg1,dst));
+ inc(src.offset);
+ inc(dst.offset);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tcgsparc.g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);
+ var
+ make_global : boolean;
+ href : treference;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef._class) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>objectsymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ if po_virtualmethod in procdef.procoptions then
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { mov 0(%rdi),%rax ; load vmt}
+ reference_reset_base(href,NR_O0,0);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_L0);
+ { jmp *vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_L0,procdef._class.vmtmethodoffset(procdef.extnumber));
+ list.concat(taicpu.op_ref_reg(A_LD,href,NR_L1));
+ list.concat(taicpu.op_reg(A_JMP,NR_L1));
+ end
+ else
+ list.concat(taicpu.op_sym(A_BA,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+{****************************************************************************
+ TCG64Sparc
+****************************************************************************}
+
+
+ procedure tcg64sparc.a_load64_reg_ref(list : taasmoutput;reg : tregister64;const ref : treference);
+ var
+ tmpref: treference;
+ begin
+ { Override this function to prevent loading the reference twice }
+ tmpref:=ref;
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
+ inc(tmpref.offset,4);
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,tmpref);
+ end;
+
+
+ procedure tcg64sparc.a_load64_ref_reg(list : taasmoutput;const ref : treference;reg : tregister64);
+ var
+ tmpref: treference;
+ begin
+ { Override this function to prevent loading the reference twice }
+ tmpref:=ref;
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
+ inc(tmpref.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
+ end;
+
+
+ procedure tcg64sparc.a_param64_ref(list : taasmoutput;const r : treference;const paraloc : tcgpara);
+ var
+ hreg64 : tregister64;
+ begin
+ { Override this function to prevent loading the reference twice.
+ Use here some extra registers, but those are optimized away by the RA }
+ hreg64.reglo:=cg.GetIntRegister(list,OS_32);
+ hreg64.reghi:=cg.GetIntRegister(list,OS_32);
+ a_load64_ref_reg(list,r,hreg64);
+ a_param64_reg(list,hreg64,paraloc);
+ end;
+
+
+ procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
+ begin
+ case op of
+ OP_ADD :
+ begin
+ op1:=A_ADDCC;
+ if checkoverflow then
+ op2:=A_ADDXCC
+ else
+ op2:=A_ADDX;
+ end;
+ OP_SUB :
+ begin
+ op1:=A_SUBCC;
+ if checkoverflow then
+ op2:=A_SUBXCC
+ else
+ op2:=A_SUBX;
+ 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 TCg64Sparc.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);
+ var
+ op1,op2 : TAsmOp;
+ begin
+ case op of
+ OP_NEG :
+ begin
+ { Use the simple code: y=0-z }
+ list.concat(taicpu.op_reg_reg_reg(A_SUBcc,NR_G0,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBX,NR_G0,regsrc.reghi,regdst.reghi));
+ exit;
+ end;
+ OP_NOT :
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reglo,NR_G0,regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reghi,NR_G0,regdst.reghi));
+ exit;
+ end;
+ end;
+ get_64bit_ops(op,op1,op2,false);
+ list.concat(taicpu.op_reg_reg_reg(op1,regdst.reglo,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(op2,regdst.reghi,regsrc.reghi,regdst.reghi));
+ end;
+
+
+ procedure TCg64Sparc.a_op64_const_reg(list:TAasmOutput;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);
+ var
+ op1,op2:TAsmOp;
+ begin
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ get_64bit_ops(op,op1,op2,false);
+ tcgsparc(cg).handle_reg_const_reg(list,op1,regdst.reglo,aint(lo(value)),regdst.reglo);
+ tcgsparc(cg).handle_reg_const_reg(list,op2,regdst.reghi,aint(hi(value)),regdst.reghi);
+ end;
+
+
+ procedure tcg64sparc.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64; regsrc,regdst : tregister64);
+ var
+ l : tlocation;
+ begin
+ a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,l);
+ end;
+
+
+ procedure tcg64sparc.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ var
+ l : tlocation;
+ begin
+ a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,l);
+ end;
+
+
+ procedure tcg64sparc.a_op64_const_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ var
+ op1,op2:TAsmOp;
+ begin
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ get_64bit_ops(op,op1,op2,setflags);
+ tcgsparc(cg).handle_reg_const_reg(list,op1,regsrc.reglo,aint(lo(value)),regdst.reglo);
+ tcgsparc(cg).handle_reg_const_reg(list,op2,regsrc.reghi,aint(hi(value)),regdst.reghi);
+ end;
+
+
+ procedure tcg64sparc.a_op64_reg_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ var
+ op1,op2:TAsmOp;
+ begin
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ get_64bit_ops(op,op1,op2,setflags);
+ list.concat(taicpu.op_reg_reg_reg(op1,regsrc2.reglo,regsrc1.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(op2,regsrc2.reghi,regsrc1.reghi,regdst.reghi));
+ end;
+
+
+begin
+ cg:=TCgSparc.Create;
+ cg64:=TCg64Sparc.Create;
+end.
diff --git a/compiler/sparc/cpubase.pas b/compiler/sparc/cpubase.pas
new file mode 100644
index 0000000000..97a6a569a6
--- /dev/null
+++ b/compiler/sparc/cpubase.pas
@@ -0,0 +1,462 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the 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 cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,strings,cutils,cclasses,aasmbase,cpuinfo,cgbase;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+{$WARNING CPU32 opcodes do not fully include the Ultra SPRAC instruction set.}
+ { don't change the order of these opcodes! }
+ TAsmOp=({$i opcode.inc});
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+ std_op2str:op2strtable=({$i strinst.inc});
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rspnor.inc}-1;
+ totherregisterset = set of tregisterindex;
+
+ const
+ { Available Superregisters }
+ {$i rspsup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBD;
+
+ { Available Registers }
+ {$i rspcon.inc}
+
+ first_int_imreg = $20;
+ first_fpu_imreg = $20;
+
+ { MM Super register first and last }
+ first_mm_supreg = 0;
+ first_mm_imreg = 0;
+
+{$warning TODO Calculate bsstart}
+ regnumber_count_bsstart = 128;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rspnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of ShortInt = (
+ {$i rspstab.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of ShortInt = (
+ {$i rspdwrf.inc}
+ );
+
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
+ C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
+ C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z,
+ C_FE,C_FG,C_FL,C_FGE,C_FLE,C_FNE
+ );
+
+ const
+ cond2str:array[TAsmCond] of string[3]=('',
+ 'gu','cc','cs','leu','cs','e','g','ge','l','le','leu','cs',
+ 'cc','gu','cc','ne','le','l','ge','g','vc','XX',
+ 'pos','ne','vs','XX','XX','XX','vs','e',
+ 'e','g','l','ge','le','ne'
+ );
+
+ const
+ CondAsmOps=2;
+ CondAsmOp:array[0..CondAsmOps-1] of TAsmOp=(
+ A_Bxx,A_FBxx
+ );
+ CondAsmOpStr:array[0..CondAsmOps-1] of string[7]=(
+ 'B','FB'
+ );
+
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags=(
+ { Integer results }
+ F_E, {Equal}
+ F_NE, {Not Equal}
+ F_G, {Greater}
+ F_L, {Less}
+ F_GE, {Greater or Equal}
+ F_LE, {Less or Equal}
+ F_A, {Above}
+ F_AE, {Above or Equal}
+ F_B, {Below}
+ F_BE, {Below or Equal}
+ F_C, {Carry}
+ F_NC, {Not Carry}
+ { Floating point results }
+ F_FE, {Equal}
+ F_FNE, {Not Equal}
+ F_FG, {Greater}
+ F_FL, {Less}
+ F_FGE, {Greater or Equal}
+ F_FLE {Less or Equal}
+ );
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 3;
+
+ {# Constant defining possibly all registers which might require saving }
+ ALL_OTHERREGISTERS = [];
+
+ general_superregisters = [RS_O0..RS_I7];
+
+ {# Table of registers which can be allocated by the code generator
+ internally, when generating the code.
+ }
+ { legend: }
+ { xxxregs = set of all possibly used registers of that type in the code }
+ { generator }
+ { usableregsxxx = set of all 32bit components of registers that can be }
+ { possible allocated to a regvar or using getregisterxxx (this }
+ { excludes registers which can be only used for parameter }
+ { passing on ABI's that define this) }
+ { c_countusableregsxxx = amount of registers in the usableregsxxx set }
+
+ maxintregs = 8;
+ { to determine how many registers to use for regvars }
+ maxintscratchregs = 3;
+ usableregsint = [RS_L0..RS_L7];
+ c_countusableregsint = 8;
+
+ maxfpuregs = 8;
+ usableregsfpu=[RS_F0..RS_F31];
+ c_countusableregsfpu=32;
+
+ mmregs = [];
+ usableregsmm = [];
+ c_countusableregsmm = 0;
+
+ { no distinction on this platform }
+ maxaddrregs = 0;
+ addrregs = [];
+ usableregsaddr = [];
+ c_countusableregsaddr = 0;
+
+{$warning firstsaveintreg shall be RS_NO}
+ firstsaveintreg = RS_L0; { Temporary, having RS_NO is broken }
+ lastsaveintreg = RS_L0; { L0..L7 are already saved, I0..O7 are parameter }
+ firstsavefpureg = RS_F2; { F0..F1 is used for return value }
+ lastsavefpureg = RS_F31;
+ firstsavemmreg = RS_INVALID;
+ lastsavemmreg = RS_INVALID;
+
+ maxvarregs = 8;
+ varregs : Array [1..maxvarregs] of Tsuperregister =
+ (RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7);
+
+ maxfpuvarregs = 1;
+ fpuvarregs : Array [1..maxfpuvarregs] of TsuperRegister =
+ (RS_F2);
+
+ {
+ max_param_regs_int = 6;
+ param_regs_int: Array[1..max_param_regs_int] of TCpuRegister =
+ (R_3,R_4,R_5,R_6,R_7,R_8,R_9,R_10);
+
+ max_param_regs_fpu = 13;
+ param_regs_fpu: Array[1..max_param_regs_fpu] of TCpuRegister =
+ (R_F1,R_F2,R_F3,R_F4,R_F5,R_F6,R_F7,R_F8,R_F9,R_F10,R_F11,R_F12,R_F13);
+
+ max_param_regs_mm = 13;
+ param_regs_mm: Array[1..max_param_regs_mm] of TCpuRegister =
+ (R_M1,R_M2,R_M3,R_M4,R_M5,R_M6,R_M7,R_M8,R_M9,R_M10,R_M11,R_M12,R_M13);
+ }
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M64;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_O6;
+ RS_STACK_POINTER_REG = RS_O6;
+ {# Frame pointer register }
+ NR_FRAME_POINTER_REG = NR_I6;
+ RS_FRAME_POINTER_REG = RS_I6;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+
+ Taken from GCC rs6000.h
+ }
+{$warning As indicated in rs6000.h, but can't find it anywhere else!}
+ {PIC_OFFSET_REG = R_30;}
+ { Return address for DWARF }
+ NR_RETURN_ADDRESS_REG = NR_I7;
+ { the return_result_reg, is used inside the called function to store its return
+ value when that is a scalar value otherwise a pointer to the address of the
+ result is placed inside it }
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_I0;
+ RS_FUNCTION_RETURN_REG = RS_I0;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_I1;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_I1;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_I0;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_I0;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_O0;
+ RS_FUNCTION_RESULT_REG = RS_O0;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_O1;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_O1;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_O0;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_O0;
+
+ NR_FPU_RESULT_REG = NR_F0;
+ NR_MM_RESULT_REG = NR_NO;
+
+ PARENT_FRAMEPOINTER_OFFSET = 68; { o0 }
+
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..0] of tsuperregister = (RS_NO);
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ const
+ simm13lo=-4096;
+ simm13hi=4095;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+
+ procedure inverse_flags(var f: TResFlags);
+ 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}
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ function reg_cgsize(const reg: tregister): tcgsize;
+ function std_regname(r:Tregister):string;
+ function std_regnum_search(const s:string):Tregister;
+ function findreg_by_number(r:Tregister):tregisterindex;
+
+
+implementation
+
+ uses
+ rgBase,verbose;
+
+ const
+ std_regname_table : TRegNameTAble = (
+ {$i rspstd.inc}
+ );
+
+ regnumber_index : TRegisterIndexTable = (
+ {$i rsprni.inc}
+ );
+
+ std_regname_index : TRegisterIndexTable = (
+ {$i rspsri.inc}
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+ const
+ CallJmpOp=[A_JMPL..A_CBccc];
+ begin
+ is_calljmp:=(o in CallJmpOp);
+ end;
+
+
+ procedure inverse_flags(var f: TResFlags);
+ const
+ inv_flags: array[TResFlags] of TResFlags =
+ (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_BE,F_B,F_AE,F_A,F_NC,F_C,
+ F_FNE,F_FE,F_FLE,F_FGE,F_FL,F_FG);
+ begin
+ f:=inv_flags[f];
+ end;
+
+
+ function flags_to_cond(const f:TResFlags):TAsmCond;
+ const
+ flags_2_cond:array[TResFlags] of TAsmCond=
+ (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_A,C_AE,C_B,C_BE,C_C,C_NC,
+ C_FE,C_FNE,C_FG,C_FL,C_FGE,C_FLE);
+ begin
+ result:=flags_2_cond[f];
+ end;
+
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ begin
+ if s in [OS_64,OS_S64] then
+ cgsize2subreg:=R_SUBQ
+ else
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ result:=OS_32;
+ R_FPUREGISTER :
+ begin
+ if getsubreg(reg)=R_SUBFD then
+ result:=OS_F64
+ else
+ result:=OS_F32;
+ end;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse: array[TAsmCond] of TAsmCond=(C_None,
+ C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
+ C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
+ C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ,
+ C_FNE,C_FLE,C_FGE,C_FL,C_FG,C_FE
+ );
+ begin
+ result := inverse[c];
+ end;
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+end.
diff --git a/compiler/sparc/cpugas.pas b/compiler/sparc/cpugas.pas
new file mode 100644
index 0000000000..9c85857f46
--- /dev/null
+++ b/compiler/sparc/cpugas.pas
@@ -0,0 +1,205 @@
+{
+ Copyright (c) 1999-2003 by Florian Klaempfl
+
+ This unit implements an asmoutput class for SPARC AT&T 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
+ TGasSPARC=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<simm13lo) or (Offset>simm13hi) then
+ internalerror(2003053008); }
+ if offset>0 then
+ GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
+ else if offset<0 then
+ GetReferenceString:=GetReferenceString+ToStr(offset);
+ {
+ else if (offset=0) and not(assigned(symbol)) then
+ GetReferenceString:=GetReferenceString+ToStr(offset);
+ }
+ 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;
+
+
+ procedure TGasSPARC.WriteInstruction(hp:Tai);
+ var
+ Op:TAsmOp;
+ s:String;
+ i:Integer;
+ begin
+ if hp.typ<>ait_instruction then
+ exit;
+ op:=taicpu(hp).opcode;
+ { translate pseudoops, this should be move to a separate pass later, so it's done before
+ peephole optimization }
+ case op of
+ A_FABSd:
+ begin
+ if (taicpu(hp).ops<>2) or
+ (taicpu(hp).oper[0]^.typ<>top_reg) or
+ (taicpu(hp).oper[1]^.typ<>top_reg) then
+ internalerror(200401045);
+ { FABSs %f<even>,%f<even> }
+ s:=#9+std_op2str[A_FABSs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ AsmWriteLn(s);
+ { FMOVs %f<odd>,%f<odd> }
+ inc(taicpu(hp).oper[0]^.reg);
+ inc(taicpu(hp).oper[1]^.reg);
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ dec(taicpu(hp).oper[0]^.reg);
+ dec(taicpu(hp).oper[1]^.reg);
+ AsmWriteLn(s);
+ end;
+ A_FMOVd:
+ begin
+ if (taicpu(hp).ops<>2) or
+ (taicpu(hp).oper[0]^.typ<>top_reg) or
+ (taicpu(hp).oper[1]^.typ<>top_reg) then
+ internalerror(200401045);
+ { FMOVs %f<even>,%f<even> }
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ AsmWriteLn(s);
+ { FMOVs %f<odd>,%f<odd> }
+ inc(taicpu(hp).oper[0]^.reg);
+ inc(taicpu(hp).oper[1]^.reg);
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ dec(taicpu(hp).oper[0]^.reg);
+ dec(taicpu(hp).oper[1]^.reg);
+ AsmWriteLn(s);
+ end
+ else
+ begin
+ { call maybe not translated to call }
+ 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_sparc_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+begin
+ RegisterAssembler(as_SPARC_as_info,TGasSPARC);
+end.
diff --git a/compiler/sparc/cpuinfo.pas b/compiler/sparc/cpuinfo.pas
new file mode 100644
index 0000000000..e6658dcf1b
--- /dev/null
+++ b/compiler/sparc/cpuinfo.pas
@@ -0,0 +1,68 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Basic Processor information for the 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 cpuinfo;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype;
+
+type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = type extended;
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors=(no_processor,SPARC_V7,SPARC_V8,SPARC_V9);
+
+ tfputype =(no_fpu,fpu_soft,fpu_hard);
+
+
+const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl
+ ];
+
+ processorsstr : array[tprocessors] of string[10] = ('',
+ 'SPARC V7',
+ 'SPARC V8',
+ 'SPARC V9'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'SOFT',
+ 'HARD'
+ );
+
+implementation
+
+end.
diff --git a/compiler/sparc/cpunode.pas b/compiler/sparc/cpunode.pas
new file mode 100644
index 0000000000..63fdb77d6f
--- /dev/null
+++ b/compiler/sparc/cpunode.pas
@@ -0,0 +1,38 @@
+{******************************************************************************
+ Copyright (c) 2000 by Florian Klaempfl
+
+ Includes the iSPARC 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
+ ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
+ ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset,
+ { this not really a node }
+ rgcpu;
+
+end.
diff --git a/compiler/sparc/cpupara.pas b/compiler/sparc/cpupara.pas
new file mode 100644
index 0000000000..e8b9e3bdb4
--- /dev/null
+++ b/compiler/sparc/cpupara.pas
@@ -0,0 +1,325 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Calling conventions for the 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 cpupara;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cclasses,
+ aasmtai,
+ cpubase,cpuinfo,
+ symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase;
+
+ type
+ TSparcParaManager=class(TParaManager)
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
+ {Returns a structure giving the information on the storage of the parameter
+ (which must be an integer parameter)
+ @param(nr Parameter number of routine, starting from 1)}
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
+ function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
+ private
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var intparareg,parasize:longint);
+ end;
+
+implementation
+
+ uses
+ cutils,verbose,systems,
+ defutil,
+ cgutils,cgobj;
+
+ type
+ tparasupregs = array[0..5] of tsuperregister;
+ pparasupregs = ^tparasupregs;
+ const
+ paraoutsupregs : tparasupregs = (RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5);
+ parainsupregs : tparasupregs = (RS_I0,RS_I1,RS_I2,RS_I3,RS_I4,RS_I5);
+
+
+ function TSparcParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
+ begin
+ result:=[RS_G1,RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,RS_O6,RS_O7];
+ end;
+
+
+ function tsparcparamanager.get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;
+ begin
+ result:=[RS_F0..RS_F31];
+ end;
+
+
+ procedure TSparcParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint;var cgpara : tcgpara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ InternalError(2002100806);
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.intsize:=tcgsize2size[OS_INT];
+ cgpara.alignment:=std_param_align;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ { The six first parameters are passed into registers }
+ dec(nr);
+ if nr<6 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,(RS_O0+nr),R_SUBWHOLE);
+ end
+ else
+ begin
+ { The other parameters are passed on the stack }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=92+(nr-6)*4;
+ end;
+ size:=OS_INT;
+ end;
+ end;
+
+
+ { true if a parameter is too large to copy and only the address is pushed }
+ function tsparcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out always require address }
+ if varspez in [vs_var,vs_out] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.deftype of
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ recorddef,
+ variantdef,
+ formaldef :
+ result:=true;
+ objectdef :
+ result:=is_object(def);
+ stringdef :
+ result:=(tstringdef(def).string_typ in [st_shortstring,st_longstring]);
+ procvardef :
+ result:=(po_methodpointer in tprocvardef(def).procoptions);
+ setdef :
+ result:=(tsetdef(def).settype<>smallset);
+ end;
+ end;
+
+
+ procedure tsparcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ var
+ retcgsize : tcgsize;
+ begin
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ retcgsize:=OS_ADDR
+ else
+ retcgsize:=def_cgsize(p.rettype.def);
+
+ location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
+ p.funcretloc[side].size:=retcgsize;
+ { void has no location }
+ if is_void(p.rettype.def) then
+ begin
+ p.funcretloc[side].loc:=LOC_VOID;
+ exit;
+ end;
+
+ { Return in FPU register? }
+ if p.rettype.def.deftype=floatdef then
+ begin
+ p.funcretloc[side].loc:=LOC_FPUREGISTER;
+ p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+ if retcgsize=OS_F64 then
+ setsubreg(p.funcretloc[side].register,R_SUBFD);
+ p.funcretloc[side].size:=retcgsize;
+ end
+ else
+ { Return in register? }
+ if not ret_in_param(p.rettype.def,p.proccalloption) then
+ begin
+{$ifndef cpu64bit}
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ { high }
+ if (side=callerside) or (po_inline in p.procoptions) then
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+ { low }
+ if (side=callerside) or (po_inline in p.procoptions) then
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+ end
+ else
+{$endif cpu64bit}
+ begin
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].size:=retcgsize;
+ if (side=callerside) or (po_inline in p.procoptions)then
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+ else
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+ end;
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REFERENCE;
+ p.funcretloc[side].size:=retcgsize;
+ end;
+ end;
+
+
+ procedure tsparcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var intparareg,parasize:longint);
+ var
+ paraloc : pcgparalocation;
+ i : integer;
+ hp : tparavarsym;
+ paracgsize : tcgsize;
+ hparasupregs : pparasupregs;
+ paralen : longint;
+ begin
+ if side=callerside then
+ hparasupregs:=@paraoutsupregs
+ else
+ hparasupregs:=@parainsupregs;
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ { currently only support C-style array of const,
+ there should be no location assigned to the vararg array itself }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(hp.vartype.def) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_G0;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption) then
+ paracgsize:=OS_ADDR
+ else
+ begin
+ paracgsize:=def_cgSize(hp.vartype.def);
+ if paracgsize=OS_NO then
+ paracgsize:=OS_ADDR;
+ end;
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].Alignment:=std_param_align;
+ paralen:=tcgsize2size[paracgsize];
+ hp.paraloc[side].intsize:=paralen;
+ while paralen>0 do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { Floats are passed in int registers,
+ We can allocate at maximum 32 bits per register }
+ if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
+ paraloc^.size:=OS_32
+ else
+ paraloc^.size:=paracgsize;
+ { ret in param? }
+ if vo_is_funcret in hp.varoptions then
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=64;
+ end
+ else if (intparareg<=high(tparasupregs)) then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE);
+ inc(intparareg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
+ { Parameters are aligned at 4 bytes }
+ inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
+ end;
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ end;
+ end;
+
+
+ function TSparcParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ intparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ parasize:=0;
+ { calculate the registers for the normal parameters }
+ create_paraloc_info_intern(p,callerside,p.paras,intparareg,parasize);
+ { append the varargs }
+ create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize);
+ result:=parasize;
+ end;
+
+
+
+ function tsparcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ intparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ parasize:=0;
+ create_paraloc_info_intern(p,side,p.paras,intparareg,parasize);
+ { Create Function result paraloc }
+ create_funcretloc_info(p,side);
+ { We need to return the size allocated on the stack }
+ result:=parasize;
+ end;
+
+
+begin
+ ParaManager:=TSparcParaManager.create;
+end.
diff --git a/compiler/sparc/cpupi.pas b/compiler/sparc/cpupi.pas
new file mode 100644
index 0000000000..e3e32bebed
--- /dev/null
+++ b/compiler/sparc/cpupi.pas
@@ -0,0 +1,84 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ 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 cpupi;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,
+ procinfo,cpuinfo,
+ psub;
+
+ type
+ TSparcProcInfo=class(tcgprocinfo)
+ public
+ constructor create(aparent:tprocinfo);override;
+ procedure allocate_push_parasize(size:longint);override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+implementation
+
+ uses
+ systems,globals,
+ tgobj,paramgr,symconst;
+
+ constructor tsparcprocinfo.create(aparent:tprocinfo);
+ begin
+ inherited create(aparent);
+ maxpushedparasize:=0;
+ end;
+
+
+ procedure tsparcprocinfo.allocate_push_parasize(size:longint);
+ begin
+ if size>maxpushedparasize then
+ maxpushedparasize:=size;
+ end;
+
+
+ function TSparcProcInfo.calc_stackframe_size:longint;
+ begin
+ {
+ Stackframe layout:
+ %fp
+ <locals>
+ <temp>
+ <arguments 6-n for calling>
+ %sp+92
+ <space for arguments 0-5> \
+ <return pointer for calling> | included in first_parm_offset
+ <register window save area for calling> /
+ %sp
+
+ Alignment must be the max available, as doubles require
+ 8 byte alignment
+ }
+ result:=Align(tg.direction*tg.lasttemp+maxpushedparasize+target_info.first_parm_offset,aktalignment.localalignmax);
+ end;
+
+
+begin
+ cprocinfo:=TSparcProcInfo;
+end.
diff --git a/compiler/sparc/cpuswtch.pas b/compiler/sparc/cpuswtch.pas
new file mode 100644
index 0000000000..f94e8c080c
--- /dev/null
+++ b/compiler/sparc/cpuswtch.pas
@@ -0,0 +1,125 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl, Pierre Muller
+
+ interprets the commandline options which are iSPARC specific
+
+ 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 cpuswtch;
+
+{$INCLUDE fpcdefs.inc}
+
+interface
+
+uses
+ options;
+
+type
+ toptionSPARC=class(toption)
+ procedure interpret_proc_specific_options(const opt:string);override;
+ end;
+
+implementation
+
+uses
+ cutils,globtype,systems,globals,cpuinfo;
+
+procedure toptionSPARC.interpret_proc_specific_options(const opt:string);
+var
+ j : longint;
+ More : string;
+begin
+ More:=Upper(copy(opt,3,length(opt)-2));
+ case opt[2] of
+ 'O' : Begin
+ j := 3;
+ While (j <= Length(Opt)) Do
+ Begin
+ case opt[j] of
+ '-' :
+ begin
+ initglobalswitches:=initglobalswitches-[cs_optimize,cs_fastoptimize,cs_slowoptimize,cs_littlesize,
+ cs_regvars,cs_uncertainopts];
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+ end;
+ 'a' :
+ begin
+ UpdateAlignmentStr(Copy(Opt,j+1,255),ParaAlignment);
+ j:=length(Opt);
+ end;
+ 'g' : initglobalswitches:=initglobalswitches+[cs_littlesize];
+ 'G' : initglobalswitches:=initglobalswitches-[cs_littlesize];
+ 'r' :
+ begin
+ initglobalswitches:=initglobalswitches+[cs_regvars];
+ Simplify_ppu:=false;
+ end;
+ 'u' : initglobalswitches:=initglobalswitches+[cs_uncertainopts];
+ '1' : initglobalswitches:=initglobalswitches-[cs_fastoptimize,cs_slowoptimize]+[cs_optimize];
+ '2' : initglobalswitches:=initglobalswitches-[cs_slowoptimize]+[cs_optimize,cs_fastoptimize];
+ '3' : initglobalswitches:=initglobalswitches+[cs_optimize,cs_fastoptimize,cs_slowoptimize];
+ 'p' :
+ Begin
+ If j < Length(Opt) Then
+ Begin
+ Case opt[j+1] Of
+ '1': initoptprocessor := SPARC_V8;
+ '2': initoptprocessor := SPARC_V9;
+ '3': initoptprocessor := SPARC_V9;
+ Else IllegalPara(Opt)
+ End;
+ Inc(j);
+ End
+ Else IllegalPara(opt)
+ End;
+{$ifdef USECMOV}
+ 's' :
+ Begin
+ If j < Length(Opt) Then
+ Begin
+ Case opt[j+1] Of
+ '3': initspecificoptprocessor:=ClassP6
+ Else IllegalPara(Opt)
+ End;
+ Inc(j);
+ End
+ Else IllegalPara(opt)
+ End
+{$endif USECMOV}
+ else IllegalPara(opt);
+ End;
+ Inc(j)
+ end;
+ end;
+ 'R' : begin
+ if More='GAS' then
+ initasmmode:=asmmode_i386_att
+ else
+ if More='STANDARD' then
+ initasmmode:=asmmode_i386_intel
+ else
+ IllegalPara(opt);
+ end;
+ else
+ IllegalPara(opt);
+ end;
+end;
+
+
+initialization
+ coption:=toptionSPARC;
+end.
diff --git a/compiler/sparc/cputarg.pas b/compiler/sparc/cputarg.pas
new file mode 100644
index 0000000000..a7b77c8467
--- /dev/null
+++ b/compiler/sparc/cputarg.pas
@@ -0,0 +1,76 @@
+{
+ Copyright (c) 2001 by Peter Vreman
+
+ Includes the i386 dependent target units
+
+ 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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{$ifndef NOOPT}
+ ,aoptcpu
+{$endif NOOPT}
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETSUNOS}
+ ,t_sunos
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ ,CpuGas
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoSparcgas}
+ ,racpugas
+ {$endif NoSparcgas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+ ;
+
+end.
diff --git a/compiler/sparc/itcpugas.pas b/compiler/sparc/itcpugas.pas
new file mode 100644
index 0000000000..c3a1ae4599
--- /dev/null
+++ b/compiler/sparc/itcpugas.pas
@@ -0,0 +1,98 @@
+{
+ Copyright (c) 1998-2002 by Mazen NEIFER
+
+ This unit contains the SPARC GAS instruction tables
+
+ 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 itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+ const
+ gas_op2str : array[tasmop] of string[14] = ({$INCLUDE strinst.inc});
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose;
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {$i rspstd.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rspsri.inc}
+ );
+
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ hr : tregister;
+ p : longint;
+ begin
+ { Double uses the same table as single }
+ hr:=r;
+ case getsubreg(hr) of
+ R_SUBFD:
+ setsubreg(hr,R_SUBFS);
+ R_SUBL,R_SUBW,R_SUBD,R_SUBQ:
+ setsubreg(hr,R_SUBD);
+ end;
+ p:=findreg_by_number(hr);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/compiler/sparc/ncpuadd.pas b/compiler/sparc/ncpuadd.pas
new file mode 100644
index 0000000000..413880988f
--- /dev/null
+++ b/compiler/sparc/ncpuadd.pas
@@ -0,0 +1,376 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Code generation for add nodes on the 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 ncpuadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgadd,cpubase;
+
+ type
+ tsparcaddnode = class(tcgaddnode)
+ private
+ function GetResFlags(unsigned:Boolean):TResFlags;
+ function GetFPUResFlags:TResFlags;
+ 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,defutil,
+ cgbase,cgcpu,cgutils,
+ cpupara,
+ ncon,nset,nadd,
+ ncgutil,cgobj;
+
+{*****************************************************************************
+ TSparcAddNode
+*****************************************************************************}
+
+ function TSparcAddNode.GetResFlags(unsigned:Boolean):TResFlags;
+ begin
+ case NodeType of
+ equaln:
+ GetResFlags:=F_E;
+ unequaln:
+ GetResFlags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swaped in flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_G;
+ lten:
+ GetResFlags:=F_GE;
+ gtn:
+ GetResFlags:=F_L;
+ gten:
+ GetResFlags:=F_LE;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_L;
+ lten:
+ GetResFlags:=F_LE;
+ gtn:
+ GetResFlags:=F_G;
+ gten:
+ GetResFlags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swaped in Flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_A;
+ lten:
+ GetResFlags:=F_AE;
+ gtn:
+ GetResFlags:=F_B;
+ gten:
+ GetResFlags:=F_BE;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_B;
+ lten:
+ GetResFlags:=F_BE;
+ gtn:
+ GetResFlags:=F_A;
+ gten:
+ GetResFlags:=F_AE;
+ end;
+ end;
+ end;
+ end;
+
+
+ function TSparcAddNode.GetFPUResFlags:TResFlags;
+ begin
+ case NodeType of
+ equaln:
+ result:=F_FE;
+ unequaln:
+ result:=F_FNE;
+ else
+ begin
+ if nf_swaped in Flags then
+ case NodeType of
+ ltn:
+ result:=F_FG;
+ lten:
+ result:=F_FGE;
+ gtn:
+ result:=F_FL;
+ gten:
+ result:=F_FLE;
+ end
+ else
+ case NodeType of
+ ltn:
+ result:=F_FL;
+ lten:
+ result:=F_FLE;
+ gtn:
+ result:=F_FG;
+ gten:
+ result:=F_FGE;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tsparcaddnode.second_addfloat;
+ var
+ op : TAsmOp;
+ begin
+ pass_left_right;
+ if (nf_swaped in flags) then
+ swapleftright;
+
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(exprasmlist,left.location,true);
+ location_force_fpureg(exprasmlist,right.location,(left.location.loc<>LOC_CFPUREGISTER));
+
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ 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_FADDd
+ else
+ op:=A_FADDs;
+ end;
+ muln :
+ begin
+ if location.size=OS_F64 then
+ op:=A_FMULd
+ else
+ op:=A_FMULs;
+ end;
+ subn :
+ begin
+ if location.size=OS_F64 then
+ op:=A_FSUBd
+ else
+ op:=A_FSUBs;
+ end;
+ slashn :
+ begin
+ if location.size=OS_F64 then
+ op:=A_FDIVd
+ else
+ op:=A_FDIVs;
+ end;
+ else
+ internalerror(200306014);
+ end;
+
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op,
+ left.location.register,right.location.register,location.register));
+ end;
+
+
+ procedure tsparcaddnode.second_cmpfloat;
+ var
+ op : tasmop;
+ begin
+ pass_left_right;
+ if (nf_swaped in flags) then
+ swapleftright;
+
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(exprasmlist,left.location,true);
+ location_force_fpureg(exprasmlist,right.location,true);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getfpuresflags;
+
+ if left.location.size=OS_F64 then
+ op:=A_FCMPd
+ else
+ op:=A_FCMPs;
+ exprasmlist.concat(taicpu.op_reg_reg(op,
+ left.location.register,right.location.register));
+ { Delay slot (can only contain integer operation) }
+ exprasmlist.concat(taicpu.op_none(A_NOP));
+ end;
+
+
+ procedure tsparcaddnode.second_cmpboolean;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ if right.location.loc = LOC_CONSTANT then
+ tcgsparc(cg).handle_reg_const_reg(exprasmlist,A_SUBcc,left.location.register,right.location.value,NR_G0)
+ else
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+ end;
+
+
+ procedure tsparcaddnode.second_cmpsmallset;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ if right.location.loc = LOC_CONSTANT then
+ tcgsparc(cg).handle_reg_const_reg(exprasmlist,A_SUBcc,left.location.register,right.location.value,NR_G0)
+ else
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+ end;
+
+
+ procedure tsparcaddnode.second_cmp64bit;
+ var
+ unsigned : boolean;
+
+ procedure firstjmp64bitcmp;
+ var
+ oldnodetype : tnodetype;
+ begin
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn:
+ begin
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),truelabel);
+ { cheat a little bit for the negative test }
+ toggleflag(nf_swaped);
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),falselabel);
+ toggleflag(nf_swaped);
+ end;
+ lten,gten:
+ begin
+ oldnodetype:=nodetype;
+ if nodetype=lten then
+ nodetype:=ltn
+ else
+ nodetype:=gtn;
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),truelabel);
+ { cheat for the negative test }
+ if nodetype=ltn then
+ nodetype:=gtn
+ else
+ nodetype:=ltn;
+ cg.a_jmp_flags(exprasmlist,getresflags(unsigned),falselabel);
+ nodetype:=oldnodetype;
+ end;
+ equaln:
+ cg.a_jmp_flags(exprasmlist,F_NE,falselabel);
+ unequaln:
+ cg.a_jmp_flags(exprasmlist,F_NE,truelabel);
+ end;
+ end;
+
+ procedure secondjmp64bitcmp;
+
+ begin
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn,lten,gten:
+ begin
+ { the comparisaion of the low dword have to be }
+ { always unsigned! }
+ cg.a_jmp_flags(exprasmlist,getresflags(true),truelabel);
+ cg.a_jmp_always(exprasmlist,falselabel);
+ end;
+ equaln:
+ begin
+ cg.a_jmp_flags(exprasmlist,F_NE,falselabel);
+ cg.a_jmp_always(exprasmlist,truelabel);
+ end;
+ unequaln:
+ begin
+ cg.a_jmp_flags(exprasmlist,F_NE,truelabel);
+ cg.a_jmp_always(exprasmlist,falselabel);
+ end;
+ end;
+ end;
+
+ begin
+ pass_left_right;
+ force_reg_left_right(false,false);
+
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+
+ location_reset(location,LOC_JUMP,OS_NO);
+
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
+ firstjmp64bitcmp;
+ exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo));
+ secondjmp64bitcmp;
+ end;
+
+
+ procedure tsparcaddnode.second_cmpordinal;
+ var
+ unsigned : boolean;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+
+ if right.location.loc = LOC_CONSTANT then
+ tcgsparc(cg).handle_reg_const_reg(exprasmlist,A_SUBcc,left.location.register,right.location.value,NR_G0)
+ else
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ end;
+
+begin
+ caddnode:=tsparcaddnode;
+end.
diff --git a/compiler/sparc/ncpucall.pas b/compiler/sparc/ncpucall.pas
new file mode 100644
index 0000000000..343957ced8
--- /dev/null
+++ b/compiler/sparc/ncpucall.pas
@@ -0,0 +1,56 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate sparc assembler for in call 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 ncpucall;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ ncgcal;
+
+ type
+ tsparccallnode = class(tcgcallnode)
+ procedure extra_post_call_code;override;
+ end;
+
+
+implementation
+
+ uses
+ cpubase,
+ aasmtai,
+ aasmcpu,
+ paramgr,
+ ncal;
+
+
+ procedure tsparccallnode.extra_post_call_code;
+ begin
+ if paramanager.ret_in_param(procdefinition.rettype.def,procdefinition.proccalloption) then
+ exprasmlist.concat(taicpu.op_const(A_UNIMP,procdefinition.rettype.def.size and $fff));
+ end;
+
+
+begin
+ ccallnode:=TSparcCallNode;
+end.
diff --git a/compiler/sparc/ncpucnv.pas b/compiler/sparc/ncpucnv.pas
new file mode 100644
index 0000000000..26df287315
--- /dev/null
+++ b/compiler/sparc/ncpucnv.pas
@@ -0,0 +1,305 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate SPARC assembler for type converting 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 ncpucnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,defcmp;
+
+ type
+ tsparctypeconvnode = class(TCgTypeConvNode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real;override;
+ procedure second_real_to_real;override;
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+ uses
+ verbose,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,
+ defutil,
+ cgbase,cgutils,pass_1,pass_2,
+ ncon,ncal,
+ ncgutil,
+ cpubase,aasmcpu,
+ tgobj,cgobj;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function tsparctypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[19];
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resulttype.def) or
+ is_currency(left.resulttype.def) then
+ begin
+ { hack to avoid double division by 10000, as it's
+ already done by resulttypepass.resulttype_int_to_real }
+ if is_currency(left.resulttype.def) then
+ left.resulttype := s64inttype;
+ if is_signed(left.resulttype.def) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resulttype.def) then
+ inserttypeconv(left,s32inttype)
+ else
+ inserttypeconv(left,u32inttype);
+ firstpass(left);
+ end;
+ result := nil;
+ if registersfpu<1 then
+ registersfpu:=1;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+ procedure tsparctypeconvnode.second_int_to_real;
+
+ procedure loadsigned;
+ begin
+ location_force_mem(exprasmlist,left.location);
+ { Load memory in fpu register }
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F32,left.location.reference,location.register);
+ tg.ungetiftemp(exprasmlist,left.location.reference);
+ { Convert value in fpu register from integer to float }
+ case tfloatdef(resulttype.def).typ of
+ s32real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FiTOs,location.register,location.register));
+ s64real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FiTOd,location.register,location.register));
+ s128real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FiTOq,location.register,location.register));
+ else
+ internalerror(200408011);
+ end;
+ end;
+
+ var
+ href : treference;
+ hregister : tregister;
+ l1,l2 : tasmlabel;
+
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ if is_signed(left.resulttype.def) then
+ begin
+ location.register:=cg.getfpuregister(exprasmlist,location.size);
+ loadsigned;
+ end
+ else
+ begin
+ objectlibrary.getdatalabel(l1);
+ objectlibrary.getjumplabel(l2);
+ reference_reset_symbol(href,l1,0);
+ hregister:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_loc_reg(exprasmlist,OS_32,left.location,hregister);
+
+ { here we need always an 64 bit register }
+ location.register:=cg.getfpuregister(exprasmlist,OS_F64);
+ location_force_mem(exprasmlist,left.location);
+ { Load memory in fpu register }
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F32,left.location.reference,location.register);
+ tg.ungetiftemp(exprasmlist,left.location.reference);
+ exprasmlist.concat(taicpu.op_reg_reg(A_FiTOd,location.register,location.register));
+
+ exprasmList.concat(Taicpu.op_reg_reg(A_CMP,hregister,NR_G0));
+ cg.a_jmp_flags(exprasmlist,F_GE,l2);
+
+ case tfloatdef(resulttype.def).typ of
+ { converting dword to s64real first and cut off at the end avoids precision loss }
+ s32real,
+ s64real:
+ begin
+ hregister:=cg.getfpuregister(exprasmlist,OS_F64);
+ asmlist[al_typedconsts].concat(tai_align.create(const_align(8)));
+ asmlist[al_typedconsts].concat(Tai_label.Create(l1));
+ { I got this constant from a test program (FK) }
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit($41f00000));
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit(0));
+
+ cg.a_loadfpu_ref_reg(exprasmlist,OS_F64,href,hregister);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_FADDD,location.register,hregister,location.register));
+ cg.a_label(exprasmlist,l2);
+
+ { cut off if we should convert to single }
+ if tfloatdef(resulttype.def).typ=s32real then
+ begin
+ hregister:=location.register;
+ location.register:=cg.getfpuregister(exprasmlist,location.size);
+ exprasmlist.concat(taicpu.op_reg_reg(A_FDTOS,hregister,location.register));
+ end;
+ end;
+ else
+ internalerror(200410031);
+ end;
+ end;
+ end;
+
+
+ procedure tsparctypeconvnode.second_real_to_real;
+ const
+ conv_op : array[tfloattype,tfloattype] of tasmop = (
+ { from: s32 s64 s80 c64 cur f128 }
+ { s32 } ( A_FMOVS,A_FDTOS,A_NONE, A_NONE, A_NONE, A_NONE ),
+ { s64 } ( A_FSTOD,A_FMOVD,A_NONE, A_NONE, A_NONE, A_NONE ),
+ { s80 } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { c64 } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { cur } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { f128 } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE )
+ );
+ var
+ op : tasmop;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ location_force_fpureg(exprasmlist,left.location,false);
+ { Convert value in fpu register from integer to float }
+ op:=conv_op[tfloatdef(resulttype.def).typ,tfloatdef(left.resulttype.def).typ];
+ if op=A_NONE then
+ internalerror(200401121);
+ location.register:=cg.getfpuregister(exprasmlist,location.size);
+ exprasmlist.concat(taicpu.op_reg_reg(op,left.location.register,location.register));
+ end;
+
+
+ procedure tsparctypeconvnode.second_int_to_bool;
+ var
+ hreg1,hreg2 : tregister;
+ resflags : tresflags;
+ opsize : tcgsize;
+ hlabel,oldtruelabel,oldfalselabel : tasmlabel;
+ begin
+ oldtruelabel:=truelabel;
+ oldfalselabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { byte(boolean) or word(wordbool) or longint(longbool) must }
+ { be accepted for var parameters }
+ if (nf_explicit in flags)and
+ (left.resulttype.def.size=resulttype.def.size)and
+ (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ begin
+ location_copy(location,left.location);
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ exit;
+ end;
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
+ opsize:=def_cgsize(left.resulttype.def);
+ case left.location.loc of
+ LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
+ begin
+ if left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
+ begin
+ hreg2:=cg.getintregister(exprasmlist,opsize);
+ cg.a_load_ref_reg(exprasmlist,opsize,opsize,left.location.reference,hreg2);
+ end
+ else
+ hreg2:=left.location.register;
+{$ifndef cpu64bit}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hreg1:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_32,hreg2,tregister(succ(longint(hreg2))),hreg1);
+ hreg2:=hreg1;
+ opsize:=OS_32;
+ end;
+{$endif cpu64bit}
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBCC,NR_G0,hreg2,NR_G0));
+ hreg1:=cg.getintregister(exprasmlist,opsize);
+ exprasmlist.concat(taicpu.op_reg_const_reg(A_ADDX,NR_G0,0,hreg1));
+ end;
+ LOC_FLAGS :
+ begin
+ hreg1:=cg.GetIntRegister(exprasmlist,location.size);
+ resflags:=left.location.resflags;
+ cg.g_flags2reg(exprasmlist,location.size,resflags,hreg1);
+ end;
+ LOC_JUMP :
+ begin
+ hreg1:=cg.getintregister(exprasmlist,OS_INT);
+ objectlibrary.getjumplabel(hlabel);
+ cg.a_label(exprasmlist,truelabel);
+ cg.a_load_const_reg(exprasmlist,OS_INT,1,hreg1);
+ cg.a_jmp_always(exprasmlist,hlabel);
+ cg.a_label(exprasmlist,falselabel);
+ cg.a_load_const_reg(exprasmlist,OS_INT,0,hreg1);
+ cg.a_label(exprasmlist,hlabel);
+ end;
+ else
+ internalerror(10062);
+ end;
+ location.register:=hreg1;
+
+ if location.size in [OS_64, OS_S64] then
+ internalerror(200408241);
+
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ end;
+
+
+begin
+ ctypeconvnode:=tsparctypeconvnode;
+end.
diff --git a/compiler/sparc/ncpuinln.pas b/compiler/sparc/ncpuinln.pas
new file mode 100644
index 0000000000..4e3dfb7fdc
--- /dev/null
+++ b/compiler/sparc/ncpuinln.pas
@@ -0,0 +1,149 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate SPARC inline 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 ncpuinln;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl,ncginl;
+
+ type
+ tsparcinlinenode = class(tcgInlineNode)
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ function first_sqrt_real: tnode; override;
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_sqrt_real; override;
+ private
+ procedure load_fpu_location;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ cutils,verbose,
+ symconst,symdef,
+ aasmtai,aasmcpu,
+ cgbase,pass_2,
+ cpubase,paramgr,
+ nbas,ncon,ncal,ncnv,nld,
+ ncgutil,cgobj,cgutils;
+
+{*****************************************************************************
+ tsparcinlinenode
+*****************************************************************************}
+
+ procedure tsparcinlinenode.load_fpu_location;
+ begin
+ secondpass(left);
+ location_force_fpureg(exprasmlist,left.location,true);
+ location_copy(location,left.location);
+ if left.location.loc=LOC_CFPUREGISTER then
+ begin
+ location.register:=cg.getfpuregister(exprasmlist,location.size);
+ location.loc := LOC_FPUREGISTER;
+ end;
+ end;
+
+
+ function tsparcinlinenode.first_abs_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ first_abs_real := nil;
+ end;
+
+
+ function tsparcinlinenode.first_sqr_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ first_sqr_real:=nil;
+ end;
+
+
+ function tsparcinlinenode.first_sqrt_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+ first_sqrt_real := nil;
+ end;
+
+
+ procedure tsparcinlinenode.second_abs_real;
+ begin
+ load_fpu_location;
+ case tfloatdef(left.resulttype.def).typ of
+ s32real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FABSs,left.location.register,location.register));
+ s64real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FABSd,left.location.register,location.register));
+ s128real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FABSq,left.location.register,location.register));
+ else
+ internalerror(200410031);
+ end;
+ end;
+
+
+ procedure tsparcinlinenode.second_sqr_real;
+ begin
+ load_fpu_location;
+ case tfloatdef(left.resulttype.def).typ of
+ s32real:
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_FMULs,left.location.register,left.location.register,location.register));
+ s64real:
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_FMULd,left.location.register,left.location.register,location.register));
+ s128real:
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_FMULq,left.location.register,left.location.register,location.register));
+ else
+ internalerror(200410032);
+ end;
+ end;
+
+
+ procedure tsparcinlinenode.second_sqrt_real;
+ begin
+ load_fpu_location;
+ case tfloatdef(left.resulttype.def).typ of
+ s32real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FSQRTs,left.location.register,location.register));
+ s64real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FSQRTd,left.location.register,location.register));
+ s128real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_FSQRTq,left.location.register,location.register));
+ else
+ internalerror(200410033);
+ end;
+ end;
+
+begin
+ cInlineNode:=tsparcinlinenode;
+end.
diff --git a/compiler/sparc/ncpumat.pas b/compiler/sparc/ncpumat.pas
new file mode 100644
index 0000000000..34879d9790
--- /dev/null
+++ b/compiler/sparc/ncpumat.pas
@@ -0,0 +1,324 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate SPARC assembler for math 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 ncpumat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat;
+
+ type
+ tSparcmoddivnode = class(tmoddivnode)
+ procedure pass_2;override;
+ end;
+
+ tSparcshlshrnode = class(tshlshrnode)
+ procedure pass_2;override;
+ { everything will be handled in pass_2 }
+ function first_shlshr64bitint: tnode; override;
+ end;
+
+ tSparcnotnode = class(tcgnotnode)
+ procedure second_boolean;override;
+ end;
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,
+ aasmbase,aasmcpu,aasmtai,
+ defutil,
+ cgbase,cgobj,pass_2,
+ ncon,
+ cpubase,
+ ncgutil,cgcpu,cgutils;
+
+{*****************************************************************************
+ TSparcMODDIVNODE
+*****************************************************************************}
+
+ procedure tSparcmoddivnode.pass_2;
+ const
+ { signed overflow }
+ divops: array[boolean, boolean] of tasmop =
+ ((A_UDIV,A_UDIVcc),(A_SDIV,A_SDIVcc));
+ var
+ power : longint;
+ op : tasmop;
+ tmpreg,
+ numerator,
+ divider,
+ resultreg : tregister;
+ overflowlabel : tasmlabel;
+ ai : taicpu;
+ begin
+ secondpass(left);
+ secondpass(right);
+ location_copy(location,left.location);
+
+ { put numerator in register }
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),true);
+ location_copy(location,left.location);
+ numerator := location.register;
+
+ if (nodetype = modn) then
+ resultreg := cg.GetIntRegister(exprasmlist,OS_INT)
+ else
+ begin
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ location.register := cg.GetIntRegister(exprasmlist,OS_INT);
+ end;
+ resultreg := location.register;
+ end;
+
+ if (nodetype = divn) and
+ (right.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(right).value,power) then
+ begin
+ tmpreg:=cg.GetIntRegister(exprasmlist,OS_INT);
+ cg.a_op_const_reg_reg(exprasmlist,OP_SAR,OS_INT,31,numerator,tmpreg);
+ { if signed, tmpreg=right value-1, otherwise 0 }
+ cg.a_op_const_reg(exprasmlist,OP_AND,OS_INT,tordconstnode(right).value-1,tmpreg);
+ { add to the left value }
+ cg.a_op_reg_reg(exprasmlist,OP_ADD,OS_INT,tmpreg,numerator);
+ cg.a_op_const_reg_reg(exprasmlist,OP_SAR,OS_INT,aword(power),numerator,resultreg);
+ end
+ else
+ begin
+ { load divider in a register if necessary }
+ location_force_reg(exprasmlist,right.location,
+ def_cgsize(right.resulttype.def),true);
+ divider := right.location.register;
+
+ { needs overflow checking, (-maxlongint-1) div (-1) overflows! }
+ { And on Sparc, the only way to catch a div-by-0 is by checking }
+ { the overflow flag (JM) }
+
+ { Fill %y with the -1 or 0 depending on the highest bit }
+ if is_signed(left.resulttype.def) then
+ begin
+ tmpreg:=cg.GetIntRegister(exprasmlist,OS_INT);
+ exprasmlist.concat(taicpu.op_reg_const_reg(A_SRA,numerator,31,tmpreg));
+ exprasmlist.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_Y));
+ end
+ else
+ exprasmlist.concat(taicpu.op_reg_reg(A_MOV,NR_G0,NR_Y));
+ { wait 3 instructions slots before we can read %y }
+ exprasmlist.concat(taicpu.op_none(A_NOP));
+ exprasmlist.concat(taicpu.op_none(A_NOP));
+ exprasmlist.concat(taicpu.op_none(A_NOP));
+
+ op := divops[is_signed(right.resulttype.def),
+ cs_check_overflow in aktlocalswitches];
+ exprasmlist.concat(taicpu.op_reg_reg_reg(op,numerator,divider,resultreg));
+
+ if (nodetype = modn) then
+ begin
+ objectlibrary.getjumplabel(overflowlabel);
+ ai:=taicpu.op_cond_sym(A_Bxx,C_O,overflowlabel);
+ ai.delayslot_annulled:=true;
+ exprasmlist.concat(ai);
+ exprasmlist.concat(taicpu.op_reg(A_NOT,resultreg));
+ cg.a_label(exprasmlist,overflowlabel);
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SMUL,resultreg,divider,resultreg));
+ exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,numerator,resultreg,resultreg));
+ end;
+ end;
+ { set result location }
+ location.loc:=LOC_REGISTER;
+ location.register:=resultreg;
+ cg.g_overflowcheck(exprasmlist,Location,ResultType.Def);
+ end;
+
+
+{*****************************************************************************
+ TSparcSHLRSHRNODE
+*****************************************************************************}
+
+ function TSparcShlShrNode.first_shlshr64bitint:TNode;
+ begin
+ { 64bit without constants need a helper }
+ if is_64bit(left.resulttype.def) and
+ (right.nodetype<>ordconstn) then
+ begin
+ result:=inherited first_shlshr64bitint;
+ exit;
+ end;
+
+ result := nil;
+ end;
+
+
+ procedure tSparcshlshrnode.pass_2;
+ var
+ hregister,resultreg,hregister1,
+ hreg64hi,hreg64lo : tregister;
+ op : topcg;
+ shiftval: aword;
+ begin
+ { 64bit without constants need a helper, and is
+ already replaced in pass1 }
+ if is_64bit(left.resulttype.def) and
+ (right.nodetype<>ordconstn) then
+ internalerror(200405301);
+
+ secondpass(left);
+ secondpass(right);
+ if is_64bit(left.resulttype.def) then
+ begin
+ location_reset(location,LOC_REGISTER,OS_64);
+
+ { load left operator in a register }
+ location_force_reg(exprasmlist,left.location,OS_64,false);
+ hreg64hi:=left.location.register64.reghi;
+ hreg64lo:=left.location.register64.reglo;
+
+ shiftval := tordconstnode(right).value and 63;
+ if shiftval > 31 then
+ begin
+ if nodetype = shln then
+ begin
+ cg.a_load_const_reg(exprasmlist,OS_32,0,hreg64hi);
+ if (shiftval and 31) <> 0 then
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHL,OS_32,shiftval and 31,hreg64lo,hreg64lo);
+ end
+ else
+ begin
+ cg.a_load_const_reg(exprasmlist,OS_32,0,hreg64lo);
+ if (shiftval and 31) <> 0 then
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHR,OS_32,shiftval and 31,hreg64hi,hreg64hi);
+ end;
+ location.register64.reglo:=hreg64hi;
+ location.register64.reghi:=hreg64lo;
+ end
+ else
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_32);
+ if nodetype = shln then
+ begin
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHR,OS_32,32-shiftval,hreg64lo,hregister);
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHL,OS_32,shiftval,hreg64hi,hreg64hi);
+ cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_32,hregister,hreg64hi,hreg64hi);
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHL,OS_32,shiftval,hreg64lo,hreg64lo);
+ end
+ else
+ begin
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHL,OS_32,32-shiftval,hreg64hi,hregister);
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHR,OS_32,shiftval,hreg64lo,hreg64lo);
+ cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_32,hregister,hreg64lo,hreg64lo);
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHR,OS_32,shiftval,hreg64hi,hreg64hi);
+ end;
+ location.register64.reghi:=hreg64hi;
+ location.register64.reglo:=hreg64lo;
+ end;
+ end
+ else
+ begin
+ { load left operators in a register }
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),true);
+ location_copy(location,left.location);
+ resultreg := location.register;
+ hregister1 := location.register;
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ resultreg := cg.GetIntRegister(exprasmlist,OS_INT);
+ location.register := resultreg;
+ end;
+ { determine operator }
+ if nodetype=shln then
+ op:=OP_SHL
+ else
+ op:=OP_SHR;
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ begin
+ if tordconstnode(right).value and 31<>0 then
+ cg.a_op_const_reg_reg(exprasmlist,op,OS_32,tordconstnode(right).value and 31,hregister1,resultreg)
+ end
+ else
+ begin
+ { load shift count in a register if necessary }
+ location_force_reg(exprasmlist,right.location,def_cgsize(right.resulttype.def),true);
+ cg.a_op_reg_reg_reg(exprasmlist,op,OS_32,right.location.register,hregister1,resultreg);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TSPARCNOTNODE
+*****************************************************************************}
+
+ procedure tsparcnotnode.second_boolean;
+ var
+ hl : tasmlabel;
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc=LOC_JUMP then
+ begin
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ location.loc:=LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER, LOC_CREGISTER, LOC_REFERENCE, LOC_CREFERENCE :
+ begin
+ location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),true);
+ exprasmlist.concat(taicpu.op_reg_const_reg(A_SUBcc,left.location.register,0,NR_G0));
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_E;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end;
+
+
+begin
+ cmoddivnode:=tSparcmoddivnode;
+ cshlshrnode:=tSparcshlshrnode;
+ cnotnode:=tSparcnotnode;
+end.
diff --git a/compiler/sparc/ncpuset.pas b/compiler/sparc/ncpuset.pas
new file mode 100644
index 0000000000..6f0b955859
--- /dev/null
+++ b/compiler/sparc/ncpuset.pas
@@ -0,0 +1,126 @@
+{
+ Copyright (c) 1998-2004 by Florian Klaempfl
+
+ Generate sparc 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 ncpuset;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ nset,
+ ncgset;
+
+ type
+ tcpucasenode = class(tcgcasenode)
+ protected
+ procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
+ function has_jumptable : boolean;override;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
+ end;
+
+
+ implementation
+
+ uses
+ globals,
+ systems,
+ cpubase,
+ aasmbase,aasmtai,aasmcpu,
+ cgbase,cgutils,cgobj,
+ procinfo;
+
+ procedure tcpucasenode.optimizevalues(var max_linear_list:aint;var max_dist:aword);
+ begin
+ { give the jump table a higher priority }
+ max_dist:=(max_dist*3) div 2;
+ end;
+
+
+ function tcpucasenode.has_jumptable : boolean;
+ begin
+ has_jumptable:=true;
+ end;
+
+
+ procedure tcpucasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ var
+ table : tasmlabel;
+ last : TConstExprInt;
+ indexreg,jmpreg,basereg : tregister;
+ href : treference;
+
+ procedure genitem(list:taasmoutput;t : pcaselabel);
+ var
+ i : aint;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ for i:=last+1 to t^._low-1 do
+ list.concat(Tai_const.Create_sym(elselabel));
+ for i:=t^._low to t^._high do
+ list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+ last:=t^._high;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+ begin
+ if not(jumptable_no_range) then
+ begin
+ { case expr less than min_ => goto elselabel }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_lt,aint(min_),hregister,elselabel);
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,jmp_gt,aint(max_),hregister,elselabel);
+ end;
+ objectlibrary.getjumplabel(table);
+ indexreg:=cg.getaddressregister(exprasmlist);
+ cg.a_op_const_reg_reg(exprasmlist,OP_SHL,OS_ADDR,2,hregister,indexreg);
+ { create reference }
+ reference_reset_symbol(href,table,0);
+ href.offset:=(-aint(min_))*4;
+ basereg:=cg.getaddressregister(exprasmlist);
+ cg.a_loadaddr_ref_reg(exprasmlist,href,basereg);
+
+ jmpreg:=cg.getaddressregister(exprasmlist);
+
+ reference_reset(href);
+ href.index:=indexreg;
+ href.base:=basereg;
+ cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,jmpreg);
+
+ exprasmlist.concat(taicpu.op_reg(A_JMP,jmpreg));
+ { Delay slot }
+ exprasmlist.concat(taicpu.op_none(A_NOP));
+ { generate jump table }
+ new_section(current_procinfo.aktlocaldata,sec_data,current_procinfo.procdef.mangledname,sizeof(aint));
+ current_procinfo.aktlocaldata.concat(Tai_label.Create(table));
+ last:=min_;
+ genitem(current_procinfo.aktlocaldata,hp);
+ end;
+
+
+
+begin
+ ccasenode:=tcpucasenode;
+end.
diff --git a/compiler/sparc/opcode.inc b/compiler/sparc/opcode.inc
new file mode 100644
index 0000000000..a3b38b4f08
--- /dev/null
+++ b/compiler/sparc/opcode.inc
@@ -0,0 +1,73 @@
+{******************************************************************************
+ *****************************************************************************}
+A_NONE,
+A_ABCD,
+A_ADD,A_ADDcc,A_ADDX,A_ADDXcc,
+A_AND,A_ANDcc,A_ANDN,A_ANDNcc,
+{Branching instructions}
+A_JMP,
+A_JMPL,
+A_CALL,
+A_BA,A_Bxx,A_FBA,A_FBxx,
+A_CBccc,
+A_FLUSH,
+{Load instructions}
+A_LDSB,A_LDSH,A_LDSTUB,
+A_LDUB,A_LDUH,A_LD,A_LDD,A_LDF,A_LDFSR,A_LDDF,A_LDC,A_LDCSR,A_LDDC,
+A_LDSBA,A_LDSHA,A_LDUBA,A_LDUHA,A_LDA,A_LDDA,
+A_LDSTUBA,
+A_MULScc,
+A_NOP,
+A_OR,A_ORcc,A_ORN,A_ORNcc,
+A_RDASR,A_RDY,A_RDPSR,A_RDWIM,A_RDTBR,
+A_RESTORE,
+A_RET,A_RETL,
+A_SAVE,
+A_SDIV,A_SDIVcc,
+A_SMUL,A_SMULcc,
+A_SETHI,
+A_SLL,A_SRL,A_SRA,
+A_STB,A_STH,A_ST,A_STD,A_STF,A_STDF,A_STFSR,A_STDFQ,
+A_STC,A_STDC,A_STCSR,A_STDCQ,
+A_STBA,A_STHA,A_STA,A_STDA,
+A_SUB,A_SUBcc,A_SUBX,A_SUBXcc,
+A_SWAP,A_SWAPA,A_Ticc,A_TADDcc,A_TSUBcc,A_TADDccTV,A_TSUBccTV,
+A_TA,A_Txx,
+A_UDIV,A_UDIVcc,
+A_UMUL,A_UMULcc,
+A_UNIMP,
+A_WRASR,A_WRY,A_WRPSR,A_WRWIM,A_WRTBR,
+A_XNOR,A_XNORcc,
+A_XOR,A_XORcc,
+ {Floating-point instructions}
+A_FiTOs,A_FiTOd,A_FiTOq,
+A_FsTOi,A_FdTOi,A_FqTOi,
+A_FsTOd,A_FsTOq,
+A_FdTOs,A_FdTOq,
+A_FqTOd,A_FqTOs,
+A_FMOVs,A_FNEGs,A_FABSs,
+A_FSQRTs,A_FSQRTd,A_FSQRTq,
+A_FADDs,A_FADDd,A_FADDq,
+A_FSUBs,A_FSUBd,A_FSUBq,
+A_FMULs,A_FMULd,A_FMULQ,
+A_FdMULq,A_FsMULd,
+A_FDIVs,A_FDIVd,A_FDIVq,
+A_FCMPs,A_FCMPd,A_FCMPq,
+A_FCPop1,A_CPop2,
+ {Synthetic instructions}
+A_btst,A_bset,A_bclr,A_btog,
+A_clr,A_clrb,A_clrh,
+A_cmp,
+A_dec,A_deccc,
+A_inc,A_inccc,
+A_MOV,
+A_NEG,
+A_not,
+A_set,
+A_skipz,A_skipnz,
+A_tst,
+{ Internal instructions }
+A_FMOVd,
+A_FABSd,
+A_FABSq
+
diff --git a/compiler/sparc/racpu.pas b/compiler/sparc/racpu.pas
new file mode 100644
index 0000000000..92b4bbce3a
--- /dev/null
+++ b/compiler/sparc/racpu.pas
@@ -0,0 +1,53 @@
+{
+ Copyright (c) 1998-2003 by Mazen NEIFER
+
+ Handles the common Sparc assembler reader routines
+
+ 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 racpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,rautils,cclasses;
+
+ type
+ TSparcOperand=class(TOperand)
+ end;
+
+ TSparcInstruction=class(TInstruction)
+ delayslot_annulled : boolean;
+ { opcode adding }
+ function ConcatInstruction(p : taasmoutput) : tai;override;
+ end;
+
+implementation
+
+ function TSparcInstruction.ConcatInstruction(p : taasmoutput) : tai;
+ begin
+ result:=inherited ConcatInstruction(p);
+ { delay slot annulled support }
+ if (result.typ=ait_instruction) and
+ delayslot_annulled then
+ taicpu(result).delayslot_annulled:=true;
+ end;
+
+end.
diff --git a/compiler/sparc/racpugas.pas b/compiler/sparc/racpugas.pas
new file mode 100644
index 0000000000..818c36b9a7
--- /dev/null
+++ b/compiler/sparc/racpugas.pas
@@ -0,0 +1,671 @@
+{
+ Copyright (c) 1998-2002 by Mazen NEIFER
+
+ Does the parsing for the i386 GNU AS styled inline assembler.
+
+ 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 racpugas;
+
+{$i fpcdefs.inc}
+
+Interface
+
+ uses
+ raatt,racpu;
+
+ type
+ tSparcReader = class(tattreader)
+ function is_asmopcode(const s: string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tSparcoperand);
+ procedure BuildOperand(oper : tSparcoperand);
+ procedure BuildOpCode(instr : tSparcinstruction);
+ procedure ReadPercent(oper : tSparcoperand);
+ procedure ReadSym(oper : tSparcoperand);
+ procedure ConvertCalljmp(instr : tSparcinstruction);
+ procedure handlepercent;override;
+ end;
+
+
+ Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmcpu,
+ { symtable }
+ symconst,symsym,
+ { parser }
+ scanner,
+ procinfo,
+ rabase,rautils,
+ cgbase,cgobj
+ ;
+
+ procedure TSparcReader.ReadSym(oper : tSparcoperand);
+ var
+ tempstr : string;
+ typesize,l,k : aint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ procedure TSparcReader.ReadPercent(oper : tSparcoperand);
+ begin
+ { check for ...@ }
+ if actasmtoken=AS_AT then
+ begin
+ if (oper.opr.ref.symbol=nil) and
+ (oper.opr.ref.offset = 0) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ if upper(actasmpattern)='LO' then
+ oper.opr.ref.refaddr:=addr_lo
+ else if upper(actasmpattern)='HI' then
+ oper.opr.ref.refaddr:=addr_hi
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end;
+
+
+ Procedure TSparcReader.BuildReference(oper : tSparcoperand);
+ var
+ l : aint;
+ regs : byte;
+ hasimm : boolean;
+ begin
+ oper.initref;
+ regs:=0;
+ hasimm:=false;
+ Consume(AS_LBRACKET);
+ repeat
+ Case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ if hasimm or (regs>1) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ break;
+ End;
+ oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+ hasimm:=true;
+ End;
+
+ AS_REGISTER:
+ Begin
+ if regs<2 then
+ begin
+ if regs=0 then
+ oper.opr.ref.base:=actasmregister
+ else
+ oper.opr.ref.index:=actasmregister;
+ inc(regs);
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ break;
+ end;
+ Consume(AS_REGISTER);
+ end;
+
+ AS_ID:
+ Begin
+ l:=BuildConstExpression(true,true);
+ inc(oper.opr.ref.offset,l);
+ End;
+
+ AS_RBRACKET:
+ begin
+ if (regs=0) and (not hasimm) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_RBRACKET);
+ break;
+ end;
+
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ break;
+ end;
+ end;
+ until false;
+ end;
+
+
+ procedure TSparcReader.handlepercent;
+ var
+ len : longint;
+ begin
+ len:=1;
+ actasmpattern[len]:='%';
+ c:=current_scanner.asmgetchar;
+ { to be a register there must be a letter and not a number }
+ while c in ['a'..'z','A'..'Z','0'..'9'] do
+ Begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ uppervar(actasmpattern);
+ if is_register(actasmpattern) then
+ exit;
+ if (actasmpattern='%HI') then
+ actasmtoken:=AS_HI
+ else if (actasmpattern='%LO')then
+ actasmtoken:=AS_LO
+ else
+ Message(asmr_e_invalid_register);
+ end;
+
+
+ Procedure TSparcReader.BuildOperand(oper : tSparcoperand);
+ var
+ expr : string;
+ typesize,l : aint;
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+ var
+ tempreg : tregister;
+ tempstr : string;
+ tempsymtyp : TAsmSymType;
+ hl : tasmlabel;
+ gotplus,
+ negative : boolean;
+ Begin
+ expr:='';
+ gotplus:=true;
+ negative:=false;
+ repeat
+ case actasmtoken of
+ AS_MINUS :
+ begin
+ consume(AS_MINUS);
+ negative:=true;
+ gotplus:=true;
+ end;
+
+ AS_PLUS :
+ begin
+ consume(AS_PLUS);
+ negative:=false;
+ gotplus:=true;
+ end;
+
+ AS_INTNUM,
+ AS_MOD:
+ Begin
+ if not gotplus then
+ Message(asmr_e_invalid_reference_syntax);
+ l:=BuildConstExpression(True,False);
+ if negative then
+ l:=-l;
+ { Constant memory offset }
+ oper.InitRef;
+ oper.opr.ref.refaddr:=addr_full;
+ oper.opr.ref.offset:=l;
+ GotPlus:=(prevasmtoken=AS_PLUS) or
+ (prevasmtoken=AS_MINUS);
+ if GotPlus then
+ negative:=(prevasmtoken=AS_MINUS);
+ end;
+
+ AS_LBRACKET :
+ begin
+ { memory reference }
+ BuildReference(oper);
+ gotplus:=false;
+ end;
+
+ AS_HI,
+ AS_LO:
+ begin
+ { Low or High part of a constant (or constant
+ memory location) }
+ oper.InitRef;
+ if actasmtoken=AS_LO then
+ oper.opr.ref.refaddr:=addr_lo
+ else
+ oper.opr.ref.refaddr:=addr_hi;
+ Consume(actasmtoken);
+ Consume(AS_LPAREN);
+ BuildConstSymbolExpression(false, true,false,l,tempstr,tempsymtyp);
+ if not assigned(oper.opr.ref.symbol) then
+ oper.opr.ref.symbol:=objectlibrary.newasmsymbol(tempstr,AB_EXTERNAL,tempsymtyp)
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ Consume(AS_RPAREN);
+ gotplus:=false;
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr,false) then
+ ReadPercent(oper)
+ else
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ gotplus:=false;
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (oper.opr.typ in [OPR_REGISTER,OPR_REFERENCE]) and gotplus then
+ begin
+ oper.initref;
+ oper.opr.ref.refaddr:=addr_full;
+ if oper.opr.ref.base<>NR_NO then
+ oper.opr.ref.base:=tempreg
+ else
+ if oper.opr.ref.index<>NR_NO then
+ oper.opr.ref.index:=tempreg
+ else
+ Message(asmr_e_multiple_index);
+ end
+ else
+ begin
+ if (oper.opr.typ<>OPR_NONE) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end;
+ gotplus:=false;
+ end;
+
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA:
+ break;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ until false;
+ end;
+
+
+{*****************************************************************************
+ TSparcReader
+*****************************************************************************}
+
+ procedure TSparcReader.BuildOpCode(instr : tSparcinstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+
+ { delayslot annulled? }
+ if (actasmtoken=AS_COMMA) then
+ begin
+ consume(AS_COMMA);
+ if actasmpattern='A' then
+ instr.delayslot_annulled:=true;
+ { force reading of AS_COMMA instead of AS_ID, otherwise
+ a label .L0 will first read a AS_DOT instead of AS_ID }
+ actasmtoken:=AS_COMMA;
+ consume(AS_COMMA);
+ end;
+
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ begin
+ { condition operands doesn't set the operand but write to the
+ condition field of the instruction
+ }
+ if instr.Operands[operandnum].opr.typ<>OPR_NONE then
+ Inc(operandnum);
+ end;
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tSparcoperand);
+ end; { end case }
+ until false;
+ if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
+ dec(operandnum);
+ instr.Ops:=operandnum;
+ end;
+
+
+ function TSparcReader.is_asmopcode(const s: string):boolean;
+ var
+ str2opEntry: tstr2opEntry;
+ cond:TAsmCond;
+ Begin
+ { making s a value parameter would break other assembler readers }
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+ { clear condition }
+ fillchar(actcondition,sizeof(actcondition),0);
+
+ str2opentry:=tstr2opentry(iasmops.search(s));
+ if assigned(str2opentry) then
+ begin
+ actopcode:=str2opentry.op;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ end
+ { not found, check branch instructions }
+ else if (Upcase(s[1])='B') or
+ ((Upcase(s[1])='F') and (Upcase(s[2])='B')) then
+ begin
+ { we can search here without an extra table which is sorted by string length
+ because we take the whole remaining string without the leading B }
+ if (Upcase(s[1])='F') then
+ actopcode := A_FBxx
+ else
+ actopcode := A_Bxx;
+ for cond:=low(TAsmCond) to high(TAsmCond) do
+ if (Upper(copy(s,2,length(s)-1))=Upper(Cond2Str[cond])) then
+ begin
+ actasmtoken:=AS_OPCODE;
+ actcondition:=cond;
+ is_asmopcode:=true;
+ end;
+ end;
+ end;
+
+
+ procedure TSparcReader.ConvertCalljmp(instr : tSparcinstruction);
+ var
+ newopr : toprrec;
+ begin
+ if instr.Operands[1].opr.typ=OPR_REFERENCE then
+ with newopr do
+ begin
+ typ:=OPR_SYMBOL;
+ symbol:=instr.Operands[1].opr.ref.symbol;
+ symofs:=instr.Operands[1].opr.ref.offset;
+ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+ (instr.Operands[1].opr.ref.index<>NR_NO) or
+ (instr.Operands[1].opr.ref.refaddr<>addr_full) then
+ Message(asmr_e_syn_operand);
+ instr.Operands[1].opr:=newopr;
+ end;
+ end;
+
+
+ procedure TSparcReader.handleopcode;
+ var
+ instr : tSparcinstruction;
+ begin
+ instr:=TSparcInstruction.Create(TSparcOperand);
+ BuildOpcode(instr);
+ with instr do
+ begin
+ condition := actcondition;
+ if is_calljmp(opcode) then
+ ConvertCalljmp(instr);
+ ConcatInstruction(curlist);
+ Free;
+ end;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_Sparc_att_info : tasmmodeinfo =
+ (
+ id : asmmode_Sparc_gas;
+ idtxt : 'GAS';
+ casmreader : TSparcReader;
+ );
+
+ asmmode_Sparc_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : TSparcReader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_Sparc_att_info);
+ RegisterAsmMode(asmmode_Sparc_standard_info);
+end.
diff --git a/compiler/sparc/rgcpu.pas b/compiler/sparc/rgcpu.pas
new file mode 100644
index 0000000000..943158fffb
--- /dev/null
+++ b/compiler/sparc/rgcpu.pas
@@ -0,0 +1,163 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the SPARC specific class for the register
+ allocator
+
+ 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 rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmcpu,aasmtai,
+ cgbase,cgutils,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu=class(trgobj)
+ procedure add_constraints(reg:tregister);override;
+ function get_spill_subreg(r : tregister) : tsubregister;override;
+ procedure do_spill_read(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure do_spill_written(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ end;
+
+
+implementation
+
+ uses
+ verbose,cutils,
+ cgobj;
+
+ procedure trgcpu.add_constraints(reg:tregister);
+ var
+ supreg,i : Tsuperregister;
+ begin
+ case getsubreg(reg) of
+ { Let 64bit floats conflict with all odd float regs }
+ R_SUBFD:
+ begin
+ supreg:=getsupreg(reg);
+ i:=RS_F1;
+ while (i<=RS_F31) do
+ begin
+ add_edge(supreg,i);
+ inc(i,2);
+ end;
+ end;
+ { Let 64bit ints conflict with all odd int regs }
+ R_SUBQ:
+ begin
+ supreg:=getsupreg(reg);
+ i:=RS_G1;
+ while (i<=RS_I7) do
+ begin
+ add_edge(supreg,i);
+ inc(i,2);
+ end;
+ end;
+ end;
+ end;
+
+
+ function trgcpu.get_spill_subreg(r : tregister) : tsubregister;
+ begin
+ if getregtype(r)=R_FPUREGISTER then
+ result:=getsubreg(r)
+ else
+ result:=defaultsub;
+ end;
+
+
+ procedure trgcpu.do_spill_read(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ helpins : tai;
+ tmpref : treference;
+ helplist : taasmoutput;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=taasmoutput.create;
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=tempreg
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ reference_reset(tmpref);
+ tmpref.offset:=spilltemp.offset;
+ tmpref.refaddr:=addr_hi;
+ helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
+
+ tmpref.refaddr:=addr_lo;
+ helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
+
+ reference_reset_base(tmpref,hreg,0);
+ tmpref.index:=spilltemp.base;
+
+ helpins:=spilling_create_load(tmpref,tempreg);
+ helplist.concat(helpins);
+ list.insertlistafter(pos,helplist)
+ end
+ else
+ inherited do_spill_read(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcpu.do_spill_written(list:Taasmoutput;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ helpins : tai;
+ tmpref : treference;
+ helplist : taasmoutput;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=taasmoutput.create;
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,R_SUBWHOLE)
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ reference_reset(tmpref);
+ tmpref.offset:=spilltemp.offset;
+ tmpref.refaddr:=addr_hi;
+ helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
+
+ tmpref.refaddr:=addr_lo;
+ helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
+
+ reference_reset_base(tmpref,hreg,0);
+ tmpref.index:=spilltemp.base;
+
+ helpins:=spilling_create_store(tempreg,tmpref);
+ helplist.concat(helpins);
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist)
+ end
+ else
+ inherited do_spill_written(list,pos,spilltemp,tempreg);
+ end;
+
+end.
diff --git a/compiler/sparc/rspcon.inc b/compiler/sparc/rspcon.inc
new file mode 100644
index 0000000000..5a84a0ba4e
--- /dev/null
+++ b/compiler/sparc/rspcon.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+NR_NO = tregister($00000000);
+NR_G0 = tregister($01040000);
+NR_G1 = tregister($01040001);
+NR_G2 = tregister($01040002);
+NR_G3 = tregister($01040003);
+NR_G4 = tregister($01040004);
+NR_G5 = tregister($01040005);
+NR_G6 = tregister($01040006);
+NR_G7 = tregister($01040007);
+NR_O0 = tregister($01040008);
+NR_O1 = tregister($01040009);
+NR_O2 = tregister($0104000a);
+NR_O3 = tregister($0104000b);
+NR_O4 = tregister($0104000c);
+NR_O5 = tregister($0104000d);
+NR_O6 = tregister($0104000e);
+NR_O7 = tregister($0104000f);
+NR_L0 = tregister($01040010);
+NR_L1 = tregister($01040011);
+NR_L2 = tregister($01040012);
+NR_L3 = tregister($01040013);
+NR_L4 = tregister($01040014);
+NR_L5 = tregister($01040015);
+NR_L6 = tregister($01040016);
+NR_L7 = tregister($01040017);
+NR_I0 = tregister($01040018);
+NR_I1 = tregister($01040019);
+NR_I2 = tregister($0104001a);
+NR_I3 = tregister($0104001b);
+NR_I4 = tregister($0104001c);
+NR_I5 = tregister($0104001d);
+NR_I6 = tregister($0104001e);
+NR_I7 = tregister($0104001f);
+NR_FP = tregister($0104001e);
+NR_SP = tregister($0104000e);
+NR_F0 = tregister($02060000);
+NR_F1 = tregister($02060001);
+NR_F2 = tregister($02060002);
+NR_F3 = tregister($02060003);
+NR_F4 = tregister($02060004);
+NR_F5 = tregister($02060005);
+NR_F6 = tregister($02060006);
+NR_F7 = tregister($02060007);
+NR_F8 = tregister($02060008);
+NR_F9 = tregister($02060009);
+NR_F10 = tregister($0206000a);
+NR_F11 = tregister($0206000b);
+NR_F12 = tregister($0206000c);
+NR_F13 = tregister($0206000d);
+NR_F14 = tregister($0206000e);
+NR_F15 = tregister($0206000f);
+NR_F16 = tregister($02060010);
+NR_F17 = tregister($02060011);
+NR_F18 = tregister($02060012);
+NR_F19 = tregister($02060013);
+NR_F20 = tregister($02060014);
+NR_F21 = tregister($02060015);
+NR_F22 = tregister($02060016);
+NR_F23 = tregister($02060017);
+NR_F24 = tregister($02060018);
+NR_F25 = tregister($02060019);
+NR_F26 = tregister($0206001a);
+NR_F27 = tregister($0206001b);
+NR_F28 = tregister($0206001c);
+NR_F29 = tregister($0206001d);
+NR_F30 = tregister($0206001e);
+NR_F31 = tregister($0206001f);
+NR_C0 = tregister($03000000);
+NR_C1 = tregister($03000001);
+NR_C2 = tregister($03000002);
+NR_C3 = tregister($03000003);
+NR_C4 = tregister($03000004);
+NR_C5 = tregister($03000005);
+NR_C6 = tregister($03000006);
+NR_C7 = tregister($03000007);
+NR_C8 = tregister($03000008);
+NR_C9 = tregister($03000009);
+NR_C10 = tregister($0300000a);
+NR_C11 = tregister($0300000b);
+NR_C12 = tregister($0300000c);
+NR_C13 = tregister($0300000d);
+NR_C14 = tregister($0300000e);
+NR_C15 = tregister($0300000f);
+NR_C16 = tregister($03000010);
+NR_C17 = tregister($03000011);
+NR_C18 = tregister($03000012);
+NR_C19 = tregister($03000013);
+NR_C20 = tregister($03000014);
+NR_C21 = tregister($03000015);
+NR_C22 = tregister($03000016);
+NR_C23 = tregister($03000017);
+NR_C24 = tregister($03000018);
+NR_C25 = tregister($03000019);
+NR_C26 = tregister($0300001a);
+NR_C27 = tregister($0300001b);
+NR_C28 = tregister($0300001c);
+NR_C29 = tregister($0300001d);
+NR_C30 = tregister($0300001e);
+NR_C31 = tregister($0300001f);
+NR_FSR = tregister($05000000);
+NR_FQ = tregister($05000001);
+NR_CSR = tregister($05000002);
+NR_CQ = tregister($05000003);
+NR_PSR = tregister($05000004);
+NR_TBR = tregister($05000005);
+NR_WIM = tregister($05000006);
+NR_Y = tregister($05000007);
+NR_ASR0 = tregister($04000000);
+NR_ASR1 = tregister($04000001);
+NR_ASR2 = tregister($04000002);
+NR_ASR3 = tregister($04000003);
+NR_ASR4 = tregister($04000004);
+NR_ASR5 = tregister($04000005);
+NR_ASR6 = tregister($04000006);
+NR_ASR7 = tregister($04000007);
+NR_ASR8 = tregister($04000008);
+NR_ASR9 = tregister($04000009);
+NR_ASR10 = tregister($0400000a);
+NR_ASR11 = tregister($0400000b);
+NR_ASR12 = tregister($0400000c);
+NR_ASR13 = tregister($0400000d);
+NR_ASR14 = tregister($0400000e);
+NR_ASR15 = tregister($0400000f);
+NR_ASR16 = tregister($04000010);
+NR_ASR17 = tregister($04000011);
+NR_ASR18 = tregister($04000012);
+NR_ASR19 = tregister($04000013);
+NR_ASR20 = tregister($04000014);
+NR_ASR21 = tregister($04000015);
+NR_ASR22 = tregister($04000016);
+NR_ASR23 = tregister($04000017);
+NR_ASR24 = tregister($04000018);
+NR_ASR25 = tregister($04000019);
+NR_ASR26 = tregister($0400001a);
+NR_ASR27 = tregister($0400001b);
+NR_ASR28 = tregister($0400001c);
+NR_ASR29 = tregister($0400001d);
+NR_ASR30 = tregister($0400001e);
+NR_ASR31 = tregister($0400001f);
diff --git a/compiler/sparc/rspdwrf.inc b/compiler/sparc/rspdwrf.inc
new file mode 100644
index 0000000000..b470be1e1d
--- /dev/null
+++ b/compiler/sparc/rspdwrf.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+-1,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+31,
+15,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+64,
+65,
+64,
+65,
+64,
+64,
+64,
+64,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32
diff --git a/compiler/sparc/rspnor.inc b/compiler/sparc/rspnor.inc
new file mode 100644
index 0000000000..b6f96d936f
--- /dev/null
+++ b/compiler/sparc/rspnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from spreg.dat }
+139
diff --git a/compiler/sparc/rspnum.inc b/compiler/sparc/rspnum.inc
new file mode 100644
index 0000000000..b268537c8b
--- /dev/null
+++ b/compiler/sparc/rspnum.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+NR_NO,
+NR_G0,
+NR_G1,
+NR_G2,
+NR_G3,
+NR_G4,
+NR_G5,
+NR_G6,
+NR_G7,
+NR_O0,
+NR_O1,
+NR_O2,
+NR_O3,
+NR_O4,
+NR_O5,
+NR_O6,
+NR_O7,
+NR_L0,
+NR_L1,
+NR_L2,
+NR_L3,
+NR_L4,
+NR_L5,
+NR_L6,
+NR_L7,
+NR_I0,
+NR_I1,
+NR_I2,
+NR_I3,
+NR_I4,
+NR_I5,
+NR_I6,
+NR_I7,
+NR_FP,
+NR_SP,
+NR_F0,
+NR_F1,
+NR_F2,
+NR_F3,
+NR_F4,
+NR_F5,
+NR_F6,
+NR_F7,
+NR_F8,
+NR_F9,
+NR_F10,
+NR_F11,
+NR_F12,
+NR_F13,
+NR_F14,
+NR_F15,
+NR_F16,
+NR_F17,
+NR_F18,
+NR_F19,
+NR_F20,
+NR_F21,
+NR_F22,
+NR_F23,
+NR_F24,
+NR_F25,
+NR_F26,
+NR_F27,
+NR_F28,
+NR_F29,
+NR_F30,
+NR_F31,
+NR_C0,
+NR_C1,
+NR_C2,
+NR_C3,
+NR_C4,
+NR_C5,
+NR_C6,
+NR_C7,
+NR_C8,
+NR_C9,
+NR_C10,
+NR_C11,
+NR_C12,
+NR_C13,
+NR_C14,
+NR_C15,
+NR_C16,
+NR_C17,
+NR_C18,
+NR_C19,
+NR_C20,
+NR_C21,
+NR_C22,
+NR_C23,
+NR_C24,
+NR_C25,
+NR_C26,
+NR_C27,
+NR_C28,
+NR_C29,
+NR_C30,
+NR_C31,
+NR_FSR,
+NR_FQ,
+NR_CSR,
+NR_CQ,
+NR_PSR,
+NR_TBR,
+NR_WIM,
+NR_Y,
+NR_ASR0,
+NR_ASR1,
+NR_ASR2,
+NR_ASR3,
+NR_ASR4,
+NR_ASR5,
+NR_ASR6,
+NR_ASR7,
+NR_ASR8,
+NR_ASR9,
+NR_ASR10,
+NR_ASR11,
+NR_ASR12,
+NR_ASR13,
+NR_ASR14,
+NR_ASR15,
+NR_ASR16,
+NR_ASR17,
+NR_ASR18,
+NR_ASR19,
+NR_ASR20,
+NR_ASR21,
+NR_ASR22,
+NR_ASR23,
+NR_ASR24,
+NR_ASR25,
+NR_ASR26,
+NR_ASR27,
+NR_ASR28,
+NR_ASR29,
+NR_ASR30,
+NR_ASR31
diff --git a/compiler/sparc/rsprni.inc b/compiler/sparc/rsprni.inc
new file mode 100644
index 0000000000..578709e2a8
--- /dev/null
+++ b/compiler/sparc/rsprni.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+34,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+33,
+32,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+107,
+108,
+109,
+110,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118,
+119,
+120,
+121,
+122,
+123,
+124,
+125,
+126,
+127,
+128,
+129,
+130,
+131,
+132,
+133,
+134,
+135,
+136,
+137,
+138,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+106
diff --git a/compiler/sparc/rspsri.inc b/compiler/sparc/rspsri.inc
new file mode 100644
index 0000000000..da5ec0a078
--- /dev/null
+++ b/compiler/sparc/rspsri.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+107,
+108,
+117,
+118,
+119,
+120,
+121,
+122,
+123,
+124,
+125,
+126,
+109,
+127,
+128,
+129,
+130,
+131,
+132,
+133,
+134,
+135,
+136,
+110,
+137,
+138,
+111,
+112,
+113,
+114,
+115,
+116,
+67,
+68,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+69,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+95,
+96,
+70,
+97,
+98,
+71,
+72,
+73,
+74,
+75,
+76,
+102,
+101,
+35,
+36,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+37,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+38,
+65,
+66,
+39,
+40,
+41,
+42,
+43,
+44,
+33,
+100,
+99,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+103,
+34,
+104,
+105,
+106,
+0
diff --git a/compiler/sparc/rspstab.inc b/compiler/sparc/rspstab.inc
new file mode 100644
index 0000000000..b470be1e1d
--- /dev/null
+++ b/compiler/sparc/rspstab.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+-1,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+31,
+15,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+64,
+65,
+64,
+65,
+64,
+64,
+64,
+64,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32
diff --git a/compiler/sparc/rspstd.inc b/compiler/sparc/rspstd.inc
new file mode 100644
index 0000000000..189ed36a2f
--- /dev/null
+++ b/compiler/sparc/rspstd.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+'INVALID',
+'%g0',
+'%g1',
+'%g2',
+'%g3',
+'%g4',
+'%g5',
+'%g6',
+'%g7',
+'%o0',
+'%o1',
+'%o2',
+'%o3',
+'%o4',
+'%o5',
+'%o6',
+'%o7',
+'%l0',
+'%l1',
+'%l2',
+'%l3',
+'%l4',
+'%l5',
+'%l6',
+'%l7',
+'%i0',
+'%i1',
+'%i2',
+'%i3',
+'%i4',
+'%i5',
+'%i6',
+'%i7',
+'%fp',
+'%sp',
+'%f0',
+'%f1',
+'%f2',
+'%f3',
+'%f4',
+'%f5',
+'%f6',
+'%f7',
+'%f8',
+'%f9',
+'%f10',
+'%f11',
+'%f12',
+'%f13',
+'%f14',
+'%f15',
+'%f16',
+'%f17',
+'%f18',
+'%f19',
+'%f20',
+'%f21',
+'%f22',
+'%f23',
+'%f24',
+'%f25',
+'%f26',
+'%f27',
+'%f28',
+'%f29',
+'%f30',
+'%f31',
+'%c0',
+'%c1',
+'%c2',
+'%c3',
+'%c4',
+'%c5',
+'%c6',
+'%c7',
+'%c8',
+'%c9',
+'%c10',
+'%c11',
+'%c12',
+'%c13',
+'%c14',
+'%c15',
+'%c16',
+'%c17',
+'%c18',
+'%c19',
+'%c20',
+'%c21',
+'%c22',
+'%c23',
+'%c24',
+'%c25',
+'%c26',
+'%c27',
+'%c28',
+'%c29',
+'%c30',
+'%c31',
+'%fsr',
+'%fq',
+'%csr',
+'%cq',
+'%psr',
+'%tbr',
+'%wim',
+'%y',
+'%asr0',
+'%asr1',
+'%asr2',
+'%asr3',
+'%asr4',
+'%asr5',
+'%asr6',
+'%asr7',
+'%asr8',
+'%asr9',
+'%asr10',
+'%asr11',
+'%asr12',
+'%asr13',
+'%asr14',
+'%asr15',
+'%asr16',
+'%asr17',
+'%asr18',
+'%asr19',
+'%asr20',
+'%asr21',
+'%asr22',
+'%asr23',
+'%asr24',
+'%asr25',
+'%asr26',
+'%asr27',
+'%asr28',
+'%asr29',
+'%asr30',
+'%asr31'
diff --git a/compiler/sparc/rspsup.inc b/compiler/sparc/rspsup.inc
new file mode 100644
index 0000000000..68600f52a6
--- /dev/null
+++ b/compiler/sparc/rspsup.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+RS_NO = $00;
+RS_G0 = $00;
+RS_G1 = $01;
+RS_G2 = $02;
+RS_G3 = $03;
+RS_G4 = $04;
+RS_G5 = $05;
+RS_G6 = $06;
+RS_G7 = $07;
+RS_O0 = $08;
+RS_O1 = $09;
+RS_O2 = $0a;
+RS_O3 = $0b;
+RS_O4 = $0c;
+RS_O5 = $0d;
+RS_O6 = $0e;
+RS_O7 = $0f;
+RS_L0 = $10;
+RS_L1 = $11;
+RS_L2 = $12;
+RS_L3 = $13;
+RS_L4 = $14;
+RS_L5 = $15;
+RS_L6 = $16;
+RS_L7 = $17;
+RS_I0 = $18;
+RS_I1 = $19;
+RS_I2 = $1a;
+RS_I3 = $1b;
+RS_I4 = $1c;
+RS_I5 = $1d;
+RS_I6 = $1e;
+RS_I7 = $1f;
+RS_FP = $1e;
+RS_SP = $0e;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_C0 = $00;
+RS_C1 = $01;
+RS_C2 = $02;
+RS_C3 = $03;
+RS_C4 = $04;
+RS_C5 = $05;
+RS_C6 = $06;
+RS_C7 = $07;
+RS_C8 = $08;
+RS_C9 = $09;
+RS_C10 = $0a;
+RS_C11 = $0b;
+RS_C12 = $0c;
+RS_C13 = $0d;
+RS_C14 = $0e;
+RS_C15 = $0f;
+RS_C16 = $10;
+RS_C17 = $11;
+RS_C18 = $12;
+RS_C19 = $13;
+RS_C20 = $14;
+RS_C21 = $15;
+RS_C22 = $16;
+RS_C23 = $17;
+RS_C24 = $18;
+RS_C25 = $19;
+RS_C26 = $1a;
+RS_C27 = $1b;
+RS_C28 = $1c;
+RS_C29 = $1d;
+RS_C30 = $1e;
+RS_C31 = $1f;
+RS_FSR = $00;
+RS_FQ = $01;
+RS_CSR = $02;
+RS_CQ = $03;
+RS_PSR = $04;
+RS_TBR = $05;
+RS_WIM = $06;
+RS_Y = $07;
+RS_ASR0 = $00;
+RS_ASR1 = $01;
+RS_ASR2 = $02;
+RS_ASR3 = $03;
+RS_ASR4 = $04;
+RS_ASR5 = $05;
+RS_ASR6 = $06;
+RS_ASR7 = $07;
+RS_ASR8 = $08;
+RS_ASR9 = $09;
+RS_ASR10 = $0a;
+RS_ASR11 = $0b;
+RS_ASR12 = $0c;
+RS_ASR13 = $0d;
+RS_ASR14 = $0e;
+RS_ASR15 = $0f;
+RS_ASR16 = $10;
+RS_ASR17 = $11;
+RS_ASR18 = $12;
+RS_ASR19 = $13;
+RS_ASR20 = $14;
+RS_ASR21 = $15;
+RS_ASR22 = $16;
+RS_ASR23 = $17;
+RS_ASR24 = $18;
+RS_ASR25 = $19;
+RS_ASR26 = $1a;
+RS_ASR27 = $1b;
+RS_ASR28 = $1c;
+RS_ASR29 = $1d;
+RS_ASR30 = $1e;
+RS_ASR31 = $1f;
diff --git a/compiler/sparc/spreg.dat b/compiler/sparc/spreg.dat
new file mode 100644
index 0000000000..d254c4fc78
--- /dev/null
+++ b/compiler/sparc/spreg.dat
@@ -0,0 +1,154 @@
+;
+; Sparc registers
+;
+; layout
+; <name>,<regtype>,<regnum>,<stdname>,<stabidx>,<dwarfidx>
+;
+NO,$00,$00,$00,INVALID,-1,-1
+; Integer registers
+G0,$01,$04,$00,%g0,1,1
+G1,$01,$04,$01,%g1,2,2
+G2,$01,$04,$02,%g2,3,3
+G3,$01,$04,$03,%g3,4,4
+G4,$01,$04,$04,%g4,5,5
+G5,$01,$04,$05,%g5,6,6
+G6,$01,$04,$06,%g6,7,7
+G7,$01,$04,$07,%g7,8,8
+O0,$01,$04,$08,%o0,9,9
+O1,$01,$04,$09,%o1,10,10
+O2,$01,$04,$0a,%o2,11,11
+O3,$01,$04,$0b,%o3,12,12
+O4,$01,$04,$0c,%o4,13,13
+O5,$01,$04,$0d,%o5,14,14
+O6,$01,$04,$0e,%o6,15,15
+O7,$01,$04,$0f,%o7,16,16
+L0,$01,$04,$10,%l0,17,17
+L1,$01,$04,$11,%l1,18,18
+L2,$01,$04,$12,%l2,19,19
+L3,$01,$04,$13,%l3,20,20
+L4,$01,$04,$14,%l4,21,21
+L5,$01,$04,$15,%l5,22,22
+L6,$01,$04,$16,%l6,23,23
+L7,$01,$04,$17,%l7,24,24
+I0,$01,$04,$18,%i0,25,25
+I1,$01,$04,$19,%i1,26,26
+I2,$01,$04,$1a,%i2,27,27
+I3,$01,$04,$1b,%i3,28,28
+I4,$01,$04,$1c,%i4,29,29
+I5,$01,$04,$1d,%i5,30,30
+I6,$01,$04,$1e,%i6,31,31
+I7,$01,$04,$1f,%i7,32,32
+; Aliases for stackpointer (%o6) and framepointer (%i6)
+FP,$01,$04,$1e,%fp,31,31
+SP,$01,$04,$0e,%sp,15,15
+; Float registers, single use
+F0,$02,$06,$00,%f0,32,32
+F1,$02,$06,$01,%f1,32,32
+F2,$02,$06,$02,%f2,32,32
+F3,$02,$06,$03,%f3,32,32
+F4,$02,$06,$04,%f4,32,32
+F5,$02,$06,$05,%f5,32,32
+F6,$02,$06,$06,%f6,32,32
+F7,$02,$06,$07,%f7,32,32
+F8,$02,$06,$08,%f8,32,32
+F9,$02,$06,$09,%f9,32,32
+F10,$02,$06,$0a,%f10,32,32
+F11,$02,$06,$0b,%f11,32,32
+F12,$02,$06,$0c,%f12,32,32
+F13,$02,$06,$0d,%f13,32,32
+F14,$02,$06,$0e,%f14,32,32
+F15,$02,$06,$0f,%f15,32,32
+F16,$02,$06,$10,%f16,32,32
+F17,$02,$06,$11,%f17,32,32
+F18,$02,$06,$12,%f18,32,32
+F19,$02,$06,$13,%f19,32,32
+F20,$02,$06,$14,%f20,32,32
+F21,$02,$06,$15,%f21,32,32
+F22,$02,$06,$16,%f22,32,32
+F23,$02,$06,$17,%f23,32,32
+F24,$02,$06,$18,%f24,32,32
+F25,$02,$06,$19,%f25,32,32
+F26,$02,$06,$1a,%f26,32,32
+F27,$02,$06,$1b,%f27,32,32
+F28,$02,$06,$1c,%f28,32,32
+F29,$02,$06,$1d,%f29,32,32
+F30,$02,$06,$1e,%f30,32,32
+F31,$02,$06,$1f,%f31,32,32
+
+; Coprocessor registers
+C0,$03,$00,$00,%c0,32,32
+C1,$03,$00,$01,%c1,32,32
+C2,$03,$00,$02,%c2,32,32
+C3,$03,$00,$03,%c3,32,32
+C4,$03,$00,$04,%c4,32,32
+C5,$03,$00,$05,%c5,32,32
+C6,$03,$00,$06,%c6,32,32
+C7,$03,$00,$07,%c7,32,32
+C8,$03,$00,$08,%c8,32,32
+C9,$03,$00,$09,%c9,32,32
+C10,$03,$00,$0a,%c10,32,32
+C11,$03,$00,$0b,%c11,32,32
+C12,$03,$00,$0c,%c12,32,32
+C13,$03,$00,$0d,%c13,32,32
+C14,$03,$00,$0e,%c14,32,32
+C15,$03,$00,$0f,%c15,32,32
+C16,$03,$00,$10,%c16,32,32
+C17,$03,$00,$11,%c17,32,32
+C18,$03,$00,$12,%c18,32,32
+C19,$03,$00,$13,%c19,32,32
+C20,$03,$00,$14,%c20,32,32
+C21,$03,$00,$15,%c21,32,32
+C22,$03,$00,$16,%c22,32,32
+C23,$03,$00,$17,%c23,32,32
+C24,$03,$00,$18,%c24,32,32
+C25,$03,$00,$19,%c25,32,32
+C26,$03,$00,$1a,%c26,32,32
+C27,$03,$00,$1b,%c27,32,32
+C28,$03,$00,$1c,%c28,32,32
+C29,$03,$00,$1d,%c29,32,32
+C30,$03,$00,$1e,%c30,32,32
+C31,$03,$00,$1f,%c31,32,32
+
+; Special registers
+FSR,$05,$00,$00,%fsr,64,64
+FQ,$05,$00,$01,%fq,65,65
+CSR,$05,$00,$02,%csr,64,64
+CQ,$05,$00,$03,%cq,65,65
+PSR,$05,$00,$04,%psr,64,64
+TBR,$05,$00,$05,%tbr,64,64
+WIM,$05,$00,$06,%wim,64,64
+Y,$05,$00,$07,%y,64,64
+
+; Ancillary State Registers
+ASR0,$04,$00,$00,%asr0,32,32
+ASR1,$04,$00,$01,%asr1,32,32
+ASR2,$04,$00,$02,%asr2,32,32
+ASR3,$04,$00,$03,%asr3,32,32
+ASR4,$04,$00,$04,%asr4,32,32
+ASR5,$04,$00,$05,%asr5,32,32
+ASR6,$04,$00,$06,%asr6,32,32
+ASR7,$04,$00,$07,%asr7,32,32
+ASR8,$04,$00,$08,%asr8,32,32
+ASR9,$04,$00,$09,%asr9,32,32
+ASR10,$04,$00,$0a,%asr10,32,32
+ASR11,$04,$00,$0b,%asr11,32,32
+ASR12,$04,$00,$0c,%asr12,32,32
+ASR13,$04,$00,$0d,%asr13,32,32
+ASR14,$04,$00,$0e,%asr14,32,32
+ASR15,$04,$00,$0f,%asr15,32,32
+ASR16,$04,$00,$10,%asr16,32,32
+ASR17,$04,$00,$11,%asr17,32,32
+ASR18,$04,$00,$12,%asr18,32,32
+ASR19,$04,$00,$13,%asr19,32,32
+ASR20,$04,$00,$14,%asr20,32,32
+ASR21,$04,$00,$15,%asr21,32,32
+ASR22,$04,$00,$16,%asr22,32,32
+ASR23,$04,$00,$17,%asr23,32,32
+ASR24,$04,$00,$18,%asr24,32,32
+ASR25,$04,$00,$19,%asr25,32,32
+ASR26,$04,$00,$1a,%asr26,32,32
+ASR27,$04,$00,$1b,%asr27,32,32
+ASR28,$04,$00,$1c,%asr28,32,32
+ASR29,$04,$00,$1d,%asr29,32,32
+ASR30,$04,$00,$1e,%asr30,32,32
+ASR31,$04,$00,$1f,%asr31,32,32
diff --git a/compiler/sparc/strinst.inc b/compiler/sparc/strinst.inc
new file mode 100644
index 0000000000..e11b5c8d92
--- /dev/null
+++ b/compiler/sparc/strinst.inc
@@ -0,0 +1,69 @@
+{******************************************************************************
+ *****************************************************************************}
+ 'none',
+ 'abcd',
+ 'add','addcc','addx','addxcc',
+ 'and','andcc','andn','andncc',
+ 'jmp',
+ 'jmpl',
+ 'call',
+ 'ba','b','fba','fb',
+ 'cbccc',
+ 'flush',
+ 'ldsb','ldsh','ldstub',
+ 'ldub','lduh','ld','ldd','ld','ldfsr','ldd','ldc','ldcsr','lddc',
+ 'ldsba','ldsha','lduba','lduha','lda','ldda',
+ 'ldstuba',
+ 'mulscc',
+ 'nop',
+ 'or','orcc','orn','orncc',
+ 'rd','rd','rd','rd','rd',
+ 'restore',
+ 'ret','retl',
+ 'save',
+ 'sdiv','sdivcc',
+ 'smul','smulcc',
+ 'sethi',
+ 'sll','srl','sra',
+ 'stb','sth','st','std','st','std','stfsr','stdfq',
+ 'stc','stdc','stcsr','stdcq',
+ 'stba','stha','sta','stda',
+ 'sub','subcc','subx','subxcc',
+ 'swap','swapa','ticc','taddcc','tsubcc','taddcctv','tsubcctv',
+ 'ta','t',
+ 'udiv','udivcc',
+ 'umul','umulcc',
+ 'unimp',
+ 'wrasr','wry','wrpsr','wrwim','wrtbr',
+ 'xnor','xnorcc',
+ 'xor','xorcc',
+ {floating-point instructions}
+ 'fitos','fitod','fitoq',
+ 'fstoi','fdtoi','fqtoi',
+ 'fstod','fstoq',
+ 'fdtos','fdtoq',
+ 'fqtod','fqtos',
+ 'fmovs','fnegs','fabss',
+ 'fsqrts','fsqrtd','fsqrtq',
+ 'fadds','faddd','faddq',
+ 'fsubs','fsubd','fsubq',
+ 'fmuls','fmuld','fmulq',
+ 'fdmulq','fsmuld',
+ 'fdivs','fdivd','fdivq',
+ 'fcmps','fcmpd','fcmpq',
+ 'fcpop1','cpop2',
+ {synthetic instructions}
+ 'btst','bset','bclr','btog',
+ 'clr','clrb','clrh',
+ 'cmp',
+ 'dec','deccc',
+ 'inc','inccc',
+ 'mov',
+ 'neg',
+ 'not',
+ 'set',
+ 'skipz','skipnz',
+ 'tst',
+ { internal instructions }
+ 'fmovd',
+ 'fabsd','fabsq'
diff --git a/compiler/switches.pas b/compiler/switches.pas
new file mode 100644
index 0000000000..9f7549c7af
--- /dev/null
+++ b/compiler/switches.pas
@@ -0,0 +1,228 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements the parsing of the switches like $I-
+
+ 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 switches;
+
+{$i fpcdefs.inc}
+
+interface
+
+procedure HandleSwitch(switch,state:char);
+function CheckSwitch(switch,state:char):boolean;
+
+
+implementation
+uses
+ globtype,systems,
+ globals,verbose,fmodule;
+
+{****************************************************************************
+ Main Switches Parsing
+****************************************************************************}
+
+type
+ TSwitchType=(ignoredsw,localsw,modulesw,globalsw,illegalsw,unsupportedsw,alignsw);
+ SwitchRec=record
+ typesw : TSwitchType;
+ setsw : byte;
+ end;
+ SwitchRecTable = array['A'..'Z'] of SwitchRec;
+
+const
+ turboSwitchTable: SwitchRecTable =(
+ {A} (typesw:alignsw; setsw:ord(cs_localnone)),
+ {B} (typesw:localsw; setsw:ord(cs_full_boolean_eval)),
+ {C} (typesw:localsw; setsw:ord(cs_do_assertion)),
+ {D} (typesw:modulesw; setsw:ord(cs_debuginfo)),
+ {E} (typesw:modulesw; setsw:ord(cs_fp_emulation)),
+ {F} (typesw:ignoredsw; setsw:ord(cs_localnone)),
+ {G} (typesw:ignoredsw; setsw:ord(cs_localnone)),
+ {H} (typesw:localsw; setsw:ord(cs_ansistrings)),
+ {I} (typesw:localsw; setsw:ord(cs_check_io)),
+ {J} (typesw:localsw; setsw:ord(cs_typed_const_writable)),
+ {K} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {L} (typesw:modulesw; setsw:ord(cs_local_browser)),
+ {M} (typesw:localsw; setsw:ord(cs_generate_rtti)),
+ {N} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {O} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {P} (typesw:modulesw; setsw:ord(cs_openstring)),
+ {Q} (typesw:localsw; setsw:ord(cs_check_overflow)),
+ {R} (typesw:localsw; setsw:ord(cs_check_range)),
+ {S} (typesw:localsw; setsw:ord(cs_check_stack)),
+ {T} (typesw:localsw; setsw:ord(cs_typed_addresses)),
+ {U} (typesw:illegalsw; setsw:ord(cs_localnone)),
+ {V} (typesw:localsw; setsw:ord(cs_strict_var_strings)),
+ {W} (typesw:localsw; setsw:ord(cs_generate_stackframes)),
+ {X} (typesw:modulesw; setsw:ord(cs_extsyntax)),
+ {Y} (typesw:modulesw; setsw:ord(cs_browser)),
+ {Z} (typesw:illegalsw; setsw:ord(cs_localnone))
+ );
+
+
+ macSwitchTable: SwitchRecTable =(
+ {A} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {B} (typesw:localsw; setsw:ord(cs_full_boolean_eval)),
+ {C} (typesw:localsw; setsw:ord(cs_do_assertion)),
+ {D} (typesw:modulesw; setsw:ord(cs_debuginfo)),
+ {E} (typesw:modulesw; setsw:ord(cs_fp_emulation)),
+ {F} (typesw:ignoredsw; setsw:ord(cs_localnone)),
+ {G} (typesw:ignoredsw; setsw:ord(cs_localnone)),
+ {H} (typesw:localsw; setsw:ord(cs_ansistrings)),
+ {I} (typesw:localsw; setsw:ord(cs_check_io)),
+ {J} (typesw:localsw; setsw:ord(cs_external_var)),
+ {K} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {L} (typesw:modulesw; setsw:ord(cs_local_browser)),
+ {M} (typesw:localsw; setsw:ord(cs_generate_rtti)),
+ {N} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {O} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {P} (typesw:modulesw; setsw:ord(cs_openstring)),
+ {Q} (typesw:localsw; setsw:ord(cs_check_overflow)),
+ {R} (typesw:localsw; setsw:ord(cs_check_range)),
+ {S} (typesw:localsw; setsw:ord(cs_check_stack)),
+ {T} (typesw:localsw; setsw:ord(cs_typed_addresses)),
+ {U} (typesw:illegalsw; setsw:ord(cs_localnone)),
+ {V} (typesw:localsw; setsw:ord(cs_strict_var_strings)),
+ {W} (typesw:localsw; setsw:ord(cs_generate_stackframes)),
+ {X} (typesw:modulesw; setsw:ord(cs_extsyntax)),
+ {Y} (typesw:modulesw; setsw:ord(cs_browser)),
+ {Z} (typesw:localsw; setsw:ord(cs_externally_visible))
+ );
+
+procedure HandleSwitch(switch,state:char);
+
+var
+ switchTablePtr: ^SwitchRecTable;
+
+begin
+ switch:=upcase(switch);
+{ Is the Switch in the letters ? }
+ if not ((switch in ['A'..'Z']) and (state in ['-','+'])) then
+ begin
+ Message(scan_w_illegal_switch);
+ exit;
+ end;
+
+{ Select switch table }
+ if m_mac in aktmodeswitches then
+ switchTablePtr:= @macSwitchTable
+ else
+ switchTablePtr:= @turboSwitchTable;
+
+{ Handle the switch }
+ with switchTablePtr^[switch] do
+ begin
+ case typesw of
+ alignsw:
+ if state='+' then
+ aktpackrecords:=4
+ else
+ aktpackrecords:=1;
+ ignoredsw :
+ Message1(scan_n_ignored_switch,'$'+switch);
+ illegalsw :
+ Message1(scan_w_illegal_switch,'$'+switch);
+ unsupportedsw :
+ Message1(scan_w_unsupported_switch,'$'+switch);
+ localsw :
+ begin
+ if not localswitcheschanged then
+ nextaktlocalswitches:=aktlocalswitches;
+ if state='+' then
+ include(nextaktlocalswitches,tlocalswitch(setsw))
+ else
+ exclude(nextaktlocalswitches,tlocalswitch(setsw));
+ localswitcheschanged:=true;
+ end;
+ modulesw :
+ begin
+ if current_module.in_global then
+ begin
+ if state='+' then
+ include(aktmoduleswitches,tmoduleswitch(setsw))
+ else
+ begin
+ { Turning off debuginfo when lineinfo is requested
+ is not possible }
+ if not((cs_use_lineinfo in aktglobalswitches) and
+ (tmoduleswitch(setsw)=cs_debuginfo)) then
+ exclude(aktmoduleswitches,tmoduleswitch(setsw));
+ end;
+ end
+ else
+ Message(scan_w_switch_is_global);
+ end;
+ globalsw :
+ begin
+ if current_module.in_global and (current_module=main_module) then
+ begin
+ if state='+' then
+ include(aktglobalswitches,tglobalswitch(setsw))
+ else
+ exclude(aktglobalswitches,tglobalswitch(setsw));
+ end
+ else
+ Message(scan_w_switch_is_global);
+ end;
+ end;
+ end;
+end;
+
+
+function CheckSwitch(switch,state:char):boolean;
+
+var
+ found : boolean;
+ switchTablePtr: ^SwitchRecTable;
+
+begin
+ switch:=upcase(switch);
+{ Is the Switch in the letters ? }
+ if not ((switch in ['A'..'Z']) and (state in ['-','+'])) then
+ begin
+ Message(scan_w_illegal_switch);
+ CheckSwitch:=false;
+ exit;
+ end;
+
+{ Select switch table }
+ if m_mac in aktmodeswitches then
+ switchTablePtr:= @macSwitchTable
+ else
+ switchTablePtr:= @turboSwitchTable;
+
+{ Check the switch }
+ with switchTablePtr^[switch] do
+ begin
+ case typesw of
+ localsw : found:=(tlocalswitch(setsw) in aktlocalswitches);
+ modulesw : found:=(tmoduleswitch(setsw) in aktmoduleswitches);
+ globalsw : found:=(tglobalswitch(setsw) in aktglobalswitches);
+ else
+ found:=false;
+ end;
+ if state='-' then
+ found:=not found;
+ CheckSwitch:=found;
+ end;
+end;
+
+
+end.
diff --git a/compiler/symbase.pas b/compiler/symbase.pas
new file mode 100644
index 0000000000..8e51a9076f
--- /dev/null
+++ b/compiler/symbase.pas
@@ -0,0 +1,333 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ This unit handles the symbol tables
+
+ 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 symbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,
+ { symtable }
+ symconst
+ ;
+
+{************************************************
+ Some internal constants
+************************************************}
+
+ const
+ hasharraysize = 256;
+ indexgrowsize = 64;
+
+{************************************************
+ Needed forward pointers
+************************************************}
+
+ type
+ tsymtable = class;
+
+{************************************************
+ TSymtableEntry
+************************************************}
+
+ tsymtableentry = class(TNamedIndexItem)
+ owner : tsymtable;
+ end;
+
+
+{************************************************
+ TDefEntry
+************************************************}
+
+ tdefentry = class(tsymtableentry)
+ deftype : tdeftype;
+ end;
+
+
+{************************************************
+ TSymEntry
+************************************************}
+
+ { this object is the base for all symbol objects }
+ tsymentry = class(tsymtableentry)
+ typ : tsymtyp;
+ end;
+
+
+{************************************************
+ TSymtable
+************************************************}
+
+ tsearchhasharray = array[0..hasharraysize-1] of tsymentry;
+ psearchhasharray = ^tsearchhasharray;
+
+ tsymtable = class
+{$ifdef EXTDEBUG}
+ private
+ procedure dumpsym(p : TNamedIndexItem;arg:pointer);
+{$endif EXTDEBUG}
+ public
+ name : pstring;
+ realname : pstring;
+ symindex,
+ defindex : TIndexArray;
+ symsearch : Tdictionary;
+ next : tsymtable;
+ defowner : tdefentry; { for records and objects }
+ symtabletype : tsymtabletype;
+ { level of symtable, used for nested procedures }
+ symtablelevel : byte;
+ moduleid : longint;
+ refcount : integer;
+ constructor Create(const s:string);
+ destructor destroy;override;
+ procedure freeinstance;override;
+ function getcopy:tsymtable;
+ procedure clear;virtual;
+ function rename(const olds,news : stringid):tsymentry;
+ procedure foreach(proc2call : tnamedindexcallback;arg:pointer);
+ procedure foreach_static(proc2call : tnamedindexstaticcallback;arg:pointer);
+ procedure insert(sym : tsymentry);virtual;
+ { deletes a tsymentry and removes it from the tsymtable}
+ procedure delete(sym:tsymentry);
+ procedure replace(oldsym,newsym:tsymentry);
+ function search(const s : stringid) : tsymentry;
+ function speedsearch(const s : stringid;speedvalue : cardinal) : tsymentry;virtual;
+ procedure registerdef(p : tdefentry);
+ function iscurrentunit:boolean;virtual;
+{$ifdef EXTDEBUG}
+ procedure dump;
+{$endif EXTDEBUG}
+ function getdefnr(l : longint) : tdefentry;
+ function getsymnr(l : longint) : tsymentry;
+ end;
+
+ var
+ registerdef : boolean; { true, when defs should be registered }
+
+ defaultsymtablestack : tsymtable; { symtablestack after default units have been loaded }
+ symtablestack : tsymtable; { linked list of symtables }
+ defaultmacrosymtablestack : tsymtable;{ macrosymtablestack after default units have been loaded }
+ macrosymtablestack: tsymtable; { linked list of macro symtables }
+
+ aktrecordsymtable : tsymtable; { current record symtable }
+ aktparasymtable : tsymtable; { current proc para symtable }
+ aktlocalsymtable : tsymtable; { current proc local symtable }
+
+ initialmacrosymtable: tsymtable; { macros initially defined by the compiler or
+ given on the command line. Is common
+ for all files compiled and do not change. }
+
+implementation
+
+ uses
+ verbose;
+
+{****************************************************************************
+ TSYMTABLE
+****************************************************************************}
+
+ constructor tsymtable.Create(const s:string);
+ begin
+ if s<>'' then
+ begin
+ name:=stringdup(upper(s));
+ realname:=stringdup(s);
+ end
+ else
+ begin
+ name:=nil;
+ realname:=nil;
+ end;
+ symtabletype:=abstractsymtable;
+ symtablelevel:=0;
+ defowner:=nil;
+ next:=nil;
+ symindex:=tindexarray.create(indexgrowsize);
+ defindex:=TIndexArray.create(indexgrowsize);
+ symsearch:=tdictionary.create;
+ symsearch.noclear:=true;
+ refcount:=1;
+ end;
+
+
+ destructor tsymtable.destroy;
+ begin
+ { freeinstance decreases refcount }
+ if refcount>1 then
+ exit;
+ stringdispose(name);
+ stringdispose(realname);
+ symindex.destroy;
+ defindex.destroy;
+ { symsearch can already be disposed or set to nil for withsymtable }
+ if assigned(symsearch) then
+ begin
+ symsearch.destroy;
+ symsearch:=nil;
+ end;
+ end;
+
+
+ procedure tsymtable.freeinstance;
+ begin
+ dec(refcount);
+ if refcount=0 then
+ inherited freeinstance;
+ end;
+
+
+ function tsymtable.getcopy:tsymtable;
+ begin
+ inc(refcount);
+ result:=self;
+ end;
+
+
+{$ifdef EXTDEBUG}
+ procedure tsymtable.dumpsym(p : TNamedIndexItem;arg:pointer);
+ begin
+ writeln(p.name);
+ end;
+
+
+ procedure tsymtable.dump;
+ begin
+ if assigned(name) then
+ writeln('Symtable ',name^)
+ else
+ writeln('Symtable <not named>');
+ symsearch.foreach(@dumpsym,nil);
+ end;
+{$endif EXTDEBUG}
+
+
+ procedure tsymtable.registerdef(p : tdefentry);
+ begin
+ defindex.insert(p);
+ { set def owner and indexnb }
+ p.owner:=self;
+ end;
+
+
+ function tsymtable.iscurrentunit:boolean;
+ begin
+ result:=false;
+ end;
+
+
+ procedure tsymtable.foreach(proc2call : tnamedindexcallback;arg:pointer);
+ begin
+ symindex.foreach(proc2call,arg);
+ end;
+
+
+ procedure tsymtable.foreach_static(proc2call : tnamedindexstaticcallback;arg:pointer);
+ begin
+ symindex.foreach_static(proc2call,arg);
+ end;
+
+
+{***********************************************
+ Table Access
+***********************************************}
+
+ procedure tsymtable.clear;
+ begin
+ symindex.clear;
+ defindex.clear;
+ end;
+
+
+ procedure tsymtable.insert(sym:tsymentry);
+ begin
+ sym.owner:=self;
+ { insert in index and search hash }
+ symindex.insert(sym);
+ symsearch.insert(sym);
+ end;
+
+ procedure tsymtable.delete(sym:tsymentry);
+ begin
+ sym.owner:=nil;
+ { remove from index and search hash }
+ symsearch.delete(sym.name);
+ symindex.delete(sym);
+ end;
+
+ procedure tsymtable.replace(oldsym,newsym:tsymentry);
+ begin
+ { Replace the entry in the dictionary, this checks
+ the name }
+ if not symsearch.replace(oldsym,newsym) then
+ internalerror(200209061);
+ { replace in index }
+ symindex.replace(oldsym,newsym);
+ { set owner of new symb }
+ newsym.owner:=self;
+ end;
+
+
+ function tsymtable.search(const s : stringid) : tsymentry;
+ begin
+ search:=speedsearch(s,getspeedvalue(s));
+ end;
+
+
+ function tsymtable.speedsearch(const s : stringid;speedvalue : cardinal) : tsymentry;
+ begin
+ speedsearch:=tsymentry(symsearch.speedsearch(s,speedvalue));
+ end;
+
+
+ function tsymtable.rename(const olds,news : stringid):tsymentry;
+ begin
+ rename:=tsymentry(symsearch.rename(olds,news));
+ end;
+
+
+ function tsymtable.getsymnr(l : longint) : tsymentry;
+ var
+ hp : tsymentry;
+ begin
+ hp:=tsymentry(symindex.search(l));
+ if hp=nil then
+ internalerror(10999);
+ getsymnr:=hp;
+ end;
+
+
+ function tsymtable.getdefnr(l : longint) : tdefentry;
+ var
+ hp : tdefentry;
+ begin
+ hp:=tdefentry(defindex.search(l));
+ if hp=nil then
+ internalerror(10998);
+ getdefnr:=hp;
+ end;
+
+
+end.
diff --git a/compiler/symconst.pas b/compiler/symconst.pas
new file mode 100644
index 0000000000..3fad77b4d7
--- /dev/null
+++ b/compiler/symconst.pas
@@ -0,0 +1,434 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Symbol table constants
+
+ 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 symconst;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype;
+
+const
+ def_alignment = 4;
+
+ { if you change one of the following contants, }
+ { you have also to change the typinfo unit}
+ { and the rtl/i386,template/rttip.inc files }
+ tkUnknown = 0;
+ tkInteger = 1;
+ tkChar = 2;
+ tkEnumeration = 3;
+ tkFloat = 4;
+ tkSet = 5;
+ tkMethod = 6;
+ tkSString = 7;
+ tkString = tkSString;
+ tkLString = 8;
+{$ifdef ansistring_bits}
+ tkA32String = 9;
+{$else}
+ tkAString = 9;
+{$endif}
+ tkWString = 10;
+ tkVariant = 11;
+ tkArray = 12;
+ tkRecord = 13;
+ tkInterface= 14;
+ tkClass = 15;
+ tkObject = 16;
+ tkWChar = 17;
+ tkBool = 18;
+ tkInt64 = 19;
+ tkQWord = 20;
+ tkDynArray = 21;
+ tkInterfaceCorba = 22;
+{$ifdef ansistring_bits}
+ tkA16string = 23;
+ tkA64string = 24;
+{$endif}
+ tkprocvar = 25;
+
+ otSByte = 0;
+ otUByte = 1;
+ otSWord = 2;
+ otUWord = 3;
+ otSLong = 4;
+ otULong = 5;
+
+ ftSingle = 0;
+ ftDouble = 1;
+ ftExtended = 2;
+ ftComp = 3;
+ ftCurr = 4;
+ ftFloat128 = 5;
+
+ mkProcedure= 0;
+ mkFunction = 1;
+ mkConstructor = 2;
+ mkDestructor = 3;
+ mkClassProcedure= 4;
+ mkClassFunction = 5;
+
+ pfvar = 1;
+ pfConst = 2;
+ pfArray = 4;
+ pfAddress = 8;
+ pfReference= 16;
+ pfOut = 32;
+
+ unknown_level = 0;
+ main_program_level = 1;
+ normal_function_level = 2;
+
+ { implicit parameter positions, normal parameters start at 10
+ and will increase with 10 for each parameter. The high parameters
+ will be inserted with n+1 }
+ paranr_parentfp = 1;
+ paranr_result = 2;
+ paranr_self = 3;
+ paranr_vmt = 4;
+ { Required to support variations of syscalls on MorphOS }
+ paranr_syscall_basesysv = 9;
+ paranr_syscall_sysvbase = high(word)-4;
+ paranr_syscall_r12base = high(word)-3;
+ paranr_syscall_legacy = high(word)-2;
+ paranr_result_leftright = high(word)-1;
+
+
+type
+ { keep this in sync with TIntfFlag in rtl/objpas/typinfo.pp }
+ TCompilerIntfFlag = (ifHasGuid,ifDispInterface,ifDispatch,ifHasStrGUID);
+
+ { Deref entry options }
+ tdereftype = (deref_nil,
+ deref_sym,
+ deref_def,
+ deref_aktrecord,
+ deref_aktstatic,
+ deref_aktglobal,
+ deref_aktlocal,
+ deref_aktpara,
+ deref_unit,
+ deref_record,
+ deref_local,
+ deref_para,
+ deref_parent_object
+ );
+
+ { symbol options }
+ tsymoption=(sp_none,
+ sp_public,
+ sp_private,
+ sp_published,
+ sp_protected,
+ sp_static,
+ sp_hint_deprecated,
+ sp_hint_platform,
+ sp_hint_library,
+ sp_hint_unimplemented,
+ sp_has_overloaded,
+ sp_internal, { internal symbol, not reported as unused }
+ sp_strictprivate,
+ sp_strictprotected
+ );
+ tsymoptions=set of tsymoption;
+
+ { flags for a definition }
+ tdefoption=(df_none,
+ { init data has been generated }
+ df_has_inittable,
+ { rtti data has been generated }
+ df_has_rttitable,
+ { type is unique, i.e. declared with type = type <tdef>; }
+ df_unique
+ );
+ tdefoptions=set of tdefoption;
+
+ { tsymlist entry types }
+ tsltype = (sl_none,
+ sl_load,
+ sl_call,
+ sl_subscript,
+ sl_vec,
+ sl_typeconv,
+ sl_absolutetype
+ );
+
+ { base types for orddef }
+ tbasetype = (
+ uvoid,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit,
+ bool8bit,bool16bit,bool32bit,
+ uchar,uwidechar,scurrency
+ );
+
+ { float types }
+ tfloattype = (
+ s32real,s64real,s80real,
+ s64comp,s64currency,s128real
+ );
+
+ { string types }
+ tstringtype = (
+ st_conststring,
+ st_shortstring,
+ st_longstring,
+ st_ansistring,
+ st_widestring
+ );
+
+ { set types }
+ tsettype = (
+ normset,smallset,varset
+ );
+
+ tvarianttype = (
+ vt_normalvariant,vt_olevariant
+ );
+
+ tcallercallee = (callerside,calleeside);
+
+ { basic type for tprocdef and tprocvardef }
+ tproctypeoption=(potype_none,
+ potype_proginit, { Program initialization }
+ potype_unitinit, { unit initialization }
+ potype_unitfinalize, { unit finalization }
+ potype_constructor, { Procedure is a constructor }
+ potype_destructor, { Procedure is a destructor }
+ potype_operator, { Procedure defines an operator }
+ potype_procedure,
+ potype_function
+ );
+ tproctypeoptions=set of tproctypeoption;
+
+ { other options for tprocdef and tprocvardef }
+ tprocoption=(po_none,
+ po_classmethod, { class method }
+ po_virtualmethod, { Procedure is a virtual method }
+ po_abstractmethod, { Procedure is an abstract method }
+ po_staticmethod, { static method }
+ po_overridingmethod, { method with override directive }
+ po_methodpointer, { method pointer, only in procvardef, also used for 'with object do' }
+ po_interrupt, { Procedure is an interrupt handler }
+ po_iocheck, { IO checking should be done after a call to the procedure }
+ po_assembler, { Procedure is written in assembler }
+ po_msgstr, { method for string message handling }
+ po_msgint, { method for int message handling }
+ po_exports, { Procedure has export directive (needed for OS/2) }
+ po_external, { Procedure is external (in other object or lib)}
+ po_overload, { procedure is declared with overload directive }
+ po_varargs, { printf like arguments }
+ po_internconst, { procedure has constant evaluator intern }
+ { flag that only the address of a method is returned and not a full methodpointer }
+ po_addressonly,
+ { procedure is exported }
+ po_public,
+ { calling convention is specified explicitly }
+ po_hascallingconvention,
+ { reintroduce flag }
+ po_reintroduce,
+ { location of parameters is given explicitly as it is necessary for some syscall
+ conventions like that one of MorphOS }
+ po_explicitparaloc,
+ { no stackframe will be generated, used by lowlevel assembler like get_frame }
+ po_nostackframe,
+ po_has_mangledname,
+ po_has_public_name,
+ po_forward,
+ po_global,
+ po_has_inlininginfo,
+ { The different kind of syscalls on MorphOS }
+ po_syscall_legacy,
+ po_syscall_sysv,
+ po_syscall_basesysv,
+ po_syscall_sysvbase,
+ po_syscall_r12base,
+ po_local,
+ { Procedure can be inlined }
+ po_inline,
+ { Procedure is used for internal compiler calls }
+ po_compilerproc
+ );
+ tprocoptions=set of tprocoption;
+
+ { options for objects and classes }
+ tobjectdeftype = (odt_none,
+ odt_class,
+ odt_object,
+ odt_interfacecom,
+ odt_interfacecorba,
+ odt_cppclass,
+ odt_dispinterface
+ );
+
+ { options for objects and classes }
+ tobjectoption=(oo_none,
+ oo_is_forward, { the class is only a forward declared yet }
+ oo_has_virtual, { the object/class has virtual methods }
+ oo_has_private,
+ oo_has_protected,
+ oo_has_strictprivate,
+ oo_has_strictprotected,
+ oo_has_constructor, { the object/class has a constructor }
+ oo_has_destructor, { the object/class has a destructor }
+ oo_has_vmt, { the object/class has a vmt }
+ oo_has_msgstr,
+ oo_has_msgint,
+ oo_can_have_published,{ the class has rtti, i.e. you can publish properties }
+ oo_has_default_property
+ );
+ tobjectoptions=set of tobjectoption;
+
+ { options for properties }
+ tpropertyoption=(ppo_none,
+ ppo_indexed,
+ ppo_defaultproperty,
+ ppo_stored,
+ ppo_hasparameters,
+ ppo_is_override
+ );
+ tpropertyoptions=set of tpropertyoption;
+
+ { options for variables }
+ tvaroption=(vo_none,
+ vo_is_C_var,
+ vo_is_external,
+ vo_is_dll_var,
+ vo_is_thread_var,
+ vo_has_local_copy,
+ vo_is_const, { variable is declared as const (parameter) and can't be written to }
+ vo_is_exported,
+ vo_is_high_para,
+ vo_is_funcret,
+ vo_is_self,
+ vo_is_vmt,
+ vo_is_result, { special result variable }
+ vo_is_parentfp,
+ vo_is_loop_counter, { used to detect assignments to loop counter }
+ vo_is_hidden_para,
+ vo_has_explicit_paraloc,
+ vo_is_syscall_lib,
+ vo_has_mangledname
+ );
+ tvaroptions=set of tvaroption;
+
+ { register variable }
+ tvarregable=(vr_none,
+ vr_intreg,
+ vr_fpureg,
+ vr_mmreg
+ );
+
+ { types of the symtables }
+ tsymtabletype = (abstractsymtable,
+ globalsymtable,staticsymtable,
+ objectsymtable,recordsymtable,
+ localsymtable,parasymtable,
+ withsymtable,stt_exceptsymtable,
+ exportedmacrosymtable, localmacrosymtable
+ );
+
+
+ { definition contains the informations about a type }
+ tdeftype = (abstractdef,arraydef,recorddef,pointerdef,orddef,
+ stringdef,enumdef,procdef,objectdef,errordef,
+ filedef,formaldef,setdef,procvardef,floatdef,
+ classrefdef,forwarddef,variantdef);
+
+ { possible types for symtable entries }
+ tsymtyp = (abstractsym,globalvarsym,localvarsym,paravarsym,fieldvarsym,
+ typesym,procsym,unitsym,constsym,enumsym,typedconstsym,
+ errorsym,syssym,labelsym,absolutevarsym,propertysym,
+ macrosym,rttisym);
+
+ { State of the variable, if it's declared, assigned or used }
+ tvarstate=(vs_none,
+ vs_declared,vs_assigned,vs_used
+ );
+
+ tvarspez = (vs_value,vs_const,vs_var,vs_out);
+
+ absolutetyp = (tovar,toasm,toaddr);
+
+ tconsttyp = (constnone,
+ constord,conststring,constreal,
+ constset,constpointer,constnil,
+ constresourcestring,constwstring,constguid
+ );
+
+ { RTTI information to store }
+ trttitype = (
+ fullrtti,initrtti
+ );
+
+ { The order is from low priority to high priority,
+ Note: the operators > and < are used on this list }
+ tequaltype = (
+ te_incompatible,
+ te_convert_operator,
+ te_convert_l3, { compatible conversion with possible loss of data }
+ te_convert_l2, { compatible less prefered conversion }
+ te_convert_l1, { compatible conversion }
+ te_equal, { the definitions are equal }
+ te_exact
+ );
+
+ tdefstabstatus = (
+ stab_state_unused,
+ stab_state_used,
+ stab_state_writing,
+ stab_state_written
+ );
+
+
+const
+ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has_protected,
+ oo_has_strictprotected,oo_has_strictprivate,oo_has_constructor,oo_has_destructor];
+ clearstack_pocalls = [
+ pocall_cdecl,pocall_cppdecl,pocall_syscall
+ ];
+
+ pushleftright_pocalls : tproccalloptions = [pocall_register,pocall_pascal,pocall_mwpascal];
+
+ SymTypeName : array[tsymtyp] of string[12] = (
+ 'abstractsym','globalvar','localvar','paravar','fieldvar',
+ 'type','proc','unit','const','enum','typed const',
+ 'errorsym','system sym','label','absolutevar','property',
+ 'macrosym','rttisym'
+ );
+
+ DefTypeName : array[tdeftype] of string[12] = (
+ 'abstractdef','arraydef','recorddef','pointerdef','orddef',
+ 'stringdef','enumdef','procdef','objectdef','errordef',
+ 'filedef','formaldef','setdef','procvardef','floatdef',
+ 'classrefdef','forwarddef','variantdef'
+ );
+
+ EqualTypeName : array[tequaltype] of string[16] = (
+ 'incompatible','convert_operator','convert_l3','convert_l2',
+ 'convert_l1','equal','exact'
+ );
+
+implementation
+
+end.
diff --git a/compiler/symdef.pas b/compiler/symdef.pas
new file mode 100644
index 0000000000..a113e68bdd
--- /dev/null
+++ b/compiler/symdef.pas
@@ -0,0 +1,5485 @@
+{
+ Symbol table implementation for the definitions
+
+ Copyright (c) 1998-2005 by Florian Klaempfl, Pierre Muller
+
+ 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 symdef;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,tokens,
+ { symtable }
+ symconst,symbase,symtype,
+ { ppu }
+ ppu,
+ { node }
+ node,
+ { aasm }
+ aasmbase,aasmtai,
+ cpubase,cpuinfo,
+ cgbase,cgutils,
+ parabase
+ ;
+
+
+ type
+{************************************************
+ TDef
+************************************************}
+
+ tstoreddef = class(tdef)
+ protected
+ typesymderef : tderef;
+ public
+ { persistent (available across units) rtti and init tables }
+ rttitablesym,
+ inittablesym : tsym; {trttisym}
+ rttitablesymderef,
+ inittablesymderef : tderef;
+ { local (per module) rtti and init tables }
+ localrttilab : array[trttitype] of tasmlabel;
+ { linked list of global definitions }
+{$ifdef EXTDEBUG}
+ fileinfo : tfileposinfo;
+{$endif}
+ constructor create;
+ constructor ppuloaddef(ppufile:tcompilerppufile);
+ procedure reset;virtual;
+ function getcopy : tstoreddef;virtual;
+ procedure ppuwritedef(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;abstract;
+ procedure buildderef;override;
+ procedure buildderefimpl;override;
+ procedure deref;override;
+ procedure derefimpl;override;
+ function size:aint;override;
+ function getvartype:longint;override;
+ function alignment:longint;override;
+ function is_publishable : boolean;override;
+ function needs_inittable : boolean;override;
+ { rtti generation }
+ procedure write_rtti_name;
+ procedure write_rtti_data(rt:trttitype);virtual;
+ procedure write_child_rtti_data(rt:trttitype);virtual;
+ function get_rtti_label(rt:trttitype):tasmsymbol;
+ { regvars }
+ function is_intregable : boolean;
+ function is_fpuregable : boolean;
+ private
+ savesize : aint;
+ end;
+
+ tfiletyp = (ft_text,ft_typed,ft_untyped);
+
+ tfiledef = class(tstoreddef)
+ filetyp : tfiletyp;
+ typedfiletype : ttype;
+ constructor createtext;
+ constructor createuntyped;
+ constructor createtyped(const tt : ttype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function gettypename:string;override;
+ function getmangledparaname:string;override;
+ procedure setsize;
+ end;
+
+ tvariantdef = class(tstoreddef)
+ varianttype : tvarianttype;
+ constructor create(v : tvarianttype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ function gettypename:string;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure setsize;
+ function is_publishable : boolean;override;
+ function needs_inittable : boolean;override;
+ procedure write_rtti_data(rt:trttitype);override;
+ end;
+
+ tformaldef = class(tstoreddef)
+ constructor create;
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypename:string;override;
+ end;
+
+ tforwarddef = class(tstoreddef)
+ tosymname : pstring;
+ forwardpos : tfileposinfo;
+ constructor create(const s:string;const pos : tfileposinfo);
+ destructor destroy;override;
+ function gettypename:string;override;
+ end;
+
+ terrordef = class(tstoreddef)
+ constructor create;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypename:string;override;
+ function getmangledparaname : string;override;
+ end;
+
+ { tpointerdef and tclassrefdef should get a common
+ base class, but I derived tclassrefdef from tpointerdef
+ to avoid problems with bugs (FK)
+ }
+
+ tpointerdef = class(tstoreddef)
+ pointertype : ttype;
+ is_far : boolean;
+ constructor create(const tt : ttype);
+ constructor createfar(const tt : ttype);
+ function getcopy : tstoreddef;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function gettypename:string;override;
+ end;
+
+ tabstractrecorddef= class(tstoreddef)
+ private
+ Count : integer;
+ FRTTIType : trttitype;
+ procedure count_field_rtti(sym : tnamedindexitem;arg:pointer);
+ procedure write_field_rtti(sym : tnamedindexitem;arg:pointer);
+ procedure generate_field_rtti(sym : tnamedindexitem;arg:pointer);
+ public
+ symtable : tsymtable;
+ procedure reset;override;
+ function getsymtable(t:tgetsymtable):tsymtable;override;
+ end;
+
+ trecorddef = class(tabstractrecorddef)
+ public
+ isunion : boolean;
+ constructor create(p : tsymtable);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function size:aint;override;
+ function alignment : longint;override;
+ function padalignment: longint;
+ function gettypename:string;override;
+ { debug }
+ function needs_inittable : boolean;override;
+ { rtti }
+ procedure write_child_rtti_data(rt:trttitype);override;
+ procedure write_rtti_data(rt:trttitype);override;
+ end;
+
+ tprocdef = class;
+ tobjectdef = class;
+ timplementedinterfaces = class;
+
+ timplintfentry = class(TNamedIndexItem)
+ intf : tobjectdef;
+ intfderef : tderef;
+ ioffset : longint;
+ implindex : longint;
+ namemappings : tdictionary;
+ procdefs : TIndexArray;
+ constructor create(aintf: tobjectdef);
+ constructor create_deref(const d:tderef);
+ destructor destroy; override;
+ end;
+
+ tobjectdef = class(tabstractrecorddef)
+ private
+ procedure count_published_properties(sym:tnamedindexitem;arg:pointer);
+ procedure write_property_info(sym : tnamedindexitem;arg:pointer);
+ procedure generate_published_child_rtti(sym : tnamedindexitem;arg:pointer);
+ procedure count_published_fields(sym:tnamedindexitem;arg:pointer);
+ procedure writefields(sym:tnamedindexitem;arg:pointer);
+ public
+ childof : tobjectdef;
+ childofderef : tderef;
+ objname,
+ objrealname : pstring;
+ objectoptions : tobjectoptions;
+ { to be able to have a variable vmt position }
+ { and no vmt field for objects without virtuals }
+ vmt_offset : longint;
+ writing_class_record_stab : boolean;
+ objecttype : tobjectdeftype;
+ iidguid: pguid;
+ iidstr: pstring;
+ lastvtableindex: longint;
+ { store implemented interfaces defs and name mappings }
+ implementedinterfaces: timplementedinterfaces;
+ constructor create(ot : tobjectdeftype;const n : string;c : tobjectdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypename:string;override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function getparentdef:tdef;override;
+ function size : aint;override;
+ function alignment:longint;override;
+ function vmtmethodoffset(index:longint):longint;
+ function members_need_inittable : boolean;
+ { this should be called when this class implements an interface }
+ procedure prepareguid;
+ function is_publishable : boolean;override;
+ function needs_inittable : boolean;override;
+ function vmt_mangledname : string;
+ function rtti_name : string;
+ procedure check_forwards;
+ function is_related(d : tdef) : boolean;override;
+ function next_free_name_index : longint;
+ procedure insertvmt;
+ procedure set_parent(c : tobjectdef);
+ function searchdestructor : tprocdef;
+ { rtti }
+ procedure write_child_rtti_data(rt:trttitype);override;
+ procedure write_rtti_data(rt:trttitype);override;
+ function generate_field_table : tasmlabel;
+ end;
+
+ timplementedinterfaces = class
+ constructor create;
+ destructor destroy; override;
+
+ function count: longint;
+ function interfaces(intfindex: longint): tobjectdef;
+ function interfacesderef(intfindex: longint): tderef;
+ function ioffsets(intfindex: longint): longint;
+ procedure setioffsets(intfindex,iofs:longint);
+ function implindex(intfindex:longint):longint;
+ procedure setimplindex(intfindex,implidx:longint);
+ function searchintf(def: tdef): longint;
+ procedure addintf(def: tdef);
+
+ procedure buildderef;
+ procedure deref;
+ { add interface reference loaded from ppu }
+ procedure addintf_deref(const d:tderef;iofs:longint);
+
+ procedure clearmappings;
+ procedure addmappings(intfindex: longint; const origname, newname: string);
+ function getmappings(intfindex: longint; const origname: string; var nextexist: pointer): string;
+
+ procedure addimplproc(intfindex: longint; procdef: tprocdef);
+ function implproccount(intfindex: longint): longint;
+ function implprocs(intfindex: longint; procindex: longint): tprocdef;
+ function isimplmergepossible(intfindex, remainindex: longint; var weight: longint): boolean;
+
+ private
+ finterfaces: tindexarray;
+ procedure checkindex(intfindex: longint);
+ end;
+
+
+ tclassrefdef = class(tpointerdef)
+ constructor create(const t:ttype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypename:string;override;
+ function is_publishable : boolean;override;
+ end;
+
+ tarraydef = class(tstoreddef)
+ lowrange,
+ highrange : aint;
+ rangetype : ttype;
+ IsConvertedPointer,
+ IsDynamicArray,
+ IsVariant,
+ IsConstructor,
+ IsArrayOfConst : boolean;
+ protected
+ _elementtype : ttype;
+ public
+ function elesize : aint;
+ function elecount : aint;
+ constructor create_from_pointer(const elemt : ttype);
+ constructor create(l,h : aint;const t : ttype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypename:string;override;
+ function getmangledparaname : string;override;
+ procedure setelementtype(t: ttype);
+ procedure buildderef;override;
+ procedure deref;override;
+ function size : aint;override;
+ function alignment : longint;override;
+ { returns the label of the range check string }
+ function needs_inittable : boolean;override;
+ procedure write_child_rtti_data(rt:trttitype);override;
+ procedure write_rtti_data(rt:trttitype);override;
+ property elementtype : ttype Read _ElementType;
+ end;
+
+ torddef = class(tstoreddef)
+ low,high : TConstExprInt;
+ typ : tbasetype;
+ constructor create(t : tbasetype;v,b : TConstExprInt);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function is_publishable : boolean;override;
+ function gettypename:string;override;
+ procedure setsize;
+ function getvartype : longint;override;
+ { rtti }
+ procedure write_rtti_data(rt:trttitype);override;
+ end;
+
+ tfloatdef = class(tstoreddef)
+ typ : tfloattype;
+ constructor create(t : tfloattype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypename:string;override;
+ function is_publishable : boolean;override;
+ procedure setsize;
+ function getvartype:longint;override;
+ { rtti }
+ procedure write_rtti_data(rt:trttitype);override;
+ end;
+
+ tabstractprocdef = class(tstoreddef)
+ { saves a definition to the return type }
+ rettype : ttype;
+ parast : tsymtable;
+ paras : tparalist;
+ proctypeoption : tproctypeoption;
+ proccalloption : tproccalloption;
+ procoptions : tprocoptions;
+ requiredargarea : aint;
+ { number of user visibile parameters }
+ maxparacount,
+ minparacount : byte;
+{$ifdef i386}
+ fpu_used : longint; { how many stack fpu must be empty }
+{$endif i386}
+ funcretloc : array[tcallercallee] of TLocation;
+ has_paraloc_info : boolean; { paraloc info is available }
+ constructor create(level:byte);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure releasemem;
+ procedure calcparas;
+ function typename_paras(showhidden:boolean): string;
+ procedure test_if_fpu_result;
+ function is_methodpointer:boolean;virtual;
+ function is_addressonly:boolean;virtual;
+ private
+ procedure count_para(p:tnamedindexitem;arg:pointer);
+ procedure insert_para(p:tnamedindexitem;arg:pointer);
+ end;
+
+ tprocvardef = class(tabstractprocdef)
+ constructor create(level:byte);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function getsymtable(t:tgetsymtable):tsymtable;override;
+ function size : aint;override;
+ function gettypename:string;override;
+ function is_publishable : boolean;override;
+ function is_methodpointer:boolean;override;
+ function is_addressonly:boolean;override;
+ function getmangledparaname:string;override;
+ { rtti }
+ procedure write_rtti_data(rt:trttitype);override;
+ end;
+
+ tmessageinf = record
+ case integer of
+ 0 : (str : pchar);
+ 1 : (i : longint);
+ end;
+
+ tinlininginfo = record
+ { node tree }
+ code : tnode;
+ flags : tprocinfoflags;
+ end;
+ pinlininginfo = ^tinlininginfo;
+
+
+{$ifdef oldregvars}
+ { register variables }
+ pregvarinfo = ^tregvarinfo;
+ tregvarinfo = record
+ regvars : array[1..maxvarregs] of tsym;
+ regvars_para : array[1..maxvarregs] of boolean;
+ regvars_refs : array[1..maxvarregs] of longint;
+
+ fpuregvars : array[1..maxfpuvarregs] of tsym;
+ fpuregvars_para : array[1..maxfpuvarregs] of boolean;
+ fpuregvars_refs : array[1..maxfpuvarregs] of longint;
+ end;
+{$endif oldregvars}
+
+ tprocdef = class(tabstractprocdef)
+ private
+ _mangledname : pstring;
+ public
+ extnumber : word;
+ messageinf : tmessageinf;
+{$ifndef EXTDEBUG}
+ { where is this function defined and what were the symbol
+ flags, needed here because there
+ is only one symbol for all overloaded functions
+ EXTDEBUG has fileinfo in tdef (PFV) }
+ fileinfo : tfileposinfo;
+{$endif}
+ symoptions : tsymoptions;
+ { symbol owning this definition }
+ procsym : tsym;
+ procsymderef : tderef;
+ { alias names }
+ aliasnames : tstringlist;
+ { symtables }
+ localst : tsymtable;
+ funcretsym : tsym;
+ funcretsymderef : tderef;
+ { browser info }
+ lastref,
+ defref,
+ lastwritten : tref;
+ refcount : longint;
+ _class : tobjectdef;
+ _classderef : tderef;
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ libsym : tsym;
+ libsymderef : tderef;
+{$endif powerpc}
+ { name of the result variable to insert in the localsymtable }
+ resultname : stringid;
+ { true, if the procedure is only declared
+ (forward procedure) }
+ forwarddef,
+ { true if the procedure is declared in the interface }
+ interfacedef : boolean;
+ { true if the procedure has a forward declaration }
+ hasforward : boolean;
+ { import info }
+ import_dll,
+ import_name : pstring;
+ import_nr : word;
+ { info for inlining the subroutine, if this pointer is nil,
+ the procedure can't be inlined }
+ inlininginfo : pinlininginfo;
+{$ifdef oldregvars}
+ regvarinfo: pregvarinfo;
+{$endif oldregvars}
+ { position in aasmoutput list }
+ procstarttai,
+ procendtai : tai;
+ constructor create(level:byte);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure buildderefimpl;override;
+ procedure deref;override;
+ procedure derefimpl;override;
+ procedure reset;override;
+ function getsymtable(t:tgetsymtable):tsymtable;override;
+ function gettypename : string;override;
+ function mangledname : string;
+ procedure setmangledname(const s : string);
+ procedure load_references(ppufile:tcompilerppufile;locals:boolean);
+ function write_references(ppufile:tcompilerppufile;locals:boolean):boolean;
+ { inserts the local symbol table, if this is not
+ no local symbol table is built. Should be called only
+ when we are sure that a local symbol table will be required.
+ }
+ procedure insert_localst;
+ function fullprocname(showhidden:boolean):string;
+ function cplusplusmangledname : string;
+ function is_methodpointer:boolean;override;
+ function is_addressonly:boolean;override;
+ function is_visible_for_object(currobjdef:tobjectdef):boolean;
+ end;
+
+ { single linked list of overloaded procs }
+ pprocdeflist = ^tprocdeflist;
+ tprocdeflist = record
+ def : tprocdef;
+ defderef : tderef;
+ next : pprocdeflist;
+ end;
+
+ tstringdef = class(tstoreddef)
+ string_typ : tstringtype;
+ len : aint;
+ constructor createshort(l : byte);
+ constructor loadshort(ppufile:tcompilerppufile);
+ constructor createlong(l : aint);
+ constructor loadlong(ppufile:tcompilerppufile);
+ {$ifdef ansistring_bits}
+ constructor createansi(l:aint;bits:Tstringbits);
+ constructor loadansi(ppufile:tcompilerppufile;bits:Tstringbits);
+ {$else}
+ constructor createansi(l : aint);
+ constructor loadansi(ppufile:tcompilerppufile);
+ {$endif}
+ constructor createwide(l : aint);
+ constructor loadwide(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ function stringtypname:string;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypename:string;override;
+ function getmangledparaname:string;override;
+ function is_publishable : boolean;override;
+ function alignment : longint;override;
+ { init/final }
+ function needs_inittable : boolean;override;
+ { rtti }
+ procedure write_rtti_data(rt:trttitype);override;
+ end;
+
+ tenumdef = class(tstoreddef)
+ minval,
+ maxval : aint;
+ has_jumps : boolean;
+ firstenum : tsym; {tenumsym}
+ basedef : tenumdef;
+ basedefderef : tderef;
+ constructor create;
+ constructor create_subrange(_basedef:tenumdef;_min,_max:aint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure derefimpl;override;
+ function gettypename:string;override;
+ function is_publishable : boolean;override;
+ procedure calcsavesize;
+ procedure setmax(_max:aint);
+ procedure setmin(_min:aint);
+ function min:aint;
+ function max:aint;
+ { rtti }
+ procedure write_rtti_data(rt:trttitype);override;
+ procedure write_child_rtti_data(rt:trttitype);override;
+ private
+ procedure correct_owner_symtable;
+ end;
+
+ tsetdef = class(tstoreddef)
+ elementtype : ttype;
+ settype : tsettype;
+ setbase,
+ setmax : aint;
+ constructor create(const t:ttype;high : aint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function gettypename:string;override;
+ function is_publishable : boolean;override;
+ { rtti }
+ procedure write_rtti_data(rt:trttitype);override;
+ procedure write_child_rtti_data(rt:trttitype);override;
+ end;
+
+ Tdefmatch=(dm_exact,dm_equal,dm_convertl1);
+
+ var
+ aktobjectdef : tobjectdef; { used for private functions check !! }
+
+ { default types }
+ generrortype, { error in definition }
+ voidpointertype, { pointer for Void-Pointerdef }
+ charpointertype, { pointer for Char-Pointerdef }
+ widecharpointertype, { pointer for WideChar-Pointerdef }
+ voidfarpointertype,
+ cformaltype, { unique formal definition }
+ voidtype, { Void (procedure) }
+ cchartype, { Char }
+ cwidechartype, { WideChar }
+ booltype, { boolean type }
+ u8inttype, { 8-Bit unsigned integer }
+ s8inttype, { 8-Bit signed integer }
+ u16inttype, { 16-Bit unsigned integer }
+ s16inttype, { 16-Bit signed integer }
+ u32inttype, { 32-Bit unsigned integer }
+ s32inttype, { 32-Bit signed integer }
+ u64inttype, { 64-bit unsigned integer }
+ s64inttype, { 64-bit signed integer }
+ s32floattype, { pointer for realconstn }
+ s64floattype, { pointer for realconstn }
+ s80floattype, { pointer to type of temp. floats }
+ s64currencytype, { pointer to a currency type }
+ cshortstringtype, { pointer to type of short string const }
+ clongstringtype, { pointer to type of long string const }
+{$ifdef ansistring_bits}
+ cansistringtype16, { pointer to type of ansi string const }
+ cansistringtype32, { pointer to type of ansi string const }
+ cansistringtype64, { pointer to type of ansi string const }
+{$else}
+ cansistringtype, { pointer to type of ansi string const }
+{$endif}
+ cwidestringtype, { pointer to type of wide string const }
+ openshortstringtype, { pointer to type of an open shortstring,
+ needed for readln() }
+ openchararraytype, { pointer to type of an open array of char,
+ needed for readln() }
+ cfiletype, { get the same definition for all file }
+ { used for stabs }
+ methodpointertype, { typecasting of methodpointers to extract self }
+ { we use only one variant def for every variant class }
+ cvarianttype,
+ colevarianttype,
+ { default integer type s32inttype on 32 bit systems, s64bittype on 64 bit systems }
+ sinttype,
+ uinttype,
+ { unsigned ord type with the same size as a pointer }
+ ptrinttype,
+ { several types to simulate more or less C++ objects for GDB }
+ vmttype,
+ vmtarraytype,
+ pvmttype : ttype; { type of classrefs, used for stabs }
+
+ { pointer to the anchestor of all classes }
+ class_tobject : tobjectdef;
+ { pointer to the ancestor of all COM interfaces }
+ interface_iunknown : tobjectdef;
+ { pointer to the TGUID type
+ of all interfaces }
+ rec_tguid : trecorddef;
+
+ const
+{$ifdef i386}
+ pbestrealtype : ^ttype = @s80floattype;
+{$endif}
+{$ifdef x86_64}
+ pbestrealtype : ^ttype = @s80floattype;
+{$endif}
+{$ifdef m68k}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif}
+{$ifdef alpha}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif}
+{$ifdef powerpc}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif}
+{$ifdef POWERPC64}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif}
+{$ifdef ia64}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif}
+{$ifdef SPARC}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif SPARC}
+{$ifdef vis}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif vis}
+{$ifdef ARM}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif ARM}
+{$ifdef MIPS}
+ pbestrealtype : ^ttype = @s64floattype;
+{$endif MIPS}
+
+ function make_mangledname(const typeprefix:string;st:tsymtable;const suffix:string):string;
+
+ { should be in the types unit, but the types unit uses the node stuff :( }
+ function is_interfacecom(def: tdef): boolean;
+ function is_interfacecorba(def: tdef): boolean;
+ function is_interface(def: tdef): boolean;
+ function is_object(def: tdef): boolean;
+ function is_class(def: tdef): boolean;
+ function is_cppclass(def: tdef): boolean;
+ function is_class_or_interface(def: tdef): boolean;
+
+
+{$ifdef x86}
+ function use_sse(def : tdef) : boolean;
+{$endif x86}
+
+implementation
+
+ uses
+ strings,
+ { global }
+ verbose,
+ { target }
+ systems,aasmcpu,paramgr,
+ { symtable }
+ symsym,symtable,symutil,defutil,
+ { module }
+ fmodule,
+ { other }
+ gendef,
+ crc
+ ;
+
+{****************************************************************************
+ Constants
+****************************************************************************}
+
+ const
+ varempty = 0;
+ varnull = 1;
+ varsmallint = 2;
+ varinteger = 3;
+ varsingle = 4;
+ vardouble = 5;
+ varcurrency = 6;
+ vardate = 7;
+ varolestr = 8;
+ vardispatch = 9;
+ varerror = 10;
+ varboolean = 11;
+ varvariant = 12;
+ varunknown = 13;
+ vardecimal = 14;
+ varshortint = 16;
+ varbyte = 17;
+ varword = 18;
+ varlongword = 19;
+ varint64 = 20;
+ varqword = 21;
+
+ varUndefined = -1;
+
+ varstrarg = $48;
+ varstring = $100;
+ varany = $101;
+ vartypemask = $fff;
+ vararray = $2000;
+ varbyref = $4000;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ function make_mangledname(const typeprefix:string;st:tsymtable;const suffix:string):string;
+ var
+ s,hs,
+ prefix : string;
+ oldlen,
+ newlen,
+ i : longint;
+ crc : dword;
+ hp : tparavarsym;
+ begin
+ prefix:='';
+ if not assigned(st) then
+ internalerror(200204212);
+ { sub procedures }
+ while (st.symtabletype=localsymtable) do
+ begin
+ if st.defowner.deftype<>procdef then
+ internalerror(200204173);
+ { Add the full mangledname of procedure to prevent
+ conflicts with 2 overloads having both a nested procedure
+ with the same name, see tb0314 (PFV) }
+ s:=tprocdef(st.defowner).procsym.name;
+ oldlen:=length(s);
+ for i:=0 to tprocdef(st.defowner).paras.count-1 do
+ begin
+ hp:=tparavarsym(tprocdef(st.defowner).paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) then
+ s:=s+'$'+hp.vartype.def.mangledparaname;
+ end;
+ if not is_void(tprocdef(st.defowner).rettype.def) then
+ s:=s+'$$'+tprocdef(st.defowner).rettype.def.mangledparaname;
+ newlen:=length(s);
+ { Replace with CRC if the parameter line is very long }
+ if (newlen-oldlen>12) and
+ ((newlen>128) or (newlen-oldlen>64)) then
+ begin
+ crc:=$ffffffff;
+ for i:=0 to tprocdef(st.defowner).paras.count-1 do
+ begin
+ hp:=tparavarsym(tprocdef(st.defowner).paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) then
+ begin
+ hs:=hp.vartype.def.mangledparaname;
+ crc:=UpdateCrc32(crc,hs[1],length(hs));
+ end;
+ end;
+ hs:=hp.vartype.def.mangledparaname;
+ crc:=UpdateCrc32(crc,hs[1],length(hs));
+ s:=Copy(s,1,oldlen)+'$crc'+hexstr(crc,8);
+ end;
+ if prefix<>'' then
+ prefix:=s+'_'+prefix
+ else
+ prefix:=s;
+ st:=st.defowner.owner;
+ end;
+ { object/classes symtable }
+ if (st.symtabletype=objectsymtable) then
+ begin
+ if st.defowner.deftype<>objectdef then
+ internalerror(200204174);
+ prefix:=tobjectdef(st.defowner).objname^+'_$_'+prefix;
+ st:=st.defowner.owner;
+ end;
+ { symtable must now be static or global }
+ if not(st.symtabletype in [staticsymtable,globalsymtable]) then
+ internalerror(200204175);
+ result:='';
+ if typeprefix<>'' then
+ result:=result+typeprefix+'_';
+ { Add P$ for program, which can have the same name as
+ a unit }
+ if (tsymtable(main_module.localsymtable)=st) and
+ (not main_module.is_unit) then
+ result:=result+'P$'+st.name^
+ else
+ result:=result+st.name^;
+ if prefix<>'' then
+ result:=result+'_'+prefix;
+ if suffix<>'' then
+ result:=result+'_'+suffix;
+ { the Darwin assembler assumes that all symbols starting with 'L' are local }
+ if (target_info.system = system_powerpc_darwin) and
+ (result[1] = 'L') then
+ result := '_' + result;
+ end;
+
+
+{****************************************************************************
+ TDEF (base class for definitions)
+****************************************************************************}
+
+ constructor tstoreddef.create;
+ begin
+ inherited create;
+ savesize := 0;
+{$ifdef EXTDEBUG}
+ fileinfo := aktfilepos;
+{$endif}
+ if registerdef then
+ symtablestack.registerdef(self);
+ fillchar(localrttilab,sizeof(localrttilab),0);
+ end;
+
+
+ constructor tstoreddef.ppuloaddef(ppufile:tcompilerppufile);
+ begin
+ inherited create;
+{$ifdef EXTDEBUG}
+ fillchar(fileinfo,sizeof(fileinfo),0);
+{$endif}
+ fillchar(localrttilab,sizeof(localrttilab),0);
+ { load }
+ indexnr:=ppufile.getword;
+ ppufile.getderef(typesymderef);
+ ppufile.getsmallset(defoptions);
+ if df_has_rttitable in defoptions then
+ ppufile.getderef(rttitablesymderef);
+ if df_has_inittable in defoptions then
+ ppufile.getderef(inittablesymderef);
+ end;
+
+
+ procedure Tstoreddef.reset;
+ begin
+ if assigned(rttitablesym) then
+ trttisym(rttitablesym).lab := nil;
+ if assigned(inittablesym) then
+ trttisym(inittablesym).lab := nil;
+ localrttilab[initrtti]:=nil;
+ localrttilab[fullrtti]:=nil;
+ end;
+
+
+ function tstoreddef.getcopy : tstoreddef;
+ begin
+ Message(sym_e_cant_create_unique_type);
+ getcopy:=terrordef.create;
+ end;
+
+
+ procedure tstoreddef.ppuwritedef(ppufile:tcompilerppufile);
+ begin
+ ppufile.putword(indexnr);
+ ppufile.putderef(typesymderef);
+ ppufile.putsmallset(defoptions);
+ if df_has_rttitable in defoptions then
+ ppufile.putderef(rttitablesymderef);
+ if df_has_inittable in defoptions then
+ ppufile.putderef(inittablesymderef);
+ end;
+
+
+ procedure tstoreddef.buildderef;
+ begin
+ typesymderef.build(typesym);
+ rttitablesymderef.build(rttitablesym);
+ inittablesymderef.build(inittablesym);
+ end;
+
+
+ procedure tstoreddef.buildderefimpl;
+ begin
+ end;
+
+
+ procedure tstoreddef.deref;
+ begin
+ typesym:=ttypesym(typesymderef.resolve);
+ if df_has_rttitable in defoptions then
+ rttitablesym:=trttisym(rttitablesymderef.resolve);
+ if df_has_inittable in defoptions then
+ inittablesym:=trttisym(inittablesymderef.resolve);
+ end;
+
+
+ procedure tstoreddef.derefimpl;
+ begin
+ end;
+
+
+ function tstoreddef.size : aint;
+ begin
+ size:=savesize;
+ end;
+
+
+ function tstoreddef.getvartype:longint;
+ begin
+ result:=varUndefined;
+ end;
+
+
+ function tstoreddef.alignment : longint;
+ begin
+ { natural alignment by default }
+ alignment:=size_2_align(savesize);
+ end;
+
+
+ procedure tstoreddef.write_rtti_name;
+ var
+ str : string;
+ begin
+ { name }
+ if assigned(typesym) then
+ begin
+ str:=ttypesym(typesym).realname;
+ asmlist[al_rtti].concat(Tai_string.Create(chr(length(str))+str));
+ end
+ else
+ asmlist[al_rtti].concat(Tai_string.Create(#0))
+ end;
+
+
+ procedure tstoreddef.write_rtti_data(rt:trttitype);
+ begin
+ asmlist[al_rtti].concat(tai_const.create_8bit(tkUnknown));
+ write_rtti_name;
+ end;
+
+
+ procedure tstoreddef.write_child_rtti_data(rt:trttitype);
+ begin
+ end;
+
+
+ function tstoreddef.get_rtti_label(rt:trttitype) : tasmsymbol;
+ begin
+ { try to reuse persistent rtti data }
+ if (rt=fullrtti) and (df_has_rttitable in defoptions) then
+ get_rtti_label:=trttisym(rttitablesym).get_label
+ else
+ if (rt=initrtti) and (df_has_inittable in defoptions) then
+ get_rtti_label:=trttisym(inittablesym).get_label
+ else
+ begin
+ if not assigned(localrttilab[rt]) then
+ begin
+ objectlibrary.getdatalabel(localrttilab[rt]);
+ write_child_rtti_data(rt);
+ maybe_new_object_file(asmlist[al_rtti]);
+ new_section(asmlist[al_rtti],sec_rodata,localrttilab[rt].name,const_align(sizeof(aint)));
+ asmlist[al_rtti].concat(Tai_symbol.Create_global(localrttilab[rt],0));
+ write_rtti_data(rt);
+ asmlist[al_rtti].concat(Tai_symbol_end.Create(localrttilab[rt]));
+ end;
+ get_rtti_label:=localrttilab[rt];
+ end;
+ end;
+
+
+ { returns true, if the definition can be published }
+ function tstoreddef.is_publishable : boolean;
+ begin
+ is_publishable:=false;
+ end;
+
+
+ { needs an init table }
+ function tstoreddef.needs_inittable : boolean;
+ begin
+ needs_inittable:=false;
+ end;
+
+
+ function tstoreddef.is_intregable : boolean;
+ begin
+ is_intregable:=false;
+ case deftype of
+ orddef,
+ pointerdef,
+ enumdef:
+ is_intregable:=true;
+ procvardef :
+ is_intregable:=not(po_methodpointer in tprocvardef(self).procoptions);
+ objectdef:
+ is_intregable:=is_class(self) or is_interface(self);
+ setdef:
+ is_intregable:=(tsetdef(self).settype=smallset);
+ end;
+ end;
+
+
+ function tstoreddef.is_fpuregable : boolean;
+ begin
+{$ifdef x86}
+ result:=use_sse(self);
+{$else x86}
+ result:=(deftype=floatdef) and not(cs_fp_emulation in aktmoduleswitches);
+{$endif x86}
+ end;
+
+
+
+{****************************************************************************
+ Tstringdef
+****************************************************************************}
+
+ constructor tstringdef.createshort(l : byte);
+ begin
+ inherited create;
+ string_typ:=st_shortstring;
+ deftype:=stringdef;
+ len:=l;
+ savesize:=len+1;
+ end;
+
+
+ constructor tstringdef.loadshort(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ string_typ:=st_shortstring;
+ deftype:=stringdef;
+ len:=ppufile.getbyte;
+ savesize:=len+1;
+ end;
+
+
+ constructor tstringdef.createlong(l : aint);
+ begin
+ inherited create;
+ string_typ:=st_longstring;
+ deftype:=stringdef;
+ len:=l;
+ savesize:=sizeof(aint);
+ end;
+
+
+ constructor tstringdef.loadlong(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=stringdef;
+ string_typ:=st_longstring;
+ len:=ppufile.getaint;
+ savesize:=sizeof(aint);
+ end;
+
+{$ifdef ansistring_bits}
+ constructor tstringdef.createansi(l:aint;bits:Tstringbits);
+ begin
+ inherited create;
+ case bits of
+ sb_16:
+ string_typ:=st_ansistring16;
+ sb_32:
+ string_typ:=st_ansistring32;
+ sb_64:
+ string_typ:=st_ansistring64;
+ end;
+ deftype:=stringdef;
+ len:=l;
+ savesize:=POINTER_SIZE;
+ end;
+
+
+ constructor tstringdef.loadansi(ppufile:tcompilerppufile;bits:Tstringbits);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=stringdef;
+ case bits of
+ sb_16:
+ string_typ:=st_ansistring16;
+ sb_32:
+ string_typ:=st_ansistring32;
+ sb_64:
+ string_typ:=st_ansistring64;
+ end;
+ len:=ppufile.getaint;
+ savesize:=POINTER_SIZE;
+ end;
+{$else}
+ constructor tstringdef.createansi(l:aint);
+ begin
+ inherited create;
+ string_typ:=st_ansistring;
+ deftype:=stringdef;
+ len:=l;
+ savesize:=sizeof(aint);
+ end;
+
+
+ constructor tstringdef.loadansi(ppufile:tcompilerppufile);
+
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=stringdef;
+ string_typ:=st_ansistring;
+ len:=ppufile.getaint;
+ savesize:=sizeof(aint);
+ end;
+{$endif}
+
+ constructor tstringdef.createwide(l : aint);
+ begin
+ inherited create;
+ string_typ:=st_widestring;
+ deftype:=stringdef;
+ len:=l;
+ savesize:=sizeof(aint);
+ end;
+
+
+ constructor tstringdef.loadwide(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=stringdef;
+ string_typ:=st_widestring;
+ len:=ppufile.getaint;
+ savesize:=sizeof(aint);
+ end;
+
+
+ function tstringdef.getcopy : tstoreddef;
+ begin
+ result:=tstringdef.create;
+ result.deftype:=stringdef;
+ tstringdef(result).string_typ:=string_typ;
+ tstringdef(result).len:=len;
+ tstringdef(result).savesize:=savesize;
+ end;
+
+
+ function tstringdef.stringtypname:string;
+{$ifdef ansistring_bits}
+ const
+ typname:array[tstringtype] of string[9]=('',
+ 'shortstr','longstr','ansistr16','ansistr32','ansistr64','widestr'
+ );
+{$else}
+ const
+ typname:array[tstringtype] of string[8]=('',
+ 'shortstr','longstr','ansistr','widestr'
+ );
+{$endif}
+ begin
+ stringtypname:=typname[string_typ];
+ end;
+
+
+ procedure tstringdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ if string_typ=st_shortstring then
+ begin
+{$ifdef extdebug}
+ if len > 255 then internalerror(12122002);
+{$endif}
+ ppufile.putbyte(byte(len))
+ end
+ else
+ ppufile.putaint(len);
+ case string_typ of
+ st_shortstring : ppufile.writeentry(ibshortstringdef);
+ st_longstring : ppufile.writeentry(iblongstringdef);
+ {$ifdef ansistring_bits}
+ st_ansistring16 : ppufile.writeentry(ibansistring16def);
+ st_ansistring32 : ppufile.writeentry(ibansistring32def);
+ st_ansistring64 : ppufile.writeentry(ibansistring64def);
+ {$else}
+ st_ansistring : ppufile.writeentry(ibansistringdef);
+ {$endif}
+ st_widestring : ppufile.writeentry(ibwidestringdef);
+ end;
+ end;
+
+
+ function tstringdef.needs_inittable : boolean;
+ begin
+ {$ifdef ansistring_bits}
+ needs_inittable:=string_typ in [st_ansistring16,st_ansistring32,st_ansistring64,st_widestring];
+ {$else}
+ needs_inittable:=string_typ in [st_ansistring,st_widestring];
+ {$endif}
+ end;
+
+
+ function tstringdef.gettypename : string;
+{$ifdef ansistring_bits}
+ const
+ names : array[tstringtype] of string[20] = ('',
+ 'shortstring','longstring','ansistring16','ansistring32','ansistring64','widestring');
+{$else}
+ const
+ names : array[tstringtype] of string[20] = ('',
+ 'ShortString','LongString','AnsiString','WideString');
+{$endif}
+ begin
+ gettypename:=names[string_typ];
+ end;
+
+
+ function tstringdef.alignment : longint;
+ begin
+ case string_typ of
+ st_widestring,
+ st_ansistring:
+ alignment:=size_2_align(savesize);
+ st_longstring,
+ st_shortstring:
+{$ifdef cpurequiresproperalignment}
+ { char to string accesses byte 0 and 1 with one word access }
+ alignment:=size_2_align(2);
+{$else cpurequiresproperalignment}
+ alignment:=size_2_align(1);
+{$endif cpurequiresproperalignment}
+ else
+ internalerror(200412301);
+ end;
+ end;
+
+
+ procedure tstringdef.write_rtti_data(rt:trttitype);
+ begin
+ case string_typ of
+ {$ifdef ansistring_bits}
+ st_ansistring16:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkA16String));
+ write_rtti_name;
+ end;
+ st_ansistring32:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkA32String));
+ write_rtti_name;
+ end;
+ st_ansistring64:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkA64String));
+ write_rtti_name;
+ end;
+ {$else}
+ st_ansistring:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkAString));
+ write_rtti_name;
+ end;
+ {$endif}
+ st_widestring:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkWString));
+ write_rtti_name;
+ end;
+ st_longstring:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkLString));
+ write_rtti_name;
+ end;
+ st_shortstring:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkSString));
+ write_rtti_name;
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(len));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ end;
+ end;
+ end;
+
+
+ function tstringdef.getmangledparaname : string;
+ begin
+ getmangledparaname:='STRING';
+ end;
+
+
+ function tstringdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+
+{****************************************************************************
+ TENUMDEF
+****************************************************************************}
+
+ constructor tenumdef.create;
+ begin
+ inherited create;
+ deftype:=enumdef;
+ minval:=0;
+ maxval:=0;
+ calcsavesize;
+ has_jumps:=false;
+ basedef:=nil;
+ firstenum:=nil;
+ correct_owner_symtable;
+ end;
+
+
+ constructor tenumdef.create_subrange(_basedef:tenumdef;_min,_max:aint);
+ begin
+ inherited create;
+ deftype:=enumdef;
+ minval:=_min;
+ maxval:=_max;
+ basedef:=_basedef;
+ calcsavesize;
+ has_jumps:=false;
+ firstenum:=basedef.firstenum;
+ while assigned(firstenum) and (tenumsym(firstenum).value<>minval) do
+ firstenum:=tenumsym(firstenum).nextenum;
+ correct_owner_symtable;
+ end;
+
+
+ constructor tenumdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=enumdef;
+ ppufile.getderef(basedefderef);
+ minval:=ppufile.getaint;
+ maxval:=ppufile.getaint;
+ savesize:=ppufile.getaint;
+ has_jumps:=false;
+ firstenum:=Nil;
+ end;
+
+
+ function tenumdef.getcopy : tstoreddef;
+ begin
+ if assigned(basedef) then
+ result:=tenumdef.create_subrange(basedef,minval,maxval)
+ else
+ begin
+ result:=tenumdef.create;
+ tenumdef(result).minval:=minval;
+ tenumdef(result).maxval:=maxval;
+ end;
+ tenumdef(result).has_jumps:=has_jumps;
+ tenumdef(result).firstenum:=firstenum;
+ tenumdef(result).basedefderef:=basedefderef;
+ end;
+
+
+ procedure tenumdef.calcsavesize;
+ begin
+ if (aktpackenum=8) or (min<low(longint)) or (int64(max)>high(cardinal)) then
+ savesize:=8
+ else
+ if (aktpackenum=4) or (min<low(smallint)) or (max>high(word)) then
+ savesize:=4
+ else
+ if (aktpackenum=2) or (min<low(shortint)) or (max>high(byte)) then
+ savesize:=2
+ else
+ savesize:=1;
+ end;
+
+
+ procedure tenumdef.setmax(_max:aint);
+ begin
+ maxval:=_max;
+ calcsavesize;
+ end;
+
+
+ procedure tenumdef.setmin(_min:aint);
+ begin
+ minval:=_min;
+ calcsavesize;
+ end;
+
+
+ function tenumdef.min:aint;
+ begin
+ min:=minval;
+ end;
+
+
+ function tenumdef.max:aint;
+ begin
+ max:=maxval;
+ end;
+
+
+ procedure tenumdef.buildderef;
+ begin
+ inherited buildderef;
+ basedefderef.build(basedef);
+ end;
+
+
+ procedure tenumdef.deref;
+ begin
+ inherited deref;
+ basedef:=tenumdef(basedefderef.resolve);
+ { restart ordering }
+ firstenum:=nil;
+ end;
+
+
+ procedure tenumdef.derefimpl;
+ begin
+ if assigned(basedef) and
+ (firstenum=nil) then
+ begin
+ firstenum:=basedef.firstenum;
+ while assigned(firstenum) and (tenumsym(firstenum).value<>minval) do
+ firstenum:=tenumsym(firstenum).nextenum;
+ end;
+ end;
+
+
+ destructor tenumdef.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ procedure tenumdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.putderef(basedefderef);
+ ppufile.putaint(min);
+ ppufile.putaint(max);
+ ppufile.putaint(savesize);
+ ppufile.writeentry(ibenumdef);
+ end;
+
+
+ { used for enumdef because the symbols are
+ inserted in the owner symtable }
+ procedure tenumdef.correct_owner_symtable;
+ var
+ st : tsymtable;
+ begin
+ if assigned(owner) and
+ (owner.symtabletype in [recordsymtable,objectsymtable]) then
+ begin
+ owner.defindex.deleteindex(self);
+ st:=owner;
+ while (st.symtabletype in [recordsymtable,objectsymtable]) do
+ st:=st.next;
+ st.registerdef(self);
+ end;
+ end;
+
+
+
+
+
+ procedure tenumdef.write_child_rtti_data(rt:trttitype);
+ begin
+ if assigned(basedef) then
+ basedef.get_rtti_label(rt);
+ end;
+
+
+ procedure tenumdef.write_rtti_data(rt:trttitype);
+ var
+ hp : tenumsym;
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkEnumeration));
+ write_rtti_name;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ case longint(savesize) of
+ 1:
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(otUByte));
+ 2:
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(otUWord));
+ 4:
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(otULong));
+ end;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(4));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(min));
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(max));
+ if assigned(basedef) then
+ asmlist[al_rtti].concat(Tai_const.Create_sym(basedef.get_rtti_label(rt)))
+ else
+ asmlist[al_rtti].concat(Tai_const.create_sym(nil));
+ hp:=tenumsym(firstenum);
+ while assigned(hp) do
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(length(hp.realname)));
+ asmlist[al_rtti].concat(Tai_string.Create(hp.realname));
+ hp:=hp.nextenum;
+ end;
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(0));
+ end;
+
+
+ function tenumdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+ function tenumdef.gettypename : string;
+
+ begin
+ gettypename:='<enumeration type>';
+ end;
+
+{****************************************************************************
+ TORDDEF
+****************************************************************************}
+
+ constructor torddef.create(t : tbasetype;v,b : TConstExprInt);
+ begin
+ inherited create;
+ deftype:=orddef;
+ low:=v;
+ high:=b;
+ typ:=t;
+ setsize;
+ end;
+
+
+ constructor torddef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=orddef;
+ typ:=tbasetype(ppufile.getbyte);
+ if sizeof(TConstExprInt)=8 then
+ begin
+ low:=ppufile.getint64;
+ high:=ppufile.getint64;
+ end
+ else
+ begin
+ low:=ppufile.getlongint;
+ high:=ppufile.getlongint;
+ end;
+ setsize;
+ end;
+
+
+ function torddef.getcopy : tstoreddef;
+ begin
+ result:=torddef.create(typ,low,high);
+ result.deftype:=orddef;
+ torddef(result).low:=low;
+ torddef(result).high:=high;
+ torddef(result).typ:=typ;
+ torddef(result).savesize:=savesize;
+ end;
+
+
+ procedure torddef.setsize;
+ const
+ sizetbl : array[tbasetype] of longint = (
+ 0,
+ 1,2,4,8,
+ 1,2,4,8,
+ 1,2,4,
+ 1,2,8
+ );
+ begin
+ savesize:=sizetbl[typ];
+ end;
+
+
+ function torddef.getvartype : longint;
+ const
+ basetype2vartype : array[tbasetype] of longint = (
+ varUndefined,
+ varbyte,varqword,varlongword,varqword,
+ varshortint,varsmallint,varinteger,varint64,
+ varboolean,varUndefined,varUndefined,
+ varUndefined,varUndefined,varCurrency);
+ begin
+ result:=basetype2vartype[typ];
+ end;
+
+
+ procedure torddef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.putbyte(byte(typ));
+ if sizeof(TConstExprInt)=8 then
+ begin
+ ppufile.putint64(low);
+ ppufile.putint64(high);
+ end
+ else
+ begin
+ ppufile.putlongint(low);
+ ppufile.putlongint(high);
+ end;
+ ppufile.writeentry(iborddef);
+ end;
+
+
+ procedure torddef.write_rtti_data(rt:trttitype);
+
+ procedure dointeger;
+ const
+ trans : array[tbasetype] of byte =
+ (otUByte{otNone},
+ otUByte,otUWord,otULong,otUByte{otNone},
+ otSByte,otSWord,otSLong,otUByte{otNone},
+ otUByte,otUWord,otULong,
+ otUByte,otUWord,otUByte);
+ begin
+ write_rtti_name;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(byte(trans[typ])));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(4));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(longint(low)));
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(longint(high)));
+ end;
+
+ begin
+ case typ of
+ s64bit :
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkInt64));
+ write_rtti_name;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ { low }
+ asmlist[al_rtti].concat(Tai_const.Create_64bit(int64($80000000) shl 32));
+ { high }
+ asmlist[al_rtti].concat(Tai_const.Create_64bit((int64($7fffffff) shl 32) or int64($ffffffff)));
+ end;
+ u64bit :
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkQWord));
+ write_rtti_name;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ { low }
+ asmlist[al_rtti].concat(Tai_const.Create_64bit(0));
+ { high }
+ asmlist[al_rtti].concat(Tai_const.Create_64bit(int64((int64($ffffffff) shl 32) or int64($ffffffff))));
+ end;
+ bool8bit:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkBool));
+ dointeger;
+ end;
+ uchar:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkChar));
+ dointeger;
+ end;
+ uwidechar:
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkWChar));
+ dointeger;
+ end;
+ else
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkInteger));
+ dointeger;
+ end;
+ end;
+ end;
+
+
+ function torddef.is_publishable : boolean;
+ begin
+ is_publishable:=(typ<>uvoid);
+ end;
+
+
+ function torddef.gettypename : string;
+
+ const
+ names : array[tbasetype] of string[20] = (
+ 'untyped',
+ 'Byte','Word','DWord','QWord',
+ 'ShortInt','SmallInt','LongInt','Int64',
+ 'Boolean','WordBool','LongBool',
+ 'Char','WideChar','Currency');
+
+ begin
+ gettypename:=names[typ];
+ end;
+
+{****************************************************************************
+ TFLOATDEF
+****************************************************************************}
+
+ constructor tfloatdef.create(t : tfloattype);
+ begin
+ inherited create;
+ deftype:=floatdef;
+ typ:=t;
+ setsize;
+ end;
+
+
+ constructor tfloatdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=floatdef;
+ typ:=tfloattype(ppufile.getbyte);
+ setsize;
+ end;
+
+
+ function tfloatdef.getcopy : tstoreddef;
+ begin
+ result:=tfloatdef.create(typ);
+ result.deftype:=floatdef;
+ tfloatdef(result).savesize:=savesize;
+ end;
+
+
+ procedure tfloatdef.setsize;
+ begin
+ case typ of
+ s32real : savesize:=4;
+ s80real : savesize:=10;
+ s64real,
+ s64currency,
+ s64comp : savesize:=8;
+ else
+ savesize:=0;
+ end;
+ end;
+
+
+ function tfloatdef.getvartype : longint;
+ const
+ floattype2vartype : array[tfloattype] of longint = (
+ varSingle,varDouble,varUndefined,
+ varUndefined,varCurrency,varUndefined);
+ begin
+ if (upper(typename)='TDATETIME') and
+ assigned(owner) and
+ assigned(owner.name) and
+ (owner.name^='SYSTEM') then
+ result:=varDate
+ else
+ result:=floattype2vartype[typ];
+ end;
+
+
+ procedure tfloatdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.putbyte(byte(typ));
+ ppufile.writeentry(ibfloatdef);
+ end;
+
+
+ procedure tfloatdef.write_rtti_data(rt:trttitype);
+ const
+ {tfloattype = (s32real,s64real,s80real,s64bit,s128bit);}
+ translate : array[tfloattype] of byte =
+ (ftSingle,ftDouble,ftExtended,ftComp,ftCurr,ftFloat128);
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkFloat));
+ write_rtti_name;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(translate[typ]));
+ end;
+
+
+ function tfloatdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+ function tfloatdef.gettypename : string;
+
+ const
+ names : array[tfloattype] of string[20] = (
+ 'Single','Double','Extended','Comp','Currency','Float128');
+
+ begin
+ gettypename:=names[typ];
+ end;
+
+{****************************************************************************
+ TFILEDEF
+****************************************************************************}
+
+ constructor tfiledef.createtext;
+ begin
+ inherited create;
+ deftype:=filedef;
+ filetyp:=ft_text;
+ typedfiletype.reset;
+ setsize;
+ end;
+
+
+ constructor tfiledef.createuntyped;
+ begin
+ inherited create;
+ deftype:=filedef;
+ filetyp:=ft_untyped;
+ typedfiletype.reset;
+ setsize;
+ end;
+
+
+ constructor tfiledef.createtyped(const tt : ttype);
+ begin
+ inherited create;
+ deftype:=filedef;
+ filetyp:=ft_typed;
+ typedfiletype:=tt;
+ setsize;
+ end;
+
+
+ constructor tfiledef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=filedef;
+ filetyp:=tfiletyp(ppufile.getbyte);
+ if filetyp=ft_typed then
+ ppufile.gettype(typedfiletype)
+ else
+ typedfiletype.reset;
+ setsize;
+ end;
+
+
+ function tfiledef.getcopy : tstoreddef;
+ begin
+ case filetyp of
+ ft_typed:
+ result:=tfiledef.createtyped(typedfiletype);
+ ft_untyped:
+ result:=tfiledef.createuntyped;
+ ft_text:
+ result:=tfiledef.createtext;
+ else
+ internalerror(2004121201);
+ end;
+ end;
+
+
+ procedure tfiledef.buildderef;
+ begin
+ inherited buildderef;
+ if filetyp=ft_typed then
+ typedfiletype.buildderef;
+ end;
+
+
+ procedure tfiledef.deref;
+ begin
+ inherited deref;
+ if filetyp=ft_typed then
+ typedfiletype.resolve;
+ end;
+
+
+ procedure tfiledef.setsize;
+ begin
+{$ifdef cpu64bit}
+ case filetyp of
+ ft_text :
+ if target_info.system in [system_x86_64_win64,system_ia64_win64] then
+ savesize:=632
+ else
+ savesize:=628;
+ ft_typed,
+ ft_untyped :
+ if target_info.system in [system_x86_64_win64,system_ia64_win64] then
+ savesize:=372
+ else
+ savesize:=368;
+ end;
+{$else cpu64bit}
+ case filetyp of
+ ft_text :
+ savesize:=592;
+ ft_typed,
+ ft_untyped :
+ savesize:=332;
+ end;
+{$endif cpu64bit}
+ end;
+
+
+ procedure tfiledef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.putbyte(byte(filetyp));
+ if filetyp=ft_typed then
+ ppufile.puttype(typedfiletype);
+ ppufile.writeentry(ibfiledef);
+ end;
+
+
+ function tfiledef.gettypename : string;
+ begin
+ case filetyp of
+ ft_untyped:
+ gettypename:='File';
+ ft_typed:
+ gettypename:='File Of '+typedfiletype.def.typename;
+ ft_text:
+ gettypename:='Text'
+ end;
+ end;
+
+
+ function tfiledef.getmangledparaname : string;
+ begin
+ case filetyp of
+ ft_untyped:
+ getmangledparaname:='FILE';
+ ft_typed:
+ getmangledparaname:='FILE$OF$'+typedfiletype.def.mangledparaname;
+ ft_text:
+ getmangledparaname:='TEXT'
+ end;
+ end;
+
+
+{****************************************************************************
+ TVARIANTDEF
+****************************************************************************}
+
+ constructor tvariantdef.create(v : tvarianttype);
+ begin
+ inherited create;
+ varianttype:=v;
+ deftype:=variantdef;
+ setsize;
+ end;
+
+
+ constructor tvariantdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ varianttype:=tvarianttype(ppufile.getbyte);
+ deftype:=variantdef;
+ setsize;
+ end;
+
+
+ function tvariantdef.getcopy : tstoreddef;
+ begin
+ result:=tvariantdef.create(varianttype);
+ end;
+
+
+ procedure tvariantdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.putbyte(byte(varianttype));
+ ppufile.writeentry(ibvariantdef);
+ end;
+
+
+ procedure tvariantdef.setsize;
+ begin
+ savesize:=16;
+ end;
+
+
+ function tvariantdef.gettypename : string;
+ begin
+ case varianttype of
+ vt_normalvariant:
+ gettypename:='Variant';
+ vt_olevariant:
+ gettypename:='OleVariant';
+ end;
+ end;
+
+
+ procedure tvariantdef.write_rtti_data(rt:trttitype);
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkVariant));
+ end;
+
+
+ function tvariantdef.needs_inittable : boolean;
+ begin
+ needs_inittable:=true;
+ end;
+
+
+ function tvariantdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+
+{****************************************************************************
+ TPOINTERDEF
+****************************************************************************}
+
+ constructor tpointerdef.create(const tt : ttype);
+ begin
+ inherited create;
+ deftype:=pointerdef;
+ pointertype:=tt;
+ is_far:=false;
+ savesize:=sizeof(aint);
+ end;
+
+
+ constructor tpointerdef.createfar(const tt : ttype);
+ begin
+ inherited create;
+ deftype:=pointerdef;
+ pointertype:=tt;
+ is_far:=true;
+ savesize:=sizeof(aint);
+ end;
+
+
+ constructor tpointerdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=pointerdef;
+ ppufile.gettype(pointertype);
+ is_far:=(ppufile.getbyte<>0);
+ savesize:=sizeof(aint);
+ end;
+
+
+ function tpointerdef.getcopy : tstoreddef;
+ begin
+ result:=tpointerdef.create(pointertype);
+ tpointerdef(result).is_far:=is_far;
+ tpointerdef(result).savesize:=savesize;
+ end;
+
+
+ procedure tpointerdef.buildderef;
+ begin
+ inherited buildderef;
+ pointertype.buildderef;
+ end;
+
+
+ procedure tpointerdef.deref;
+ begin
+ inherited deref;
+ pointertype.resolve;
+ end;
+
+
+ procedure tpointerdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.puttype(pointertype);
+ ppufile.putbyte(byte(is_far));
+ ppufile.writeentry(ibpointerdef);
+ end;
+
+
+ function tpointerdef.gettypename : string;
+ begin
+ if is_far then
+ gettypename:='^'+pointertype.def.typename+';far'
+ else
+ gettypename:='^'+pointertype.def.typename;
+ end;
+
+
+{****************************************************************************
+ TCLASSREFDEF
+****************************************************************************}
+
+ constructor tclassrefdef.create(const t:ttype);
+ begin
+ inherited create(t);
+ deftype:=classrefdef;
+ end;
+
+
+ constructor tclassrefdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ { be careful, tclassdefref inherits from tpointerdef }
+ inherited ppuloaddef(ppufile);
+ deftype:=classrefdef;
+ ppufile.gettype(pointertype);
+ is_far:=false;
+ savesize:=sizeof(aint);
+ end;
+
+
+ procedure tclassrefdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ { be careful, tclassdefref inherits from tpointerdef }
+ inherited ppuwritedef(ppufile);
+ ppufile.puttype(pointertype);
+ ppufile.writeentry(ibclassrefdef);
+ end;
+
+
+ function tclassrefdef.gettypename : string;
+ begin
+ gettypename:='Class Of '+pointertype.def.typename;
+ end;
+
+
+ function tclassrefdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+
+
+{***************************************************************************
+ TSETDEF
+***************************************************************************}
+
+ constructor tsetdef.create(const t:ttype;high : aint);
+ begin
+ inherited create;
+ deftype:=setdef;
+ elementtype:=t;
+ // setbase:=low;
+ setmax:=high;
+ if high<32 then
+ begin
+ settype:=smallset;
+ {$ifdef testvarsets}
+ if aktsetalloc=0 THEN { $PACKSET Fixed?}
+ {$endif}
+ savesize:=Sizeof(longint)
+ {$ifdef testvarsets}
+ else {No, use $PACKSET VALUE for rounding}
+ savesize:=aktsetalloc*((high+aktsetalloc*8-1) DIV (aktsetalloc*8))
+ {$endif}
+ ;
+ end
+ else
+ if high<256 then
+ begin
+ settype:=normset;
+ savesize:=32;
+ end
+ else
+{$ifdef testvarsets}
+ if high<$10000 then
+ begin
+ settype:=varset;
+ savesize:=4*((high+31) div 32);
+ end
+ else
+{$endif testvarsets}
+ Message(sym_e_ill_type_decl_set);
+ end;
+
+
+ constructor tsetdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=setdef;
+ ppufile.gettype(elementtype);
+ settype:=tsettype(ppufile.getbyte);
+ case settype of
+ normset : savesize:=32;
+ varset : savesize:=ppufile.getlongint;
+ smallset : savesize:=Sizeof(longint);
+ end;
+ end;
+
+
+ destructor tsetdef.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ function tsetdef.getcopy : tstoreddef;
+ begin
+ case settype of
+ smallset:
+ result:=tsetdef.create(elementtype,31);
+ normset:
+ result:=tsetdef.create(elementtype,255);
+ else
+ internalerror(2004121202);
+ end;
+ end;
+
+
+ procedure tsetdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.puttype(elementtype);
+ ppufile.putbyte(byte(settype));
+ if settype=varset then
+ ppufile.putlongint(savesize);
+ if settype=normset then
+ ppufile.putaint(savesize);
+ ppufile.writeentry(ibsetdef);
+ end;
+
+
+ procedure tsetdef.buildderef;
+ begin
+ inherited buildderef;
+ elementtype.buildderef;
+ end;
+
+
+ procedure tsetdef.deref;
+ begin
+ inherited deref;
+ elementtype.resolve;
+ end;
+
+
+ procedure tsetdef.write_child_rtti_data(rt:trttitype);
+ begin
+ tstoreddef(elementtype.def).get_rtti_label(rt);
+ end;
+
+
+ procedure tsetdef.write_rtti_data(rt:trttitype);
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkSet));
+ write_rtti_name;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(otULong));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_sym(tstoreddef(elementtype.def).get_rtti_label(rt)));
+ end;
+
+
+ function tsetdef.is_publishable : boolean;
+ begin
+ is_publishable:=(settype=smallset);
+ end;
+
+
+ function tsetdef.gettypename : string;
+ begin
+ if assigned(elementtype.def) then
+ gettypename:='Set Of '+elementtype.def.typename
+ else
+ gettypename:='Empty Set';
+ end;
+
+
+{***************************************************************************
+ TFORMALDEF
+***************************************************************************}
+
+ constructor tformaldef.create;
+ var
+ stregdef : boolean;
+ begin
+ stregdef:=registerdef;
+ registerdef:=false;
+ inherited create;
+ deftype:=formaldef;
+ registerdef:=stregdef;
+ { formaldef must be registered at unit level !! }
+ if registerdef and assigned(current_module) then
+ if assigned(current_module.localsymtable) then
+ tsymtable(current_module.localsymtable).registerdef(self)
+ else if assigned(current_module.globalsymtable) then
+ tsymtable(current_module.globalsymtable).registerdef(self);
+ savesize:=0;
+ end;
+
+
+ constructor tformaldef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=formaldef;
+ savesize:=0;
+ end;
+
+
+ procedure tformaldef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.writeentry(ibformaldef);
+ end;
+
+
+ function tformaldef.gettypename : string;
+ begin
+ gettypename:='<Formal type>';
+ end;
+
+
+{***************************************************************************
+ TARRAYDEF
+***************************************************************************}
+
+ constructor tarraydef.create(l,h : aint;const t : ttype);
+ begin
+ inherited create;
+ deftype:=arraydef;
+ lowrange:=l;
+ highrange:=h;
+ rangetype:=t;
+ elementtype.reset;
+ IsVariant:=false;
+ IsConstructor:=false;
+ IsArrayOfConst:=false;
+ IsDynamicArray:=false;
+ IsConvertedPointer:=false;
+ end;
+
+
+ constructor tarraydef.create_from_pointer(const elemt : ttype);
+ begin
+ self.create(0,$7fffffff,s32inttype);
+ IsConvertedPointer:=true;
+ setelementtype(elemt);
+ end;
+
+
+ constructor tarraydef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=arraydef;
+ { the addresses are calculated later }
+ ppufile.gettype(_elementtype);
+ ppufile.gettype(rangetype);
+ lowrange:=ppufile.getaint;
+ highrange:=ppufile.getaint;
+ IsArrayOfConst:=boolean(ppufile.getbyte);
+ IsDynamicArray:=boolean(ppufile.getbyte);
+ IsVariant:=false;
+ IsConstructor:=false;
+ end;
+
+
+ function tarraydef.getcopy : tstoreddef;
+ begin
+ result:=tarraydef.create(lowrange,highrange,rangetype);
+ tarraydef(result).IsConvertedPointer:=IsConvertedPointer;
+ tarraydef(result).IsDynamicArray:=IsDynamicArray;
+ tarraydef(result).IsVariant:=IsVariant;
+ tarraydef(result).IsConstructor:=IsConstructor;
+ tarraydef(result).IsArrayOfConst:=IsArrayOfConst;
+ tarraydef(result)._elementtype:=_elementtype;
+ end;
+
+
+ procedure tarraydef.buildderef;
+ begin
+ inherited buildderef;
+ _elementtype.buildderef;
+ rangetype.buildderef;
+ end;
+
+
+ procedure tarraydef.deref;
+ begin
+ inherited deref;
+ _elementtype.resolve;
+ rangetype.resolve;
+ end;
+
+
+ procedure tarraydef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.puttype(_elementtype);
+ ppufile.puttype(rangetype);
+ ppufile.putaint(lowrange);
+ ppufile.putaint(highrange);
+ ppufile.putbyte(byte(IsArrayOfConst));
+ ppufile.putbyte(byte(IsDynamicArray));
+ ppufile.writeentry(ibarraydef);
+ end;
+
+
+ function tarraydef.elesize : aint;
+ begin
+ elesize:=_elementtype.def.size;
+ end;
+
+
+ function tarraydef.elecount : aint;
+ var
+ qhigh,qlow : qword;
+ begin
+ if IsDynamicArray then
+ begin
+ result:=0;
+ exit;
+ end;
+ if (highrange>0) and (lowrange<0) then
+ begin
+ qhigh:=highrange;
+ qlow:=qword(-lowrange);
+ { prevent overflow, return -1 to indicate overflow }
+ if qhigh+qlow>qword(high(aint)-1) then
+ result:=-1
+ else
+ result:=qhigh+qlow+1;
+ end
+ else
+ result:=int64(highrange)-lowrange+1;
+ end;
+
+
+ function tarraydef.size : aint;
+ var
+ cachedelecount,
+ cachedelesize : aint;
+ begin
+ if IsDynamicArray then
+ begin
+ size:=sizeof(aint);
+ exit;
+ end;
+ { Tarraydef.size may never be called for an open array! }
+ if highrange<lowrange then
+ internalerror(99080501);
+ cachedelesize:=elesize;
+ cachedelecount:=elecount;
+ { prevent overflow, return -1 to indicate overflow }
+ if (cachedelesize <> 0) and
+ (
+ (cachedelecount < 0) or
+ ((high(aint) div cachedelesize) < cachedelecount) or
+ { also lowrange*elesize must be < high(aint) to prevent overflow when
+ accessing the array, see ncgmem (PFV) }
+ ((high(aint) div cachedelesize) < abs(lowrange))
+ ) then
+ result:=-1
+ else
+ result:=cachedelesize*cachedelecount;
+ end;
+
+
+ procedure tarraydef.setelementtype(t: ttype);
+ begin
+ _elementtype:=t;
+ if not(IsDynamicArray or
+ IsConvertedPointer or
+ (highrange<lowrange)) then
+ begin
+ if (size=-1) then
+ Message(sym_e_segment_too_large);
+ end;
+ end;
+
+
+ function tarraydef.alignment : longint;
+ begin
+ { alignment is the size of the elements }
+ if (elementtype.def.deftype in [arraydef,recorddef]) or
+ ((elementtype.def.deftype=objectdef) and
+ is_object(elementtype.def)) then
+ alignment:=elementtype.def.alignment
+ else
+ alignment:=elesize;
+ end;
+
+
+ function tarraydef.needs_inittable : boolean;
+ begin
+ needs_inittable:=IsDynamicArray or elementtype.def.needs_inittable;
+ end;
+
+
+ procedure tarraydef.write_child_rtti_data(rt:trttitype);
+ begin
+ tstoreddef(elementtype.def).get_rtti_label(rt);
+ end;
+
+
+ procedure tarraydef.write_rtti_data(rt:trttitype);
+ begin
+ if IsDynamicArray then
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkdynarray))
+ else
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkarray));
+ write_rtti_name;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ { size of elements }
+ asmlist[al_rtti].concat(Tai_const.Create_aint(elesize));
+ if not(IsDynamicArray) then
+ asmlist[al_rtti].concat(Tai_const.Create_aint(elecount));
+ { element type }
+ asmlist[al_rtti].concat(Tai_const.Create_sym(tstoreddef(elementtype.def).get_rtti_label(rt)));
+ { variant type }
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(tstoreddef(elementtype.def).getvartype));
+ end;
+
+
+ function tarraydef.gettypename : string;
+ begin
+ if isarrayofconst or isConstructor then
+ begin
+ if isvariant or ((highrange=-1) and (lowrange=0)) then
+ gettypename:='Array Of Const'
+ else
+ gettypename:='Array Of '+elementtype.def.typename;
+ end
+ else if ((highrange=-1) and (lowrange=0)) or IsDynamicArray then
+ gettypename:='Array Of '+elementtype.def.typename
+ else
+ begin
+ if rangetype.def.deftype=enumdef then
+ gettypename:='Array['+rangetype.def.typename+'] Of '+elementtype.def.typename
+ else
+ gettypename:='Array['+tostr(lowrange)+'..'+
+ tostr(highrange)+'] Of '+elementtype.def.typename
+ end;
+ end;
+
+
+ function tarraydef.getmangledparaname : string;
+ begin
+ if isarrayofconst then
+ getmangledparaname:='array_of_const'
+ else
+ if ((highrange=-1) and (lowrange=0)) then
+ getmangledparaname:='array_of_'+elementtype.def.mangledparaname
+ else
+ internalerror(200204176);
+ end;
+
+
+{***************************************************************************
+ tabstractrecorddef
+***************************************************************************}
+
+ function tabstractrecorddef.getsymtable(t:tgetsymtable):tsymtable;
+ begin
+ if t=gs_record then
+ getsymtable:=symtable
+ else
+ getsymtable:=nil;
+ end;
+
+
+ procedure tabstractrecorddef.reset;
+ begin
+ tstoredsymtable(symtable).reset_all_defs;
+ end;
+
+
+ procedure tabstractrecorddef.count_field_rtti(sym : tnamedindexitem;arg:pointer);
+ begin
+ if (FRTTIType=fullrtti) or
+ ((tsym(sym).typ=fieldvarsym) and
+ tfieldvarsym(sym).vartype.def.needs_inittable) then
+ inc(Count);
+ end;
+
+
+ procedure tabstractrecorddef.generate_field_rtti(sym:tnamedindexitem;arg:pointer);
+ begin
+ if (FRTTIType=fullrtti) or
+ ((tsym(sym).typ=fieldvarsym) and
+ tfieldvarsym(sym).vartype.def.needs_inittable) then
+ tstoreddef(tfieldvarsym(sym).vartype.def).get_rtti_label(FRTTIType);
+ end;
+
+
+ procedure tabstractrecorddef.write_field_rtti(sym : tnamedindexitem;arg:pointer);
+ begin
+ if (FRTTIType=fullrtti) or
+ ((tsym(sym).typ=fieldvarsym) and
+ tfieldvarsym(sym).vartype.def.needs_inittable) then
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_sym(tstoreddef(tfieldvarsym(sym).vartype.def).get_rtti_label(FRTTIType)));
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(tfieldvarsym(sym).fieldoffset));
+ end;
+ end;
+
+
+
+{***************************************************************************
+ trecorddef
+***************************************************************************}
+
+ constructor trecorddef.create(p : tsymtable);
+ begin
+ inherited create;
+ deftype:=recorddef;
+ symtable:=p;
+ symtable.defowner:=self;
+ isunion:=false;
+ end;
+
+
+ constructor trecorddef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=recorddef;
+ symtable:=trecordsymtable.create(0);
+ trecordsymtable(symtable).datasize:=ppufile.getaint;
+ trecordsymtable(symtable).fieldalignment:=shortint(ppufile.getbyte);
+ trecordsymtable(symtable).recordalignment:=shortint(ppufile.getbyte);
+ trecordsymtable(symtable).padalignment:=shortint(ppufile.getbyte);
+ trecordsymtable(symtable).ppuload(ppufile);
+ symtable.defowner:=self;
+ isunion:=false;
+ end;
+
+
+ destructor trecorddef.destroy;
+ begin
+ if assigned(symtable) then
+ symtable.free;
+ inherited destroy;
+ end;
+
+
+ function trecorddef.getcopy : tstoreddef;
+ begin
+ result:=trecorddef.create(symtable.getcopy);
+ trecorddef(result).isunion:=isunion;
+ end;
+
+
+ function trecorddef.needs_inittable : boolean;
+ begin
+ needs_inittable:=trecordsymtable(symtable).needs_init_final
+ end;
+
+
+ procedure trecorddef.buildderef;
+ var
+ oldrecsyms : tsymtable;
+ begin
+ inherited buildderef;
+ oldrecsyms:=aktrecordsymtable;
+ aktrecordsymtable:=symtable;
+ { now build the definitions }
+ tstoredsymtable(symtable).buildderef;
+ aktrecordsymtable:=oldrecsyms;
+ end;
+
+
+ procedure trecorddef.deref;
+ var
+ oldrecsyms : tsymtable;
+ begin
+ inherited deref;
+ oldrecsyms:=aktrecordsymtable;
+ aktrecordsymtable:=symtable;
+ { now dereference the definitions }
+ tstoredsymtable(symtable).deref;
+ aktrecordsymtable:=oldrecsyms;
+ { assign TGUID? load only from system unit }
+ if not(assigned(rec_tguid)) and
+ (upper(typename)='TGUID') and
+ assigned(owner) and
+ assigned(owner.name) and
+ (owner.name^='SYSTEM') then
+ rec_tguid:=self;
+ end;
+
+
+ procedure trecorddef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.putaint(trecordsymtable(symtable).datasize);
+ ppufile.putbyte(byte(trecordsymtable(symtable).fieldalignment));
+ ppufile.putbyte(byte(trecordsymtable(symtable).recordalignment));
+ ppufile.putbyte(byte(trecordsymtable(symtable).padalignment));
+ ppufile.writeentry(ibrecorddef);
+ trecordsymtable(symtable).ppuwrite(ppufile);
+ end;
+
+
+ function trecorddef.size:aint;
+ begin
+ result:=trecordsymtable(symtable).datasize;
+ end;
+
+
+ function trecorddef.alignment:longint;
+ begin
+ alignment:=trecordsymtable(symtable).recordalignment;
+ end;
+
+
+ function trecorddef.padalignment:longint;
+ begin
+ padalignment := trecordsymtable(symtable).padalignment;
+ end;
+
+
+ procedure trecorddef.write_child_rtti_data(rt:trttitype);
+ begin
+ FRTTIType:=rt;
+ symtable.foreach(@generate_field_rtti,nil);
+ end;
+
+
+ procedure trecorddef.write_rtti_data(rt:trttitype);
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkrecord));
+ write_rtti_name;
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(size));
+ Count:=0;
+ FRTTIType:=rt;
+ symtable.foreach(@count_field_rtti,nil);
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(Count));
+ symtable.foreach(@write_field_rtti,nil);
+ end;
+
+
+ function trecorddef.gettypename : string;
+ begin
+ gettypename:='<record type>'
+ end;
+
+
+{***************************************************************************
+ TABSTRACTPROCDEF
+***************************************************************************}
+
+ constructor tabstractprocdef.create(level:byte);
+ begin
+ inherited create;
+ parast:=tparasymtable.create(level);
+ parast.defowner:=self;
+ parast.next:=owner;
+ paras:=nil;
+ minparacount:=0;
+ maxparacount:=0;
+ proctypeoption:=potype_none;
+ proccalloption:=pocall_none;
+ procoptions:=[];
+ rettype:=voidtype;
+{$ifdef i386}
+ fpu_used:=0;
+{$endif i386}
+ savesize:=sizeof(aint);
+ requiredargarea:=0;
+ has_paraloc_info:=false;
+
+ location_reset(funcretloc[callerside],LOC_INVALID,OS_NO);
+ location_reset(funcretloc[calleeside],LOC_INVALID,OS_NO);
+ end;
+
+
+ destructor tabstractprocdef.destroy;
+ begin
+ if assigned(paras) then
+ begin
+{$ifdef MEMDEBUG}
+ memprocpara.start;
+{$endif MEMDEBUG}
+ paras.free;
+{$ifdef MEMDEBUG}
+ memprocpara.stop;
+{$endif MEMDEBUG}
+ end;
+ if assigned(parast) then
+ begin
+{$ifdef MEMDEBUG}
+ memprocparast.start;
+{$endif MEMDEBUG}
+ parast.free;
+{$ifdef MEMDEBUG}
+ memprocparast.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tabstractprocdef.releasemem;
+ begin
+ if assigned(paras) then
+ begin
+ paras.free;
+ paras:=nil;
+ end;
+ parast.free;
+ parast:=nil;
+ end;
+
+
+ procedure tabstractprocdef.count_para(p:tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ inc(plongint(arg)^);
+ if not(vo_is_hidden_para in tparavarsym(p).varoptions) then
+ begin
+ if not assigned(tparavarsym(p).defaultconstsym) then
+ inc(minparacount);
+ inc(maxparacount);
+ end;
+ end;
+
+
+ procedure tabstractprocdef.insert_para(p:tnamedindexitem;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ paras.add(p);
+ end;
+
+
+ procedure tabstractprocdef.calcparas;
+ var
+ paracount : longint;
+ begin
+ { This can already be assigned when
+ we need to reresolve this unit (PFV) }
+ if assigned(paras) then
+ paras.free;
+ paras:=tparalist.create;
+ paracount:=0;
+ minparacount:=0;
+ maxparacount:=0;
+ parast.foreach(@count_para,@paracount);
+ paras.capacity:=paracount;
+ { Insert parameters in table }
+ parast.foreach(@insert_para,nil);
+ { Order parameters }
+ paras.sortparas;
+ end;
+
+
+ { all functions returning in FPU are
+ assume to use 2 FPU registers
+ until the function implementation
+ is processed PM }
+ procedure tabstractprocdef.test_if_fpu_result;
+ begin
+{$ifdef i386}
+ if assigned(rettype.def) and
+ (rettype.def.deftype=floatdef) then
+ fpu_used:=maxfpuregs;
+{$endif i386}
+ end;
+
+
+ procedure tabstractprocdef.buildderef;
+ begin
+ { released procdef? }
+ if not assigned(parast) then
+ exit;
+ inherited buildderef;
+ rettype.buildderef;
+ { parast }
+ tparasymtable(parast).buildderef;
+ end;
+
+
+ procedure tabstractprocdef.deref;
+ begin
+ inherited deref;
+ rettype.resolve;
+ { parast }
+ tparasymtable(parast).deref;
+ { recalculated parameters }
+ calcparas;
+ end;
+
+
+ constructor tabstractprocdef.ppuload(ppufile:tcompilerppufile);
+ var
+ b : byte;
+ begin
+ inherited ppuloaddef(ppufile);
+ parast:=nil;
+ Paras:=nil;
+ minparacount:=0;
+ maxparacount:=0;
+ ppufile.gettype(rettype);
+{$ifdef i386}
+ fpu_used:=ppufile.getbyte;
+{$else}
+ ppufile.getbyte;
+{$endif i386}
+ proctypeoption:=tproctypeoption(ppufile.getbyte);
+ proccalloption:=tproccalloption(ppufile.getbyte);
+ ppufile.getnormalset(procoptions);
+
+ location_reset(funcretloc[callerside],LOC_INVALID,OS_NO);
+ location_reset(funcretloc[calleeside],LOC_INVALID,OS_NO);
+ if po_explicitparaloc in procoptions then
+ begin
+ b:=ppufile.getbyte;
+ if b<>sizeof(funcretloc[callerside]) then
+ internalerror(200411154);
+ ppufile.getdata(funcretloc[callerside],sizeof(funcretloc[callerside]));
+ end;
+
+ savesize:=sizeof(aint);
+ has_paraloc_info:=(po_explicitparaloc in procoptions);
+ end;
+
+
+ procedure tabstractprocdef.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ { released procdef? }
+ if not assigned(parast) then
+ exit;
+ inherited ppuwritedef(ppufile);
+ ppufile.puttype(rettype);
+ oldintfcrc:=ppufile.do_interface_crc;
+ ppufile.do_interface_crc:=false;
+{$ifdef i386}
+ if simplify_ppu then
+ fpu_used:=0;
+ ppufile.putbyte(fpu_used);
+{$else}
+ ppufile.putbyte(0);
+{$endif}
+ ppufile.putbyte(ord(proctypeoption));
+ ppufile.putbyte(ord(proccalloption));
+ ppufile.putnormalset(procoptions);
+ ppufile.do_interface_crc:=oldintfcrc;
+
+ if (po_explicitparaloc in procoptions) then
+ begin
+ { Make a 'valid' funcretloc for procedures }
+ ppufile.putbyte(sizeof(funcretloc[callerside]));
+ ppufile.putdata(funcretloc[callerside],sizeof(funcretloc[callerside]));
+ end;
+ end;
+
+
+ function tabstractprocdef.typename_paras(showhidden:boolean) : string;
+ var
+ hs,s : string;
+ hp : TParavarsym;
+ hpc : tconstsym;
+ first : boolean;
+ i : integer;
+ begin
+ s:='';
+ first:=true;
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) or
+ (showhidden) then
+ begin
+ if first then
+ begin
+ s:=s+'(';
+ first:=false;
+ end
+ else
+ s:=s+',';
+ case hp.varspez of
+ vs_var :
+ s:=s+'var';
+ vs_const :
+ s:=s+'const';
+ vs_out :
+ s:=s+'out';
+ end;
+ if assigned(hp.vartype.def.typesym) then
+ begin
+ if s<>'(' then
+ s:=s+' ';
+ hs:=hp.vartype.def.typesym.realname;
+ if hs[1]<>'$' then
+ s:=s+hp.vartype.def.typesym.realname
+ else
+ s:=s+hp.vartype.def.gettypename;
+ end
+ else
+ s:=s+hp.vartype.def.gettypename;
+ { default value }
+ if assigned(hp.defaultconstsym) then
+ begin
+ hpc:=tconstsym(hp.defaultconstsym);
+ hs:='';
+ case hpc.consttyp of
+ conststring,
+ constresourcestring :
+ hs:=strpas(pchar(hpc.value.valueptr));
+ constreal :
+ str(pbestreal(hpc.value.valueptr)^,hs);
+ constpointer :
+ hs:=tostr(hpc.value.valueordptr);
+ constord :
+ begin
+ if is_boolean(hpc.consttype.def) then
+ begin
+ if hpc.value.valueord<>0 then
+ hs:='TRUE'
+ else
+ hs:='FALSE';
+ end
+ else
+ hs:=tostr(hpc.value.valueord);
+ end;
+ constnil :
+ hs:='nil';
+ constset :
+ hs:='<set>';
+ end;
+ if hs<>'' then
+ s:=s+'="'+hs+'"';
+ end;
+ end;
+ end;
+ if not first then
+ s:=s+')';
+ if (po_varargs in procoptions) then
+ s:=s+';VarArgs';
+ typename_paras:=s;
+ end;
+
+
+ function tabstractprocdef.is_methodpointer:boolean;
+ begin
+ result:=false;
+ end;
+
+
+ function tabstractprocdef.is_addressonly:boolean;
+ begin
+ result:=true;
+ end;
+
+
+{***************************************************************************
+ TPROCDEF
+***************************************************************************}
+
+ constructor tprocdef.create(level:byte);
+ begin
+ inherited create(level);
+ deftype:=procdef;
+ _mangledname:=nil;
+ fileinfo:=aktfilepos;
+ extnumber:=$ffff;
+ aliasnames:=tstringlist.create;
+ funcretsym:=nil;
+ localst := nil;
+ defref:=nil;
+ lastwritten:=nil;
+ refcount:=0;
+ if (cs_browser in aktmoduleswitches) and make_ref then
+ begin
+ defref:=tref.create(defref,@akttokenpos);
+ inc(refcount);
+ end;
+ lastref:=defref;
+ forwarddef:=true;
+ interfacedef:=false;
+ hasforward:=false;
+ _class := nil;
+ import_dll:=nil;
+ import_name:=nil;
+ import_nr:=0;
+ inlininginfo:=nil;
+ end;
+
+
+ constructor tprocdef.ppuload(ppufile:tcompilerppufile);
+ var
+ level : byte;
+ begin
+ inherited ppuload(ppufile);
+ deftype:=procdef;
+
+ if po_has_mangledname in procoptions then
+ _mangledname:=stringdup(ppufile.getstring)
+ else
+ _mangledname:=nil;
+ extnumber:=ppufile.getword;
+ level:=ppufile.getbyte;
+ ppufile.getderef(_classderef);
+ ppufile.getderef(procsymderef);
+ ppufile.getposinfo(fileinfo);
+ ppufile.getsmallset(symoptions);
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ ppufile.getderef(libsymderef);
+{$endif powerpc}
+ { import stuff }
+ import_dll:=nil;
+ import_name:=nil;
+ import_nr:=0;
+ { inline stuff }
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ ppufile.getderef(funcretsymderef);
+ new(inlininginfo);
+ ppufile.getsmallset(inlininginfo^.flags);
+ end
+ else
+ begin
+ inlininginfo:=nil;
+ funcretsym:=nil;
+ end;
+ { load para symtable }
+ parast:=tparasymtable.create(level);
+ tparasymtable(parast).ppuload(ppufile);
+ parast.defowner:=self;
+ { load local symtable }
+ if (po_has_inlininginfo in procoptions) or
+ ((current_module.flags and uf_local_browser)<>0) then
+ begin
+ localst:=tlocalsymtable.create(level);
+ tlocalsymtable(localst).ppuload(ppufile);
+ localst.defowner:=self;
+ end
+ else
+ localst:=nil;
+ { inline stuff }
+ if (po_has_inlininginfo in procoptions) then
+ inlininginfo^.code:=ppuloadnodetree(ppufile);
+ { default values for no persistent data }
+ if (cs_link_deffile in aktglobalswitches) and
+ (tf_need_export in target_info.flags) and
+ (po_exports in procoptions) then
+ deffile.AddExport(mangledname);
+ aliasnames:=tstringlist.create;
+ forwarddef:=false;
+ interfacedef:=false;
+ hasforward:=false;
+ lastref:=nil;
+ lastwritten:=nil;
+ defref:=nil;
+ refcount:=0;
+ { Disable po_has_inlining until the derefimpl is done }
+ exclude(procoptions,po_has_inlininginfo);
+ end;
+
+
+ destructor tprocdef.destroy;
+ begin
+ if assigned(defref) then
+ begin
+ defref.freechain;
+ defref.free;
+ end;
+ aliasnames.free;
+ if assigned(localst) and (localst.symtabletype<>staticsymtable) then
+ begin
+{$ifdef MEMDEBUG}
+ memproclocalst.start;
+{$endif MEMDEBUG}
+ localst.free;
+{$ifdef MEMDEBUG}
+ memproclocalst.start;
+{$endif MEMDEBUG}
+ end;
+ if assigned(inlininginfo) then
+ begin
+{$ifdef MEMDEBUG}
+ memprocnodetree.start;
+{$endif MEMDEBUG}
+ tnode(inlininginfo^.code).free;
+{$ifdef MEMDEBUG}
+ memprocnodetree.start;
+{$endif MEMDEBUG}
+ dispose(inlininginfo);
+ end;
+ stringdispose(import_dll);
+ stringdispose(import_name);
+ if (po_msgstr in procoptions) then
+ strdispose(messageinf.str);
+ if assigned(_mangledname) then
+ begin
+{$ifdef MEMDEBUG}
+ memmanglednames.start;
+{$endif MEMDEBUG}
+ stringdispose(_mangledname);
+{$ifdef MEMDEBUG}
+ memmanglednames.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tprocdef.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ { released procdef? }
+ if not assigned(parast) then
+ exit;
+
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=localst;
+
+ inherited ppuwrite(ppufile);
+ oldintfcrc:=ppufile.do_interface_crc;
+ ppufile.do_interface_crc:=false;
+ ppufile.do_interface_crc:=oldintfcrc;
+ if po_has_mangledname in procoptions then
+ ppufile.putstring(_mangledname^);
+ ppufile.putword(extnumber);
+ ppufile.putbyte(parast.symtablelevel);
+ ppufile.putderef(_classderef);
+ ppufile.putderef(procsymderef);
+ ppufile.putposinfo(fileinfo);
+ ppufile.putsmallset(symoptions);
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ ppufile.putderef(libsymderef);
+{$endif powerpc}
+ { inline stuff }
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ ppufile.putderef(funcretsymderef);
+ ppufile.putsmallset(inlininginfo^.flags);
+ end;
+ ppufile.do_crc:=oldintfcrc;
+
+ { write this entry }
+ ppufile.writeentry(ibprocdef);
+
+ { Save the para symtable, this is taken from the interface }
+ tparasymtable(parast).ppuwrite(ppufile);
+
+ { save localsymtable for inline procedures or when local
+ browser info is requested, this has no influence on the crc }
+ if (po_has_inlininginfo in procoptions) or
+ ((current_module.flags and uf_local_browser)<>0) then
+ begin
+ { we must write a localsymtable }
+ if not assigned(localst) then
+ insert_localst;
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ tlocalsymtable(localst).ppuwrite(ppufile);
+ ppufile.do_crc:=oldintfcrc;
+ end;
+
+ { node tree for inlining }
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ if (po_has_inlininginfo in procoptions) then
+ ppuwritenodetree(ppufile,inlininginfo^.code);
+ ppufile.do_crc:=oldintfcrc;
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ procedure tprocdef.reset;
+ begin
+ inherited reset;
+ procstarttai:=nil;
+ procendtai:=nil;
+ end;
+
+
+ procedure tprocdef.insert_localst;
+ begin
+ localst:=tlocalsymtable.create(parast.symtablelevel);
+ localst.defowner:=self;
+ { this is used by insert
+ to check same names in parast and localst }
+ localst.next:=parast;
+ end;
+
+
+ function tprocdef.fullprocname(showhidden:boolean):string;
+ var
+ s : string;
+ t : ttoken;
+ begin
+{$ifdef EXTDEBUG}
+ showhidden:=true;
+{$endif EXTDEBUG}
+ s:='';
+ if owner.symtabletype=localsymtable then
+ s:=s+'local ';
+ if assigned(_class) then
+ begin
+ if po_classmethod in procoptions then
+ s:=s+'class ';
+ s:=s+_class.objrealname^+'.';
+ end;
+ if proctypeoption=potype_operator then
+ begin
+ for t:=NOTOKEN to last_overloaded do
+ if procsym.realname='$'+overloaded_names[t] then
+ begin
+ s:='operator '+arraytokeninfo[t].str+typename_paras(showhidden);
+ break;
+ end;
+ end
+ else
+ s:=s+procsym.realname+typename_paras(showhidden);
+ case proctypeoption of
+ potype_constructor:
+ s:='constructor '+s;
+ potype_destructor:
+ s:='destructor '+s;
+ else
+ if assigned(rettype.def) and
+ not(is_void(rettype.def)) then
+ s:=s+':'+rettype.def.gettypename;
+ end;
+ { forced calling convention? }
+ if (po_hascallingconvention in procoptions) then
+ s:=s+';'+ProcCallOptionStr[proccalloption];
+ fullprocname:=s;
+ end;
+
+
+ function tprocdef.is_methodpointer:boolean;
+ begin
+ result:=assigned(_class);
+ end;
+
+
+ function tprocdef.is_addressonly:boolean;
+ begin
+ result:=assigned(owner) and
+ (owner.symtabletype<>objectsymtable);
+ end;
+
+
+ function tprocdef.is_visible_for_object(currobjdef:tobjectdef):boolean;
+ begin
+ is_visible_for_object:=false;
+
+ { private symbols are allowed when we are in the same
+ module as they are defined }
+ if (sp_private in symoptions) and
+ (owner.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ not(owner.defowner.owner.iscurrentunit) then
+ exit;
+
+ if (sp_strictprivate in symoptions) then
+ begin
+ result:=currobjdef=tobjectdef(owner.defowner);
+ exit;
+ end;
+
+ if (sp_strictprotected in symoptions) then
+ begin
+ result:=assigned(currobjdef) and
+ currobjdef.is_related(tobjectdef(owner.defowner));
+ exit;
+ end;
+
+ { protected symbols are visible in the module that defines them and
+ also visible to related objects. The related object must be defined
+ in the current module }
+ if (sp_protected in symoptions) and
+ (
+ (
+ (owner.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ not(owner.defowner.owner.iscurrentunit)
+ ) and
+ not(
+ assigned(currobjdef) and
+ (currobjdef.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ (currobjdef.owner.iscurrentunit) and
+ currobjdef.is_related(tobjectdef(owner.defowner))
+ )
+ ) then
+ exit;
+
+ is_visible_for_object:=true;
+ end;
+
+
+ function tprocdef.getsymtable(t:tgetsymtable):tsymtable;
+ begin
+ case t of
+ gs_local :
+ getsymtable:=localst;
+ gs_para :
+ getsymtable:=parast;
+ else
+ getsymtable:=nil;
+ end;
+ end;
+
+
+ procedure tprocdef.load_references(ppufile:tcompilerppufile;locals:boolean);
+ var
+ pos : tfileposinfo;
+ move_last : boolean;
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=localst;
+
+ move_last:=lastwritten=lastref;
+ while (not ppufile.endofentry) do
+ begin
+ ppufile.getposinfo(pos);
+ inc(refcount);
+ lastref:=tref.create(lastref,@pos);
+ lastref.is_written:=true;
+ if refcount=1 then
+ defref:=lastref;
+ end;
+ if move_last then
+ lastwritten:=lastref;
+ if ((current_module.flags and uf_local_browser)<>0) and
+ assigned(localst) and
+ locals then
+ begin
+ tparasymtable(parast).load_references(ppufile,locals);
+ tlocalsymtable(localst).load_references(ppufile,locals);
+ end;
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ Const
+ local_symtable_index : word = $8001;
+
+ function tprocdef.write_references(ppufile:tcompilerppufile;locals:boolean):boolean;
+ var
+ ref : tref;
+{$ifdef supportbrowser}
+ pdo : tobjectdef;
+{$endif supportbrowser}
+ move_last : boolean;
+ d : tderef;
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ d.reset;
+ move_last:=lastwritten=lastref;
+ if move_last and
+ (((current_module.flags and uf_local_browser)=0) or
+ not locals) then
+ exit;
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=localst;
+ { write address of this symbol }
+ d.build(self);
+ ppufile.putderef(d);
+ { write refs }
+ if assigned(lastwritten) then
+ ref:=lastwritten
+ else
+ ref:=defref;
+ while assigned(ref) do
+ begin
+ if ref.moduleindex=current_module.unit_index then
+ begin
+ ppufile.putposinfo(ref.posinfo);
+ ref.is_written:=true;
+ if move_last then
+ lastwritten:=ref;
+ end
+ else if not ref.is_written then
+ move_last:=false
+ else if move_last then
+ lastwritten:=ref;
+ ref:=ref.nextref;
+ end;
+ ppufile.writeentry(ibdefref);
+ write_references:=true;
+{$ifdef supportbrowser}
+ if ((current_module.flags and uf_local_browser)<>0) and
+ assigned(localst) and
+ locals then
+ begin
+ pdo:=_class;
+ if (owner.symtabletype<>localsymtable) then
+ while assigned(pdo) do
+ begin
+ if pdo.symtable<>aktrecordsymtable then
+ begin
+ pdo.symtable.moduleid:=local_symtable_index;
+ inc(local_symtable_index);
+ end;
+ pdo:=pdo.childof;
+ end;
+ parast.moduleid:=local_symtable_index;
+ inc(local_symtable_index);
+ localst.moduleid:=local_symtable_index;
+ inc(local_symtable_index);
+ tstoredsymtable(parast).write_references(ppufile,locals);
+ tstoredsymtable(localst).write_references(ppufile,locals);
+ { decrement for }
+ local_symtable_index:=local_symtable_index-2;
+ pdo:=_class;
+ if (owner.symtabletype<>localsymtable) then
+ while assigned(pdo) do
+ begin
+ if pdo.symtable<>aktrecordsymtable then
+ dec(local_symtable_index);
+ pdo:=pdo.childof;
+ end;
+ end;
+{$endif supportbrowser}
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ procedure tprocdef.buildderef;
+ var
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=localst;
+
+ inherited buildderef;
+ _classderef.build(_class);
+ { procsym that originaly defined this definition, should be in the
+ same symtable }
+ procsymderef.build(procsym);
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ libsymderef.build(libsym);
+{$endif powerpc}
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ procedure tprocdef.buildderefimpl;
+ var
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ { released procdef? }
+ if not assigned(parast) then
+ exit;
+
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=localst;
+
+ inherited buildderefimpl;
+
+ { Locals }
+ if assigned(localst) and
+ ((po_has_inlininginfo in procoptions) or
+ ((current_module.flags and uf_local_browser)<>0)) then
+ begin
+ tlocalsymtable(localst).buildderef;
+ tlocalsymtable(localst).buildderefimpl;
+ end;
+
+ { inline tree }
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ funcretsymderef.build(funcretsym);
+ inlininginfo^.code.buildderefimpl;
+ end;
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ procedure tprocdef.deref;
+ var
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ { released procdef? }
+ if not assigned(parast) then
+ exit;
+
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=localst;
+
+ inherited deref;
+ _class:=tobjectdef(_classderef.resolve);
+ { procsym that originaly defined this definition, should be in the
+ same symtable }
+ procsym:=tprocsym(procsymderef.resolve);
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ libsym:=tsym(libsymderef.resolve);
+{$endif powerpc}
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ procedure tprocdef.derefimpl;
+ var
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=localst;
+
+ { Enable has_inlininginfo when the inlininginfo
+ structure is available. The has_inlininginfo was disabled
+ after the load, since the data was invalid }
+ if assigned(inlininginfo) then
+ include(procoptions,po_has_inlininginfo);
+
+ { Locals }
+ if assigned(localst) then
+ begin
+ tlocalsymtable(localst).deref;
+ tlocalsymtable(localst).derefimpl;
+ end;
+
+ { Inline }
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ inlininginfo^.code.derefimpl;
+ { funcretsym, this is always located in the localst }
+ funcretsym:=tsym(funcretsymderef.resolve);
+ end
+ else
+ begin
+ { safety }
+ funcretsym:=nil;
+ end;
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ function tprocdef.gettypename : string;
+ begin
+ gettypename := FullProcName(false);
+ end;
+
+
+ function tprocdef.mangledname : string;
+ var
+ hp : TParavarsym;
+ hs : string;
+ crc : dword;
+ newlen,
+ oldlen,
+ i : integer;
+ begin
+ if assigned(_mangledname) then
+ begin
+ {$ifdef compress}
+ mangledname:=minilzw_decode(_mangledname^);
+ {$else}
+ mangledname:=_mangledname^;
+ {$endif}
+ exit;
+ end;
+ { we need to use the symtable where the procsym is inserted,
+ because that is visible to the world }
+ mangledname:=make_mangledname('',procsym.owner,procsym.name);
+ oldlen:=length(mangledname);
+ { add parameter types }
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) then
+ mangledname:=mangledname+'$'+hp.vartype.def.mangledparaname;
+ end;
+ { add resulttype, add $$ as separator to make it unique from a
+ parameter separator }
+ if not is_void(rettype.def) then
+ mangledname:=mangledname+'$$'+rettype.def.mangledparaname;
+ newlen:=length(mangledname);
+ { Replace with CRC if the parameter line is very long }
+ if (newlen-oldlen>12) and
+ ((newlen>128) or (newlen-oldlen>64)) then
+ begin
+ crc:=$ffffffff;
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) then
+ begin
+ hs:=hp.vartype.def.mangledparaname;
+ crc:=UpdateCrc32(crc,hs[1],length(hs));
+ end;
+ end;
+ hs:=hp.vartype.def.mangledparaname;
+ crc:=UpdateCrc32(crc,hs[1],length(hs));
+ mangledname:=Copy(mangledname,1,oldlen)+'$crc'+hexstr(crc,8);
+ end;
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(mangledname));
+ {$else}
+ _mangledname:=stringdup(mangledname);
+ {$endif}
+ end;
+
+
+ function tprocdef.cplusplusmangledname : string;
+
+ function getcppparaname(p : tdef) : string;
+
+ const
+ ordtype2str : array[tbasetype] of string[2] = (
+ '',
+ 'Uc','Us','Ui','Us',
+ 'Sc','s','i','x',
+ 'b','b','b',
+ 'c','w','x');
+
+ var
+ s : string;
+
+ begin
+ case p.deftype of
+ orddef:
+ s:=ordtype2str[torddef(p).typ];
+ pointerdef:
+ s:='P'+getcppparaname(tpointerdef(p).pointertype.def);
+ else
+ internalerror(2103001);
+ end;
+ getcppparaname:=s;
+ end;
+
+ var
+ s,s2 : string;
+ hp : TParavarsym;
+ i : integer;
+
+ begin
+ s := procsym.realname;
+ if procsym.owner.symtabletype=objectsymtable then
+ begin
+ s2:=upper(tobjectdef(procsym.owner.defowner).typesym.realname);
+ case proctypeoption of
+ potype_destructor:
+ s:='_$_'+tostr(length(s2))+s2;
+ potype_constructor:
+ s:='___'+tostr(length(s2))+s2;
+ else
+ s:='_'+s+'__'+tostr(length(s2))+s2;
+ end;
+
+ end
+ else s:=s+'__';
+
+ s:=s+'F';
+
+ { concat modifiers }
+ { !!!!! }
+
+ { now we handle the parameters }
+ if maxparacount>0 then
+ begin
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ s2:=getcppparaname(hp.vartype.def);
+ if hp.varspez in [vs_var,vs_out] then
+ s2:='R'+s2;
+ s:=s+s2;
+ end;
+ end
+ else
+ s:=s+'v';
+ cplusplusmangledname:=s;
+ end;
+
+
+ procedure tprocdef.setmangledname(const s : string);
+ begin
+ { This is not allowed anymore, the forward declaration
+ already needs to create the correct mangledname, no changes
+ afterwards are allowed (PFV) }
+ if assigned(_mangledname) then
+ internalerror(200411171);
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(s));
+ {$else}
+ _mangledname:=stringdup(s);
+ {$endif}
+ include(procoptions,po_has_mangledname);
+ end;
+
+
+{***************************************************************************
+ TPROCVARDEF
+***************************************************************************}
+
+ constructor tprocvardef.create(level:byte);
+ begin
+ inherited create(level);
+ deftype:=procvardef;
+ end;
+
+
+ constructor tprocvardef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ deftype:=procvardef;
+ { load para symtable }
+ parast:=tparasymtable.create(unknown_level);
+ tparasymtable(parast).ppuload(ppufile);
+ parast.defowner:=self;
+ end;
+
+
+ function tprocvardef.getcopy : tstoreddef;
+ begin
+ result:=self;
+ (*
+ { saves a definition to the return type }
+ rettype : ttype;
+ parast : tsymtable;
+ paras : tparalist;
+ proctypeoption : tproctypeoption;
+ proccalloption : tproccalloption;
+ procoptions : tprocoptions;
+ requiredargarea : aint;
+ { number of user visibile parameters }
+ maxparacount,
+ minparacount : byte;
+{$ifdef i386}
+ fpu_used : longint; { how many stack fpu must be empty }
+{$endif i386}
+ funcretloc : array[tcallercallee] of TLocation;
+ has_paraloc_info : boolean; { paraloc info is available }
+
+ tprocvardef = class(tabstractprocdef)
+ constructor create(level:byte);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ *)
+ end;
+
+
+ procedure tprocvardef.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=nil;
+
+ { here we cannot get a real good value so just give something }
+ { plausible (PM) }
+ { a more secure way would be
+ to allways store in a temp }
+{$ifdef i386}
+ if is_fpu(rettype.def) then
+ fpu_used:={2}maxfpuregs
+ else
+ fpu_used:=0;
+{$endif i386}
+ inherited ppuwrite(ppufile);
+
+ { Write this entry }
+ ppufile.writeentry(ibprocvardef);
+
+ { Save the para symtable, this is taken from the interface }
+ tparasymtable(parast).ppuwrite(ppufile);
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ procedure tprocvardef.buildderef;
+ var
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=nil;
+
+ inherited buildderef;
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ procedure tprocvardef.deref;
+ var
+ oldparasymtable,
+ oldlocalsymtable : tsymtable;
+ begin
+ oldparasymtable:=aktparasymtable;
+ oldlocalsymtable:=aktlocalsymtable;
+ aktparasymtable:=parast;
+ aktlocalsymtable:=nil;
+
+ inherited deref;
+
+ aktparasymtable:=oldparasymtable;
+ aktlocalsymtable:=oldlocalsymtable;
+ end;
+
+
+ function tprocvardef.getsymtable(t:tgetsymtable):tsymtable;
+ begin
+ case t of
+ gs_para :
+ getsymtable:=parast;
+ else
+ getsymtable:=nil;
+ end;
+ end;
+
+
+ function tprocvardef.size : aint;
+ begin
+ if (po_methodpointer in procoptions) and
+ not(po_addressonly in procoptions) then
+ size:=2*sizeof(aint)
+ else
+ size:=sizeof(aint);
+ end;
+
+
+ function tprocvardef.is_methodpointer:boolean;
+ begin
+ result:=(po_methodpointer in procoptions);
+ end;
+
+
+ function tprocvardef.is_addressonly:boolean;
+ begin
+ result:=not(po_methodpointer in procoptions) or
+ (po_addressonly in procoptions);
+ end;
+
+
+ function tprocvardef.getmangledparaname:string;
+ begin
+ result:='procvar';
+ end;
+
+
+ procedure tprocvardef.write_rtti_data(rt:trttitype);
+
+ procedure write_para(parasym:tparavarsym);
+ var
+ paraspec : byte;
+ begin
+ { only store user visible parameters }
+ if not(vo_is_hidden_para in parasym.varoptions) then
+ begin
+ case parasym.varspez of
+ vs_value: paraspec := 0;
+ vs_const: paraspec := pfConst;
+ vs_var : paraspec := pfVar;
+ vs_out : paraspec := pfOut;
+ end;
+ { write flags for current parameter }
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(paraspec));
+ { write name of current parameter }
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(length(parasym.realname)));
+ asmlist[al_rtti].concat(Tai_string.Create(parasym.realname));
+
+ { write name of type of current parameter }
+ tstoreddef(parasym.vartype.def).write_rtti_name;
+ end;
+ end;
+
+ var
+ methodkind : byte;
+ i : integer;
+ begin
+ if po_methodpointer in procoptions then
+ begin
+ { write method id and name }
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkmethod));
+ write_rtti_name;
+
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ { write kind of method (can only be function or procedure)}
+ if rettype.def = voidtype.def then
+ methodkind := mkProcedure
+ else
+ methodkind := mkFunction;
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(methodkind));
+
+ { get # of parameters }
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(maxparacount));
+
+ { write parameter info. The parameters must be written in reverse order
+ if this method uses right to left parameter pushing! }
+ if proccalloption in pushleftright_pocalls then
+ begin
+ for i:=0 to paras.count-1 do
+ write_para(tparavarsym(paras[i]));
+ end
+ else
+ begin
+ for i:=paras.count-1 downto 0 do
+ write_para(tparavarsym(paras[i]));
+ end;
+
+ { write name of result type }
+ tstoreddef(rettype.def).write_rtti_name;
+ end
+ else
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkprocvar));
+ write_rtti_name;
+ end;
+ end;
+
+
+ function tprocvardef.is_publishable : boolean;
+ begin
+ is_publishable:=(po_methodpointer in procoptions);
+ end;
+
+
+ function tprocvardef.gettypename : string;
+ var
+ s: string;
+ showhidden : boolean;
+ begin
+{$ifdef EXTDEBUG}
+ showhidden:=true;
+{$else EXTDEBUG}
+ showhidden:=false;
+{$endif EXTDEBUG}
+ s:='<';
+ if po_classmethod in procoptions then
+ s := s+'class method type of'
+ else
+ if po_addressonly in procoptions then
+ s := s+'address of'
+ else
+ s := s+'procedure variable type of';
+ if po_local in procoptions then
+ s := s+' local';
+ if assigned(rettype.def) and
+ (rettype.def<>voidtype.def) then
+ s:=s+' function'+typename_paras(showhidden)+':'+rettype.def.gettypename
+ else
+ s:=s+' procedure'+typename_paras(showhidden);
+ if po_methodpointer in procoptions then
+ s := s+' of object';
+ gettypename := s+';'+ProcCallOptionStr[proccalloption]+'>';
+ end;
+
+
+{***************************************************************************
+ TOBJECTDEF
+***************************************************************************}
+
+
+ constructor tobjectdef.create(ot : tobjectdeftype;const n : string;c : tobjectdef);
+ begin
+ inherited create;
+ objecttype:=ot;
+ deftype:=objectdef;
+ objectoptions:=[];
+ childof:=nil;
+ symtable:=tobjectsymtable.create(n,aktpackrecords);
+ { create space for vmt !! }
+ vmt_offset:=0;
+ symtable.defowner:=self;
+ lastvtableindex:=0;
+ set_parent(c);
+ objname:=stringdup(upper(n));
+ objrealname:=stringdup(n);
+ if objecttype in [odt_interfacecorba,odt_interfacecom] then
+ prepareguid;
+ { setup implemented interfaces }
+ if objecttype in [odt_class,odt_interfacecorba] then
+ implementedinterfaces:=timplementedinterfaces.create
+ else
+ implementedinterfaces:=nil;
+ writing_class_record_stab:=false;
+ end;
+
+
+ constructor tobjectdef.ppuload(ppufile:tcompilerppufile);
+ var
+ i,implintfcount: longint;
+ d : tderef;
+ begin
+ inherited ppuloaddef(ppufile);
+ deftype:=objectdef;
+ objecttype:=tobjectdeftype(ppufile.getbyte);
+ objrealname:=stringdup(ppufile.getstring);
+ objname:=stringdup(upper(objrealname^));
+ symtable:=tobjectsymtable.create(objrealname^,0);
+ tobjectsymtable(symtable).datasize:=ppufile.getaint;
+ tobjectsymtable(symtable).fieldalignment:=ppufile.getbyte;
+ tobjectsymtable(symtable).recordalignment:=ppufile.getbyte;
+ vmt_offset:=ppufile.getlongint;
+ ppufile.getderef(childofderef);
+ ppufile.getsmallset(objectoptions);
+
+ { load guid }
+ iidstr:=nil;
+ if objecttype in [odt_interfacecom,odt_interfacecorba] then
+ begin
+ new(iidguid);
+ ppufile.getguid(iidguid^);
+ iidstr:=stringdup(ppufile.getstring);
+ lastvtableindex:=ppufile.getlongint;
+ end;
+
+ { load implemented interfaces }
+ if objecttype in [odt_class,odt_interfacecorba] then
+ begin
+ implementedinterfaces:=timplementedinterfaces.create;
+ implintfcount:=ppufile.getlongint;
+ for i:=1 to implintfcount do
+ begin
+ ppufile.getderef(d);
+ implementedinterfaces.addintf_deref(d,ppufile.getlongint);
+ end;
+ end
+ else
+ implementedinterfaces:=nil;
+
+ tobjectsymtable(symtable).ppuload(ppufile);
+
+ symtable.defowner:=self;
+
+ { handles the predefined class tobject }
+ { the last TOBJECT which is loaded gets }
+ { it ! }
+ if (childof=nil) and
+ (objecttype=odt_class) and
+ (objname^='TOBJECT') then
+ class_tobject:=self;
+ if (childof=nil) and
+ (objecttype=odt_interfacecom) and
+ (objname^='IUNKNOWN') then
+ interface_iunknown:=self;
+ writing_class_record_stab:=false;
+ end;
+
+ destructor tobjectdef.destroy;
+ begin
+ if assigned(symtable) then
+ symtable.free;
+ stringdispose(objname);
+ stringdispose(objrealname);
+ if assigned(iidstr) then
+ stringdispose(iidstr);
+ if assigned(implementedinterfaces) then
+ implementedinterfaces.free;
+ if assigned(iidguid) then
+ dispose(iidguid);
+ inherited destroy;
+ end;
+
+
+ function tobjectdef.getcopy : tstoreddef;
+ begin
+ result:=inherited getcopy;
+ (*
+ result:=tobjectdef.create(objecttype,objname^,childof);
+ childofderef : tderef;
+ objname,
+ objrealname : pstring;
+ objectoptions : tobjectoptions;
+ { to be able to have a variable vmt position }
+ { and no vmt field for objects without virtuals }
+ vmt_offset : longint;
+ writing_class_record_stab : boolean;
+ objecttype : tobjectdeftype;
+ iidguid: pguid;
+ iidstr: pstring;
+ lastvtableindex: longint;
+ { store implemented interfaces defs and name mappings }
+ implementedinterfaces: timplementedinterfaces;
+ *)
+ end;
+
+
+ procedure tobjectdef.ppuwrite(ppufile:tcompilerppufile);
+ var
+ implintfcount : longint;
+ i : longint;
+ begin
+ inherited ppuwritedef(ppufile);
+ ppufile.putbyte(byte(objecttype));
+ ppufile.putstring(objrealname^);
+ ppufile.putaint(tobjectsymtable(symtable).datasize);
+ ppufile.putbyte(tobjectsymtable(symtable).fieldalignment);
+ ppufile.putbyte(tobjectsymtable(symtable).recordalignment);
+ ppufile.putlongint(vmt_offset);
+ ppufile.putderef(childofderef);
+ ppufile.putsmallset(objectoptions);
+ if objecttype in [odt_interfacecom,odt_interfacecorba] then
+ begin
+ ppufile.putguid(iidguid^);
+ ppufile.putstring(iidstr^);
+ ppufile.putlongint(lastvtableindex);
+ end;
+
+ if objecttype in [odt_class,odt_interfacecorba] then
+ begin
+ implintfcount:=implementedinterfaces.count;
+ ppufile.putlongint(implintfcount);
+ for i:=1 to implintfcount do
+ begin
+ ppufile.putderef(implementedinterfaces.interfacesderef(i));
+ ppufile.putlongint(implementedinterfaces.ioffsets(i));
+ end;
+ end;
+
+ ppufile.writeentry(ibobjectdef);
+
+ tobjectsymtable(symtable).ppuwrite(ppufile);
+ end;
+
+
+ function tobjectdef.gettypename:string;
+ begin
+ gettypename:=typename;
+ end;
+
+
+ procedure tobjectdef.buildderef;
+ var
+ oldrecsyms : tsymtable;
+ begin
+ inherited buildderef;
+ childofderef.build(childof);
+ oldrecsyms:=aktrecordsymtable;
+ aktrecordsymtable:=symtable;
+ tstoredsymtable(symtable).buildderef;
+ aktrecordsymtable:=oldrecsyms;
+ if objecttype in [odt_class,odt_interfacecorba] then
+ implementedinterfaces.buildderef;
+ end;
+
+
+ procedure tobjectdef.deref;
+ var
+ oldrecsyms : tsymtable;
+ begin
+ inherited deref;
+ childof:=tobjectdef(childofderef.resolve);
+ oldrecsyms:=aktrecordsymtable;
+ aktrecordsymtable:=symtable;
+ tstoredsymtable(symtable).deref;
+ aktrecordsymtable:=oldrecsyms;
+ if objecttype in [odt_class,odt_interfacecorba] then
+ implementedinterfaces.deref;
+ end;
+
+
+ function tobjectdef.getparentdef:tdef;
+ begin
+{$warning TODO Remove getparentdef hack}
+ { With 2 forward declared classes with the child class before the
+ parent class the child class is written earlier to the ppu. Leaving it
+ possible to have a reference to the parent class for property overriding,
+ but the parent class still has the childof not resolved yet (PFV) }
+ if childof=nil then
+ childof:=tobjectdef(childofderef.resolve);
+ result:=childof;
+ end;
+
+
+ procedure tobjectdef.prepareguid;
+ begin
+ { set up guid }
+ if not assigned(iidguid) then
+ begin
+ new(iidguid);
+ fillchar(iidguid^,sizeof(iidguid^),0); { default null guid }
+ end;
+ { setup iidstring }
+ if not assigned(iidstr) then
+ iidstr:=stringdup(''); { default is empty string }
+ end;
+
+
+ procedure tobjectdef.set_parent( c : tobjectdef);
+ begin
+ { nothing to do if the parent was not forward !}
+ if assigned(childof) then
+ exit;
+ childof:=c;
+ { some options are inherited !! }
+ if assigned(c) then
+ begin
+ { only important for classes }
+ lastvtableindex:=c.lastvtableindex;
+ objectoptions:=objectoptions+(c.objectoptions*
+ inherited_objectoptions);
+ if not (objecttype in [odt_interfacecom,odt_interfacecorba]) then
+ begin
+ { add the data of the anchestor class }
+ inc(tobjectsymtable(symtable).datasize,tobjectsymtable(c.symtable).datasize);
+ if (oo_has_vmt in objectoptions) and
+ (oo_has_vmt in c.objectoptions) then
+ dec(tobjectsymtable(symtable).datasize,sizeof(aint));
+ { if parent has a vmt field then
+ the offset is the same for the child PM }
+ if (oo_has_vmt in c.objectoptions) or is_class(self) then
+ begin
+ vmt_offset:=c.vmt_offset;
+ include(objectoptions,oo_has_vmt);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tobjectdef.insertvmt;
+ begin
+ if objecttype in [odt_interfacecom,odt_interfacecorba] then
+ exit;
+ if (oo_has_vmt in objectoptions) then
+ internalerror(12345)
+ else
+ begin
+ tobjectsymtable(symtable).datasize:=align(tobjectsymtable(symtable).datasize,
+ tobjectsymtable(symtable).fieldalignment);
+
+{$ifdef cpurequiresproperalignment}
+ tobjectsymtable(symtable).datasize:=align(tobjectsymtable(symtable).datasize,sizeof(aint));
+{$endif cpurequiresproperalignment}
+
+ vmt_offset:=tobjectsymtable(symtable).datasize;
+ inc(tobjectsymtable(symtable).datasize,sizeof(aint));
+ include(objectoptions,oo_has_vmt);
+ end;
+ end;
+
+
+
+ procedure tobjectdef.check_forwards;
+ begin
+ if not(objecttype in [odt_interfacecom,odt_interfacecorba]) then
+ tstoredsymtable(symtable).check_forwards;
+ if (oo_is_forward in objectoptions) then
+ begin
+ { ok, in future, the forward can be resolved }
+ Message1(sym_e_class_forward_not_resolved,objrealname^);
+ exclude(objectoptions,oo_is_forward);
+ end;
+ end;
+
+
+ { true, if self inherits from d (or if they are equal) }
+ function tobjectdef.is_related(d : tdef) : boolean;
+ var
+ hp : tobjectdef;
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ if hp=d then
+ begin
+ is_related:=true;
+ exit;
+ end;
+ hp:=hp.childof;
+ end;
+ is_related:=false;
+ end;
+
+
+(* procedure tobjectdef._searchdestructor(sym : tnamedindexitem;arg:pointer);
+
+ var
+ p : pprocdeflist;
+
+ begin
+ { if we found already a destructor, then we exit }
+ if assigned(sd) then
+ exit;
+ if tsym(sym).typ=procsym then
+ begin
+ p:=tprocsym(sym).defs;
+ while assigned(p) do
+ begin
+ if p^.def.proctypeoption=potype_destructor then
+ begin
+ sd:=p^.def;
+ exit;
+ end;
+ p:=p^.next;
+ end;
+ end;
+ end;*)
+
+ procedure _searchdestructor(sym:Tnamedindexitem;sd:pointer);
+
+ begin
+ { if we found already a destructor, then we exit }
+ if (ppointer(sd)^=nil) and
+ (Tsym(sym).typ=procsym) then
+ ppointer(sd)^:=Tprocsym(sym).search_procdef_bytype(potype_destructor);
+ end;
+
+ function tobjectdef.searchdestructor : tprocdef;
+
+ var
+ o : tobjectdef;
+ sd : tprocdef;
+ begin
+ searchdestructor:=nil;
+ o:=self;
+ sd:=nil;
+ while assigned(o) do
+ begin
+ o.symtable.foreach_static(@_searchdestructor,@sd);
+ if assigned(sd) then
+ begin
+ searchdestructor:=sd;
+ exit;
+ end;
+ o:=o.childof;
+ end;
+ end;
+
+
+ function tobjectdef.size : aint;
+ begin
+ if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba] then
+ result:=sizeof(aint)
+ else
+ result:=tobjectsymtable(symtable).datasize;
+ end;
+
+
+ function tobjectdef.alignment:longint;
+ begin
+ if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba] then
+ alignment:=sizeof(aint)
+ else
+ alignment:=tobjectsymtable(symtable).recordalignment;
+ end;
+
+
+ function tobjectdef.vmtmethodoffset(index:longint):longint;
+ begin
+ { for offset of methods for classes, see rtl/inc/objpash.inc }
+ case objecttype of
+ odt_class:
+ { the +2*sizeof(Aint) is size and -size }
+ vmtmethodoffset:=(index+10)*sizeof(aint)+2*sizeof(AInt);
+ odt_interfacecom,odt_interfacecorba:
+ vmtmethodoffset:=index*sizeof(aint);
+ else
+{$ifdef WITHDMT}
+ vmtmethodoffset:=(index+4)*sizeof(aint);
+{$else WITHDMT}
+ vmtmethodoffset:=(index+3)*sizeof(aint);
+{$endif WITHDMT}
+ end;
+ end;
+
+
+ function tobjectdef.vmt_mangledname : string;
+ begin
+ if not(oo_has_vmt in objectoptions) then
+ Message1(parser_n_object_has_no_vmt,objrealname^);
+ vmt_mangledname:=make_mangledname('VMT',owner,objname^);
+ end;
+
+
+ function tobjectdef.rtti_name : string;
+ begin
+ rtti_name:=make_mangledname('RTTI',owner,objname^);
+ end;
+
+
+ function tobjectdef.needs_inittable : boolean;
+ begin
+ case objecttype of
+ odt_class :
+ needs_inittable:=false;
+ odt_interfacecom:
+ needs_inittable:=true;
+ odt_interfacecorba:
+ needs_inittable:=is_related(interface_iunknown);
+ odt_object:
+ needs_inittable:=tobjectsymtable(symtable).needs_init_final;
+ else
+ internalerror(200108267);
+ end;
+ end;
+
+
+ function tobjectdef.members_need_inittable : boolean;
+ begin
+ members_need_inittable:=tobjectsymtable(symtable).needs_init_final;
+ end;
+
+
+ procedure tobjectdef.count_published_properties(sym:tnamedindexitem;arg:pointer);
+ begin
+ if needs_prop_entry(tsym(sym)) and
+ (tsym(sym).typ<>fieldvarsym) then
+ inc(count);
+ end;
+
+
+ procedure tobjectdef.write_property_info(sym : tnamedindexitem;arg:pointer);
+ var
+ proctypesinfo : byte;
+
+ procedure writeproc(proc : tsymlist; shiftvalue : byte);
+
+ var
+ typvalue : byte;
+ hp : psymlistitem;
+ address : longint;
+ def : tdef;
+ begin
+ if not(assigned(proc) and assigned(proc.firstsym)) then
+ begin
+ asmlist[al_rtti].concat(Tai_const.create(ait_const_ptr,1));
+ typvalue:=3;
+ end
+ else if proc.firstsym^.sym.typ=fieldvarsym then
+ begin
+ address:=0;
+ hp:=proc.firstsym;
+ def:=nil;
+ while assigned(hp) do
+ begin
+ case hp^.sltype of
+ sl_load :
+ begin
+ def:=tfieldvarsym(hp^.sym).vartype.def;
+ inc(address,tfieldvarsym(hp^.sym).fieldoffset);
+ end;
+ sl_subscript :
+ begin
+ if not(assigned(def) and (def.deftype=recorddef)) then
+ internalerror(200402171);
+ inc(address,tfieldvarsym(hp^.sym).fieldoffset);
+ def:=tfieldvarsym(hp^.sym).vartype.def;
+ end;
+ sl_vec :
+ begin
+ if not(assigned(def) and (def.deftype=arraydef)) then
+ internalerror(200402172);
+ def:=tarraydef(def).elementtype.def;
+ inc(address,def.size*hp^.value);
+ end;
+ end;
+ hp:=hp^.next;
+ end;
+ asmlist[al_rtti].concat(Tai_const.create(ait_const_ptr,address));
+ typvalue:=0;
+ end
+ else
+ begin
+ { When there was an error then procdef is not assigned }
+ if not assigned(proc.procdef) then
+ exit;
+ if not(po_virtualmethod in tprocdef(proc.procdef).procoptions) then
+ begin
+ asmlist[al_rtti].concat(Tai_const.createname(tprocdef(proc.procdef).mangledname,AT_FUNCTION,0));
+ typvalue:=1;
+ end
+ else
+ begin
+ { virtual method, write vmt offset }
+ asmlist[al_rtti].concat(Tai_const.create(ait_const_ptr,
+ tprocdef(proc.procdef)._class.vmtmethodoffset(tprocdef(proc.procdef).extnumber)));
+ typvalue:=2;
+ end;
+ end;
+ proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
+ end;
+
+ begin
+ if needs_prop_entry(tsym(sym)) then
+ case tsym(sym).typ of
+ fieldvarsym:
+ begin
+{$ifdef dummy}
+ if not(tvarsym(sym).vartype.def.deftype=objectdef) or
+ not(tobjectdef(tvarsym(sym).vartype.def).is_class) then
+ internalerror(1509992);
+ { access to implicit class property as field }
+ proctypesinfo:=(0 shl 0) or (0 shl 2) or (0 shl 4);
+ asmlist[al_rtti].concat(Tai_const_symbol.Createname(tvarsym(sym.vartype.def.get_rtti_label),AT_DATA,0));
+ asmlist[al_rtti].concat(Tai_const.create(ait_const_ptr,tvarsym(sym.address)));
+ asmlist[al_rtti].concat(Tai_const.create(ait_const_ptr,tvarsym(sym.address)));
+ { by default stored }
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(1));
+ { index as well as ... }
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(0));
+ { default value are zero }
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(0));
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(count));
+ inc(count);
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(proctypesinfo));
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(length(tvarsym(sym.realname))));
+ asmlist[al_rtti].concat(Tai_string.Create(tvarsym(sym.realname)));
+{$endif dummy}
+ end;
+ propertysym:
+ begin
+ if ppo_indexed in tpropertysym(sym).propoptions then
+ proctypesinfo:=$40
+ else
+ proctypesinfo:=0;
+ asmlist[al_rtti].concat(Tai_const.Create_sym(tstoreddef(tpropertysym(sym).proptype.def).get_rtti_label(fullrtti)));
+ writeproc(tpropertysym(sym).readaccess,0);
+ writeproc(tpropertysym(sym).writeaccess,2);
+ { isn't it stored ? }
+ if not(ppo_stored in tpropertysym(sym).propoptions) then
+ begin
+ asmlist[al_rtti].concat(Tai_const.create_sym(nil));
+ proctypesinfo:=proctypesinfo or (3 shl 4);
+ end
+ else
+ writeproc(tpropertysym(sym).storedaccess,4);
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).index));
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).default));
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(count));
+ inc(count);
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(proctypesinfo));
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(length(tpropertysym(sym).realname)));
+ asmlist[al_rtti].concat(Tai_string.Create(tpropertysym(sym).realname));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ end;
+ else internalerror(1509992);
+ end;
+ end;
+
+
+ procedure tobjectdef.generate_published_child_rtti(sym : tnamedindexitem;arg:pointer);
+ begin
+ if needs_prop_entry(tsym(sym)) then
+ begin
+ case tsym(sym).typ of
+ propertysym:
+ tstoreddef(tpropertysym(sym).proptype.def).get_rtti_label(fullrtti);
+ fieldvarsym:
+ tstoreddef(tfieldvarsym(sym).vartype.def).get_rtti_label(fullrtti);
+ else
+ internalerror(1509991);
+ end;
+ end;
+ end;
+
+
+ procedure tobjectdef.write_child_rtti_data(rt:trttitype);
+ begin
+ FRTTIType:=rt;
+ case rt of
+ initrtti :
+ symtable.foreach(@generate_field_rtti,nil);
+ fullrtti :
+ symtable.foreach(@generate_published_child_rtti,nil);
+ else
+ internalerror(200108301);
+ end;
+ end;
+
+
+ type
+ tclasslistitem = class(TLinkedListItem)
+ index : longint;
+ p : tobjectdef;
+ end;
+
+ var
+ classtablelist : tlinkedlist;
+ tablecount : longint;
+
+ function searchclasstablelist(p : tobjectdef) : tclasslistitem;
+
+ var
+ hp : tclasslistitem;
+
+ begin
+ hp:=tclasslistitem(classtablelist.first);
+ while assigned(hp) do
+ if hp.p=p then
+ begin
+ searchclasstablelist:=hp;
+ exit;
+ end
+ else
+ hp:=tclasslistitem(hp.next);
+ searchclasstablelist:=nil;
+ end;
+
+
+ procedure tobjectdef.count_published_fields(sym:tnamedindexitem;arg:pointer);
+ var
+ hp : tclasslistitem;
+ begin
+ if needs_prop_entry(tsym(sym)) and
+ (tsym(sym).typ=fieldvarsym) then
+ begin
+ if tfieldvarsym(sym).vartype.def.deftype<>objectdef then
+ internalerror(0206001);
+ hp:=searchclasstablelist(tobjectdef(tfieldvarsym(sym).vartype.def));
+ if not(assigned(hp)) then
+ begin
+ hp:=tclasslistitem.create;
+ hp.p:=tobjectdef(tfieldvarsym(sym).vartype.def);
+ hp.index:=tablecount;
+ classtablelist.concat(hp);
+ inc(tablecount);
+ end;
+ inc(count);
+ end;
+ end;
+
+
+ procedure tobjectdef.writefields(sym:tnamedindexitem;arg:pointer);
+ var
+ hp : tclasslistitem;
+ begin
+ if needs_prop_entry(tsym(sym)) and
+ (tsym(sym).typ=fieldvarsym) then
+ begin
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(AInt)));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_aint(tfieldvarsym(sym).fieldoffset));
+ hp:=searchclasstablelist(tobjectdef(tfieldvarsym(sym).vartype.def));
+ if not(assigned(hp)) then
+ internalerror(0206002);
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(hp.index));
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(length(tfieldvarsym(sym).realname)));
+ asmlist[al_rtti].concat(Tai_string.Create(tfieldvarsym(sym).realname));
+ end;
+ end;
+
+
+ function tobjectdef.generate_field_table : tasmlabel;
+ var
+ fieldtable,
+ classtable : tasmlabel;
+ hp : tclasslistitem;
+
+ begin
+ classtablelist:=TLinkedList.Create;
+ objectlibrary.getdatalabel(fieldtable);
+ objectlibrary.getdatalabel(classtable);
+ count:=0;
+ tablecount:=0;
+ maybe_new_object_file(asmlist[al_rtti]);
+ new_section(asmlist[al_rtti],sec_rodata,classtable.name,const_align(sizeof(aint)));
+ { fields }
+ symtable.foreach({$ifdef FPC}@{$endif}count_published_fields,nil);
+ asmlist[al_rtti].concat(Tai_label.Create(fieldtable));
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(count));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_sym(classtable));
+ symtable.foreach({$ifdef FPC}@{$endif}writefields,nil);
+
+ { generate the class table }
+ asmlist[al_rtti].concat(tai_align.create(const_align(sizeof(aint))));
+ asmlist[al_rtti].concat(Tai_label.Create(classtable));
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(tablecount));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ hp:=tclasslistitem(classtablelist.first);
+ while assigned(hp) do
+ begin
+ asmlist[al_rtti].concat(Tai_const.Createname(tobjectdef(hp.p).vmt_mangledname,AT_DATA,0));
+ hp:=tclasslistitem(hp.next);
+ end;
+
+ generate_field_table:=fieldtable;
+ classtablelist.free;
+ end;
+
+
+ function tobjectdef.next_free_name_index : longint;
+ var
+ i : longint;
+ begin
+ if assigned(childof) and (oo_can_have_published in childof.objectoptions) then
+ i:=childof.next_free_name_index
+ else
+ i:=0;
+ count:=0;
+ symtable.foreach(@count_published_properties,nil);
+ next_free_name_index:=i+count;
+ end;
+
+
+ procedure tobjectdef.write_rtti_data(rt:trttitype);
+ var
+ i : longint;
+ begin
+ case objecttype of
+ odt_class:
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkclass));
+ odt_object:
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkobject));
+ odt_interfacecom:
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkinterface));
+ odt_interfacecorba:
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(tkinterfaceCorba));
+ else
+ exit;
+ end;
+
+ { generate the name }
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(length(objrealname^)));
+ asmlist[al_rtti].concat(Tai_string.Create(objrealname^));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ case rt of
+ initrtti :
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(size));
+ if objecttype in [odt_class,odt_object] then
+ begin
+ count:=0;
+ FRTTIType:=rt;
+ symtable.foreach(@count_field_rtti,nil);
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(count));
+ symtable.foreach(@write_field_rtti,nil);
+ end;
+ end;
+ fullrtti :
+ begin
+ if not(objecttype in [odt_interfacecom,odt_interfacecorba]) then
+ begin
+ if (oo_has_vmt in objectoptions) then
+ asmlist[al_rtti].concat(Tai_const.Createname(vmt_mangledname,AT_DATA,0))
+ else
+ asmlist[al_rtti].concat(Tai_const.create_sym(nil));
+ end;
+
+ { write parent typeinfo }
+ if assigned(childof) and ((oo_can_have_published in childof.objectoptions) or
+ (objecttype in [odt_interfacecom,odt_interfacecorba])) then
+ asmlist[al_rtti].concat(Tai_const.Create_sym(childof.get_rtti_label(fullrtti)))
+ else
+ asmlist[al_rtti].concat(Tai_const.create_sym(nil));
+
+ if objecttype in [odt_object,odt_class] then
+ begin
+ { count total number of properties }
+ if assigned(childof) and (oo_can_have_published in childof.objectoptions) then
+ count:=childof.next_free_name_index
+ else
+ count:=0;
+
+ { write it }
+ symtable.foreach(@count_published_properties,nil);
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(count));
+ end
+ else
+ { interface: write flags, iid and iidstr }
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(
+ { ugly, but working }
+ longint([
+ TCompilerIntfFlag(ord(ifHasGuid)*ord(assigned(iidguid))),
+ TCompilerIntfFlag(ord(ifHasStrGUID)*ord(assigned(iidstr)))
+ ])
+ {
+ ifDispInterface,
+ ifDispatch, }
+ ));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_const.Create_32bit(longint(iidguid^.D1)));
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(iidguid^.D2));
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(iidguid^.D3));
+ for i:=Low(iidguid^.D4) to High(iidguid^.D4) do
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(iidguid^.D4[i]));
+ end;
+
+ { write unit name }
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
+ asmlist[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
+
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+
+ { write iidstr }
+ if objecttype in [odt_interfacecom,odt_interfacecorba] then
+ begin
+ if assigned(iidstr) then
+ begin
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(length(iidstr^)));
+ asmlist[al_rtti].concat(Tai_string.Create(iidstr^));
+ end
+ else
+ asmlist[al_rtti].concat(Tai_const.Create_8bit(0));
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ end;
+
+ if objecttype in [odt_object,odt_class] then
+ begin
+ { write published properties count }
+ count:=0;
+ symtable.foreach(@count_published_properties,nil);
+ asmlist[al_rtti].concat(Tai_const.Create_16bit(count));
+
+{$ifdef cpurequiresproperalignment}
+ asmlist[al_rtti].concat(Tai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+ end;
+
+ { count is used to write nameindex }
+
+ { but we need an offset of the owner }
+ { to give each property an own slot }
+ if assigned(childof) and (oo_can_have_published in childof.objectoptions) then
+ count:=childof.next_free_name_index
+ else
+ count:=0;
+
+ symtable.foreach(@write_property_info,nil);
+ end;
+ end;
+ end;
+
+
+ function tobjectdef.is_publishable : boolean;
+ begin
+ is_publishable:=objecttype in [odt_class,odt_interfacecom,odt_interfacecorba];
+ end;
+
+
+{****************************************************************************
+ TIMPLEMENTEDINTERFACES
+****************************************************************************}
+ type
+ tnamemap = class(TNamedIndexItem)
+ newname: pstring;
+ constructor create(const aname, anewname: string);
+ destructor destroy; override;
+ end;
+
+ constructor tnamemap.create(const aname, anewname: string);
+ begin
+ inherited createname(aname);
+ newname:=stringdup(anewname);
+ end;
+
+ destructor tnamemap.destroy;
+ begin
+ stringdispose(newname);
+ inherited destroy;
+ end;
+
+
+ type
+ tprocdefstore = class(TNamedIndexItem)
+ procdef: tprocdef;
+ constructor create(aprocdef: tprocdef);
+ end;
+
+ constructor tprocdefstore.create(aprocdef: tprocdef);
+ begin
+ inherited create;
+ procdef:=aprocdef;
+ end;
+
+
+ constructor timplintfentry.create(aintf: tobjectdef);
+ begin
+ inherited create;
+ intf:=aintf;
+ ioffset:=-1;
+ namemappings:=nil;
+ procdefs:=nil;
+ end;
+
+
+ constructor timplintfentry.create_deref(const d:tderef);
+ begin
+ inherited create;
+ intf:=nil;
+ intfderef:=d;
+ ioffset:=-1;
+ namemappings:=nil;
+ procdefs:=nil;
+ end;
+
+
+ destructor timplintfentry.destroy;
+ begin
+ if assigned(namemappings) then
+ namemappings.free;
+ if assigned(procdefs) then
+ procdefs.free;
+ inherited destroy;
+ end;
+
+
+ constructor timplementedinterfaces.create;
+ begin
+ finterfaces:=tindexarray.create(1);
+ end;
+
+ destructor timplementedinterfaces.destroy;
+ begin
+ finterfaces.destroy;
+ end;
+
+ function timplementedinterfaces.count: longint;
+ begin
+ count:=finterfaces.count;
+ end;
+
+ procedure timplementedinterfaces.checkindex(intfindex: longint);
+ begin
+ if (intfindex<1) or (intfindex>count) then
+ InternalError(200006123);
+ end;
+
+ function timplementedinterfaces.interfaces(intfindex: longint): tobjectdef;
+ begin
+ checkindex(intfindex);
+ interfaces:=timplintfentry(finterfaces.search(intfindex)).intf;
+ end;
+
+ function timplementedinterfaces.interfacesderef(intfindex: longint): tderef;
+ begin
+ checkindex(intfindex);
+ interfacesderef:=timplintfentry(finterfaces.search(intfindex)).intfderef;
+ end;
+
+ function timplementedinterfaces.ioffsets(intfindex: longint): longint;
+ begin
+ checkindex(intfindex);
+ ioffsets:=timplintfentry(finterfaces.search(intfindex)).ioffset;
+ end;
+
+ procedure timplementedinterfaces.setioffsets(intfindex,iofs:longint);
+ begin
+ checkindex(intfindex);
+ timplintfentry(finterfaces.search(intfindex)).ioffset:=iofs;
+ end;
+
+ function timplementedinterfaces.implindex(intfindex:longint):longint;
+ begin
+ checkindex(intfindex);
+ result:=timplintfentry(finterfaces.search(intfindex)).implindex;
+ end;
+
+ procedure timplementedinterfaces.setimplindex(intfindex,implidx:longint);
+ begin
+ checkindex(intfindex);
+ timplintfentry(finterfaces.search(intfindex)).implindex:=implidx;
+ end;
+
+ function timplementedinterfaces.searchintf(def: tdef): longint;
+ var
+ i: longint;
+ begin
+ i:=1;
+ while (i<=count) and (tdef(interfaces(i))<>def) do inc(i);
+ if i<=count then
+ searchintf:=i
+ else
+ searchintf:=-1;
+ end;
+
+
+ procedure timplementedinterfaces.buildderef;
+ var
+ i: longint;
+ begin
+ for i:=1 to count do
+ with timplintfentry(finterfaces.search(i)) do
+ intfderef.build(intf);
+ end;
+
+
+ procedure timplementedinterfaces.deref;
+ var
+ i: longint;
+ begin
+ for i:=1 to count do
+ with timplintfentry(finterfaces.search(i)) do
+ intf:=tobjectdef(intfderef.resolve);
+ end;
+
+ procedure timplementedinterfaces.addintf_deref(const d:tderef;iofs:longint);
+ var
+ hintf : timplintfentry;
+ begin
+ hintf:=timplintfentry.create_deref(d);
+ hintf.ioffset:=iofs;
+ finterfaces.insert(hintf);
+ end;
+
+ procedure timplementedinterfaces.addintf(def: tdef);
+ begin
+ if not assigned(def) or (searchintf(def)<>-1) or (def.deftype<>objectdef) or
+ not (tobjectdef(def).objecttype in [odt_interfacecom,odt_interfacecorba]) then
+ internalerror(200006124);
+ finterfaces.insert(timplintfentry.create(tobjectdef(def)));
+ end;
+
+ procedure timplementedinterfaces.clearmappings;
+ var
+ i: longint;
+ begin
+ for i:=1 to count do
+ with timplintfentry(finterfaces.search(i)) do
+ begin
+ if assigned(namemappings) then
+ namemappings.free;
+ namemappings:=nil;
+ end;
+ end;
+
+ procedure timplementedinterfaces.addmappings(intfindex: longint; const origname, newname: string);
+ begin
+ checkindex(intfindex);
+ with timplintfentry(finterfaces.search(intfindex)) do
+ begin
+ if not assigned(namemappings) then
+ namemappings:=tdictionary.create;
+ namemappings.insert(tnamemap.create(origname,newname));
+ end;
+ end;
+
+ function timplementedinterfaces.getmappings(intfindex: longint; const origname: string; var nextexist: pointer): string;
+ begin
+ checkindex(intfindex);
+ if not assigned(nextexist) then
+ with timplintfentry(finterfaces.search(intfindex)) do
+ begin
+ if assigned(namemappings) then
+ nextexist:=namemappings.search(origname)
+ else
+ nextexist:=nil;
+ end;
+ if assigned(nextexist) then
+ begin
+ getmappings:=tnamemap(nextexist).newname^;
+ nextexist:=tnamemap(nextexist).listnext;
+ end
+ else
+ getmappings:='';
+ end;
+
+ procedure timplementedinterfaces.addimplproc(intfindex: longint; procdef: tprocdef);
+ var
+ found : boolean;
+ i : longint;
+ begin
+ checkindex(intfindex);
+ with timplintfentry(finterfaces.search(intfindex)) do
+ begin
+ if not assigned(procdefs) then
+ procdefs:=tindexarray.create(4);
+ { No duplicate entries of the same procdef }
+ found:=false;
+ for i:=1 to procdefs.count do
+ if tprocdefstore(procdefs.search(i)).procdef=procdef then
+ begin
+ found:=true;
+ break;
+ end;
+ if not found then
+ procdefs.insert(tprocdefstore.create(procdef));
+ end;
+ end;
+
+ function timplementedinterfaces.implproccount(intfindex: longint): longint;
+ begin
+ checkindex(intfindex);
+ with timplintfentry(finterfaces.search(intfindex)) do
+ if assigned(procdefs) then
+ implproccount:=procdefs.count
+ else
+ implproccount:=0;
+ end;
+
+ function timplementedinterfaces.implprocs(intfindex: longint; procindex: longint): tprocdef;
+ begin
+ checkindex(intfindex);
+ with timplintfentry(finterfaces.search(intfindex)) do
+ if assigned(procdefs) then
+ implprocs:=tprocdefstore(procdefs.search(procindex)).procdef
+ else
+ internalerror(200006131);
+ end;
+
+ function timplementedinterfaces.isimplmergepossible(intfindex, remainindex: longint; var weight: longint): boolean;
+ var
+ possible: boolean;
+ i: longint;
+ iiep1: TIndexArray;
+ iiep2: TIndexArray;
+ begin
+ checkindex(intfindex);
+ checkindex(remainindex);
+ iiep1:=timplintfentry(finterfaces.search(intfindex)).procdefs;
+ iiep2:=timplintfentry(finterfaces.search(remainindex)).procdefs;
+ if not assigned(iiep1) then { empty interface is mergeable :-) }
+ begin
+ possible:=true;
+ weight:=0;
+ end
+ else
+ begin
+ possible:=assigned(iiep2) and (iiep1.count<=iiep2.count);
+ i:=1;
+ while (possible) and (i<=iiep1.count) do
+ begin
+ possible:=
+ (tprocdefstore(iiep1.search(i)).procdef=tprocdefstore(iiep2.search(i)).procdef);
+ inc(i);
+ end;
+ if possible then
+ weight:=iiep1.count;
+ end;
+ isimplmergepossible:=possible;
+ end;
+
+
+{****************************************************************************
+ TFORWARDDEF
+****************************************************************************}
+
+ constructor tforwarddef.create(const s:string;const pos : tfileposinfo);
+ var
+ oldregisterdef : boolean;
+ begin
+ { never register the forwarddefs, they are disposed at the
+ end of the type declaration block }
+ oldregisterdef:=registerdef;
+ registerdef:=false;
+ inherited create;
+ registerdef:=oldregisterdef;
+ deftype:=forwarddef;
+ tosymname:=stringdup(s);
+ forwardpos:=pos;
+ end;
+
+
+ function tforwarddef.gettypename:string;
+ begin
+ gettypename:='unresolved forward to '+tosymname^;
+ end;
+
+ destructor tforwarddef.destroy;
+ begin
+ if assigned(tosymname) then
+ stringdispose(tosymname);
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TERRORDEF
+****************************************************************************}
+
+ constructor terrordef.create;
+ begin
+ inherited create;
+ deftype:=errordef;
+ end;
+
+
+ procedure terrordef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ { Can't write errordefs to ppu }
+ internalerror(200411063);
+ end;
+
+
+ function terrordef.gettypename:string;
+ begin
+ gettypename:='<erroneous type>';
+ end;
+
+
+ function terrordef.getmangledparaname:string;
+ begin
+ getmangledparaname:='error';
+ end;
+
+
+{****************************************************************************
+ Definition Helpers
+****************************************************************************}
+
+ function is_interfacecom(def: tdef): boolean;
+ begin
+ is_interfacecom:=
+ assigned(def) and
+ (def.deftype=objectdef) and
+ (tobjectdef(def).objecttype=odt_interfacecom);
+ end;
+
+ function is_interfacecorba(def: tdef): boolean;
+ begin
+ is_interfacecorba:=
+ assigned(def) and
+ (def.deftype=objectdef) and
+ (tobjectdef(def).objecttype=odt_interfacecorba);
+ end;
+
+ function is_interface(def: tdef): boolean;
+ begin
+ is_interface:=
+ assigned(def) and
+ (def.deftype=objectdef) and
+ (tobjectdef(def).objecttype in [odt_interfacecom,odt_interfacecorba]);
+ end;
+
+
+ function is_class(def: tdef): boolean;
+ begin
+ is_class:=
+ assigned(def) and
+ (def.deftype=objectdef) and
+ (tobjectdef(def).objecttype=odt_class);
+ end;
+
+ function is_object(def: tdef): boolean;
+ begin
+ is_object:=
+ assigned(def) and
+ (def.deftype=objectdef) and
+ (tobjectdef(def).objecttype=odt_object);
+ end;
+
+ function is_cppclass(def: tdef): boolean;
+ begin
+ is_cppclass:=
+ assigned(def) and
+ (def.deftype=objectdef) and
+ (tobjectdef(def).objecttype=odt_cppclass);
+ end;
+
+ function is_class_or_interface(def: tdef): boolean;
+ begin
+ is_class_or_interface:=
+ assigned(def) and
+ (def.deftype=objectdef) and
+ (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba]);
+ end;
+
+
+{$ifdef x86}
+ function use_sse(def : tdef) : boolean;
+ begin
+ use_sse:=(is_single(def) and (aktfputype in sse_singlescalar)) or
+ (is_double(def) and (aktfputype in sse_doublescalar));
+ end;
+{$endif x86}
+
+end.
diff --git a/compiler/symnot.pas b/compiler/symnot.pas
new file mode 100644
index 0000000000..198bc43063
--- /dev/null
+++ b/compiler/symnot.pas
@@ -0,0 +1,63 @@
+{
+ Copyright (c) 2002 by Daniel Mantione
+
+ This unit contains support routines for the variable access
+ notifier.
+
+ 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 symnot;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses cclasses,symtype;
+
+type Tnotification_flag=(vn_onread,vn_onwrite,vn_unknown);
+ Tnotification_flags=set of Tnotification_flag;
+
+ Tnotification_callback=procedure(not_type:Tnotification_flag;
+ symbol:Tsym) of object;
+
+ Tnotification=class(Tlinkedlistitem)
+ flags:Tnotification_flags;
+ callback:Tnotification_callback;
+ id:cardinal;
+ constructor create(Aflags:Tnotification_flags;
+ Acallback:Tnotification_callback);
+ end;
+
+implementation
+
+var notification_counter:cardinal;
+
+constructor Tnotification.create(Aflags:Tnotification_flags;
+ Acallback:Tnotification_callback);
+
+begin
+ inherited create;
+ flags:=Aflags;
+ callback:=Acallback;
+ id:=notification_counter;
+ inc(notification_counter);
+end;
+
+begin
+ notification_counter:=0;
+end.
diff --git a/compiler/symsym.pas b/compiler/symsym.pas
new file mode 100644
index 0000000000..71d8c093c8
--- /dev/null
+++ b/compiler/symsym.pas
@@ -0,0 +1,2349 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Implementation for the symbols types of the symtable
+
+ 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 symsym;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,
+ { target }
+ globtype,globals,widestr,
+ { symtable }
+ symconst,symbase,symtype,symdef,defcmp,
+ { ppu }
+ ppu,
+ cclasses,symnot,
+ { aasm }
+ aasmbase,
+ cpuinfo,cpubase,cgbase,cgutils,parabase
+ ;
+
+ type
+ { this class is the base for all symbol objects }
+ tstoredsym = class(tsym)
+ public
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ end;
+
+ tlabelsym = class(tstoredsym)
+ used,
+ defined : boolean;
+ { points to the matching node, only valid resulttype pass is run and
+ the goto<->label relation in the node tree is created, should
+ be a tnode }
+ code : pointer;
+
+ { when the label is defined in an asm block, this points to the
+ generated asmlabel }
+ asmblocklabel : tasmlabel;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tunitsym = class(Tstoredsym)
+ unitsymtable : tsymtable;
+ constructor create(const n : string;ref : tsymtable);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ terrorsym = class(Tsym)
+ constructor create;
+ end;
+
+ Tprocdefcallback = procedure(p:Tprocdef;arg:pointer);
+
+ tprocsym = class(tstoredsym)
+ protected
+ pdlistfirst,
+ pdlistlast : pprocdeflist; { linked list of overloaded procdefs }
+ function getprocdef(nr:cardinal):Tprocdef;
+ public
+ procdef_count : byte;
+ overloadchecked : boolean;
+ property procdef[nr:cardinal]:Tprocdef read getprocdef;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ { writes all declarations except the specified one }
+ procedure write_parameter_lists(skipdef:tprocdef);
+ { tests, if all procedures definitions are defined and not }
+ { only forward }
+ procedure check_forward;
+ procedure unchain_overload;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure addprocdef(p:tprocdef);
+ procedure addprocdef_deref(const d:tderef);
+ procedure add_para_match_to(Aprocsym:Tprocsym;cpoptions:tcompare_paras_options);
+ procedure concat_procdefs_to(s:Tprocsym);
+ procedure foreach_procdef_static(proc2call:Tprocdefcallback;arg:pointer);
+ function first_procdef:Tprocdef;
+ function last_procdef:Tprocdef;
+ function search_procdef_nopara_boolret:Tprocdef;
+ function search_procdef_bytype(pt:Tproctypeoption):Tprocdef;
+ function search_procdef_bypara(para:tlist;retdef:tdef;cpoptions:tcompare_paras_options):Tprocdef;
+ function search_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
+ function search_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ function write_references(ppufile:tcompilerppufile;locals:boolean):boolean;override;
+ { currobjdef is the object def to assume, this is necessary for protected and
+ private,
+ context is the object def we're really in, this is for the strict stuff
+ }
+ function is_visible_for_object(currobjdef:tdef;context:tdef):boolean;override;
+ end;
+
+ ttypesym = class(Tstoredsym)
+ restype : ttype;
+ constructor create(const n : string;const tt : ttype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function gettypedef:tdef;override;
+ procedure load_references(ppufile:tcompilerppufile;locals:boolean);override;
+ function write_references(ppufile:tcompilerppufile;locals:boolean):boolean;override;
+ end;
+
+ tabstractvarsym = class(tstoredsym)
+ varoptions : tvaroptions;
+ varspez : tvarspez; { sets the type of access }
+ varregable : tvarregable;
+ varstate : tvarstate;
+ notifications : Tlinkedlist;
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function getsize : longint;
+ function is_regvar:boolean;
+ procedure trigger_notifications(what:Tnotification_flag);
+ function register_notification(flags:Tnotification_flags;
+ callback:Tnotification_callback):cardinal;
+ procedure unregister_notification(id:cardinal);
+ private
+ procedure setvartype(const newtype: ttype);
+ _vartype : ttype;
+ public
+ property vartype: ttype read _vartype write setvartype;
+ end;
+
+ tfieldvarsym = class(tabstractvarsym)
+ fieldoffset : aint; { offset in record/object }
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tabstractnormalvarsym = class(tabstractvarsym)
+ defaultconstsym : tsym;
+ defaultconstsymderef : tderef;
+ localloc : TLocation; { register/reference for local var }
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tlocalvarsym = class(tabstractnormalvarsym)
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tparavarsym = class(tabstractnormalvarsym)
+ paraloc : array[tcallercallee] of TCGPara;
+ paranr : word; { position of this parameter }
+{$ifdef EXTDEBUG}
+ eqval : tequaltype;
+{$endif EXTDEBUG}
+ constructor create(const n : string;nr:word;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tglobalvarsym = class(tabstractnormalvarsym)
+ private
+ _mangledname : pstring;
+ public
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor create_dll(const n : string;vsp:tvarspez;const tt : ttype);
+ constructor create_C(const n,mangled : string;vsp:tvarspez;const tt : ttype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ procedure set_mangledname(const s:string);
+ end;
+
+ tabsolutevarsym = class(tabstractvarsym)
+ public
+ abstyp : absolutetyp;
+{$ifdef i386}
+ absseg : boolean;
+{$endif i386}
+ asmname : pstring;
+ addroffset : aint;
+ ref : tsymlist;
+ constructor create(const n : string;const tt : ttype);
+ constructor create_ref(const n : string;const tt : ttype;_ref:tsymlist);
+ destructor destroy;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure buildderef;override;
+ procedure deref;override;
+ function mangledname : string;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tpropertysym = class(Tstoredsym)
+ propoptions : tpropertyoptions;
+ propoverriden : tpropertysym;
+ propoverridenderef : tderef;
+ proptype,
+ indextype : ttype;
+ index,
+ default : longint;
+ readaccess,
+ writeaccess,
+ storedaccess : tsymlist;
+ constructor create(const n : string);
+ destructor destroy;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getsize : longint;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypedef:tdef;override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure dooverride(overriden:tpropertysym);
+ end;
+
+ ttypedconstsym = class(tstoredsym)
+ private
+ _mangledname : pstring;
+ public
+ typedconsttype : ttype;
+ is_writable : boolean;
+ constructor create(const n : string;p : tdef;writable : boolean);
+ constructor createtype(const n : string;const tt : ttype;writable : boolean);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function mangledname : string;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function getsize:longint;
+ end;
+
+ tconstvalue = record
+ case integer of
+ 0: (valueord : tconstexprint);
+ 1: (valueordptr : tconstptruint);
+ 2: (valueptr : pointer; len : longint);
+ end;
+
+ tconstsym = class(tstoredsym)
+ consttype : ttype;
+ consttyp : tconsttyp;
+ value : tconstvalue;
+ resstrindex : longint; { needed for resource strings }
+ constructor create_ord(const n : string;t : tconsttyp;v : tconstexprint;const tt:ttype);
+ constructor create_ordptr(const n : string;t : tconsttyp;v : tconstptruint;const tt:ttype);
+ constructor create_ptr(const n : string;t : tconsttyp;v : pointer;const tt:ttype);
+ constructor create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
+ constructor create_wstring(const n : string;t : tconsttyp;pw:pcompilerwidestring);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tenumsym = class(Tstoredsym)
+ value : longint;
+ definition : tenumdef;
+ definitionderef : tderef;
+ nextenum : tenumsym;
+ constructor create(const n : string;def : tenumdef;v : longint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure order;
+ end;
+
+ tsyssym = class(Tstoredsym)
+ number : longint;
+ constructor create(const n : string;l : longint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ const
+ maxmacrolen=16*1024;
+
+ type
+ pmacrobuffer = ^tmacrobuffer;
+ tmacrobuffer = array[0..maxmacrolen-1] of char;
+
+ tmacro = class(tstoredsym)
+ {Normally true, but false when a previously defined macro is undef-ed}
+ defined : boolean;
+ {True if this is a mac style compiler variable, in which case no macro
+ substitutions shall be done.}
+ is_compiler_var : boolean;
+ {Whether the macro was used. NOTE: A use of a macro which was never defined}
+ {e. g. an IFDEF which returns false, will not be registered as used,}
+ {since there is no place to register its use. }
+ is_used : boolean;
+ buftext : pchar;
+ buflen : longint;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ end;
+
+ { compiler generated symbol to point to rtti and init/finalize tables }
+ trttisym = class(tstoredsym)
+ private
+ _mangledname : pstring;
+ public
+ lab : tasmsymbol;
+ rttityp : trttitype;
+ constructor create(const n:string;rt:trttitype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ function get_label:tasmsymbol;
+ end;
+
+ var
+ generrorsym : tsym;
+
+implementation
+
+ uses
+ { global }
+ verbose,
+ { target }
+ systems,
+ { symtable }
+ defutil,symtable,
+ { tree }
+ node,
+ { aasm }
+ { codegen }
+ paramgr,cresstr,
+ procinfo
+ ;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+{****************************************************************************
+ TSYM (base for all symtypes)
+****************************************************************************}
+
+ constructor tstoredsym.create(const n : string);
+ begin
+ inherited create(n);
+ end;
+
+
+ constructor tstoredsym.ppuload(ppufile:tcompilerppufile);
+ var
+ nr : word;
+ s : string;
+ begin
+ nr:=ppufile.getword;
+ s:=ppufile.getstring;
+ if s[1]='$' then
+ inherited createname(copy(s,2,255))
+ else
+ inherited createname(upper(s));
+ _realname:=stringdup(s);
+ typ:=abstractsym;
+ { force the correct indexnr. must be after create! }
+ indexnr:=nr;
+ ppufile.getposinfo(fileinfo);
+ ppufile.getsmallset(symoptions);
+ lastref:=nil;
+ defref:=nil;
+ refs:=0;
+ lastwritten:=nil;
+ refcount:=0;
+ isstabwritten := false;
+ end;
+
+
+ procedure tstoredsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ ppufile.putword(indexnr);
+ ppufile.putstring(_realname^);
+ ppufile.putposinfo(fileinfo);
+ ppufile.putsmallset(symoptions);
+ end;
+
+
+ destructor tstoredsym.destroy;
+ begin
+ if assigned(defref) then
+ begin
+{$ifdef MEMDEBUG}
+ membrowser.start;
+{$endif MEMDEBUG}
+ defref.freechain;
+ defref.free;
+{$ifdef MEMDEBUG}
+ membrowser.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TLABELSYM
+****************************************************************************}
+
+ constructor tlabelsym.create(const n : string);
+ begin
+ inherited create(n);
+ typ:=labelsym;
+ used:=false;
+ defined:=false;
+ code:=nil;
+ end;
+
+
+ constructor tlabelsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=labelsym;
+ code:=nil;
+ used:=false;
+ defined:=true;
+ end;
+
+
+ procedure tlabelsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ if owner.symtabletype=globalsymtable then
+ Message(sym_e_ill_label_decl)
+ else
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(iblabelsym);
+ end;
+ end;
+
+
+{****************************************************************************
+ TUNITSYM
+****************************************************************************}
+
+ constructor tunitsym.create(const n : string;ref : tsymtable);
+ var
+ old_make_ref : boolean;
+ begin
+ old_make_ref:=make_ref;
+ make_ref:=false;
+ inherited create(n);
+ make_ref:=old_make_ref;
+ typ:=unitsym;
+ unitsymtable:=ref;
+ end;
+
+ constructor tunitsym.ppuload(ppufile:tcompilerppufile);
+
+ begin
+ inherited ppuload(ppufile);
+ typ:=unitsym;
+ unitsymtable:=nil;
+ end;
+
+ destructor tunitsym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+ procedure tunitsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(ibunitsym);
+ end;
+
+{****************************************************************************
+ TPROCSYM
+****************************************************************************}
+
+ constructor tprocsym.create(const n : string);
+
+ begin
+ inherited create(n);
+ typ:=procsym;
+ pdlistfirst:=nil;
+ pdlistlast:=nil;
+ owner:=nil;
+ { the tprocdef have their own symoptions, make the procsym
+ always visible }
+ symoptions:=[sp_public];
+ overloadchecked:=false;
+ procdef_count:=0;
+ end;
+
+
+ constructor tprocsym.ppuload(ppufile:tcompilerppufile);
+ var
+ pdderef : tderef;
+ i,n : longint;
+ begin
+ inherited ppuload(ppufile);
+ typ:=procsym;
+ pdlistfirst:=nil;
+ pdlistlast:=nil;
+ procdef_count:=0;
+ n:=ppufile.getword;
+ for i:=1to n do
+ begin
+ ppufile.getderef(pdderef);
+ addprocdef_deref(pdderef);
+ end;
+ overloadchecked:=false;
+ end;
+
+
+ destructor tprocsym.destroy;
+ var
+ hp,p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ hp:=p^.next;
+ dispose(p);
+ p:=hp;
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tprocsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ p : pprocdeflist;
+ n : word;
+ begin
+ inherited ppuwrite(ppufile);
+ { count procdefs }
+ n:=0;
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ { only write the proc definitions that belong
+ to this procsym and are in the global symtable }
+ if p^.def.owner=owner then
+ inc(n);
+ p:=p^.next;
+ end;
+ ppufile.putword(n);
+ { write procdefs }
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ { only write the proc definitions that belong
+ to this procsym and are in the global symtable }
+ if p^.def.owner=owner then
+ ppufile.putderef(p^.defderef);
+ p:=p^.next;
+ end;
+ ppufile.writeentry(ibprocsym);
+ end;
+
+
+ procedure tprocsym.write_parameter_lists(skipdef:tprocdef);
+ var
+ p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if p^.def<>skipdef then
+ MessagePos1(p^.def.fileinfo,sym_h_param_list,p^.def.fullprocname(false));
+ p:=p^.next;
+ end;
+ end;
+
+ {Makes implicit externals (procedures declared in the interface
+ section which do not have a counterpart in the implementation)
+ to be an imported procedure. For mode macpas.}
+ procedure import_implict_external(pd:tabstractprocdef);
+
+ begin
+ tprocdef(pd).forwarddef:=false;
+ tprocdef(pd).setmangledname(target_info.CPrefix+tprocdef(pd).procsym.realname);
+ end;
+
+
+ procedure tprocsym.check_forward;
+ var
+ p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if (p^.def.owner=owner) and (p^.def.forwarddef) then
+ begin
+ if (m_mac in aktmodeswitches) and (p^.def.interfacedef) then
+ import_implict_external(p^.def)
+ else
+ begin
+ MessagePos1(p^.def.fileinfo,sym_e_forward_not_resolved,p^.def.fullprocname(false));
+ { Turn further error messages off }
+ p^.def.forwarddef:=false;
+ end
+ end;
+ p:=p^.next;
+ end;
+ end;
+
+
+ procedure tprocsym.buildderef;
+ var
+ p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if p^.def.owner=owner then
+ p^.defderef.build(p^.def);
+ p:=p^.next;
+ end;
+ end;
+
+
+ procedure tprocsym.deref;
+ var
+ p : pprocdeflist;
+ begin
+ { We have removed the overloaded entries, because they
+ are not valid anymore and we can't deref them because
+ the unit were they come from is not necessary in
+ our uses clause (PFV) }
+ unchain_overload;
+ { Deref our own procdefs }
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if not(
+ (p^.def=nil) or
+ (p^.def.owner=owner)
+ ) then
+ internalerror(200310291);
+ p^.def:=tprocdef(p^.defderef.resolve);
+ p:=p^.next;
+ end;
+ end;
+
+
+ procedure tprocsym.addprocdef(p:tprocdef);
+ var
+ pd : pprocdeflist;
+ begin
+ new(pd);
+ pd^.def:=p;
+ pd^.defderef.reset;
+ pd^.next:=nil;
+ { Add at end of list to keep always
+ a correct order, also after loading from ppu }
+ if assigned(pdlistlast) then
+ begin
+ pdlistlast^.next:=pd;
+ pdlistlast:=pd;
+ end
+ else
+ begin
+ pdlistfirst:=pd;
+ pdlistlast:=pd;
+ end;
+ inc(procdef_count);
+ end;
+
+
+ procedure tprocsym.addprocdef_deref(const d:tderef);
+ var
+ pd : pprocdeflist;
+ begin
+ new(pd);
+ pd^.def:=nil;
+ pd^.defderef:=d;
+ pd^.next:=nil;
+ { Add at end of list to keep always
+ a correct order, also after loading from ppu }
+ if assigned(pdlistlast) then
+ begin
+ pdlistlast^.next:=pd;
+ pdlistlast:=pd;
+ end
+ else
+ begin
+ pdlistfirst:=pd;
+ pdlistlast:=pd;
+ end;
+ inc(procdef_count);
+ end;
+
+
+ function Tprocsym.getprocdef(nr:cardinal):Tprocdef;
+ var
+ i : cardinal;
+ pd : pprocdeflist;
+ begin
+ pd:=pdlistfirst;
+ for i:=2 to nr do
+ begin
+ if not assigned(pd) then
+ internalerror(200209051);
+ pd:=pd^.next;
+ end;
+ getprocdef:=pd^.def;
+ end;
+
+
+ procedure Tprocsym.add_para_match_to(Aprocsym:Tprocsym;cpoptions:tcompare_paras_options);
+ var
+ pd:pprocdeflist;
+ begin
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ if Aprocsym.search_procdef_bypara(pd^.def.paras,nil,cpoptions)=nil then
+ Aprocsym.addprocdef(pd^.def);
+ pd:=pd^.next;
+ end;
+ end;
+
+
+ procedure Tprocsym.concat_procdefs_to(s:Tprocsym);
+ var
+ pd : pprocdeflist;
+ begin
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ s.addprocdef(pd^.def);
+ pd:=pd^.next;
+ end;
+ end;
+
+
+ function Tprocsym.first_procdef:Tprocdef;
+ begin
+ if assigned(pdlistfirst) then
+ first_procdef:=pdlistfirst^.def
+ else
+ first_procdef:=nil;
+ end;
+
+
+ function Tprocsym.last_procdef:Tprocdef;
+ begin
+ if assigned(pdlistlast) then
+ last_procdef:=pdlistlast^.def
+ else
+ last_procdef:=nil;
+ end;
+
+
+ procedure Tprocsym.foreach_procdef_static(proc2call:Tprocdefcallback;arg:pointer);
+ var
+ p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ proc2call(p^.def,arg);
+ p:=p^.next;
+ end;
+ end;
+
+
+ function Tprocsym.search_procdef_nopara_boolret:Tprocdef;
+ var
+ p : pprocdeflist;
+ begin
+ search_procdef_nopara_boolret:=nil;
+ p:=pdlistfirst;
+ while p<>nil do
+ begin
+ if (p^.def.maxparacount=0) and
+ is_boolean(p^.def.rettype.def) then
+ begin
+ search_procdef_nopara_boolret:=p^.def;
+ break;
+ end;
+ p:=p^.next;
+ end;
+ end;
+
+
+ function Tprocsym.search_procdef_bytype(pt:Tproctypeoption):Tprocdef;
+ var
+ p : pprocdeflist;
+ begin
+ search_procdef_bytype:=nil;
+ p:=pdlistfirst;
+ while p<>nil do
+ begin
+ if p^.def.proctypeoption=pt then
+ begin
+ search_procdef_bytype:=p^.def;
+ break;
+ end;
+ p:=p^.next;
+ end;
+ end;
+
+
+ function Tprocsym.search_procdef_bypara(para:tlist;retdef:tdef;
+ cpoptions:tcompare_paras_options):Tprocdef;
+ var
+ pd : pprocdeflist;
+ eq : tequaltype;
+ begin
+ search_procdef_bypara:=nil;
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ if assigned(retdef) then
+ eq:=compare_defs(retdef,pd^.def.rettype.def,nothingn)
+ else
+ eq:=te_equal;
+ if (eq>=te_equal) or
+ ((cpo_allowconvert in cpoptions) and (eq>te_incompatible)) then
+ begin
+ eq:=compare_paras(para,pd^.def.paras,cp_value_equal_const,cpoptions);
+ if (eq>=te_equal) or
+ ((cpo_allowconvert in cpoptions) and (eq>te_incompatible)) then
+ begin
+ search_procdef_bypara:=pd^.def;
+ break;
+ end;
+ end;
+ pd:=pd^.next;
+ end;
+ end;
+
+ function Tprocsym.search_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
+ var
+ pd : pprocdeflist;
+ eq,besteq : tequaltype;
+ bestpd : tprocdef;
+ begin
+ { This function will return the pprocdef of pprocsym that
+ is the best match for procvardef. When there are multiple
+ matches it returns nil.}
+ search_procdef_byprocvardef:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ eq:=proc_to_procvar_equal(pd^.def,d);
+ if eq>=te_equal then
+ begin
+ { multiple procvars with the same equal level }
+ if assigned(bestpd) and
+ (besteq=eq) then
+ exit;
+ if eq>besteq then
+ begin
+ besteq:=eq;
+ bestpd:=pd^.def;
+ end;
+ end;
+ pd:=pd^.next;
+ end;
+ search_procdef_byprocvardef:=bestpd;
+ end;
+
+
+ function Tprocsym.search_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ var
+ convtyp : tconverttype;
+ pd : pprocdeflist;
+ bestpd : tprocdef;
+ eq : tequaltype;
+ hpd : tprocdef;
+ i : byte;
+ begin
+ result:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ if equal_defs(todef,pd^.def.rettype.def) and
+ { the result type must be always really equal and not an alias,
+ if you mess with this code, check tw4093 }
+ ((todef=pd^.def.rettype.def) or
+ (
+ not(df_unique in todef.defoptions) and
+ not(df_unique in pd^.def.rettype.def.defoptions)
+ )
+ ) then
+ begin
+ i:=0;
+ { ignore vs_hidden parameters }
+ while (i<pd^.def.paras.count) and
+ assigned(pd^.def.paras[i]) and
+ (vo_is_hidden_para in tparavarsym(pd^.def.paras[i]).varoptions) do
+ inc(i);
+ if (i<pd^.def.paras.count) and
+ assigned(pd^.def.paras[i]) then
+ begin
+ eq:=compare_defs_ext(fromdef,tparavarsym(pd^.def.paras[i]).vartype.def,nothingn,convtyp,hpd,[]);
+
+ { alias? if yes, only l1 choice,
+ if you mess with this code, check tw4093 }
+ if (eq=te_exact) and
+ (fromdef<>tparavarsym(pd^.def.paras[i]).vartype.def) and
+ ((df_unique in fromdef.defoptions) or
+ (df_unique in tparavarsym(pd^.def.paras[i]).vartype.def.defoptions)) then
+ eq:=te_convert_l1;
+
+ if eq=te_exact then
+ begin
+ besteq:=eq;
+ result:=pd^.def;
+ exit;
+ end;
+ if eq>besteq then
+ begin
+ bestpd:=pd^.def;
+ besteq:=eq;
+ end;
+ end;
+ end;
+ pd:=pd^.next;
+ end;
+ result:=bestpd;
+ end;
+
+
+ function tprocsym.write_references(ppufile:tcompilerppufile;locals:boolean) : boolean;
+ var
+ p : pprocdeflist;
+ begin
+ write_references:=false;
+ if not inherited write_references(ppufile,locals) then
+ exit;
+ write_references:=true;
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if p^.def.owner=owner then
+ p^.def.write_references(ppufile,locals);
+ p:=p^.next;
+ end;
+ end;
+
+
+ procedure tprocsym.unchain_overload;
+ var
+ p,hp : pprocdeflist;
+ begin
+ { remove all overloaded procdefs from the
+ procdeflist that are not in the current symtable }
+ overloadchecked:=false;
+ p:=pdlistfirst;
+ { reset new lists }
+ pdlistfirst:=nil;
+ pdlistlast:=nil;
+ while assigned(p) do
+ begin
+ hp:=p^.next;
+ { only keep the proc definitions:
+ - are not deref'd (def=nil)
+ - are in the same symtable as the procsym (for example both
+ are in the staticsymtable) }
+ if (p^.def=nil) or
+ (p^.def.owner=owner) then
+ begin
+ { keep, add to list }
+ if assigned(pdlistlast) then
+ begin
+ pdlistlast^.next:=p;
+ pdlistlast:=p;
+ end
+ else
+ begin
+ pdlistfirst:=p;
+ pdlistlast:=p;
+ end;
+ p^.next:=nil;
+ end
+ else
+ begin
+ { remove }
+ dispose(p);
+ dec(procdef_count);
+ end;
+ p:=hp;
+ end;
+ end;
+
+
+ function tprocsym.is_visible_for_object(currobjdef:tdef;context:tdef):boolean;
+ var
+ p : pprocdeflist;
+ begin
+ { This procsym is visible, when there is at least
+ one of the procdefs visible }
+ result:=false;
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if (p^.def.owner=owner) and
+ p^.def.is_visible_for_object(tobjectdef(currobjdef)) then
+ begin
+ result:=true;
+ exit;
+ end;
+ p:=p^.next;
+ end;
+ end;
+
+
+
+{****************************************************************************
+ TERRORSYM
+****************************************************************************}
+
+ constructor terrorsym.create;
+ begin
+ inherited create('');
+ typ:=errorsym;
+ end;
+
+{****************************************************************************
+ TPROPERTYSYM
+****************************************************************************}
+
+ constructor tpropertysym.create(const n : string);
+ begin
+ inherited create(n);
+ typ:=propertysym;
+ propoptions:=[];
+ index:=0;
+ default:=0;
+ proptype.reset;
+ indextype.reset;
+ readaccess:=tsymlist.create;
+ writeaccess:=tsymlist.create;
+ storedaccess:=tsymlist.create;
+ end;
+
+
+ constructor tpropertysym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=propertysym;
+ ppufile.getsmallset(propoptions);
+ if (ppo_is_override in propoptions) then
+ begin
+ ppufile.getderef(propoverridenderef);
+ { we need to have these objects initialized }
+ readaccess:=tsymlist.create;
+ writeaccess:=tsymlist.create;
+ storedaccess:=tsymlist.create;
+ end
+ else
+ begin
+ ppufile.gettype(proptype);
+ index:=ppufile.getlongint;
+ default:=ppufile.getlongint;
+ ppufile.gettype(indextype);
+ readaccess:=ppufile.getsymlist;
+ writeaccess:=ppufile.getsymlist;
+ storedaccess:=ppufile.getsymlist;
+ end;
+ end;
+
+
+ destructor tpropertysym.destroy;
+ begin
+ readaccess.free;
+ writeaccess.free;
+ storedaccess.free;
+ inherited destroy;
+ end;
+
+
+ function tpropertysym.gettypedef:tdef;
+ begin
+ gettypedef:=proptype.def;
+ end;
+
+
+ procedure tpropertysym.buildderef;
+ begin
+ if (ppo_is_override in propoptions) then
+ begin
+ propoverridenderef.build(propoverriden);
+ end
+ else
+ begin
+ proptype.buildderef;
+ indextype.buildderef;
+ readaccess.buildderef;
+ writeaccess.buildderef;
+ storedaccess.buildderef;
+ end;
+ end;
+
+
+ procedure tpropertysym.deref;
+ begin
+ if (ppo_is_override in propoptions) then
+ begin
+ propoverriden:=tpropertysym(propoverridenderef.resolve);
+ dooverride(propoverriden);
+ end
+ else
+ begin
+ proptype.resolve;
+ indextype.resolve;
+ readaccess.resolve;
+ writeaccess.resolve;
+ storedaccess.resolve;
+ end;
+ end;
+
+
+ function tpropertysym.getsize : longint;
+ begin
+ getsize:=0;
+ end;
+
+
+ procedure tpropertysym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putsmallset(propoptions);
+ if (ppo_is_override in propoptions) then
+ ppufile.putderef(propoverridenderef)
+ else
+ begin
+ ppufile.puttype(proptype);
+ ppufile.putlongint(index);
+ ppufile.putlongint(default);
+ ppufile.puttype(indextype);
+ ppufile.putsymlist(readaccess);
+ ppufile.putsymlist(writeaccess);
+ ppufile.putsymlist(storedaccess);
+ end;
+ ppufile.writeentry(ibpropertysym);
+ end;
+
+
+ procedure tpropertysym.dooverride(overriden:tpropertysym);
+ begin
+ propoverriden:=overriden;
+ proptype:=overriden.proptype;
+ propoptions:=overriden.propoptions+[ppo_is_override];
+ index:=overriden.index;
+ default:=overriden.default;
+ indextype:=overriden.indextype;
+ readaccess.free;
+ readaccess:=overriden.readaccess.getcopy;
+ writeaccess.free;
+ writeaccess:=overriden.writeaccess.getcopy;
+ storedaccess.free;
+ storedaccess:=overriden.storedaccess.getcopy;
+ end;
+
+
+{****************************************************************************
+ TABSTRACTVARSYM
+****************************************************************************}
+
+ constructor tabstractvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n);
+ vartype:=tt;
+ varspez:=vsp;
+ varstate:=vs_declared;
+ varoptions:=vopts;
+ end;
+
+
+ constructor tabstractvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ varstate:=vs_used;
+ varspez:=tvarspez(ppufile.getbyte);
+ varregable:=tvarregable(ppufile.getbyte);
+ ppufile.gettype(_vartype);
+ ppufile.getsmallset(varoptions);
+ end;
+
+
+ destructor tabstractvarsym.destroy;
+ begin
+ if assigned(notifications) then
+ notifications.destroy;
+ inherited destroy;
+ end;
+
+
+ procedure tabstractvarsym.buildderef;
+ begin
+ vartype.buildderef;
+ end;
+
+
+ procedure tabstractvarsym.deref;
+ begin
+ vartype.resolve;
+ end;
+
+
+ procedure tabstractvarsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(varspez));
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ ppufile.putbyte(byte(varregable));
+ ppufile.do_crc:=oldintfcrc;
+ ppufile.puttype(vartype);
+ ppufile.putsmallset(varoptions);
+ end;
+
+
+ function tabstractvarsym.getsize : longint;
+ begin
+ if assigned(vartype.def) and
+ ((vartype.def.deftype<>arraydef) or
+ tarraydef(vartype.def).isDynamicArray or
+ (tarraydef(vartype.def).highrange>=tarraydef(vartype.def).lowrange)) then
+ result:=vartype.def.size
+ else
+ result:=0;
+ end;
+
+
+ function tabstractvarsym.is_regvar:boolean;
+ begin
+ { Register variables are not allowed in the following cases:
+ - regvars are disabled
+ - exceptions are used (after an exception is raised the contents of the
+ registers is not valid anymore)
+ - it has a local copy
+ - the value needs to be in memory (i.e. reference counted) }
+ result:=(cs_regvars in aktglobalswitches) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) and
+ not(vo_has_local_copy in varoptions) and
+ (varregable<>vr_none);
+ end;
+
+
+ procedure tabstractvarsym.trigger_notifications(what:Tnotification_flag);
+
+ var n:Tnotification;
+
+ begin
+ if assigned(notifications) then
+ begin
+ n:=Tnotification(notifications.first);
+ while assigned(n) do
+ begin
+ if what in n.flags then
+ n.callback(what,self);
+ n:=Tnotification(n.next);
+ end;
+ end;
+ end;
+
+ function Tabstractvarsym.register_notification(flags:Tnotification_flags;callback:
+ Tnotification_callback):cardinal;
+
+ var n:Tnotification;
+
+ begin
+ if not assigned(notifications) then
+ notifications:=Tlinkedlist.create;
+ n:=Tnotification.create(flags,callback);
+ register_notification:=n.id;
+ notifications.concat(n);
+ end;
+
+ procedure Tabstractvarsym.unregister_notification(id:cardinal);
+
+ var n:Tnotification;
+
+ begin
+ if not assigned(notifications) then
+ internalerror(200212311)
+ else
+ begin
+ n:=Tnotification(notifications.first);
+ while assigned(n) do
+ begin
+ if n.id=id then
+ begin
+ notifications.remove(n);
+ n.destroy;
+ exit;
+ end;
+ n:=Tnotification(n.next);
+ end;
+ internalerror(200212311)
+ end;
+ end;
+
+ procedure tabstractvarsym.setvartype(const newtype: ttype);
+ begin
+ _vartype := newtype;
+ { can we load the value into a register ? }
+ if not assigned(owner) or
+ (owner.symtabletype in [localsymtable,parasymtable]) or
+ (
+ (owner.symtabletype=staticsymtable) and
+ not(cs_create_pic in aktmoduleswitches)
+ ) then
+ begin
+ if tstoreddef(vartype.def).is_intregable then
+ varregable:=vr_intreg
+ else
+{ $warning TODO: no fpu regvar in staticsymtable yet, need initialization with 0 }
+ if {(
+ not assigned(owner) or
+ (owner.symtabletype<>staticsymtable)
+ ) and }
+ tstoreddef(vartype.def).is_fpuregable then
+ begin
+{$ifdef x86}
+ if use_sse(vartype.def) then
+ varregable:=vr_mmreg
+ else
+{$else x86}
+ varregable:=vr_fpureg;
+{$endif x86}
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TFIELDVARSYM
+****************************************************************************}
+
+ constructor tfieldvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ typ:=fieldvarsym;
+ fieldoffset:=0;
+ end;
+
+
+ constructor tfieldvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=fieldvarsym;
+ fieldoffset:=ppufile.getaint;
+ end;
+
+
+ procedure tfieldvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putaint(fieldoffset);
+ ppufile.writeentry(ibfieldvarsym);
+ end;
+
+
+{****************************************************************************
+ TABSTRACTNORMALVARSYM
+****************************************************************************}
+
+ constructor tabstractnormalvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ fillchar(localloc,sizeof(localloc),0);
+ defaultconstsym:=nil;
+ end;
+
+
+ constructor tabstractnormalvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ fillchar(localloc,sizeof(localloc),0);
+ ppufile.getderef(defaultconstsymderef);
+ end;
+
+
+ procedure tabstractnormalvarsym.buildderef;
+ begin
+ inherited buildderef;
+ defaultconstsymderef.build(defaultconstsym);
+ end;
+
+
+ procedure tabstractnormalvarsym.deref;
+ begin
+ inherited deref;
+ defaultconstsym:=tsym(defaultconstsymderef.resolve);
+ end;
+
+
+ procedure tabstractnormalvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(defaultconstsymderef);
+ end;
+
+
+{****************************************************************************
+ TGLOBALVARSYM
+****************************************************************************}
+
+ constructor tglobalvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ typ:=globalvarsym;
+ _mangledname:=nil;
+ end;
+
+
+ constructor tglobalvarsym.create_dll(const n : string;vsp:tvarspez;const tt : ttype);
+ begin
+ tglobalvarsym(self).create(n,vsp,tt,[vo_is_dll_var]);
+ end;
+
+
+ constructor tglobalvarsym.create_C(const n,mangled : string;vsp:tvarspez;const tt : ttype);
+ begin
+ tglobalvarsym(self).create(n,vsp,tt,[]);
+ set_mangledname(mangled);
+ end;
+
+
+ constructor tglobalvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=globalvarsym;
+ if vo_has_mangledname in varoptions then
+ _mangledname:=stringdup(ppufile.getstring)
+ else
+ _mangledname:=nil;
+ end;
+
+
+ destructor tglobalvarsym.destroy;
+ begin
+ if assigned(_mangledname) then
+ begin
+{$ifdef MEMDEBUG}
+ memmanglednames.start;
+{$endif MEMDEBUG}
+ stringdispose(_mangledname);
+{$ifdef MEMDEBUG}
+ memmanglednames.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tglobalvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ if vo_has_mangledname in varoptions then
+ ppufile.putstring(_mangledname^);
+ ppufile.writeentry(ibglobalvarsym);
+ end;
+
+
+ function tglobalvarsym.mangledname:string;
+ begin
+ if not assigned(_mangledname) then
+ begin
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(make_mangledname('U',owner,name)));
+ {$else}
+ _mangledname:=stringdup(make_mangledname('U',owner,name));
+ {$endif}
+ end;
+ result:=_mangledname^;
+ end;
+
+
+ procedure tglobalvarsym.set_mangledname(const s:string);
+ begin
+ stringdispose(_mangledname);
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(s));
+ {$else}
+ _mangledname:=stringdup(s);
+ {$endif}
+ include(varoptions,vo_has_mangledname);
+ end;
+
+
+{****************************************************************************
+ TLOCALVARSYM
+****************************************************************************}
+
+ constructor tlocalvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ typ:=localvarsym;
+ end;
+
+
+ constructor tlocalvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=localvarsym;
+ end;
+
+
+ procedure tlocalvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(iblocalvarsym);
+ end;
+
+
+{****************************************************************************
+ TPARAVARSYM
+****************************************************************************}
+
+ constructor tparavarsym.create(const n : string;nr:word;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ typ:=paravarsym;
+ paranr:=nr;
+ paraloc[calleeside].init;
+ paraloc[callerside].init;
+ end;
+
+
+ destructor tparavarsym.destroy;
+ begin
+ paraloc[calleeside].done;
+ paraloc[callerside].done;
+ inherited destroy;
+ end;
+
+
+ constructor tparavarsym.ppuload(ppufile:tcompilerppufile);
+ var
+ b : byte;
+ begin
+ inherited ppuload(ppufile);
+ paranr:=ppufile.getword;
+ paraloc[calleeside].init;
+ paraloc[callerside].init;
+ if vo_has_explicit_paraloc in varoptions then
+ begin
+ b:=ppufile.getbyte;
+ if b<>sizeof(paraloc[callerside].location^) then
+ internalerror(200411154);
+ ppufile.getdata(paraloc[callerside].add_location^,sizeof(paraloc[callerside].location^));
+ paraloc[callerside].size:=paraloc[callerside].location^.size;
+ paraloc[callerside].intsize:=tcgsize2size[paraloc[callerside].size];
+ end;
+ typ:=paravarsym;
+ end;
+
+
+ procedure tparavarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putword(paranr);
+ if vo_has_explicit_paraloc in varoptions then
+ begin
+ paraloc[callerside].check_simple_location;
+ ppufile.putbyte(sizeof(paraloc[callerside].location^));
+ ppufile.putdata(paraloc[callerside].location^,sizeof(paraloc[callerside].location^));
+ end;
+ ppufile.writeentry(ibparavarsym);
+ end;
+
+
+{****************************************************************************
+ TABSOLUTEVARSYM
+****************************************************************************}
+
+ constructor tabsolutevarsym.create(const n : string;const tt : ttype);
+ begin
+ inherited create(n,vs_value,tt,[]);
+ typ:=absolutevarsym;
+ ref:=nil;
+ end;
+
+
+ constructor tabsolutevarsym.create_ref(const n : string;const tt : ttype;_ref:tsymlist);
+ begin
+ inherited create(n,vs_value,tt,[]);
+ typ:=absolutevarsym;
+ ref:=_ref;
+ end;
+
+
+ destructor tabsolutevarsym.destroy;
+ begin
+ if assigned(ref) then
+ ref.free;
+ inherited destroy;
+ end;
+
+
+ constructor tabsolutevarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=absolutevarsym;
+ ref:=nil;
+ asmname:=nil;
+ abstyp:=absolutetyp(ppufile.getbyte);
+{$ifdef i386}
+ absseg:=false;
+{$endif i386}
+ case abstyp of
+ tovar :
+ ref:=ppufile.getsymlist;
+ toasm :
+ asmname:=stringdup(ppufile.getstring);
+ toaddr :
+ begin
+ addroffset:=ppufile.getaint;
+{$ifdef i386}
+ absseg:=boolean(ppufile.getbyte);
+{$endif i386}
+ end;
+ end;
+ end;
+
+
+ procedure tabsolutevarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(abstyp));
+ case abstyp of
+ tovar :
+ ppufile.putsymlist(ref);
+ toasm :
+ ppufile.putstring(asmname^);
+ toaddr :
+ begin
+ ppufile.putaint(addroffset);
+{$ifdef i386}
+ ppufile.putbyte(byte(absseg));
+{$endif i386}
+ end;
+ end;
+ ppufile.writeentry(ibabsolutevarsym);
+ end;
+
+
+ procedure tabsolutevarsym.buildderef;
+ begin
+ inherited buildderef;
+ if (abstyp=tovar) then
+ ref.buildderef;
+ end;
+
+
+ procedure tabsolutevarsym.deref;
+ begin
+ inherited deref;
+ { own absolute deref }
+ if (abstyp=tovar) then
+ ref.resolve;
+ end;
+
+
+ function tabsolutevarsym.mangledname : string;
+ begin
+ case abstyp of
+ toasm :
+ mangledname:=asmname^;
+ toaddr :
+ mangledname:='$'+tostr(addroffset);
+ else
+ internalerror(200411061);
+ end;
+ end;
+
+
+{****************************************************************************
+ TTYPEDCONSTSYM
+*****************************************************************************}
+
+ constructor ttypedconstsym.create(const n : string;p : tdef;writable : boolean);
+ begin
+ inherited create(n);
+ typ:=typedconstsym;
+ typedconsttype.setdef(p);
+ is_writable:=writable;
+ end;
+
+
+ constructor ttypedconstsym.createtype(const n : string;const tt : ttype;writable : boolean);
+ begin
+ inherited create(n);
+ typ:=typedconstsym;
+ typedconsttype:=tt;
+ is_writable:=writable;
+ end;
+
+
+ constructor ttypedconstsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=typedconstsym;
+ ppufile.gettype(typedconsttype);
+ is_writable:=boolean(ppufile.getbyte);
+ end;
+
+
+ destructor ttypedconstsym.destroy;
+ begin
+ if assigned(_mangledname) then
+ begin
+{$ifdef MEMDEBUG}
+ memmanglednames.start;
+{$endif MEMDEBUG}
+ stringdispose(_mangledname);
+{$ifdef MEMDEBUG}
+ memmanglednames.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+ function ttypedconstsym.mangledname:string;
+ begin
+ if not assigned(_mangledname) then
+ begin
+ {$ifdef compress}
+ _mangledname:=stringdup(make_mangledname('TC',owner,name));
+ {$else}
+ _mangledname:=stringdup(make_mangledname('TC',owner,name));
+ {$endif}
+ end;
+ result:=_mangledname^;
+ end;
+
+
+ function ttypedconstsym.getsize : longint;
+ begin
+ if assigned(typedconsttype.def) then
+ getsize:=typedconsttype.def.size
+ else
+ getsize:=0;
+ end;
+
+
+ procedure ttypedconstsym.buildderef;
+ begin
+ typedconsttype.buildderef;
+ end;
+
+
+ procedure ttypedconstsym.deref;
+ begin
+ typedconsttype.resolve;
+ end;
+
+
+ procedure ttypedconstsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(typedconsttype);
+ ppufile.putbyte(byte(is_writable));
+ ppufile.writeentry(ibtypedconstsym);
+ end;
+
+
+{****************************************************************************
+ TCONSTSYM
+****************************************************************************}
+
+ constructor tconstsym.create_ord(const n : string;t : tconsttyp;v : tconstexprint;const tt:ttype);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ value.valueord:=v;
+ ResStrIndex:=0;
+ consttype:=tt;
+ end;
+
+
+ constructor tconstsym.create_ordptr(const n : string;t : tconsttyp;v : tconstptruint;const tt:ttype);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ value.valueordptr:=v;
+ ResStrIndex:=0;
+ consttype:=tt;
+ end;
+
+
+ constructor tconstsym.create_ptr(const n : string;t : tconsttyp;v : pointer;const tt:ttype);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ value.valueptr:=v;
+ ResStrIndex:=0;
+ consttype:=tt;
+ end;
+
+
+ constructor tconstsym.create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ value.valueptr:=str;
+ consttype.reset;
+ value.len:=l;
+ if t=constresourcestring then
+ ResStrIndex:=resourcestrings.Register(name,pchar(value.valueptr),value.len);
+ end;
+
+
+ constructor tconstsym.create_wstring(const n : string;t : tconsttyp;pw:pcompilerwidestring);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ pcompilerwidestring(value.valueptr):=pw;
+ consttype.reset;
+ value.len:=getlengthwidestring(pw);
+ end;
+
+
+ constructor tconstsym.ppuload(ppufile:tcompilerppufile);
+ var
+ pd : pbestreal;
+ ps : pnormalset;
+ pc : pchar;
+ pw : pcompilerwidestring;
+ begin
+ inherited ppuload(ppufile);
+ typ:=constsym;
+ consttype.reset;
+ consttyp:=tconsttyp(ppufile.getbyte);
+ fillchar(value, sizeof(value), #0);
+ case consttyp of
+ constord :
+ begin
+ ppufile.gettype(consttype);
+ value.valueord:=ppufile.getexprint;
+ end;
+ constpointer :
+ begin
+ ppufile.gettype(consttype);
+ value.valueordptr:=ppufile.getptruint;
+ end;
+ constwstring :
+ begin
+ initwidestring(pw);
+ setlengthwidestring(pw,ppufile.getlongint);
+ ppufile.getdata(pw^.data,pw^.len*sizeof(tcompilerwidechar));
+ pcompilerwidestring(value.valueptr):=pw;
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ value.len:=ppufile.getlongint;
+ getmem(pc,value.len+1);
+ ppufile.getdata(pc^,value.len);
+ if consttyp=constresourcestring then
+ ResStrIndex:=ppufile.getlongint;
+ value.valueptr:=pc;
+ end;
+ constreal :
+ begin
+ new(pd);
+ pd^:=ppufile.getreal;
+ value.valueptr:=pd;
+ end;
+ constset :
+ begin
+ ppufile.gettype(consttype);
+ new(ps);
+ ppufile.getnormalset(ps^);
+ value.valueptr:=ps;
+ end;
+ constguid :
+ begin
+ new(pguid(value.valueptr));
+ ppufile.getdata(value.valueptr^,sizeof(tguid));
+ end;
+ constnil : ;
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(ord(consttyp)));
+ end;
+ end;
+
+
+ destructor tconstsym.destroy;
+ begin
+ case consttyp of
+ conststring,
+ constresourcestring :
+ freemem(pchar(value.valueptr),value.len+1);
+ constwstring :
+ donewidestring(pcompilerwidestring(value.valueptr));
+ constreal :
+ dispose(pbestreal(value.valueptr));
+ constset :
+ dispose(pnormalset(value.valueptr));
+ constguid :
+ dispose(pguid(value.valueptr));
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tconstsym.buildderef;
+ begin
+ if consttyp in [constord,constpointer,constset] then
+ consttype.buildderef;
+ end;
+
+
+ procedure tconstsym.deref;
+ begin
+ if consttyp in [constord,constpointer,constset] then
+ consttype.resolve;
+ end;
+
+
+ procedure tconstsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(consttyp));
+ case consttyp of
+ constnil : ;
+ constord :
+ begin
+ ppufile.puttype(consttype);
+ ppufile.putexprint(value.valueord);
+ end;
+ constpointer :
+ begin
+ ppufile.puttype(consttype);
+ ppufile.putptruint(value.valueordptr);
+ end;
+ constwstring :
+ begin
+ ppufile.putlongint(getlengthwidestring(pcompilerwidestring(value.valueptr)));
+ ppufile.putdata(pcompilerwidestring(value.valueptr)^.data,pcompilerwidestring(value.valueptr)^.len*sizeof(tcompilerwidechar));
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ ppufile.putlongint(value.len);
+ ppufile.putdata(pchar(value.valueptr)^,value.len);
+ if consttyp=constresourcestring then
+ ppufile.putlongint(ResStrIndex);
+ end;
+ constreal :
+ ppufile.putreal(pbestreal(value.valueptr)^);
+ constset :
+ begin
+ ppufile.puttype(consttype);
+ ppufile.putnormalset(value.valueptr^);
+ end;
+ constguid :
+ ppufile.putdata(value.valueptr^,sizeof(tguid));
+ else
+ internalerror(13);
+ end;
+ ppufile.writeentry(ibconstsym);
+ end;
+
+
+{****************************************************************************
+ TENUMSYM
+****************************************************************************}
+
+ constructor tenumsym.create(const n : string;def : tenumdef;v : longint);
+ begin
+ inherited create(n);
+ typ:=enumsym;
+ definition:=def;
+ value:=v;
+ { First entry? Then we need to set the minval }
+ if def.firstenum=nil then
+ begin
+ if v>0 then
+ def.has_jumps:=true;
+ def.setmin(v);
+ def.setmax(v);
+ end
+ else
+ begin
+ { check for jumps }
+ if v>def.max+1 then
+ def.has_jumps:=true;
+ { update low and high }
+ if def.min>v then
+ def.setmin(v);
+ if def.max<v then
+ def.setmax(v);
+ end;
+ order;
+ end;
+
+
+ constructor tenumsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=enumsym;
+ ppufile.getderef(definitionderef);
+ value:=ppufile.getlongint;
+ nextenum := Nil;
+ end;
+
+
+ procedure tenumsym.buildderef;
+ begin
+ definitionderef.build(definition);
+ end;
+
+
+ procedure tenumsym.deref;
+ begin
+ definition:=tenumdef(definitionderef.resolve);
+ order;
+ end;
+
+ procedure tenumsym.order;
+ var
+ sym : tenumsym;
+ begin
+ sym := tenumsym(definition.firstenum);
+ if sym = nil then
+ begin
+ definition.firstenum := self;
+ nextenum := nil;
+ exit;
+ end;
+ { reorder the symbols in increasing value }
+ if value < sym.value then
+ begin
+ nextenum := sym;
+ definition.firstenum := self;
+ end
+ else
+ begin
+ while (sym.value <= value) and assigned(sym.nextenum) do
+ sym := sym.nextenum;
+ nextenum := sym.nextenum;
+ sym.nextenum := self;
+ end;
+ end;
+
+ procedure tenumsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(definitionderef);
+ ppufile.putlongint(value);
+ ppufile.writeentry(ibenumsym);
+ end;
+
+
+{****************************************************************************
+ TTYPESYM
+****************************************************************************}
+
+ constructor ttypesym.create(const n : string;const tt : ttype);
+
+ begin
+ inherited create(n);
+ typ:=typesym;
+ restype:=tt;
+ { register the typesym for the definition }
+ if assigned(restype.def) and
+ (restype.def.deftype<>errordef) and
+ not(assigned(restype.def.typesym)) then
+ restype.def.typesym:=self;
+ end;
+
+
+ constructor ttypesym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=typesym;
+ ppufile.gettype(restype);
+ end;
+
+
+ function ttypesym.gettypedef:tdef;
+ begin
+ gettypedef:=restype.def;
+ end;
+
+
+ procedure ttypesym.buildderef;
+ begin
+ restype.buildderef;
+ end;
+
+
+ procedure ttypesym.deref;
+ begin
+ restype.resolve;
+ end;
+
+
+ procedure ttypesym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(restype);
+ ppufile.writeentry(ibtypesym);
+ end;
+
+
+ procedure ttypesym.load_references(ppufile:tcompilerppufile;locals:boolean);
+ begin
+ inherited load_references(ppufile,locals);
+ if (restype.def.deftype=recorddef) then
+ tstoredsymtable(trecorddef(restype.def).symtable).load_references(ppufile,locals);
+ if (restype.def.deftype=objectdef) then
+ tstoredsymtable(tobjectdef(restype.def).symtable).load_references(ppufile,locals);
+ end;
+
+
+ function ttypesym.write_references(ppufile:tcompilerppufile;locals:boolean):boolean;
+ var
+ d : tderef;
+ begin
+ d.reset;
+ if not inherited write_references(ppufile,locals) then
+ begin
+ { write address of this symbol if record or object
+ even if no real refs are there
+ because we need it for the symtable }
+ if (restype.def.deftype in [recorddef,objectdef]) then
+ begin
+ d.build(self);
+ ppufile.putderef(d);
+ ppufile.writeentry(ibsymref);
+ end;
+ end;
+ write_references:=true;
+ if (restype.def.deftype=recorddef) then
+ tstoredsymtable(trecorddef(restype.def).symtable).write_references(ppufile,locals);
+ if (restype.def.deftype=objectdef) then
+ tstoredsymtable(tobjectdef(restype.def).symtable).write_references(ppufile,locals);
+ end;
+
+
+{****************************************************************************
+ TSYSSYM
+****************************************************************************}
+
+ constructor tsyssym.create(const n : string;l : longint);
+ begin
+ inherited create(n);
+ typ:=syssym;
+ number:=l;
+ end;
+
+ constructor tsyssym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=syssym;
+ number:=ppufile.getlongint;
+ end;
+
+ destructor tsyssym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+ procedure tsyssym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(number);
+ ppufile.writeentry(ibsyssym);
+ end;
+
+
+{*****************************************************************************
+ TMacro
+*****************************************************************************}
+
+ constructor tmacro.create(const n : string);
+ begin
+ inherited create(n);
+ typ:= macrosym;
+ owner:= nil;
+
+ defined:=false;
+ is_used:=false;
+ is_compiler_var:= false;
+ buftext:=nil;
+ buflen:=0;
+ end;
+
+ constructor tmacro.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=macrosym;
+ name:=ppufile.getstring;
+ defined:=boolean(ppufile.getbyte);
+ is_compiler_var:=boolean(ppufile.getbyte);
+ is_used:=false;
+ buflen:= ppufile.getlongint;
+ if buflen > 0 then
+ begin
+ getmem(buftext, buflen);
+ ppufile.getdata(buftext^, buflen)
+ end
+ else
+ buftext:=nil;
+ end;
+
+ destructor tmacro.destroy;
+ begin
+ if assigned(buftext) then
+ freemem(buftext,buflen);
+ inherited destroy;
+ end;
+
+ procedure tmacro.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putstring(name);
+ ppufile.putbyte(byte(defined));
+ ppufile.putbyte(byte(is_compiler_var));
+ ppufile.putlongint(buflen);
+ if buflen > 0 then
+ ppufile.putdata(buftext^,buflen);
+ ppufile.writeentry(ibmacrosym);
+ end;
+
+
+{****************************************************************************
+ TRTTISYM
+****************************************************************************}
+
+ constructor trttisym.create(const n:string;rt:trttitype);
+ const
+ prefix : array[trttitype] of string[5]=('$rtti','$init');
+ begin
+ inherited create(prefix[rt]+n);
+ include(symoptions,sp_internal);
+ typ:=rttisym;
+ lab:=nil;
+ rttityp:=rt;
+ end;
+
+
+ destructor trttisym.destroy;
+ begin
+ if assigned(_mangledname) then
+ begin
+{$ifdef MEMDEBUG}
+ memmanglednames.start;
+{$endif MEMDEBUG}
+ stringdispose(_mangledname);
+{$ifdef MEMDEBUG}
+ memmanglednames.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+ constructor trttisym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=rttisym;
+ lab:=nil;
+ rttityp:=trttitype(ppufile.getbyte);
+ end;
+
+
+ procedure trttisym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(rttityp));
+ ppufile.writeentry(ibrttisym);
+ end;
+
+
+ function trttisym.mangledname : string;
+ const
+ prefix : array[trttitype] of string[5]=('RTTI_','INIT_');
+ begin
+ if not assigned(_mangledname) then
+ _mangledname:=stringdup(make_mangledname(prefix[rttityp],owner,Copy(name,5,255)));
+ result:=_mangledname^;
+ end;
+
+
+ function trttisym.get_label:tasmsymbol;
+ begin
+ { the label is always a global label }
+ if not assigned(lab) then
+ lab:=objectlibrary.newasmsymbol(mangledname,AB_EXTERNAL,AT_DATA);
+ get_label:=lab;
+ end;
+
+
+end.
diff --git a/compiler/symtable.pas b/compiler/symtable.pas
new file mode 100644
index 0000000000..60fcacbe31
--- /dev/null
+++ b/compiler/symtable.pas
@@ -0,0 +1,2303 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ This unit handles the symbol tables
+
+ 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 symtable;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ cpuinfo,globtype,tokens,
+ { symtable }
+ symconst,symbase,symtype,symdef,symsym,
+ { ppu }
+ ppu,
+ { assembler }
+ aasmtai
+ ;
+
+
+{****************************************************************************
+ Symtable types
+****************************************************************************}
+
+ type
+ tstoredsymtable = class(tsymtable)
+ private
+ b_needs_init_final : boolean;
+ procedure _needs_init_final(p : tnamedindexitem;arg:pointer);
+ procedure check_forward(sym : TNamedIndexItem;arg:pointer);
+ procedure labeldefined(p : TNamedIndexItem;arg:pointer);
+ procedure varsymbolused(p : TNamedIndexItem;arg:pointer);
+ procedure TestPrivate(p : TNamedIndexItem;arg:pointer);
+ procedure objectprivatesymbolused(p : TNamedIndexItem;arg:pointer);
+ procedure unchain_overloads(p : TNamedIndexItem;arg:pointer);
+ procedure loaddefs(ppufile:tcompilerppufile);
+ procedure loadsyms(ppufile:tcompilerppufile);
+ procedure reset_def(def:Tnamedindexitem;arg:pointer);
+ procedure writedefs(ppufile:tcompilerppufile);
+ procedure writesyms(ppufile:tcompilerppufile);
+ public
+ { load/write }
+ procedure ppuload(ppufile:tcompilerppufile);virtual;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ procedure load_references(ppufile:tcompilerppufile;locals:boolean);virtual;
+ procedure write_references(ppufile:tcompilerppufile;locals:boolean);virtual;
+ procedure buildderef;virtual;
+ procedure buildderefimpl;virtual;
+ procedure deref;virtual;
+ procedure derefimpl;virtual;
+ procedure duplicatesym(dupsym,sym:tsymentry);
+ procedure insert(sym : tsymentry);override;
+ procedure reset_all_defs;virtual;
+ function speedsearch(const s : stringid;speedvalue : cardinal) : tsymentry;override;
+ procedure allsymbolsused;
+ procedure allprivatesused;
+ procedure check_forwards;
+ procedure checklabels;
+ function needs_init_final : boolean;
+ procedure unchain_overloaded;
+ procedure testfordefaultproperty(p : TNamedIndexItem;arg:pointer);
+ end;
+
+ tabstractrecordsymtable = class(tstoredsymtable)
+ public
+ datasize : aint;
+ usefieldalignment, { alignment to use for fields (PACKRECORDS value), -1 is C style }
+ recordalignment, { alignment required when inserting this record }
+ fieldalignment, { alignment current alignment used when fields are inserted }
+ padalignment : shortint; { size to a multiple of which the symtable has to be rounded up }
+ constructor create(const n:string;usealign:shortint);
+ procedure ppuload(ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure load_references(ppufile:tcompilerppufile;locals:boolean);override;
+ procedure write_references(ppufile:tcompilerppufile;locals:boolean);override;
+ procedure insertfield(sym:tfieldvarsym;addsym:boolean);
+ procedure addalignmentpadding;
+ end;
+
+ trecordsymtable = class(tabstractrecordsymtable)
+ public
+ constructor create(usealign:shortint);
+ procedure insertunionst(unionst : trecordsymtable;offset : longint);
+ end;
+
+ tobjectsymtable = class(tabstractrecordsymtable)
+ public
+ constructor create(const n:string;usealign:shortint);
+ procedure insert(sym : tsymentry);override;
+ end;
+
+ tabstractlocalsymtable = class(tstoredsymtable)
+ public
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tlocalsymtable = class(tabstractlocalsymtable)
+ public
+ constructor create(level:byte);
+ procedure insert(sym : tsymentry);override;
+ end;
+
+ tparasymtable = class(tabstractlocalsymtable)
+ public
+ constructor create(level:byte);
+ procedure insert(sym : tsymentry);override;
+ end;
+
+ tabstractunitsymtable = class(tstoredsymtable)
+ public
+ constructor create(const n : string;id:word);
+ function iscurrentunit:boolean;override;
+ end;
+
+ tglobalsymtable = class(tabstractunitsymtable)
+ public
+ unittypecount : word;
+ constructor create(const n : string;id:word);
+ procedure ppuload(ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure load_references(ppufile:tcompilerppufile;locals:boolean);override;
+ procedure write_references(ppufile:tcompilerppufile;locals:boolean);override;
+ procedure insert(sym : tsymentry);override;
+ end;
+
+ tstaticsymtable = class(tabstractunitsymtable)
+ public
+ constructor create(const n : string;id:word);
+ procedure ppuload(ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure load_references(ppufile:tcompilerppufile;locals:boolean);override;
+ procedure write_references(ppufile:tcompilerppufile;locals:boolean);override;
+ procedure insert(sym : tsymentry);override;
+ end;
+
+ twithsymtable = class(tsymtable)
+ withrefnode : pointer; { tnode }
+ constructor create(aowner:tdef;asymsearch:TDictionary;refnode:pointer{tnode});
+ destructor destroy;override;
+ procedure clear;override;
+ end;
+
+ tstt_exceptsymtable = class(tsymtable)
+ public
+ constructor create;
+ end;
+
+ tmacrosymtable = class(tstoredsymtable)
+ public
+ constructor create(exported: boolean);
+ procedure ppuload(ppufile:tcompilerppufile);override;
+ end;
+
+ var
+ constsymtable : tsymtable; { symtable were the constants can be inserted }
+ systemunit : tglobalsymtable; { pointer to the system unit }
+
+{****************************************************************************
+ Functions
+****************************************************************************}
+
+{*** Misc ***}
+ procedure globaldef(const s : string;var t:ttype);
+ function findunitsymtable(st:tsymtable):tsymtable;
+ function FullTypeName(def,otherdef:tdef):string;
+ procedure incompatibletypes(def1,def2:tdef);
+
+{*** Search ***}
+ function searchsym(const s : stringid;var srsym:tsym;var srsymtable:tsymtable):boolean;
+ function searchsym_type(const s : stringid;var srsym:tsym;var srsymtable:tsymtable):boolean;
+ function searchsymonlyin(p : tsymtable;const s : stringid):tsym;
+ function searchsym_in_class(classh:tobjectdef;const s : stringid):tsym;
+ function searchsym_in_class_by_msgint(classh:tobjectdef;i:longint):tsym;
+ function searchsym_in_class_by_msgstr(classh:tobjectdef;const s:string):tsym;
+ function searchsystype(const s: stringid; var srsym: ttypesym): boolean;
+{$ifdef notused}
+ function searchsysvar(const s: stringid; var srsym: tsym; var symowner: tsymtable): boolean;
+{$endif notused}
+ function search_class_member(pd : tobjectdef;const s : string):tsym;
+ function search_assignment_operator(from_def,to_def:Tdef):Tprocdef;
+ {Looks for macro s (must be given in upper case) in the macrosymbolstack, }
+ {and returns it if found. Returns nil otherwise.}
+ function search_macro(const s : string):tsym;
+
+{*** Object Helpers ***}
+ procedure search_class_overloads(aprocsym : tprocsym);
+ function search_default_property(pd : tobjectdef) : tpropertysym;
+
+{*** Macro Helpers ***}
+ {If called initially, the following procedures manipulate macros in }
+ {initialmacrotable, otherwise they manipulate system macros local to a module.}
+ {Name can be given in any case (it will be converted to upper case).}
+ procedure def_system_macro(const name : string);
+ procedure set_system_macro(const name, value : string);
+ procedure set_system_compvar(const name, value : string);
+ procedure undef_system_macro(const name : string);
+
+{*** symtable stack ***}
+{$ifdef DEBUG}
+ procedure test_symtablestack;
+ procedure list_symtablestack;
+{$endif DEBUG}
+
+{$ifdef UNITALIASES}
+ type
+ punit_alias = ^tunit_alias;
+ tunit_alias = object(TNamedIndexItem)
+ newname : pstring;
+ constructor init(const n:string);
+ destructor done;virtual;
+ end;
+ var
+ unitaliases : pdictionary;
+
+ procedure addunitalias(const n:string);
+ function getunitalias(const n:string):string;
+{$endif UNITALIASES}
+
+{*** Init / Done ***}
+ procedure InitSymtable;
+ procedure DoneSymtable;
+
+ const
+ overloaded_names : array [NOTOKEN..last_overloaded] of string[16] =
+ ('error',
+ 'plus','minus','star','slash','equal',
+ 'greater','lower','greater_or_equal',
+ 'lower_or_equal',
+ 'sym_diff','starstar',
+ 'as','is','in','or',
+ 'and','div','mod','not','shl','shr','xor',
+ 'assign');
+
+
+
+implementation
+
+ uses
+ { global }
+ verbose,globals,
+ { target }
+ systems,
+ { symtable }
+ symutil,defcmp,
+ { module }
+ fmodule,
+ { codegen }
+ procinfo
+ ;
+
+ var
+ dupnr : longint; { unique number for duplicate symbols }
+
+
+{*****************************************************************************
+ TStoredSymtable
+*****************************************************************************}
+
+ procedure tstoredsymtable.ppuload(ppufile:tcompilerppufile);
+ begin
+ { load definitions }
+ loaddefs(ppufile);
+
+ { load symbols }
+ loadsyms(ppufile);
+ end;
+
+
+ procedure tstoredsymtable.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ { write definitions }
+ writedefs(ppufile);
+
+ { write symbols }
+ writesyms(ppufile);
+ end;
+
+
+ procedure tstoredsymtable.loaddefs(ppufile:tcompilerppufile);
+ var
+ hp : tdef;
+ b : byte;
+ begin
+ { load start of definition section, which holds the amount of defs }
+ if ppufile.readentry<>ibstartdefs then
+ Message(unit_f_ppu_read_error);
+ ppufile.getlongint;
+ { read definitions }
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibpointerdef : hp:=tpointerdef.ppuload(ppufile);
+ ibarraydef : hp:=tarraydef.ppuload(ppufile);
+ iborddef : hp:=torddef.ppuload(ppufile);
+ ibfloatdef : hp:=tfloatdef.ppuload(ppufile);
+ ibprocdef : hp:=tprocdef.ppuload(ppufile);
+ ibshortstringdef : hp:=tstringdef.loadshort(ppufile);
+ iblongstringdef : hp:=tstringdef.loadlong(ppufile);
+{$ifdef ansistring_bits}
+ ibansistring16def : hp:=tstringdef.loadansi(ppufile,sb_16);
+ ibansistring32def : hp:=tstringdef.loadansi(ppufile,sb_32);
+ ibansistring64def : hp:=tstringdef.loadansi(ppufile,sb_64);
+{$else}
+ ibansistringdef : hp:=tstringdef.loadansi(ppufile);
+{$endif}
+ ibwidestringdef : hp:=tstringdef.loadwide(ppufile);
+ ibrecorddef : hp:=trecorddef.ppuload(ppufile);
+ ibobjectdef : hp:=tobjectdef.ppuload(ppufile);
+ ibenumdef : hp:=tenumdef.ppuload(ppufile);
+ ibsetdef : hp:=tsetdef.ppuload(ppufile);
+ ibprocvardef : hp:=tprocvardef.ppuload(ppufile);
+ ibfiledef : hp:=tfiledef.ppuload(ppufile);
+ ibclassrefdef : hp:=tclassrefdef.ppuload(ppufile);
+ ibformaldef : hp:=tformaldef.ppuload(ppufile);
+ ibvariantdef : hp:=tvariantdef.ppuload(ppufile);
+ ibenddefs : break;
+ ibend : Message(unit_f_ppu_read_error);
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ hp.owner:=self;
+ defindex.insert(hp);
+ until false;
+ end;
+
+
+ procedure tstoredsymtable.loadsyms(ppufile:tcompilerppufile);
+ var
+ b : byte;
+ sym : tsym;
+ begin
+ { load start of definition section, which holds the amount of defs }
+ if ppufile.readentry<>ibstartsyms then
+ Message(unit_f_ppu_read_error);
+ { skip amount of symbols, not used currently }
+ ppufile.getlongint;
+ { now read the symbols }
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibtypesym : sym:=ttypesym.ppuload(ppufile);
+ ibprocsym : sym:=tprocsym.ppuload(ppufile);
+ ibconstsym : sym:=tconstsym.ppuload(ppufile);
+ ibglobalvarsym : sym:=tglobalvarsym.ppuload(ppufile);
+ iblocalvarsym : sym:=tlocalvarsym.ppuload(ppufile);
+ ibparavarsym : sym:=tparavarsym.ppuload(ppufile);
+ ibfieldvarsym : sym:=tfieldvarsym.ppuload(ppufile);
+ ibabsolutevarsym : sym:=tabsolutevarsym.ppuload(ppufile);
+ ibenumsym : sym:=tenumsym.ppuload(ppufile);
+ ibtypedconstsym : sym:=ttypedconstsym.ppuload(ppufile);
+ ibpropertysym : sym:=tpropertysym.ppuload(ppufile);
+ ibunitsym : sym:=tunitsym.ppuload(ppufile);
+ iblabelsym : sym:=tlabelsym.ppuload(ppufile);
+ ibsyssym : sym:=tsyssym.ppuload(ppufile);
+ ibrttisym : sym:=trttisym.ppuload(ppufile);
+ ibmacrosym : sym:=tmacro.ppuload(ppufile);
+ ibendsyms : break;
+ ibend : Message(unit_f_ppu_read_error);
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ sym.owner:=self;
+ symindex.insert(sym);
+ symsearch.insert(sym);
+ until false;
+ end;
+
+
+ procedure tstoredsymtable.writedefs(ppufile:tcompilerppufile);
+ var
+ pd : tstoreddef;
+ begin
+ { each definition get a number, write then the amount of defs to the
+ ibstartdef entry }
+ ppufile.putlongint(defindex.count);
+ ppufile.writeentry(ibstartdefs);
+ { now write the definition }
+ pd:=tstoreddef(defindex.first);
+ while assigned(pd) do
+ begin
+ pd.ppuwrite(ppufile);
+ pd:=tstoreddef(pd.indexnext);
+ end;
+ { write end of definitions }
+ ppufile.writeentry(ibenddefs);
+ end;
+
+
+ procedure tstoredsymtable.writesyms(ppufile:tcompilerppufile);
+ var
+ pd : Tstoredsym;
+ begin
+ { each definition get a number, write then the amount of syms and the
+ datasize to the ibsymdef entry }
+ ppufile.putlongint(symindex.count);
+ ppufile.writeentry(ibstartsyms);
+ { foreach is used to write all symbols }
+ pd:=Tstoredsym(symindex.first);
+ while assigned(pd) do
+ begin
+ pd.ppuwrite(ppufile);
+ pd:=Tstoredsym(pd.indexnext);
+ end;
+ { end of symbols }
+ ppufile.writeentry(ibendsyms);
+ end;
+
+
+ procedure tstoredsymtable.load_references(ppufile:tcompilerppufile;locals:boolean);
+ var
+ b : byte;
+ d : tderef;
+ sym : Tsym;
+ prdef : tstoreddef;
+ begin
+ b:=ppufile.readentry;
+ if b <> ibbeginsymtablebrowser then
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibsymref :
+ begin
+ ppufile.getderef(d);
+ sym:=Tsym(d.resolve);
+ if assigned(sym) then
+ sym.load_references(ppufile,locals);
+ end;
+ ibdefref :
+ begin
+ ppufile.getderef(d);
+ prdef:=tstoreddef(d.resolve);
+ if assigned(prdef) then
+ begin
+ if prdef.deftype<>procdef then
+ Message(unit_f_ppu_read_error);
+ tprocdef(prdef).load_references(ppufile,locals);
+ end;
+ end;
+ ibendsymtablebrowser :
+ break;
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ until false;
+ end;
+
+
+ procedure tstoredsymtable.write_references(ppufile:tcompilerppufile;locals:boolean);
+ var
+ pd : Tsym;
+ begin
+ ppufile.writeentry(ibbeginsymtablebrowser);
+ { write all symbols }
+ pd:=Tsym(symindex.first);
+ while assigned(pd) do
+ begin
+ pd.write_references(ppufile,locals);
+ pd:=Tsym(pd.indexnext);
+ end;
+ ppufile.writeentry(ibendsymtablebrowser);
+ end;
+
+
+ procedure tstoredsymtable.buildderef;
+ var
+ hp : tdef;
+ hs : tsym;
+ begin
+ { interface definitions }
+ hp:=tdef(defindex.first);
+ while assigned(hp) do
+ begin
+ hp.buildderef;
+ hp:=tdef(hp.indexnext);
+ end;
+ { interface symbols }
+ hs:=tsym(symindex.first);
+ while assigned(hs) do
+ begin
+ hs.buildderef;
+ hs:=tsym(hs.indexnext);
+ end;
+ end;
+
+
+ procedure tstoredsymtable.buildderefimpl;
+ var
+ hp : tdef;
+ begin
+ { definitions }
+ hp:=tdef(defindex.first);
+ while assigned(hp) do
+ begin
+ hp.buildderefimpl;
+ hp:=tdef(hp.indexnext);
+ end;
+ end;
+
+
+ procedure tstoredsymtable.deref;
+ var
+ hp : tdef;
+ hs : tsym;
+ begin
+ { first deref the interface ttype symbols. This is needs
+ to be done before the interface defs are derefed, because
+ the interface defs can contain references to the type symbols
+ which then already need to contain a resolved restype field (PFV) }
+ hs:=tsym(symindex.first);
+ while assigned(hs) do
+ begin
+ if hs.typ=typesym then
+ hs.deref;
+ hs:=tsym(hs.indexnext);
+ end;
+ { deref the interface definitions }
+ hp:=tdef(defindex.first);
+ while assigned(hp) do
+ begin
+ hp.deref;
+ hp:=tdef(hp.indexnext);
+ end;
+ { deref the interface symbols }
+ hs:=tsym(symindex.first);
+ while assigned(hs) do
+ begin
+ if hs.typ<>typesym then
+ hs.deref;
+ hs:=tsym(hs.indexnext);
+ end;
+ end;
+
+
+ procedure tstoredsymtable.derefimpl;
+ var
+ hp : tdef;
+ begin
+ { definitions }
+ hp:=tdef(defindex.first);
+ while assigned(hp) do
+ begin
+ hp.derefimpl;
+ hp:=tdef(hp.indexnext);
+ end;
+ end;
+
+
+ procedure tstoredsymtable.duplicatesym(dupsym,sym:tsymentry);
+ var
+ st : tsymtable;
+ begin
+ Message1(sym_e_duplicate_id,tsym(sym).realname);
+ st:=findunitsymtable(sym.owner);
+ with tsym(sym).fileinfo do
+ begin
+ if assigned(st) and
+ (st.symtabletype=globalsymtable) and
+ (not st.iscurrentunit) then
+ Message2(sym_h_duplicate_id_where,'unit '+st.name^,tostr(line))
+ else
+ Message2(sym_h_duplicate_id_where,current_module.sourcefiles.get_file_name(fileindex),tostr(line));
+ end;
+ { Rename duplicate sym to an unreachable name, but it can be
+ inserted in the symtable without errors }
+ if assigned(dupsym) then
+ begin
+ inc(dupnr);
+ dupsym.name:='dup'+tostr(dupnr)+dupsym.name;
+ end;
+ end;
+
+
+ procedure tstoredsymtable.insert(sym:tsymentry);
+ var
+ hsym : tsym;
+ begin
+ { set owner and sym indexnb }
+ sym.owner:=self;
+
+ { check the current symtable }
+ hsym:=tsym(search(sym.name));
+ if assigned(hsym) then
+ begin
+ { in TP and Delphi you can have a local with the
+ same name as the function, the function is then hidden for
+ the user. (Under delphi it can still be accessed using result),
+ but don't allow hiding of RESULT }
+ if (m_duplicate_names in aktmodeswitches) and
+ (sym.typ in [localvarsym,paravarsym,absolutevarsym]) and
+ (vo_is_funcret in tabstractvarsym(sym).varoptions) and
+ not((m_result in aktmodeswitches) and
+ (vo_is_result in tabstractvarsym(sym).varoptions)) then
+ sym.name:='hidden'+sym.name
+ else
+ DuplicateSym(sym,hsym);
+ end;
+
+ { register definition of typesym }
+ if (sym.typ = typesym) and
+ assigned(ttypesym(sym).restype.def) then
+ begin
+ if not(assigned(ttypesym(sym).restype.def.owner)) and
+ (ttypesym(sym).restype.def.deftype<>errordef) then
+ registerdef(ttypesym(sym).restype.def);
+ end;
+
+ { insert in index and search hash }
+ symindex.insert(sym);
+ symsearch.insert(sym);
+ end;
+
+
+ function tstoredsymtable.speedsearch(const s : stringid;speedvalue : cardinal) : tsymentry;
+ var
+ hp : Tsym;
+ newref : tref;
+ begin
+ hp:=Tsym(inherited speedsearch(s,speedvalue));
+ if assigned(hp) then
+ begin
+ { reject non static members in static procedures }
+ if (symtabletype=objectsymtable) and
+ not(sp_static in hp.symoptions) and
+ allow_only_static then
+ Message(sym_e_only_static_in_static);
+
+ { unit uses count }
+ if assigned(current_module) and
+ (symtabletype=globalsymtable) then
+ begin
+ if tglobalsymtable(self).moduleid>=current_module.unitmapsize then
+ internalerror(200501152);
+ inc(current_module.unitmap[tglobalsymtable(self).moduleid].refs);
+ end;
+
+ if make_ref and (cs_browser in aktmoduleswitches) then
+ begin
+ newref:=tref.create(hp.lastref,@akttokenpos);
+ { for symbols that are in tables without browser info or syssyms }
+ if hp.refcount=0 then
+ begin
+ hp.defref:=newref;
+ hp.lastref:=newref;
+ end
+ else
+ if resolving_forward and assigned(hp.defref) then
+ { put it as second reference }
+ begin
+ newref.nextref:=hp.defref.nextref;
+ hp.defref.nextref:=newref;
+ hp.lastref.nextref:=nil;
+ end
+ else
+ hp.lastref:=newref;
+ inc(hp.refcount);
+ end;
+ if make_ref then
+ inc(hp.refs);
+ end; { value was not found }
+ speedsearch:=hp;
+ end;
+
+
+{**************************************
+ Callbacks
+**************************************}
+
+ procedure TStoredSymtable.check_forward(sym : TNamedIndexItem;arg:pointer);
+ begin
+ if tsym(sym).typ=procsym then
+ tprocsym(sym).check_forward
+ { check also object method table }
+ { we needn't to test the def list }
+ { because each object has to have a type sym,
+ only test objects declarations, not type renamings }
+ else
+ if (tsym(sym).typ=typesym) and
+ assigned(ttypesym(sym).restype.def) and
+ (ttypesym(sym).restype.def.typesym=ttypesym(sym)) and
+ (ttypesym(sym).restype.def.deftype=objectdef) then
+ tobjectdef(ttypesym(sym).restype.def).check_forwards;
+ end;
+
+
+ procedure TStoredSymtable.labeldefined(p : TNamedIndexItem;arg:pointer);
+ begin
+ if (tsym(p).typ=labelsym) and
+ not(tlabelsym(p).defined) then
+ begin
+ if tlabelsym(p).used then
+ Message1(sym_e_label_used_and_not_defined,tlabelsym(p).realname)
+ else
+ Message1(sym_w_label_not_defined,tlabelsym(p).realname);
+ end;
+ end;
+
+
+ procedure TStoredSymtable.varsymbolused(p : TNamedIndexItem;arg:pointer);
+ begin
+ if (tsym(p).typ in [globalvarsym,localvarsym,paravarsym,fieldvarsym]) and
+ ((tsym(p).owner.symtabletype in
+ [parasymtable,localsymtable,objectsymtable,staticsymtable])) then
+ begin
+ { unused symbol should be reported only if no }
+ { error is reported }
+ { if the symbol is in a register it is used }
+ { also don't count the value parameters which have local copies }
+ { also don't claim for high param of open parameters (PM) }
+ if (Errorcount<>0) or
+ (vo_is_hidden_para in tabstractvarsym(p).varoptions) then
+ exit;
+ if (tstoredsym(p).refs=0) then
+ begin
+ if (vo_is_funcret in tabstractvarsym(p).varoptions) then
+ begin
+ { don't warn about the result of constructors }
+ if (tsym(p).owner.symtabletype<>localsymtable) or
+ (tprocdef(tsym(p).owner.defowner).proctypeoption<>potype_constructor) then
+ MessagePos(tsym(p).fileinfo,sym_w_function_result_not_set)
+ end
+ else if (tsym(p).owner.symtabletype=parasymtable) then
+ MessagePos1(tsym(p).fileinfo,sym_h_para_identifier_not_used,tsym(p).realname)
+ else if (tsym(p).owner.symtabletype=objectsymtable) then
+ MessagePos2(tsym(p).fileinfo,sym_n_private_identifier_not_used,tsym(p).owner.realname^,tsym(p).realname)
+ else
+ MessagePos1(tsym(p).fileinfo,sym_n_local_identifier_not_used,tsym(p).realname);
+ end
+ else if tabstractvarsym(p).varstate=vs_assigned then
+ begin
+ if (tsym(p).owner.symtabletype=parasymtable) then
+ begin
+ if not(tabstractvarsym(p).varspez in [vs_var,vs_out]) and
+ not(vo_is_funcret in tabstractvarsym(p).varoptions) then
+ MessagePos1(tsym(p).fileinfo,sym_h_para_identifier_only_set,tsym(p).realname)
+ end
+ else if (tsym(p).owner.symtabletype=objectsymtable) then
+ MessagePos2(tsym(p).fileinfo,sym_n_private_identifier_only_set,tsym(p).owner.realname^,tsym(p).realname)
+ else if not(vo_is_exported in tabstractvarsym(p).varoptions) and
+ not(vo_is_funcret in tabstractvarsym(p).varoptions) then
+ MessagePos1(tsym(p).fileinfo,sym_n_local_identifier_only_set,tsym(p).realname);
+ end;
+ end
+ else if ((tsym(p).owner.symtabletype in
+ [objectsymtable,parasymtable,localsymtable,staticsymtable])) then
+ begin
+ if (Errorcount<>0) or
+ (sp_internal in tsym(p).symoptions) then
+ exit;
+ { do not claim for inherited private fields !! }
+ if (Tsym(p).refs=0) and (tsym(p).owner.symtabletype=objectsymtable) then
+ MessagePos2(tsym(p).fileinfo,sym_n_private_method_not_used,tsym(p).owner.realname^,tsym(p).realname)
+ { units references are problematic }
+ else
+ begin
+ if (Tsym(p).refs=0) and
+ not(tsym(p).typ in [enumsym,unitsym]) and
+ not(is_funcret_sym(tsym(p))) and
+ (
+ (tsym(p).typ<>procsym) or
+ ((tsym(p).owner.symtabletype=staticsymtable) and
+ not current_module.is_unit)
+ ) then
+ MessagePos2(tsym(p).fileinfo,sym_h_local_symbol_not_used,SymTypeName[tsym(p).typ],tsym(p).realname);
+ end;
+ end;
+ end;
+
+
+ procedure TStoredSymtable.TestPrivate(p : TNamedIndexItem;arg:pointer);
+ begin
+ if sp_private in tsym(p).symoptions then
+ varsymbolused(p,arg);
+ end;
+
+
+ procedure TStoredSymtable.objectprivatesymbolused(p : TNamedIndexItem;arg:pointer);
+ begin
+ {
+ Don't test simple object aliases PM
+ }
+ if (tsym(p).typ=typesym) and
+ (ttypesym(p).restype.def.deftype=objectdef) and
+ (ttypesym(p).restype.def.typesym=tsym(p)) then
+ tobjectdef(ttypesym(p).restype.def).symtable.foreach(@TestPrivate,nil);
+ end;
+
+
+ procedure tstoredsymtable.unchain_overloads(p : TNamedIndexItem;arg:pointer);
+ begin
+ if tsym(p).typ=procsym then
+ tprocsym(p).unchain_overload;
+ end;
+
+
+ procedure Tstoredsymtable.reset_def(def:Tnamedindexitem;arg:pointer);
+ begin
+ Tstoreddef(def).reset;
+ end;
+
+
+{***********************************************
+ Process all entries
+***********************************************}
+
+ procedure Tstoredsymtable.reset_all_defs;
+ begin
+ defindex.foreach(@reset_def,nil);
+ end;
+
+
+ { checks, if all procsyms and methods are defined }
+ procedure tstoredsymtable.check_forwards;
+ begin
+ foreach(@check_forward,nil);
+ end;
+
+
+ procedure tstoredsymtable.checklabels;
+ begin
+ foreach(@labeldefined,nil);
+ end;
+
+
+ procedure tstoredsymtable.allsymbolsused;
+ begin
+ foreach(@varsymbolused,nil);
+ end;
+
+
+ procedure tstoredsymtable.allprivatesused;
+ begin
+ foreach(@objectprivatesymbolused,nil);
+ end;
+
+
+ procedure tstoredsymtable.unchain_overloaded;
+ begin
+ foreach(@unchain_overloads,nil);
+ end;
+
+
+ procedure TStoredSymtable._needs_init_final(p : tnamedindexitem;arg:pointer);
+ begin
+ if b_needs_init_final then
+ exit;
+ case tsym(p).typ of
+ fieldvarsym,
+ globalvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ if not(is_class(tabstractvarsym(p).vartype.def)) and
+ tstoreddef(tabstractvarsym(p).vartype.def).needs_inittable then
+ b_needs_init_final:=true;
+ end;
+ typedconstsym :
+ begin
+ if ttypedconstsym(p).is_writable and
+ tstoreddef(ttypedconstsym(p).typedconsttype.def).needs_inittable then
+ b_needs_init_final:=true;
+ end;
+ end;
+ end;
+
+
+ { returns true, if p contains data which needs init/final code }
+ function tstoredsymtable.needs_init_final : boolean;
+ begin
+ b_needs_init_final:=false;
+ foreach(@_needs_init_final,nil);
+ needs_init_final:=b_needs_init_final;
+ end;
+
+
+{****************************************************************************
+ TAbstractRecordSymtable
+****************************************************************************}
+
+ constructor tabstractrecordsymtable.create(const n:string;usealign:shortint);
+ begin
+ inherited create(n);
+ datasize:=0;
+ recordalignment:=1;
+ usefieldalignment:=usealign;
+ padalignment:=1;
+ { recordalign -1 means C record packing, that starts
+ with an alignment of 1 }
+ if usealign=-1 then
+ fieldalignment:=1
+ else
+ fieldalignment:=usealign;
+ end;
+
+
+ procedure tabstractrecordsymtable.ppuload(ppufile:tcompilerppufile);
+ var
+ storesymtable : tsymtable;
+ begin
+ storesymtable:=aktrecordsymtable;
+ aktrecordsymtable:=self;
+
+ inherited ppuload(ppufile);
+
+ aktrecordsymtable:=storesymtable;
+ end;
+
+
+ procedure tabstractrecordsymtable.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldtyp : byte;
+ storesymtable : tsymtable;
+ begin
+ storesymtable:=aktrecordsymtable;
+ aktrecordsymtable:=self;
+ oldtyp:=ppufile.entrytyp;
+ ppufile.entrytyp:=subentryid;
+
+ inherited ppuwrite(ppufile);
+
+ ppufile.entrytyp:=oldtyp;
+ aktrecordsymtable:=storesymtable;
+ end;
+
+
+ procedure tabstractrecordsymtable.load_references(ppufile:tcompilerppufile;locals:boolean);
+ var
+ storesymtable : tsymtable;
+ begin
+ storesymtable:=aktrecordsymtable;
+ aktrecordsymtable:=self;
+
+ inherited load_references(ppufile,locals);
+
+ aktrecordsymtable:=storesymtable;
+ end;
+
+
+ procedure tabstractrecordsymtable.write_references(ppufile:tcompilerppufile;locals:boolean);
+ var
+ storesymtable : tsymtable;
+ begin
+ storesymtable:=aktrecordsymtable;
+ aktrecordsymtable:=self;
+
+ inherited write_references(ppufile,locals);
+
+ aktrecordsymtable:=storesymtable;
+ end;
+
+
+ procedure tabstractrecordsymtable.insertfield(sym : tfieldvarsym;addsym:boolean);
+ var
+ l : aint;
+ varalignrecord,
+ varalignfield,
+ varalign : longint;
+ vardef : tdef;
+ begin
+ if addsym then
+ insert(sym);
+ { this symbol can't be loaded to a register }
+ sym.varregable:=vr_none;
+ { Calculate field offset }
+ l:=sym.getsize;
+ vardef:=sym.vartype.def;
+ varalign:=vardef.alignment;
+ { Calc the alignment size for C style records }
+ if (usefieldalignment=-1) then
+ begin
+ if (varalign>4) and
+ ((varalign mod 4)<>0) and
+ (vardef.deftype=arraydef) then
+ Message1(sym_w_wrong_C_pack,vardef.typename);
+ if varalign=0 then
+ varalign:=l;
+ if (fieldalignment<aktalignment.maxCrecordalign) then
+ begin
+ if (varalign>16) and (fieldalignment<32) then
+ fieldalignment:=32
+ else if (varalign>12) and (fieldalignment<16) then
+ fieldalignment:=16
+ { 12 is needed for long double }
+ else if (varalign>8) and (fieldalignment<12) then
+ fieldalignment:=12
+ else if (varalign>4) and (fieldalignment<8) then
+ fieldalignment:=8
+ else if (varalign>2) and (fieldalignment<4) then
+ fieldalignment:=4
+ else if (varalign>1) and (fieldalignment<2) then
+ fieldalignment:=2;
+ { darwin/x86 aligns long doubles on 16 bytes }
+ if (target_info.system = system_i386_darwin) and
+ (fieldalignment = 12) then
+ fieldalignment := 16;
+ end;
+ fieldalignment:=min(fieldalignment,aktalignment.maxCrecordalign);
+ end;
+ if varalign=0 then
+ varalign:=size_2_align(l);
+ varalignfield:=used_align(varalign,aktalignment.recordalignmin,fieldalignment);
+ sym.fieldoffset:=align(datasize,varalignfield);
+ if (aword(l)+sym.fieldoffset)>high(aint) then
+ begin
+ Message(sym_e_segment_too_large);
+ datasize:=high(aint);
+ end
+ else
+ datasize:=sym.fieldoffset+l;
+ { Calc alignment needed for this record }
+ if (usefieldalignment=-1) then
+ varalignrecord:=used_align(varalign,aktalignment.recordalignmin,aktalignment.maxCrecordalign)
+ else
+ if (usefieldalignment=0) then
+ varalignrecord:=used_align(varalign,aktalignment.recordalignmin,aktalignment.recordalignmax)
+ else
+ begin
+ { packrecords is set explicit, ignore recordalignmax limit }
+ varalignrecord:=used_align(varalign,aktalignment.recordalignmin,usefieldalignment);
+ end;
+ recordalignment:=max(recordalignment,varalignrecord);
+ end;
+
+
+ procedure tabstractrecordsymtable.addalignmentpadding;
+ begin
+ { make the record size aligned correctly so it can be
+ used as elements in an array. For C records we
+ use the fieldalignment, because that is updated with the
+ used alignment. }
+ if (padalignment = 1) then
+ if usefieldalignment=-1 then
+ padalignment:=fieldalignment
+ else
+ padalignment:=recordalignment;
+ datasize:=align(datasize,padalignment);
+ end;
+
+
+{****************************************************************************
+ TRecordSymtable
+****************************************************************************}
+
+ constructor trecordsymtable.create(usealign:shortint);
+ begin
+ inherited create('',usealign);
+ symtabletype:=recordsymtable;
+ end;
+
+
+ { this procedure is reserved for inserting case variant into
+ a record symtable }
+ { the offset is the location of the start of the variant
+ and datasize and dataalignment corresponds to
+ the complete size (see code in pdecl unit) PM }
+ procedure trecordsymtable.insertunionst(unionst : trecordsymtable;offset : longint);
+ var
+ ps,nps : tfieldvarsym;
+ pd,npd : tdef;
+ varalignrecord,varalign,
+ storesize,storealign : longint;
+ begin
+ storesize:=datasize;
+ storealign:=fieldalignment;
+ datasize:=offset;
+ ps:=tfieldvarsym(unionst.symindex.first);
+ while assigned(ps) do
+ begin
+ nps:=tfieldvarsym(ps.indexnext);
+ { remove from current symtable }
+ unionst.symindex.deleteindex(ps);
+ ps.left:=nil;
+ ps.right:=nil;
+ { add to this record }
+ ps.owner:=self;
+ datasize:=ps.fieldoffset+offset;
+ symindex.insert(ps);
+ symsearch.insert(ps);
+ { update address }
+ ps.fieldoffset:=datasize;
+
+ { update alignment of this record }
+ varalign:=ps.vartype.def.alignment;
+ if varalign=0 then
+ varalign:=size_2_align(ps.getsize);
+ varalignrecord:=used_align(varalign,aktalignment.recordalignmin,fieldalignment);
+ recordalignment:=max(recordalignment,varalignrecord);
+
+ { next }
+ ps:=nps;
+ end;
+ pd:=tdef(unionst.defindex.first);
+ while assigned(pd) do
+ begin
+ npd:=tdef(pd.indexnext);
+ unionst.defindex.deleteindex(pd);
+ pd.left:=nil;
+ pd.right:=nil;
+ registerdef(pd);
+ pd:=npd;
+ end;
+ datasize:=storesize;
+ fieldalignment:=storealign;
+ end;
+
+
+{****************************************************************************
+ TObjectSymtable
+****************************************************************************}
+
+ constructor tobjectsymtable.create(const n:string;usealign:shortint);
+ begin
+ inherited create(n,usealign);
+ symtabletype:=objectsymtable;
+ end;
+
+
+ procedure tobjectsymtable.insert(sym:tsymentry);
+ var
+ hsym : tsym;
+ begin
+ { check for duplicate field id in inherited classes }
+ if (sym.typ=fieldvarsym) and
+ assigned(defowner) and
+ (
+ not(m_delphi in aktmodeswitches) or
+ is_object(tdef(defowner))
+ ) then
+ begin
+ { but private ids can be reused }
+ hsym:=search_class_member(tobjectdef(defowner),sym.name);
+ if assigned(hsym) and
+ tsym(hsym).is_visible_for_object(tobjectdef(defowner),tobjectdef(defowner)) then
+ DuplicateSym(sym,hsym);
+ end;
+ inherited insert(sym);
+ end;
+
+
+{****************************************************************************
+ TAbstractLocalSymtable
+****************************************************************************}
+
+ procedure tabstractlocalsymtable.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldtyp : byte;
+ begin
+ oldtyp:=ppufile.entrytyp;
+ ppufile.entrytyp:=subentryid;
+
+ { write definitions }
+ writedefs(ppufile);
+ { write symbols }
+ writesyms(ppufile);
+
+ ppufile.entrytyp:=oldtyp;
+ end;
+
+
+{****************************************************************************
+ TLocalSymtable
+****************************************************************************}
+
+ constructor tlocalsymtable.create(level:byte);
+ begin
+ inherited create('');
+ symtabletype:=localsymtable;
+ symtablelevel:=level;
+ end;
+
+
+ procedure tlocalsymtable.insert(sym:tsymentry);
+ var
+ hsym : tsym;
+ begin
+ { need to hide function result? }
+ hsym:=tsym(search(sym.name));
+ if assigned(hsym) then
+ begin
+ { a local and the function can have the same
+ name in TP and Delphi, but RESULT not }
+ if (m_duplicate_names in aktmodeswitches) and
+ (hsym.typ in [absolutevarsym,localvarsym]) and
+ (vo_is_funcret in tabstractvarsym(hsym).varoptions) and
+ not((m_result in aktmodeswitches) and
+ (vo_is_result in tabstractvarsym(hsym).varoptions)) then
+ hsym.owner.rename(hsym.name,'hidden'+hsym.name)
+ else
+ DuplicateSym(sym,hsym);
+ end;
+
+ if assigned(next) and
+ (next.symtabletype=parasymtable) then
+ begin
+ { check para symtable }
+ hsym:=tsym(next.search(sym.name));
+ if assigned(hsym) then
+ begin
+ { a local and the function can have the same
+ name in TP and Delphi, but RESULT not }
+ if (m_duplicate_names in aktmodeswitches) and
+ (sym.typ in [absolutevarsym,paravarsym]) and
+ (vo_is_funcret in tabstractvarsym(sym).varoptions) and
+ not((m_result in aktmodeswitches) and
+ (vo_is_result in tabstractvarsym(sym).varoptions)) then
+ sym.name:='hidden'+sym.name
+ else
+ DuplicateSym(sym,hsym);
+ end;
+ { check for duplicate id in local symtable of methods }
+ if assigned(next.next) and
+ { funcretsym is allowed !! }
+ (not is_funcret_sym(sym)) and
+ (next.next.symtabletype=objectsymtable) then
+ begin
+ hsym:=search_class_member(tobjectdef(next.next.defowner),sym.name);
+ if assigned(hsym) and
+ { private ids can be reused }
+ (hsym.is_visible_for_object(tobjectdef(next.next.defowner),tobjectdef(next.next.defowner)) or
+ (hsym.owner.defowner.owner.symtabletype<>globalsymtable)) then
+ begin
+ { delphi allows to reuse the names in a class, but not
+ in object (tp7 compatible) }
+ if not((m_delphi in aktmodeswitches) and
+ is_class(tdef(next.next.defowner))) then
+ DuplicateSym(sym,hsym);
+ end;
+ end;
+ end;
+
+ inherited insert(sym);
+ end;
+
+
+{****************************************************************************
+ TParaSymtable
+****************************************************************************}
+
+ constructor tparasymtable.create(level:byte);
+ begin
+ inherited create('');
+ symtabletype:=parasymtable;
+ symtablelevel:=level;
+ end;
+
+
+ procedure tparasymtable.insert(sym:tsymentry);
+ var
+ hsym : tsym;
+ begin
+ { check for duplicate id in para symtable of methods }
+ if assigned(next) and
+ (next.symtabletype=objectsymtable) and
+ { funcretsym is allowed }
+ (not is_funcret_sym(sym)) then
+ begin
+ hsym:=search_class_member(tobjectdef(next.defowner),sym.name);
+ { private ids can be reused }
+ if assigned(hsym) and
+ Tsym(hsym).is_visible_for_object(tobjectdef(next.defowner),tobjectdef(next.defowner)) then
+ begin
+ { delphi allows to reuse the names in a class, but not
+ in object (tp7 compatible) }
+ if not((m_delphi in aktmodeswitches) and
+ is_class_or_interface(tobjectdef(next.defowner))) then
+ DuplicateSym(sym,hsym);
+ end;
+ end;
+
+ inherited insert(sym);
+ end;
+
+
+{****************************************************************************
+ TAbstractUnitSymtable
+****************************************************************************}
+
+ constructor tabstractunitsymtable.create(const n : string;id:word);
+ begin
+ inherited create(n);
+ moduleid:=id;
+ symsearch.usehash;
+ end;
+
+
+ function tabstractunitsymtable.iscurrentunit:boolean;
+ begin
+ result:=assigned(current_module) and
+ (
+ (current_module.globalsymtable=self) or
+ (current_module.localsymtable=self)
+ );
+ end;
+
+
+{****************************************************************************
+ TStaticSymtable
+****************************************************************************}
+
+ constructor tstaticsymtable.create(const n : string;id:word);
+ begin
+ inherited create(n,id);
+ symtabletype:=staticsymtable;
+ symtablelevel:=main_program_level;
+ end;
+
+
+ procedure tstaticsymtable.ppuload(ppufile:tcompilerppufile);
+ begin
+ next:=symtablestack;
+ symtablestack:=self;
+
+ inherited ppuload(ppufile);
+
+ { now we can deref the syms and defs }
+ deref;
+
+ { restore symtablestack }
+ symtablestack:=next;
+ end;
+
+
+ procedure tstaticsymtable.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ end;
+
+
+ procedure tstaticsymtable.load_references(ppufile:tcompilerppufile;locals:boolean);
+ begin
+ inherited load_references(ppufile,locals);
+ end;
+
+
+ procedure tstaticsymtable.write_references(ppufile:tcompilerppufile;locals:boolean);
+ begin
+ inherited write_references(ppufile,locals);
+ end;
+
+
+ procedure tstaticsymtable.insert(sym:tsymentry);
+ var
+ hsym : tsym;
+ begin
+ { also check the global symtable }
+ if assigned(next) and
+ (next.symtabletype=globalsymtable) and
+ (next.iscurrentunit) then
+ begin
+ hsym:=tsym(next.search(sym.name));
+ if assigned(hsym) then
+ begin
+ { Delphi you can have a symbol with the same name as the
+ unit, the unit can then not be accessed anymore using
+ <unit>.<id>, so we can hide the symbol }
+ if (m_duplicate_names in aktmodeswitches) and
+ (hsym.typ=symconst.unitsym) then
+ hsym.owner.rename(hsym.name,'hidden'+hsym.name)
+ else
+ DuplicateSym(sym,hsym);
+ end;
+ end;
+
+ inherited insert(sym);
+ end;
+
+
+{****************************************************************************
+ TGlobalSymtable
+****************************************************************************}
+
+ constructor tglobalsymtable.create(const n : string;id:word);
+ begin
+ inherited create(n,id);
+ symtabletype:=globalsymtable;
+ symtablelevel:=main_program_level;
+ end;
+
+
+ procedure tglobalsymtable.ppuload(ppufile:tcompilerppufile);
+ begin
+ next:=symtablestack;
+ symtablestack:=self;
+
+ inherited ppuload(ppufile);
+
+ { now we can deref the syms and defs }
+ deref;
+
+ { restore symtablestack }
+ symtablestack:=next;
+ end;
+
+
+ procedure tglobalsymtable.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ { write the symtable entries }
+ inherited ppuwrite(ppufile);
+ end;
+
+
+ procedure tglobalsymtable.load_references(ppufile:tcompilerppufile;locals:boolean);
+ begin
+ inherited load_references(ppufile,locals);
+ end;
+
+
+ procedure tglobalsymtable.write_references(ppufile:tcompilerppufile;locals:boolean);
+ begin
+ inherited write_references(ppufile,locals);
+ end;
+
+
+ procedure tglobalsymtable.insert(sym:tsymentry);
+ var
+ hsym : tsym;
+ begin
+ hsym:=tsym(search(sym.name));
+ if assigned(hsym) then
+ begin
+ { Delphi you can have a symbol with the same name as the
+ unit, the unit can then not be accessed anymore using
+ <unit>.<id>, so we can hide the symbol }
+ if (m_duplicate_names in aktmodeswitches) and
+ (hsym.typ=symconst.unitsym) then
+ hsym.owner.rename(hsym.name,'hidden'+hsym.name)
+ else
+ DuplicateSym(sym,hsym);
+ end;
+
+ inherited insert(sym);
+ end;
+
+
+{****************************************************************************
+ TWITHSYMTABLE
+****************************************************************************}
+
+ constructor twithsymtable.create(aowner:tdef;asymsearch:TDictionary;refnode:pointer{tnode});
+ begin
+ inherited create('');
+ symtabletype:=withsymtable;
+ withrefnode:=refnode;
+ { we don't need the symsearch }
+ symsearch.free;
+ { set the defaults }
+ symsearch:=asymsearch;
+ defowner:=aowner;
+ end;
+
+
+ destructor twithsymtable.destroy;
+ begin
+ tobject(withrefnode).free;
+ symsearch:=nil;
+ inherited destroy;
+ end;
+
+
+ procedure twithsymtable.clear;
+ begin
+ { remove no entry from a withsymtable as it is only a pointer to the
+ recorddef or objectdef symtable }
+ end;
+
+
+{****************************************************************************
+ TSTT_ExceptionSymtable
+****************************************************************************}
+
+ constructor tstt_exceptsymtable.create;
+ begin
+ inherited create('');
+ symtabletype:=stt_exceptsymtable;
+ end;
+
+
+{****************************************************************************
+ TMacroSymtable
+****************************************************************************}
+
+ constructor tmacrosymtable.create(exported: boolean);
+ begin
+ inherited create('');
+ if exported then
+ symtabletype:=exportedmacrosymtable
+ else
+ symtabletype:=localmacrosymtable;
+ symtablelevel:=main_program_level;
+ end;
+
+
+ procedure tmacrosymtable.ppuload(ppufile:tcompilerppufile);
+ begin
+ next:=macrosymtablestack;
+ macrosymtablestack:=self;
+
+ inherited ppuload(ppufile);
+
+ { restore symtablestack }
+ macrosymtablestack:=next;
+ end;
+
+
+{*****************************************************************************
+ Helper Routines
+*****************************************************************************}
+
+ function findunitsymtable(st:tsymtable):tsymtable;
+ begin
+ findunitsymtable:=nil;
+ repeat
+ if not assigned(st) then
+ internalerror(5566561);
+ case st.symtabletype of
+ localsymtable,
+ parasymtable,
+ staticsymtable :
+ exit;
+ globalsymtable :
+ begin
+ findunitsymtable:=st;
+ exit;
+ end;
+ objectsymtable :
+ st:=st.defowner.owner;
+ recordsymtable :
+ begin
+ { don't continue when the current
+ symtable is used for variant records }
+ if trecorddef(st.defowner).isunion then
+ begin
+ findunitsymtable:=nil;
+ exit;
+ end
+ else
+ st:=st.defowner.owner;
+ end;
+ else
+ internalerror(5566562);
+ end;
+ until false;
+ end;
+
+
+ function FullTypeName(def,otherdef:tdef):string;
+ var
+ s1,s2 : string;
+ begin
+ s1:=def.typename;
+ { When the names are the same try to include the unit name }
+ if assigned(otherdef) and
+ (def.owner.symtabletype in [globalsymtable,staticsymtable]) then
+ begin
+ s2:=otherdef.typename;
+ if upper(s1)=upper(s2) then
+ s1:=def.owner.realname^+'.'+s1;
+ end;
+ FullTypeName:=s1;
+ end;
+
+
+ procedure incompatibletypes(def1,def2:tdef);
+ begin
+ { When there is an errordef there is already an error message show }
+ if (def2.deftype=errordef) or
+ (def1.deftype=errordef) then
+ exit;
+ CGMessage2(type_e_incompatible_types,FullTypeName(def1,def2),FullTypeName(def2,def1));
+ end;
+
+
+{*****************************************************************************
+ Search
+*****************************************************************************}
+
+ function searchsym(const s : stringid;var srsym:tsym;var srsymtable:tsymtable):boolean;
+ var
+ speedvalue : cardinal;
+ topclass : tobjectdef;
+ context : tobjectdef;
+ begin
+ speedvalue:=getspeedvalue(s);
+ srsymtable:=symtablestack;
+ while assigned(srsymtable) do
+ begin
+ srsym:=tsym(srsymtable.speedsearch(s,speedvalue));
+ if assigned(srsym) then
+ begin
+ topclass:=nil;
+ { use the class from withsymtable only when it is
+ defined in this unit }
+ if (srsymtable.symtabletype=withsymtable) and
+ assigned(srsymtable.defowner) and
+ (srsymtable.defowner.deftype=objectdef) and
+ (srsymtable.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ (srsymtable.defowner.owner.iscurrentunit) then
+ topclass:=tobjectdef(srsymtable.defowner)
+ else
+ begin
+ if assigned(current_procinfo) then
+ topclass:=current_procinfo.procdef._class;
+ end;
+ if assigned(current_procinfo) then
+ context:=current_procinfo.procdef._class
+ else
+ context:=nil;
+ if tsym(srsym).is_visible_for_object(topclass,context) then
+ begin
+ { we need to know if a procedure references symbols
+ in the static symtable, because then it can't be
+ inlined from outside this unit }
+ if assigned(current_procinfo) and
+ (srsym.owner.symtabletype=staticsymtable) then
+ include(current_procinfo.flags,pi_uses_static_symtable);
+ searchsym:=true;
+ exit;
+ end;
+ end;
+ srsymtable:=srsymtable.next;
+ end;
+ searchsym:=false;
+ end;
+
+
+ function searchsym_type(const s : stringid;var srsym:tsym;var srsymtable:tsymtable):boolean;
+ var
+ speedvalue : cardinal;
+ begin
+ speedvalue:=getspeedvalue(s);
+ srsymtable:=symtablestack;
+ while assigned(srsymtable) do
+ begin
+ {
+ It is not possible to have type defintions in:
+ records
+ objects
+ parameters
+ }
+ if not(srsymtable.symtabletype in [recordsymtable,objectsymtable,parasymtable]) then
+ begin
+ srsym:=tsym(srsymtable.speedsearch(s,speedvalue));
+ if assigned(srsym) and
+ (not assigned(current_procinfo) or
+ tsym(srsym).is_visible_for_object(current_procinfo.procdef._class,current_procinfo.procdef._class)) then
+ begin
+ result:=true;
+ exit;
+ end
+ end;
+ srsymtable:=srsymtable.next;
+ end;
+ result:=false;
+ end;
+
+
+ function searchsymonlyin(p : tsymtable;const s : stringid):tsym;
+ var
+ srsym : tsym;
+ begin
+ { the caller have to take care if srsym=nil }
+ if assigned(p) then
+ begin
+ srsym:=tsym(p.search(s));
+ if assigned(srsym) then
+ begin
+ searchsymonlyin:=srsym;
+ exit;
+ end;
+ { also check in the local symtbale if it exists }
+ if (p.symtabletype=globalsymtable) and
+ (p.iscurrentunit) then
+ begin
+ srsym:=tsym(current_module.localsymtable.search(s));
+ if assigned(srsym) then
+ begin
+ searchsymonlyin:=srsym;
+ exit;
+ end;
+ end
+ end;
+ searchsymonlyin:=nil;
+ end;
+
+
+ function searchsym_in_class(classh:tobjectdef;const s : stringid):tsym;
+ var
+ speedvalue : cardinal;
+ topclassh : tobjectdef;
+ sym : tsym;
+ begin
+ speedvalue:=getspeedvalue(s);
+ { when the class passed is defined in this unit we
+ need to use the scope of that class. This is a trick
+ that can be used to access protected members in other
+ units. At least kylix supports it this way (PFV) }
+ if assigned(classh) and
+ (classh.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ classh.owner.iscurrentunit then
+ topclassh:=classh
+ else
+ begin
+ if assigned(current_procinfo) then
+ topclassh:=current_procinfo.procdef._class
+ else
+ topclassh:=nil;
+ end;
+ sym:=nil;
+ while assigned(classh) do
+ begin
+ sym:=tsym(classh.symtable.speedsearch(s,speedvalue));
+ if assigned(sym) and
+ tsym(sym).is_visible_for_object(topclassh,current_procinfo.procdef._class) then
+ break
+ else
+ sym:=nil;
+ classh:=classh.childof;
+ end;
+ searchsym_in_class:=sym;
+ end;
+
+
+ function searchsym_in_class_by_msgint(classh:tobjectdef;i:longint):tsym;
+ var
+ topclassh : tobjectdef;
+ def : tdef;
+ sym : tsym;
+ begin
+ { when the class passed is defined in this unit we
+ need to use the scope of that class. This is a trick
+ that can be used to access protected members in other
+ units. At least kylix supports it this way (PFV) }
+ if assigned(classh) and
+ (classh.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ classh.owner.iscurrentunit then
+ topclassh:=classh
+ else
+ begin
+ if assigned(current_procinfo) then
+ topclassh:=current_procinfo.procdef._class
+ else
+ topclassh:=nil;
+ end;
+ sym:=nil;
+ def:=nil;
+ while assigned(classh) do
+ begin
+ def:=tdef(classh.symtable.defindex.first);
+ while assigned(def) do
+ begin
+ if (def.deftype=procdef) and
+ (po_msgint in tprocdef(def).procoptions) and
+ (tprocdef(def).messageinf.i=i) then
+ begin
+ sym:=tprocdef(def).procsym;
+ if assigned(topclassh) then
+ begin
+ if tprocdef(def).is_visible_for_object(topclassh) then
+ break;
+ end
+ else
+ break;
+ end;
+ def:=tdef(def.indexnext);
+ end;
+ if assigned(sym) then
+ break;
+ classh:=classh.childof;
+ end;
+ searchsym_in_class_by_msgint:=sym;
+ end;
+
+
+ function searchsym_in_class_by_msgstr(classh:tobjectdef;const s:string):tsym;
+ var
+ topclassh : tobjectdef;
+ def : tdef;
+ sym : tsym;
+ begin
+ { when the class passed is defined in this unit we
+ need to use the scope of that class. This is a trick
+ that can be used to access protected members in other
+ units. At least kylix supports it this way (PFV) }
+ if assigned(classh) and
+ (classh.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ classh.owner.iscurrentunit then
+ topclassh:=classh
+ else
+ begin
+ if assigned(current_procinfo) then
+ topclassh:=current_procinfo.procdef._class
+ else
+ topclassh:=nil;
+ end;
+ sym:=nil;
+ def:=nil;
+ while assigned(classh) do
+ begin
+ def:=tdef(classh.symtable.defindex.first);
+ while assigned(def) do
+ begin
+ if (def.deftype=procdef) and
+ (po_msgstr in tprocdef(def).procoptions) and
+ (tprocdef(def).messageinf.str=s) then
+ begin
+ sym:=tprocdef(def).procsym;
+ if assigned(topclassh) then
+ begin
+ if tprocdef(def).is_visible_for_object(topclassh) then
+ break;
+ end
+ else
+ break;
+ end;
+ def:=tdef(def.indexnext);
+ end;
+ if assigned(sym) then
+ break;
+ classh:=classh.childof;
+ end;
+ searchsym_in_class_by_msgstr:=sym;
+ end;
+
+
+ function search_assignment_operator(from_def,to_def:Tdef):Tprocdef;
+
+ var st:Tsymtable;
+ sym:Tprocsym;
+ sv:cardinal;
+ curreq,
+ besteq : tequaltype;
+ currpd,
+ bestpd : tprocdef;
+ begin
+ st:=symtablestack;
+ sv:=getspeedvalue('assign');
+ besteq:=te_incompatible;
+ bestpd:=nil;
+ while st<>nil do
+ begin
+ sym:=Tprocsym(st.speedsearch('assign',sv));
+ if sym<>nil then
+ begin
+ if sym.typ<>procsym then
+ internalerror(200402031);
+ { if the source type is an alias then this is only the second choice,
+ if you mess with this code, check tw4093 }
+ currpd:=sym.search_procdef_assignment_operator(from_def,to_def,curreq);
+ if curreq>besteq then
+ begin
+ besteq:=curreq;
+ bestpd:=currpd;
+ if (besteq=te_exact) then
+ break;
+ end;
+ end;
+ st:=st.next;
+ end;
+ result:=bestpd;
+ end;
+
+ function searchsystype(const s: stringid; var srsym: ttypesym): boolean;
+ var
+ symowner: tsymtable;
+ begin
+ if not(cs_compilesystem in aktmoduleswitches) then
+ srsym := ttypesym(searchsymonlyin(systemunit,s))
+ else
+ searchsym(s,tsym(srsym),symowner);
+ searchsystype :=
+ assigned(srsym) and
+ (srsym.typ = typesym);
+ end;
+
+
+{$ifdef notused}
+ function searchsysvar(const s: stringid; var srsym: tsym; var symowner: tsymtable): boolean;
+ begin
+ if not(cs_compilesystem in aktmoduleswitches) then
+ begin
+ srsym := searchsymonlyin(systemunit,s);
+ symowner := systemunit;
+ end
+ else
+ searchsym(s,tsym(srsym),symowner);
+ searchsysvar :=
+ assigned(srsym) and
+ (srsym.typ = globalvarsym);
+ end;
+{$endif notused}
+
+
+ function search_class_member(pd : tobjectdef;const s : string):tsym;
+ { searches n in symtable of pd and all anchestors }
+ var
+ speedvalue : cardinal;
+ srsym : tsym;
+ begin
+ speedvalue:=getspeedvalue(s);
+ while assigned(pd) do
+ begin
+ srsym:=tsym(pd.symtable.speedsearch(s,speedvalue));
+ if assigned(srsym) then
+ begin
+ search_class_member:=srsym;
+ exit;
+ end;
+ pd:=pd.childof;
+ end;
+ search_class_member:=nil;
+ end;
+
+ function search_macro(const s : string):tsym;
+ var
+ p : tsymtable;
+ speedvalue : cardinal;
+ srsym : tsym;
+
+ begin
+ speedvalue:= getspeedvalue(s);
+ p:=macrosymtablestack;
+ while assigned(p) do
+ begin
+ srsym:=tsym(p.speedsearch(s,speedvalue));
+ if assigned(srsym) then
+ begin
+ search_macro:= srsym;
+ exit;
+ end;
+ p:=p.next;
+ end;
+ search_macro:= nil;
+ end;
+
+
+{*****************************************************************************
+ Definition Helpers
+*****************************************************************************}
+
+ procedure globaldef(const s : string;var t:ttype);
+
+ var st : string;
+ symt : tsymtable;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ srsym := nil;
+ if pos('.',s) > 0 then
+ begin
+ st := copy(s,1,pos('.',s)-1);
+ searchsym(st,srsym,srsymtable);
+ st := copy(s,pos('.',s)+1,255);
+ if assigned(srsym) then
+ begin
+ if srsym.typ = unitsym then
+ begin
+ symt := tunitsym(srsym).unitsymtable;
+ srsym := tsym(symt.search(st));
+ end else srsym := nil;
+ end;
+ end else st := s;
+ if srsym = nil then
+ searchsym(st,srsym,srsymtable);
+ if srsym = nil then
+ srsym:=searchsymonlyin(systemunit,st);
+ if (not assigned(srsym)) or
+ (srsym.typ<>typesym) then
+ begin
+ Message(type_e_type_id_expected);
+ t:=generrortype;
+ exit;
+ end;
+ t := ttypesym(srsym).restype;
+ end;
+
+{****************************************************************************
+ Object Helpers
+****************************************************************************}
+
+ procedure search_class_overloads(aprocsym : tprocsym);
+ { searches n in symtable of pd and all anchestors }
+ var
+ speedvalue : cardinal;
+ srsym : tprocsym;
+ s : string;
+ objdef : tobjectdef;
+ begin
+ if aprocsym.overloadchecked then
+ exit;
+ aprocsym.overloadchecked:=true;
+ if (aprocsym.owner.symtabletype<>objectsymtable) then
+ internalerror(200111021);
+ objdef:=tobjectdef(aprocsym.owner.defowner);
+ { we start in the parent }
+ if not assigned(objdef.childof) then
+ exit;
+ objdef:=objdef.childof;
+ s:=aprocsym.name;
+ speedvalue:=getspeedvalue(s);
+ while assigned(objdef) do
+ begin
+ srsym:=tprocsym(objdef.symtable.speedsearch(s,speedvalue));
+ if assigned(srsym) then
+ begin
+ if (srsym.typ<>procsym) then
+ internalerror(200111022);
+ if srsym.is_visible_for_object(tobjectdef(aprocsym.owner.defowner),tobjectdef(aprocsym.owner.defowner)) then
+ begin
+ srsym.add_para_match_to(Aprocsym,[cpo_ignorehidden,cpo_allowdefaults]);
+ { we can stop if the overloads were already added
+ for the found symbol }
+ if srsym.overloadchecked then
+ break;
+ end;
+ end;
+ { next parent }
+ objdef:=objdef.childof;
+ end;
+ end;
+
+
+ procedure tstoredsymtable.testfordefaultproperty(p : TNamedIndexItem;arg:pointer);
+ begin
+ if (tsym(p).typ=propertysym) and
+ (ppo_defaultproperty in tpropertysym(p).propoptions) then
+ ppointer(arg)^:=p;
+ end;
+
+
+ function search_default_property(pd : tobjectdef) : tpropertysym;
+ { returns the default property of a class, searches also anchestors }
+ var
+ _defaultprop : tpropertysym;
+ begin
+ _defaultprop:=nil;
+ while assigned(pd) do
+ begin
+ pd.symtable.foreach(@tstoredsymtable(pd.symtable).testfordefaultproperty,@_defaultprop);
+ if assigned(_defaultprop) then
+ break;
+ pd:=pd.childof;
+ end;
+ search_default_property:=_defaultprop;
+ end;
+
+{****************************************************************************
+ Macro Helpers
+****************************************************************************}
+{NOTE: Initially, macrosymtablestack contains initialmacrosymtable.}
+
+ procedure def_system_macro(const name : string);
+ var
+ mac : tmacro;
+ s: string;
+ begin
+ if name = '' then
+ internalerror(2004121201);
+ s:= upper(name);
+ mac:=tmacro(search_macro(s));
+ if not assigned(mac) then
+ begin
+ mac:=tmacro.create(s);
+ if macrosymtablestack.symtabletype=localmacrosymtable then
+ macrosymtablestack.insert(mac)
+ else
+ macrosymtablestack.next.insert(mac)
+ end;
+ if not mac.defined then
+ Message1(parser_c_macro_defined,mac.name);
+ mac.defined:=true;
+ end;
+
+ procedure set_system_macro(const name, value : string);
+ var
+ mac : tmacro;
+ s: string;
+ begin
+ if name = '' then
+ internalerror(2004121201);
+ s:= upper(name);
+ mac:=tmacro(search_macro(s));
+ if not assigned(mac) then
+ begin
+ mac:=tmacro.create(s);
+ if macrosymtablestack.symtabletype=localmacrosymtable then
+ macrosymtablestack.insert(mac)
+ else
+ macrosymtablestack.next.insert(mac)
+ end
+ else
+ begin
+ mac.is_compiler_var:=false;
+ if assigned(mac.buftext) then
+ freemem(mac.buftext,mac.buflen);
+ end;
+ Message2(parser_c_macro_set_to,mac.name,value);
+ mac.buflen:=length(value);
+ getmem(mac.buftext,mac.buflen);
+ move(value[1],mac.buftext^,mac.buflen);
+ mac.defined:=true;
+ end;
+
+ procedure set_system_compvar(const name, value : string);
+ var
+ mac : tmacro;
+ s: string;
+ begin
+ if name = '' then
+ internalerror(2004121201);
+ s:= upper(name);
+ mac:=tmacro(search_macro(s));
+ if not assigned(mac) then
+ begin
+ mac:=tmacro.create(s);
+ mac.is_compiler_var:=true;
+ if macrosymtablestack.symtabletype=localmacrosymtable then
+ macrosymtablestack.insert(mac)
+ else
+ macrosymtablestack.next.insert(mac)
+ end
+ else
+ begin
+ mac.is_compiler_var:=true;
+ if assigned(mac.buftext) then
+ freemem(mac.buftext,mac.buflen);
+ end;
+ Message2(parser_c_macro_set_to,mac.name,value);
+ mac.buflen:=length(value);
+ getmem(mac.buftext,mac.buflen);
+ move(value[1],mac.buftext^,mac.buflen);
+ mac.defined:=true;
+ end;
+
+ procedure undef_system_macro(const name : string);
+ var
+ mac : tmacro;
+ s: string;
+ begin
+ if name = '' then
+ internalerror(2004121201);
+ s:= upper(name);
+ mac:=tmacro(search_macro(s));
+ if not assigned(mac) then
+ {If not found, then it's already undefined.}
+ else
+ begin
+ if mac.defined then
+ Message1(parser_c_macro_undefined,mac.name);
+ mac.defined:=false;
+ mac.is_compiler_var:=false;
+ { delete old definition }
+ if assigned(mac.buftext) then
+ begin
+ freemem(mac.buftext,mac.buflen);
+ mac.buftext:=nil;
+ end;
+ end;
+ end;
+
+{$ifdef UNITALIASES}
+{****************************************************************************
+ TUNIT_ALIAS
+ ****************************************************************************}
+
+ constructor tunit_alias.create(const n:string);
+ var
+ i : longint;
+ begin
+ i:=pos('=',n);
+ if i=0 then
+ fail;
+ inherited createname(Copy(n,1,i-1));
+ newname:=stringdup(Copy(n,i+1,255));
+ end;
+
+
+ destructor tunit_alias.destroy;
+ begin
+ stringdispose(newname);
+ inherited destroy;
+ end;
+
+
+ procedure addunitalias(const n:string);
+ begin
+ unitaliases^.insert(tunit_alias,init(Upper(n))));
+ end;
+
+
+ function getunitalias(const n:string):string;
+ var
+ p : punit_alias;
+ begin
+ p:=punit_alias(unitaliases^.search(Upper(n)));
+ if assigned(p) then
+ getunitalias:=punit_alias(p).newname^
+ else
+ getunitalias:=n;
+ end;
+{$endif UNITALIASES}
+
+
+{****************************************************************************
+ Symtable Stack
+****************************************************************************}
+
+{$ifdef DEBUG}
+ procedure test_symtablestack;
+ var
+ p : tsymtable;
+ i : longint;
+ begin
+ p:=symtablestack;
+ i:=0;
+ while assigned(p) do
+ begin
+ inc(i);
+ p:=p.next;
+ if i>500 then
+ Message(sym_f_internal_error_in_symtablestack);
+ end;
+ end;
+
+ procedure list_symtablestack;
+ var
+ p : tsymtable;
+ i : longint;
+ begin
+ p:=symtablestack;
+ i:=0;
+ while assigned(p) do
+ begin
+ inc(i);
+ writeln(i,' ',p.name^);
+ p:=p.next;
+ if i>500 then
+ Message(sym_f_internal_error_in_symtablestack);
+ end;
+ end;
+{$endif DEBUG}
+
+
+{****************************************************************************
+ Init/Done Symtable
+****************************************************************************}
+
+ procedure InitSymtable;
+ begin
+ { Reset symbolstack }
+ registerdef:=false;
+ symtablestack:=nil;
+ macrosymtablestack:=nil;
+ systemunit:=nil;
+ { create error syms and def }
+ generrorsym:=terrorsym.create;
+ generrortype.setdef(terrordef.create);
+{$ifdef UNITALIASES}
+ { unit aliases }
+ unitaliases:=tdictionary.create;
+{$endif}
+ initialmacrosymtable:= tmacrosymtable.create(false);
+ macrosymtablestack:= initialmacrosymtable;
+
+ { set some global vars to nil, might be important for the ide }
+ class_tobject:=nil;
+ interface_iunknown:=nil;
+ rec_tguid:=nil;
+
+ dupnr:=0;
+ end;
+
+
+ procedure DoneSymtable;
+ begin
+ generrorsym.free;
+ generrortype.def.free;
+{$ifdef UNITALIASES}
+ unitaliases.free;
+{$endif}
+ initialmacrosymtable.Free;
+ end;
+
+end.
diff --git a/compiler/symtype.pas b/compiler/symtype.pas
new file mode 100644
index 0000000000..a23b374324
--- /dev/null
+++ b/compiler/symtype.pas
@@ -0,0 +1,1447 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ This unit handles the symbol tables
+
+ 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 symtype;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,
+{$ifdef MEMDEBUG}
+ cclasses,
+{$endif MEMDEBUG}
+ { global }
+ globtype,globals,
+ { symtable }
+ symconst,symbase,
+ { aasm }
+ aasmbase,ppu,cpuinfo
+ ;
+
+ type
+{************************************************
+ Required Forwards
+************************************************}
+
+ tsym = class;
+ Tcompilerppufile=class;
+
+
+{************************************************
+ TRef
+************************************************}
+
+ tref = class
+ nextref : tref;
+ posinfo : tfileposinfo;
+ moduleindex : longint;
+ is_written : boolean;
+ constructor create(ref:tref;pos:pfileposinfo);
+ procedure freechain;
+ destructor destroy;override;
+ end;
+
+{************************************************
+ TDef
+************************************************}
+
+ tgetsymtable = (gs_none,gs_record,gs_local,gs_para);
+
+ tdef = class(tdefentry)
+ typesym : tsym; { which type the definition was generated this def }
+ { stabs debugging }
+ stab_number : word;
+ stab_state : tdefstabstatus;
+ defoptions : tdefoptions;
+ constructor create;
+ procedure buildderef;virtual;abstract;
+ procedure buildderefimpl;virtual;abstract;
+ procedure deref;virtual;abstract;
+ procedure derefimpl;virtual;abstract;
+ function typename:string;
+ function gettypename:string;virtual;
+ function mangledparaname:string;
+ function getmangledparaname:string;virtual;
+ function size:aint;virtual;abstract;
+ function alignment:longint;virtual;abstract;
+ function getvartype:longint;virtual;abstract;
+ function getparentdef:tdef;virtual;
+ function getsymtable(t:tgetsymtable):tsymtable;virtual;
+ function is_publishable:boolean;virtual;abstract;
+ function needs_inittable:boolean;virtual;abstract;
+ function is_related(def:tdef):boolean;virtual;
+ end;
+
+{************************************************
+ TSym
+************************************************}
+
+ { this object is the base for all symbol objects }
+ tsym = class(tsymentry)
+ protected
+ public
+ _realname : pstring;
+ fileinfo : tfileposinfo;
+ symoptions : tsymoptions;
+ refs : longint;
+ lastref,
+ defref,
+ lastwritten : tref;
+ refcount : longint;
+ isstabwritten : boolean;
+ constructor create(const n : string);
+ destructor destroy;override;
+ function realname:string;
+ function mangledname:string; virtual;
+ procedure buildderef;virtual;
+ procedure deref;virtual;
+ function gettypedef:tdef;virtual;
+ procedure load_references(ppufile:tcompilerppufile;locals:boolean);virtual;
+ function write_references(ppufile:tcompilerppufile;locals:boolean):boolean;virtual;
+ { currobjdef is the object def to assume, this is necessary for protected and
+ private,
+ context is the object def we're really in, this is for the strict stuff
+ }
+ function is_visible_for_object(currobjdef:tdef;context : tdef):boolean;virtual;
+ end;
+
+ tsymarr = array[0..maxlongint div sizeof(pointer)-1] of tsym;
+ psymarr = ^tsymarr;
+
+{************************************************
+ TDeref
+************************************************}
+
+ tderef = object
+ dataidx : longint;
+ procedure reset;
+ procedure build(s:tsymtableentry);
+ function resolve:tsymtableentry;
+ end;
+
+{************************************************
+ TType
+************************************************}
+
+ ttype = object
+ def : tdef;
+ sym : tsym;
+ deref : tderef;
+ procedure reset;
+ procedure setdef(p:tdef);
+ procedure setsym(p:tsym);
+ procedure resolve;
+ procedure buildderef;
+ end;
+
+{************************************************
+ TSymList
+************************************************}
+
+ psymlistitem = ^tsymlistitem;
+ tsymlistitem = record
+ sltype : tsltype;
+ next : psymlistitem;
+ case byte of
+ 0 : (sym : tsym; symderef : tderef);
+ 1 : (value : TConstExprInt);
+ 2 : (tt : ttype);
+ end;
+
+ tsymlist = class
+ procdef : tdef;
+ procdefderef : tderef;
+ firstsym,
+ lastsym : psymlistitem;
+ constructor create;
+ destructor destroy;override;
+ function empty:boolean;
+ procedure addsym(slt:tsltype;p:tsym);
+ procedure addsymderef(slt:tsltype;const d:tderef);
+ procedure addconst(slt:tsltype;v:TConstExprInt);
+ procedure addtype(slt:tsltype;const tt:ttype);
+ procedure clear;
+ function getcopy:tsymlist;
+ procedure resolve;
+ procedure buildderef;
+ end;
+
+{************************************************
+ Tcompilerppufile
+************************************************}
+ tcompilerppufile=class(tppufile)
+ public
+ procedure checkerror;
+ procedure getguid(var g: tguid);
+ function getexprint:tconstexprint;
+ function getptruint:TConstPtrUInt;
+ procedure getposinfo(var p:tfileposinfo);
+ procedure getderef(var d:tderef);
+ function getsymlist:tsymlist;
+ procedure gettype(var t:ttype);
+ function getasmsymbol:tasmsymbol;
+ procedure putguid(const g: tguid);
+ procedure putexprint(v:tconstexprint);
+ procedure PutPtrUInt(v:TConstPtrUInt);
+ procedure putposinfo(const p:tfileposinfo);
+ procedure putderef(const d:tderef);
+ procedure putsymlist(p:tsymlist);
+ procedure puttype(const t:ttype);
+ procedure putasmsymbol(s:tasmsymbol);
+ end;
+
+{$ifdef MEMDEBUG}
+ var
+ membrowser,
+ memrealnames,
+ memmanglednames,
+ memprocpara,
+ memprocparast,
+ memproclocalst,
+ memprocnodetree : tmemdebug;
+{$endif MEMDEBUG}
+
+ const
+ current_object_option : tsymoptions = [sp_public];
+
+
+implementation
+
+ uses
+ verbose,
+ fmodule
+ ;
+
+
+{****************************************************************************
+ Tdef
+****************************************************************************}
+
+ constructor tdef.create;
+ begin
+ inherited create;
+ deftype:=abstractdef;
+ owner := nil;
+ typesym := nil;
+ defoptions:=[];
+ stab_state:=stab_state_unused;
+ stab_number:=0;
+ end;
+
+
+ function tdef.typename:string;
+ begin
+ if assigned(typesym) and
+ not(deftype in [procvardef,procdef]) and
+ assigned(typesym._realname) and
+ (typesym._realname^[1]<>'$') then
+ typename:=typesym._realname^
+ else
+ typename:=gettypename;
+ end;
+
+
+ function tdef.gettypename : string;
+ begin
+ gettypename:='<unknown type>'
+ end;
+
+
+ function tdef.mangledparaname:string;
+ begin
+ if assigned(typesym) then
+ mangledparaname:=typesym.name
+ else
+ mangledparaname:=getmangledparaname;
+ end;
+
+
+ function tdef.getmangledparaname:string;
+ begin
+ result:='<unknown type>';
+ end;
+
+
+ function tdef.getparentdef:tdef;
+ begin
+ result:=nil;
+ end;
+
+
+ function tdef.getsymtable(t:tgetsymtable):tsymtable;
+ begin
+ result:=nil;
+ end;
+
+
+ function tdef.is_related(def:tdef):boolean;
+ begin
+ result:=false;
+ end;
+
+
+{****************************************************************************
+ TSYM (base for all symtypes)
+****************************************************************************}
+
+ constructor tsym.create(const n : string);
+ begin
+ if n[1]='$' then
+ inherited createname(copy(n,2,255))
+ else
+ inherited createname(upper(n));
+ _realname:=stringdup(n);
+ typ:=abstractsym;
+ symoptions:=[];
+ defref:=nil;
+ refs:=0;
+ lastwritten:=nil;
+ refcount:=0;
+ fileinfo:=akttokenpos;
+ if (cs_browser in aktmoduleswitches) and make_ref then
+ begin
+ defref:=tref.create(defref,@akttokenpos);
+ inc(refcount);
+ end;
+ lastref:=defref;
+ isstabwritten := false;
+ symoptions:=current_object_option;
+ end;
+
+
+ destructor tsym.destroy;
+ begin
+{$ifdef MEMDEBUG}
+ memrealnames.start;
+{$endif MEMDEBUG}
+ stringdispose(_realname);
+{$ifdef MEMDEBUG}
+ memrealnames.stop;
+{$endif MEMDEBUG}
+ inherited destroy;
+ end;
+
+
+ procedure Tsym.buildderef;
+ begin
+ end;
+
+
+ procedure Tsym.deref;
+ begin
+ end;
+
+
+ function tsym.realname : string;
+ begin
+ if assigned(_realname) then
+ realname:=_realname^
+ else
+ realname:=name;
+ end;
+
+
+ function tsym.mangledname : string;
+ begin
+ internalerror(200204171);
+ end;
+
+
+ function tsym.gettypedef:tdef;
+ begin
+ gettypedef:=nil;
+ end;
+
+
+ procedure Tsym.load_references(ppufile:tcompilerppufile;locals:boolean);
+ var
+ pos : tfileposinfo;
+ move_last : boolean;
+ begin
+ move_last:=lastwritten=lastref;
+ while (not ppufile.endofentry) do
+ begin
+ ppufile.getposinfo(pos);
+ inc(refcount);
+ lastref:=tref.create(lastref,@pos);
+ lastref.is_written:=true;
+ if refcount=1 then
+ defref:=lastref;
+ end;
+ if move_last then
+ lastwritten:=lastref;
+ end;
+
+ { big problem here :
+ wrong refs were written because of
+ interface parsing of other units PM
+ moduleindex must be checked !! }
+
+ function Tsym.write_references(ppufile:tcompilerppufile;locals:boolean):boolean;
+ var
+ d : tderef;
+ ref : tref;
+ symref_written,move_last : boolean;
+ begin
+ write_references:=false;
+ if lastwritten=lastref then
+ exit;
+ { should we update lastref }
+ move_last:=true;
+ symref_written:=false;
+ { write symbol refs }
+ d.reset;
+ if assigned(lastwritten) then
+ ref:=lastwritten
+ else
+ ref:=defref;
+ while assigned(ref) do
+ begin
+ if ref.moduleindex=current_module.unit_index then
+ begin
+ { write address to this symbol }
+ if not symref_written then
+ begin
+ d.build(self);
+ ppufile.putderef(d);
+ symref_written:=true;
+ end;
+ ppufile.putposinfo(ref.posinfo);
+ ref.is_written:=true;
+ if move_last then
+ lastwritten:=ref;
+ end
+ else if not ref.is_written then
+ move_last:=false
+ else if move_last then
+ lastwritten:=ref;
+ ref:=ref.nextref;
+ end;
+ if symref_written then
+ ppufile.writeentry(ibsymref);
+ write_references:=symref_written;
+ end;
+
+
+ function tsym.is_visible_for_object(currobjdef:Tdef;context : tdef):boolean;
+ begin
+ is_visible_for_object:=false;
+
+ { private symbols are allowed when we are in the same
+ module as they are defined }
+ if (sp_private in symoptions) and
+ assigned(owner.defowner) and
+ (owner.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ (not owner.defowner.owner.iscurrentunit) then
+ exit;
+
+ if (sp_strictprivate in symoptions) then
+ begin
+ result:=assigned(currobjdef) and
+ (context=tdef(owner.defowner));
+ exit;
+ end;
+
+ if (sp_strictprotected in symoptions) then
+ begin
+ result:=assigned(context) and
+ context.is_related(tdef(owner.defowner));
+ exit;
+ end;
+
+ { protected symbols are visible in the module that defines them and
+ also visible to related objects }
+ if (sp_protected in symoptions) and
+ (
+ (
+ assigned(owner.defowner) and
+ (owner.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ (not owner.defowner.owner.iscurrentunit)
+ ) and
+ not(
+ assigned(currobjdef) and
+ (currobjdef.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ (currobjdef.owner.iscurrentunit) and
+ currobjdef.is_related(tdef(owner.defowner))
+ )
+ ) then
+ exit;
+
+ is_visible_for_object:=true;
+ end;
+
+{****************************************************************************
+ TRef
+****************************************************************************}
+
+ constructor tref.create(ref :tref;pos : pfileposinfo);
+ begin
+ nextref:=nil;
+ if pos<>nil then
+ posinfo:=pos^;
+ if assigned(current_module) then
+ moduleindex:=current_module.unit_index;
+ if assigned(ref) then
+ ref.nextref:=self;
+ is_written:=false;
+ end;
+
+ procedure tref.freechain;
+ var
+ p,q : tref;
+ begin
+ p:=nextref;
+ nextref:=nil;
+ while assigned(p) do
+ begin
+ q:=p.nextref;
+ p.free;
+ p:=q;
+ end;
+ end;
+
+ destructor tref.destroy;
+ begin
+ nextref:=nil;
+ end;
+
+
+{****************************************************************************
+ TType
+****************************************************************************}
+
+ procedure ttype.reset;
+ begin
+ def:=nil;
+ sym:=nil;
+ end;
+
+
+ procedure ttype.setdef(p:tdef);
+ begin
+ def:=p;
+ sym:=nil;
+ end;
+
+
+ procedure ttype.setsym(p:tsym);
+ begin
+ sym:=p;
+ def:=p.gettypedef;
+ if not assigned(def) then
+ internalerror(1234005);
+ end;
+
+
+ procedure ttype.resolve;
+ var
+ p : tsymtableentry;
+ begin
+ p:=deref.resolve;
+ if assigned(p) then
+ begin
+ if p is tsym then
+ begin
+ setsym(tsym(p));
+ if not assigned(def) then
+ internalerror(200212272);
+ end
+ else
+ begin
+ setdef(tdef(p));
+ end;
+ end
+ else
+ reset;
+ end;
+
+
+ procedure ttype.buildderef;
+ begin
+ { Write symbol references when the symbol is a redefine,
+ but don't write symbol references for the current unit
+ and for the system unit }
+ if assigned(sym) and
+ (
+ (sym<>def.typesym) or
+ (
+ not((sym.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ sym.owner.iscurrentunit)
+ )
+ ) then
+ deref.build(sym)
+ else
+ deref.build(def);
+ end;
+
+
+{****************************************************************************
+ TSymList
+****************************************************************************}
+
+ constructor tsymlist.create;
+ begin
+ procdef:=nil; { needed for procedures }
+ firstsym:=nil;
+ lastsym:=nil;
+ end;
+
+
+ destructor tsymlist.destroy;
+ begin
+ clear;
+ end;
+
+
+ function tsymlist.empty:boolean;
+ begin
+ empty:=(firstsym=nil);
+ end;
+
+
+ procedure tsymlist.clear;
+ var
+ hp : psymlistitem;
+ begin
+ while assigned(firstsym) do
+ begin
+ hp:=firstsym;
+ firstsym:=firstsym^.next;
+ dispose(hp);
+ end;
+ firstsym:=nil;
+ lastsym:=nil;
+ procdef:=nil;
+ end;
+
+
+ procedure tsymlist.addsym(slt:tsltype;p:tsym);
+ var
+ hp : psymlistitem;
+ begin
+ if not assigned(p) then
+ internalerror(200110203);
+ new(hp);
+ fillchar(hp^,sizeof(tsymlistitem),0);
+ hp^.sltype:=slt;
+ hp^.sym:=p;
+ hp^.symderef.reset;
+ if assigned(lastsym) then
+ lastsym^.next:=hp
+ else
+ firstsym:=hp;
+ lastsym:=hp;
+ end;
+
+
+ procedure tsymlist.addsymderef(slt:tsltype;const d:tderef);
+ var
+ hp : psymlistitem;
+ begin
+ new(hp);
+ fillchar(hp^,sizeof(tsymlistitem),0);
+ hp^.sltype:=slt;
+ hp^.symderef:=d;
+ if assigned(lastsym) then
+ lastsym^.next:=hp
+ else
+ firstsym:=hp;
+ lastsym:=hp;
+ end;
+
+
+ procedure tsymlist.addconst(slt:tsltype;v:TConstExprInt);
+ var
+ hp : psymlistitem;
+ begin
+ new(hp);
+ fillchar(hp^,sizeof(tsymlistitem),0);
+ hp^.sltype:=slt;
+ hp^.value:=v;
+ if assigned(lastsym) then
+ lastsym^.next:=hp
+ else
+ firstsym:=hp;
+ lastsym:=hp;
+ end;
+
+
+ procedure tsymlist.addtype(slt:tsltype;const tt:ttype);
+ var
+ hp : psymlistitem;
+ begin
+ new(hp);
+ fillchar(hp^,sizeof(tsymlistitem),0);
+ hp^.sltype:=slt;
+ hp^.tt:=tt;
+ if assigned(lastsym) then
+ lastsym^.next:=hp
+ else
+ firstsym:=hp;
+ lastsym:=hp;
+ end;
+
+
+ function tsymlist.getcopy:tsymlist;
+ var
+ hp : tsymlist;
+ hp2 : psymlistitem;
+ hpn : psymlistitem;
+ begin
+ hp:=tsymlist.create;
+ hp.procdef:=procdef;
+ hp2:=firstsym;
+ while assigned(hp2) do
+ begin
+ new(hpn);
+ hpn^:=hp2^;
+ hpn^.next:=nil;
+ if assigned(hp.lastsym) then
+ hp.lastsym^.next:=hpn
+ else
+ hp.firstsym:=hpn;
+ hp.lastsym:=hpn;
+ hp2:=hp2^.next;
+ end;
+ getcopy:=hp;
+ end;
+
+
+ procedure tsymlist.resolve;
+ var
+ hp : psymlistitem;
+ begin
+ procdef:=tdef(procdefderef.resolve);
+ hp:=firstsym;
+ while assigned(hp) do
+ begin
+ case hp^.sltype of
+ sl_call,
+ sl_load,
+ sl_subscript :
+ hp^.sym:=tsym(hp^.symderef.resolve);
+ sl_absolutetype,
+ sl_typeconv :
+ hp^.tt.resolve;
+ sl_vec :
+ ;
+ else
+ internalerror(200110205);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure tsymlist.buildderef;
+ var
+ hp : psymlistitem;
+ begin
+ procdefderef.build(procdef);
+ hp:=firstsym;
+ while assigned(hp) do
+ begin
+ case hp^.sltype of
+ sl_call,
+ sl_load,
+ sl_subscript :
+ hp^.symderef.build(hp^.sym);
+ sl_absolutetype,
+ sl_typeconv :
+ hp^.tt.buildderef;
+ sl_vec :
+ ;
+ else
+ internalerror(200110205);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+{****************************************************************************
+ Tderef
+****************************************************************************}
+
+
+ procedure tderef.reset;
+ begin
+ dataidx:=-1;
+ end;
+
+
+ procedure tderef.build(s:tsymtableentry);
+ var
+ len : byte;
+ data : array[0..255] of byte;
+
+ function is_child(currdef,ownerdef:tdef):boolean;
+ begin
+ while assigned(currdef) and
+ (currdef<>ownerdef) do
+ currdef:=currdef.getparentdef;
+ result:=assigned(currdef);
+ end;
+
+ procedure addowner(s:tsymtableentry);
+ var
+ idx : longint;
+ begin
+ if not assigned(s.owner) then
+ internalerror(200306063);
+ case s.owner.symtabletype of
+ globalsymtable :
+ begin
+ if s.owner.iscurrentunit then
+ begin
+ data[len]:=ord(deref_aktglobal);
+ inc(len);
+ end
+ else
+ begin
+ { register that the unit is needed for resolving }
+ idx:=current_module.derefidx_unit(s.owner.moduleid);
+ data[len]:=ord(deref_unit);
+ data[len+1]:=idx shr 8;
+ data[len+2]:=idx and $ff;
+ inc(len,3);
+ end;
+ end;
+ staticsymtable :
+ begin
+ { only references to the current static symtable are allowed }
+ if not s.owner.iscurrentunit then
+ internalerror(200306233);
+ data[len]:=ord(deref_aktstatic);
+ inc(len);
+ end;
+ localsymtable :
+ begin
+ addowner(s.owner.defowner);
+ data[len]:=ord(deref_def);
+ data[len+1]:=s.owner.defowner.indexnr shr 8;
+ data[len+2]:=s.owner.defowner.indexnr and $ff;
+ data[len+3]:=ord(deref_local);
+ inc(len,4);
+ end;
+ parasymtable :
+ begin
+ addowner(s.owner.defowner);
+ data[len]:=ord(deref_def);
+ data[len+1]:=s.owner.defowner.indexnr shr 8;
+ data[len+2]:=s.owner.defowner.indexnr and $ff;
+ data[len+3]:=ord(deref_para);
+ inc(len,4);
+ end;
+ objectsymtable,
+ recordsymtable :
+ begin
+ addowner(s.owner.defowner);
+ data[len]:=ord(deref_def);
+ data[len+1]:=s.owner.defowner.indexnr shr 8;
+ data[len+2]:=s.owner.defowner.indexnr and $ff;
+ data[len+3]:=ord(deref_record);
+ inc(len,4);
+ end;
+ else
+ internalerror(200306065);
+ end;
+ if len>252 then
+ internalerror(200306062);
+ end;
+
+ procedure addparentobject(currdef,ownerdef:tdef);
+ var
+ nextdef : tdef;
+ begin
+ if not assigned(currdef) then
+ internalerror(200306185);
+ { Already handled by derefaktrecordindex }
+ if currdef=ownerdef then
+ internalerror(200306188);
+ { Generate a direct reference to the top parent
+ class available in the current unit, this is required because
+ the parent class is maybe not resolved yet and therefor
+ has the childof value not available yet }
+ while (currdef<>ownerdef) do
+ begin
+ nextdef:=currdef.getparentdef;
+ { objects are only allowed in globalsymtable,staticsymtable }
+ if not(nextdef.owner.symtabletype in [globalsymtable,staticsymtable]) then
+ internalerror(200306187);
+ { Next parent is in a different unit, then stop }
+ if not(nextdef.owner.iscurrentunit) then
+ break;
+ currdef:=nextdef;
+ end;
+ { Add reference where to start the parent lookup }
+ if currdef=aktrecordsymtable.defowner then
+ begin
+ data[len]:=ord(deref_aktrecord);
+ inc(len);
+ end
+ else
+ begin
+ if currdef.owner.symtabletype=globalsymtable then
+ data[len]:=ord(deref_aktglobal)
+ else
+ data[len]:=ord(deref_aktstatic);
+ data[len+1]:=ord(deref_def);
+ data[len+2]:=currdef.indexnr shr 8;
+ data[len+3]:=currdef.indexnr and $ff;
+ data[len+4]:=ord(deref_record);
+ inc(len,5);
+ end;
+ { When the current found parent in this module is not the owner we
+ add derefs for the parent classes not available in this unit }
+ while (currdef<>ownerdef) do
+ begin
+ data[len]:=ord(deref_parent_object);
+ inc(len);
+ currdef:=currdef.getparentdef;
+ { It should be valid as it is checked by is_child }
+ if not assigned(currdef) then
+ internalerror(200306186);
+ end;
+ end;
+
+ begin
+ { skip length byte }
+ len:=1;
+ if assigned(s) then
+ begin
+ { Static symtable of current unit ? }
+ if (s.owner.symtabletype=staticsymtable) and
+ s.owner.iscurrentunit then
+ begin
+ data[len]:=ord(deref_aktstatic);
+ inc(len);
+ end
+ { Global symtable of current unit ? }
+ else if (s.owner.symtabletype=globalsymtable) and
+ s.owner.iscurrentunit then
+ begin
+ data[len]:=ord(deref_aktglobal);
+ inc(len);
+ end
+ { Current record/object symtable ? }
+ else if (s.owner=aktrecordsymtable) then
+ begin
+ data[len]:=ord(deref_aktrecord);
+ inc(len);
+ end
+ { Current local symtable ? }
+ else if (s.owner=aktlocalsymtable) then
+ begin
+ data[len]:=ord(deref_aktlocal);
+ inc(len);
+ end
+ { Current para symtable ? }
+ else if (s.owner=aktparasymtable) then
+ begin
+ data[len]:=ord(deref_aktpara);
+ inc(len);
+ end
+ { Parent class? }
+ else if assigned(aktrecordsymtable) and
+ (aktrecordsymtable.symtabletype=objectsymtable) and
+ (s.owner.symtabletype=objectsymtable) and
+ is_child(tdef(aktrecordsymtable.defowner),tdef(s.owner.defowner)) then
+ begin
+ addparentobject(tdef(aktrecordsymtable.defowner),tdef(s.owner.defowner));
+ end
+ else
+ { Default, start by building from unit symtable }
+ begin
+ addowner(s);
+ end;
+ { Add index of the symbol/def }
+ if s is tsym then
+ data[len]:=ord(deref_sym)
+ else
+ data[len]:=ord(deref_def);
+ data[len+1]:=s.indexnr shr 8;
+ data[len+2]:=s.indexnr and $ff;
+ inc(len,3);
+ end
+ else
+ begin
+ { nil pointer }
+ data[len]:=0;
+ inc(len);
+ end;
+ { store data length in first byte }
+ data[0]:=len-1;
+ { store index and write to derefdata }
+ dataidx:=current_module.derefdata.size;
+ current_module.derefdata.write(data,len);
+ end;
+
+
+ function tderef.resolve:tsymtableentry;
+ var
+ pd : tdef;
+ pm : tmodule;
+ typ : tdereftype;
+ st : tsymtable;
+ idx : word;
+ i : aint;
+ len : byte;
+ data : array[0..255] of byte;
+ begin
+ result:=nil;
+ { not initialized or error }
+ if dataidx<0 then
+ internalerror(200306067);
+ { read data }
+ current_module.derefdata.seek(dataidx);
+ if current_module.derefdata.read(len,1)<>1 then
+ internalerror(200310221);
+ if len>0 then
+ begin
+ if current_module.derefdata.read(data,len)<>len then
+ internalerror(200310222);
+ end;
+ { process data }
+ st:=nil;
+ i:=0;
+ while (i<len) do
+ begin
+ typ:=tdereftype(data[i]);
+ inc(i);
+ case typ of
+ deref_nil :
+ begin
+ result:=nil;
+ { Only allowed when no other deref is available }
+ if len<>1 then
+ internalerror(200306232);
+ end;
+ deref_sym :
+ begin
+ if not assigned(st) then
+ internalerror(200309141);
+ idx:=(data[i] shl 8) or data[i+1];
+ inc(i,2);
+ result:=st.getsymnr(idx);
+ end;
+ deref_def :
+ begin
+ if not assigned(st) then
+ internalerror(200309142);
+ idx:=(data[i] shl 8) or data[i+1];
+ inc(i,2);
+ result:=st.getdefnr(idx);
+ end;
+ deref_aktrecord :
+ st:=aktrecordsymtable;
+ deref_aktstatic :
+ st:=current_module.localsymtable;
+ deref_aktglobal :
+ st:=current_module.globalsymtable;
+ deref_aktlocal :
+ st:=aktlocalsymtable;
+ deref_aktpara :
+ st:=aktparasymtable;
+ deref_unit :
+ begin
+ idx:=(data[i] shl 8) or data[i+1];
+ inc(i,2);
+ pm:=current_module.resolve_unit(idx);
+ st:=pm.globalsymtable;
+ end;
+ deref_local :
+ begin
+ if not assigned(result) then
+ internalerror(200306069);
+ st:=tdef(result).getsymtable(gs_local);
+ result:=nil;
+ if not assigned(st) then
+ internalerror(200212275);
+ end;
+ deref_para :
+ begin
+ if not assigned(result) then
+ internalerror(2003060610);
+ st:=tdef(result).getsymtable(gs_para);
+ result:=nil;
+ if not assigned(st) then
+ internalerror(200212276);
+ end;
+ deref_record :
+ begin
+ if not assigned(result) then
+ internalerror(200306068);
+ st:=tdef(result).getsymtable(gs_record);
+ result:=nil;
+ if not assigned(st) then
+ internalerror(200212274);
+ end;
+ deref_parent_object :
+ begin
+ { load current object symtable if no
+ symtable is available yet }
+ if st=nil then
+ begin
+ st:=aktrecordsymtable;
+ if not assigned(st) then
+ internalerror(200306068);
+ end;
+ if st.symtabletype<>objectsymtable then
+ internalerror(200306189);
+ pd:=tdef(st.defowner).getparentdef;
+ if not assigned(pd) then
+ internalerror(200306184);
+ st:=pd.getsymtable(gs_record);
+ if not assigned(st) then
+ internalerror(200212274);
+ end;
+ else
+ internalerror(200212277);
+ end;
+ end;
+ end;
+
+{*****************************************************************************
+ TCompilerPPUFile
+*****************************************************************************}
+
+ procedure tcompilerppufile.checkerror;
+ begin
+ if error then
+ Message(unit_f_ppu_read_error);
+ end;
+
+
+ procedure tcompilerppufile.getguid(var g: tguid);
+ begin
+ getdata(g,sizeof(g));
+ end;
+
+
+ function tcompilerppufile.getexprint:tconstexprint;
+ begin
+ if sizeof(tconstexprint)=8 then
+ result:=tconstexprint(getint64)
+ else
+ result:=tconstexprint(getlongint);
+ end;
+
+
+ function tcompilerppufile.getPtrUInt:TConstPtrUInt;
+ begin
+ if sizeof(TConstPtrUInt)=8 then
+ result:=tconstptruint(getint64)
+ else
+ result:=TConstPtrUInt(getlongint);
+ end;
+
+
+ procedure tcompilerppufile.getposinfo(var p:tfileposinfo);
+ var
+ info : byte;
+ begin
+ {
+ info byte layout in bits:
+ 0-1 - amount of bytes for fileindex
+ 2-3 - amount of bytes for line
+ 4-5 - amount of bytes for column
+ }
+ info:=getbyte;
+ case (info and $03) of
+ 0 : p.fileindex:=getbyte;
+ 1 : p.fileindex:=getword;
+ 2 : p.fileindex:=(getbyte shl 16) or getword;
+ 3 : p.fileindex:=getlongint;
+ end;
+ case ((info shr 2) and $03) of
+ 0 : p.line:=getbyte;
+ 1 : p.line:=getword;
+ 2 : p.line:=(getbyte shl 16) or getword;
+ 3 : p.line:=getlongint;
+ end;
+ case ((info shr 4) and $03) of
+ 0 : p.column:=getbyte;
+ 1 : p.column:=getword;
+ 2 : p.column:=(getbyte shl 16) or getword;
+ 3 : p.column:=getlongint;
+ end;
+ end;
+
+
+ procedure tcompilerppufile.getderef(var d:tderef);
+ begin
+ d.dataidx:=getlongint;
+ end;
+
+
+ function tcompilerppufile.getsymlist:tsymlist;
+ var
+ symderef : tderef;
+ tt : ttype;
+ slt : tsltype;
+ idx : longint;
+ p : tsymlist;
+ begin
+ p:=tsymlist.create;
+ getderef(p.procdefderef);
+ repeat
+ slt:=tsltype(getbyte);
+ case slt of
+ sl_none :
+ break;
+ sl_call,
+ sl_load,
+ sl_subscript :
+ begin
+ getderef(symderef);
+ p.addsymderef(slt,symderef);
+ end;
+ sl_absolutetype,
+ sl_typeconv :
+ begin
+ gettype(tt);
+ p.addtype(slt,tt);
+ end;
+ sl_vec :
+ begin
+ idx:=getlongint;
+ p.addconst(slt,idx);
+ end;
+ else
+ internalerror(200110204);
+ end;
+ until false;
+ getsymlist:=tsymlist(p);
+ end;
+
+
+ procedure tcompilerppufile.gettype(var t:ttype);
+ begin
+ getderef(t.deref);
+ t.def:=nil;
+ t.sym:=nil;
+ end;
+
+
+ function tcompilerppufile.getasmsymbol:tasmsymbol;
+ begin
+ getasmsymbol:=tasmsymbol(pointer(ptrint(getlongint)));
+ end;
+
+
+ procedure tcompilerppufile.putposinfo(const p:tfileposinfo);
+ var
+ oldcrc : boolean;
+ info : byte;
+ begin
+ { posinfo is not relevant for changes in PPU }
+ oldcrc:=do_crc;
+ do_crc:=false;
+ {
+ info byte layout in bits:
+ 0-1 - amount of bytes for fileindex
+ 2-3 - amount of bytes for line
+ 4-5 - amount of bytes for column
+ }
+ info:=0;
+ { calculate info byte }
+ if (p.fileindex>$ff) then
+ begin
+ if (p.fileindex<=$ffff) then
+ info:=info or $1
+ else
+ if (p.fileindex<=$ffffff) then
+ info:=info or $2
+ else
+ info:=info or $3;
+ end;
+ if (p.line>$ff) then
+ begin
+ if (p.line<=$ffff) then
+ info:=info or $4
+ else
+ if (p.line<=$ffffff) then
+ info:=info or $8
+ else
+ info:=info or $c;
+ end;
+ if (p.column>$ff) then
+ begin
+ if (p.column<=$ffff) then
+ info:=info or $10
+ else
+ if (p.column<=$ffffff) then
+ info:=info or $20
+ else
+ info:=info or $30;
+ end;
+ { write data }
+ putbyte(info);
+ case (info and $03) of
+ 0 : putbyte(p.fileindex);
+ 1 : putword(p.fileindex);
+ 2 : begin
+ putbyte(p.fileindex shr 16);
+ putword(p.fileindex and $ffff);
+ end;
+ 3 : putlongint(p.fileindex);
+ end;
+ case ((info shr 2) and $03) of
+ 0 : putbyte(p.line);
+ 1 : putword(p.line);
+ 2 : begin
+ putbyte(p.line shr 16);
+ putword(p.line and $ffff);
+ end;
+ 3 : putlongint(p.line);
+ end;
+ case ((info shr 4) and $03) of
+ 0 : putbyte(p.column);
+ 1 : putword(p.column);
+ 2 : begin
+ putbyte(p.column shr 16);
+ putword(p.column and $ffff);
+ end;
+ 3 : putlongint(p.column);
+ end;
+ do_crc:=oldcrc;
+ end;
+
+
+ procedure tcompilerppufile.putguid(const g: tguid);
+ begin
+ putdata(g,sizeof(g));
+ end;
+
+
+ procedure tcompilerppufile.putexprint(v:tconstexprint);
+ begin
+ if sizeof(TConstExprInt)=8 then
+ putint64(int64(v))
+ else if sizeof(TConstExprInt)=4 then
+ putlongint(longint(v))
+ else
+ internalerror(2002082601);
+ end;
+
+
+ procedure tcompilerppufile.PutPtrUInt(v:TConstPtrUInt);
+ begin
+ if sizeof(TConstPtrUInt)=8 then
+ putint64(int64(v))
+ else if sizeof(TConstPtrUInt)=4 then
+ putlongint(longint(v))
+ else
+ internalerror(2002082601);
+ end;
+
+
+ procedure tcompilerppufile.putderef(const d:tderef);
+ var
+ oldcrc : boolean;
+ begin
+ oldcrc:=do_crc;
+ do_crc:=false;
+ putlongint(d.dataidx);
+ do_crc:=oldcrc;
+ end;
+
+
+ procedure tcompilerppufile.putsymlist(p:tsymlist);
+ var
+ hp : psymlistitem;
+ begin
+ putderef(p.procdefderef);
+ hp:=p.firstsym;
+ while assigned(hp) do
+ begin
+ putbyte(byte(hp^.sltype));
+ case hp^.sltype of
+ sl_call,
+ sl_load,
+ sl_subscript :
+ putderef(hp^.symderef);
+ sl_absolutetype,
+ sl_typeconv :
+ puttype(hp^.tt);
+ sl_vec :
+ putlongint(hp^.value);
+ else
+ internalerror(200110205);
+ end;
+ hp:=hp^.next;
+ end;
+ putbyte(byte(sl_none));
+ end;
+
+
+ procedure tcompilerppufile.puttype(const t:ttype);
+ begin
+ putderef(t.deref);
+ end;
+
+
+ procedure tcompilerppufile.putasmsymbol(s:tasmsymbol);
+ begin
+ if assigned(s) then
+ begin
+ if s.ppuidx=-1 then
+ begin
+ inc(objectlibrary.asmsymbolppuidx);
+ s.ppuidx:=objectlibrary.asmsymbolppuidx;
+ end;
+ putlongint(s.ppuidx);
+ end
+ else
+ putlongint(0);
+ end;
+
+{$ifdef MEMDEBUG}
+initialization
+ membrowser:=TMemDebug.create('BrowserRefs');
+ membrowser.stop;
+ memrealnames:=TMemDebug.create('Realnames');
+ memrealnames.stop;
+ memmanglednames:=TMemDebug.create('Manglednames');
+ memmanglednames.stop;
+ memprocpara:=TMemDebug.create('ProcPara');
+ memprocpara.stop;
+ memprocparast:=TMemDebug.create('ProcParaSt');
+ memprocparast.stop;
+ memproclocalst:=TMemDebug.create('ProcLocalSt');
+ memproclocalst.stop;
+ memprocnodetree:=TMemDebug.create('ProcNodeTree');
+ memprocnodetree.stop;
+
+finalization
+ membrowser.free;
+ memrealnames.free;
+ memmanglednames.free;
+ memprocpara.free;
+ memprocparast.free;
+ memproclocalst.free;
+ memprocnodetree.free;
+{$endif MEMDEBUG}
+
+end.
diff --git a/compiler/symutil.pas b/compiler/symutil.pas
new file mode 100644
index 0000000000..6e9c87b1a8
--- /dev/null
+++ b/compiler/symutil.pas
@@ -0,0 +1,119 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit provides some help routines for symbol handling
+
+ 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 symutil;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symbase,symtype,symsym,cclasses;
+
+ function is_funcret_sym(p:tsymentry):boolean;
+
+ { returns true, if sym needs an entry in the proplist of a class rtti }
+ function needs_prop_entry(sym : tsym) : boolean;
+
+ function equal_constsym(sym1,sym2:tconstsym):boolean;
+
+ procedure count_locals(p:tnamedindexitem;arg:pointer);
+
+implementation
+
+ uses
+ globtype,cpuinfo,procinfo,
+ symconst,widestr;
+
+
+ function is_funcret_sym(p:tsymentry):boolean;
+ begin
+ is_funcret_sym:=(p.typ in [absolutevarsym,localvarsym,paravarsym]) and
+ (vo_is_funcret in tabstractvarsym(p).varoptions);
+ end;
+
+
+ function needs_prop_entry(sym : tsym) : boolean;
+
+ begin
+ needs_prop_entry:=(sp_published in tsym(sym).symoptions) and
+ (sym.typ in [propertysym,fieldvarsym]);
+ end;
+
+
+ function equal_constsym(sym1,sym2:tconstsym):boolean;
+ var
+ p1,p2,pend : pchar;
+ begin
+ equal_constsym:=false;
+ if sym1.consttyp<>sym2.consttyp then
+ exit;
+ case sym1.consttyp of
+ constord :
+ equal_constsym:=(sym1.value.valueord=sym2.value.valueord);
+ constpointer :
+ equal_constsym:=(sym1.value.valueordptr=sym2.value.valueordptr);
+ conststring,constresourcestring :
+ begin
+ if sym1.value.len=sym2.value.len then
+ begin
+ p1:=pchar(sym1.value.valueptr);
+ p2:=pchar(sym2.value.valueptr);
+ pend:=p1+sym1.value.len;
+ while (p1<pend) do
+ begin
+ if p1^<>p2^ then
+ break;
+ inc(p1);
+ inc(p2);
+ end;
+ if (p1=pend) then
+ equal_constsym:=true;
+ end;
+ end;
+ constwstring :
+ begin
+ if (sym1.value.len=sym2.value.len) and
+ (comparewidestrings(sym1.value.valueptr,sym2.value.valueptr)=0) then
+ equal_constsym:=true;
+ end;
+ constreal :
+ equal_constsym:=(pbestreal(sym1.value.valueptr)^=pbestreal(sym2.value.valueptr)^);
+ constset :
+ equal_constsym:=(pnormalset(sym1.value.valueptr)^=pnormalset(sym2.value.valueptr)^);
+ constnil :
+ equal_constsym:=true;
+ end;
+ end;
+
+
+ procedure count_locals(p:tnamedindexitem;arg:pointer);
+ begin
+ { Count only varsyms, but ignore the funcretsym }
+ if (tsym(p).typ in [localvarsym,paravarsym]) and
+ (tsym(p)<>current_procinfo.procdef.funcretsym) and
+ (not(vo_is_parentfp in tabstractvarsym(p).varoptions) or
+ (tstoredsym(p).refs>0)) then
+ inc(plongint(arg)^);
+ end;
+
+
+end.
diff --git a/compiler/systems.pas b/compiler/systems.pas
new file mode 100644
index 0000000000..7f1a2ba4f0
--- /dev/null
+++ b/compiler/systems.pas
@@ -0,0 +1,801 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains information about the target systems supported
+ (these are not processor specific)
+
+ This program is free software; you can redistribute it and/or modify
+ iu under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 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 systems;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+ type
+ tendian = (endian_little,endian_big);
+
+ (*
+ IMPORTANT NOTE:
+ The value of this enumeration is stored in PPU files.
+ Therefore adding new CPU targets should not change the
+ values of the pre-existing targets. (CEC)
+ FURTHERMORE : Make sure that this branch values, are
+ consistant with the main branch version always.
+ *)
+ tsystemcpu=
+ (
+ cpu_no, { 0 }
+ cpu_i386, { 1 }
+ cpu_m68k, { 2 }
+ cpu_alpha, { 3 }
+ cpu_powerpc, { 4 }
+ cpu_sparc, { 5 }
+ cpu_vm, { 6 }
+ cpu_iA64, { 7 }
+ cpu_x86_64, { 8 }
+ cpu_mips, { 9 }
+ cpu_arm, { 10 }
+ cpu_powerpc64 { 11 }
+ );
+
+ tasmmode= (asmmode_none
+ { standard assembler (cpu dependant) with full parsing }
+ ,asmmode_standard
+ ,asmmode_i386_att
+ ,asmmode_i386_intel
+ ,asmmode_ppc_gas
+ ,asmmode_ppc_motorola
+ ,asmmode_arm_gas
+ ,asmmode_sparc_gas
+ ,asmmode_x86_64_gas
+ ,asmmode_m68k_mot
+ );
+
+ (* IMPORTANT NOTE:
+ the integer value of this enum is stored in PPU
+ files to recognize the target, so if you add new targets
+ allways add them at end PM
+ FURTHERMORE : Make sure that this branch values are
+ consistant with the main branch version always. (CEC)
+ *)
+ type
+ tsystem =
+ (
+ system_none, { 0 }
+ obsolete_system_i386_GO32V1,{ 1 }
+ system_i386_GO32V2, { 2 }
+ system_i386_linux, { 3 }
+ system_i386_OS2, { 4 }
+ system_i386_Win32, { 5 }
+ system_i386_freebsd, { 6 }
+ system_m68k_Amiga, { 7 }
+ system_m68k_Atari, { 8 }
+ system_m68k_Mac, { 9 }
+ system_m68k_linux, { 10 }
+ system_m68k_PalmOS, { 11 }
+ system_alpha_linux, { 12 }
+ system_powerpc_linux, { 13 }
+ system_powerpc_macos, { 14 }
+ system_i386_solaris, { 15 }
+ system_i386_beos, { 16 }
+ system_i386_netbsd, { 17 }
+ system_m68k_netbsd, { 18 }
+ system_i386_Netware, { 19 }
+ system_i386_qnx, { 20 }
+ system_i386_wdosx, { 21 }
+ system_sparc_solaris, { 22 }
+ system_sparc_linux, { 23 }
+ system_i386_openbsd, { 24 }
+ system_m68k_openbsd, { 25 }
+ system_x86_64_linux, { 26 }
+ system_powerpc_darwin, { 27 }
+ system_i386_EMX, { 28 }
+ system_powerpc_netbsd, { 29 }
+ system_powerpc_openbsd, { 30 }
+ system_arm_linux, { 31 }
+ system_i386_watcom, { 32 }
+ system_powerpc_MorphOS, { 33 }
+ system_x86_64_freebsd, { 34 }
+ system_i386_netwlibc, { 35 }
+ system_powerpc_Amiga, { 36 }
+ system_x86_64_win64, { 37 }
+ system_arm_wince, { 38 }
+ system_ia64_win64, { 39 }
+ system_i386_wince, { 40 }
+ system_x86_6432_linux, { 41 }
+ system_arm_gba, { 42 }
+ system_powerpc64_linux, { 43 }
+ system_i386_darwin { 44 }
+ );
+
+ tasm = (as_none
+ ,as_gas { standard gnu assembler }
+ ,as_i386_as_aout
+ ,as_i386_nasmcoff
+ ,as_i386_nasmwin32
+ ,as_i386_nasmwdosx
+ ,as_i386_nasmelf
+ ,as_i386_nasmobj
+ ,as_i386_nasmbeos
+ ,as_i386_tasm
+ ,as_i386_masm
+ ,as_i386_wasm
+ ,as_i386_coff
+ ,as_i386_pecoff
+ ,as_i386_elf32
+ ,as_i386_pecoffwdosx
+ ,as_m68k_mit
+ ,as_powerpc_mpw
+ ,as_darwin
+ ,as_x86_64_masm
+ ,as_x86_64_pecoff
+ ,as_i386_pecoffwince
+ ,as_arm_pecoffwince
+ );
+
+ tar = (ar_none
+ ,ar_gnu_ar,ar_mpw_ar
+ );
+
+ tres = (res_none
+ ,res_gnu_windres,res_emxbind
+ ,res_m68k_palmos,res_m68k_mpw
+ ,res_powerpc_mpw,res_elf
+ ,res_gnu_wince_windres
+ );
+
+ tdbg = (dbg_none
+ ,dbg_stabs,dbg_dwarf
+ );
+
+ tscripttype = (script_none
+ ,script_dos,script_unix,script_amiga,
+ script_mpw
+ );
+
+ tabi = (abi_default
+ ,abi_powerpc_sysv,abi_powerpc_aix
+ );
+
+{*****************************************************************************
+ Structures
+*****************************************************************************}
+
+ type
+ { Abstract linker class which is implemented in link module }
+ TAbstractLinker = class
+ end;
+
+ TAbstractLinkerClass = class of TAbstractLinker;
+
+
+ { Abstract assembler class which is implemented in assemble module }
+ TAbstractAssembler = class
+ end;
+
+ TAbstractAssemblerClass = class of TAbstractAssembler;
+
+
+ palignmentinfo = ^talignmentinfo;
+ talignmentinfo = record
+ procalign,
+ loopalign,
+ jumpalign,
+ constalignmin,
+ constalignmax,
+ varalignmin,
+ varalignmax,
+ localalignmin,
+ localalignmax,
+ recordalignmin,
+ recordalignmax,
+ maxCrecordalign : longint;
+ end;
+
+ tasmflags = (af_none,
+ af_outputbinary,af_allowdirect,
+ af_needar,af_smartlink_sections,
+ af_labelprefix_only_inside_procedure,
+ af_supports_dwarf
+ );
+
+ pasminfo = ^tasminfo;
+ tasminfo = record
+ id : tasm;
+ idtxt : string[12];
+ asmbin : string[8];
+ asmcmd : string[50];
+ supported_target : tsystem;
+ flags : set of tasmflags;
+ labelprefix : string[3];
+ comment : string[3];
+ end;
+
+ parinfo = ^tarinfo;
+ tarinfo = record
+ id : tar;
+ arcmd : string[50];
+ end;
+
+ presinfo = ^tresinfo;
+ tresinfo = record
+ id : tres;
+ resbin : string[8];
+ rescmd : string[50];
+ end;
+
+ pdbginfo = ^tdbginfo;
+ tdbginfo = record
+ id : tdbg;
+ idtxt : string[12];
+ end;
+
+ tsystemflags = (tf_none,
+ tf_under_development,
+ tf_need_export,tf_needs_isconsole,
+ tf_code_small,tf_static_reg_based,
+ tf_needs_symbol_size,
+ tf_smartlink_sections,
+ tf_needs_dwarf_cfi,
+ tf_use_8_3,
+ tf_pic_uses_got,
+ tf_library_needs_pic,
+ tf_needs_symbol_type
+ );
+
+ psysteminfo = ^tsysteminfo;
+ { using packed causes bus errors on processors which require alignment }
+ tsysteminfo = record
+ system : tsystem;
+ name : string[34];
+ shortname : string[9];
+ flags : set of tsystemflags;
+ cpu : tsystemcpu;
+ unit_env : string[16];
+ extradefines : string[40];
+ exeext,
+ defext,
+ scriptext,
+ smartext,
+ unitext,
+ unitlibext,
+ asmext,
+ objext,
+ resext,
+ resobjext : string[4];
+ sharedlibext : string[10];
+ staticlibext,
+ staticlibprefix : string[4];
+ sharedlibprefix : string[4];
+ sharedClibext : string[10];
+ staticClibext,
+ staticClibprefix : string[4];
+ sharedClibprefix : string[4];
+ p_ext_support:Boolean; {Whether extension .p is supported by default}
+ Cprefix : string[2];
+ newline : string[2];
+ dirsep : char;
+ files_case_relevent : boolean;
+ assem : tasm;
+ assemextern : tasm; { external assembler, used by -a }
+ link : tabstractlinkerclass;
+ linkextern : tabstractlinkerclass; { external linker, used by -s }
+ ar : tar;
+ res : tres;
+ dbg : tdbg;
+ script : tscripttype;
+ endian : tendian;
+ alignment : talignmentinfo;
+ {
+ Offset from the argument pointer register to the first
+ argument's address. On some machines it may depend on
+ the data type of the function.
+ (see also FIRST_PARM_OFFSET in GCC source)
+ }
+ first_parm_offset : longint;
+ stacksize : longint;
+ DllScanSupported : boolean;
+ use_function_relative_addresses : boolean;
+ abi : tabi;
+ end;
+
+ const
+ { alias for supported_target field in tasminfo }
+ system_any = system_none;
+
+ system_wince : set of tsystem = [system_arm_wince,system_i386_wince];
+ system_linux = [system_i386_linux,system_x86_64_linux,system_powerpc_linux,
+ system_arm_linux,system_sparc_linux,system_alpha_linux,system_m68k_linux,
+ system_x86_6432_linux];
+ { all real windows systems, no cripple ones like wince, wdosx et. al. }
+ system_windows : set of tsystem = [system_i386_win32,system_x86_64_win64,system_ia64_win64];
+ { all windows systems }
+ system_all_windows : set of tsystem = [system_i386_win32,system_x86_64_win64,system_ia64_win64,
+ system_arm_wince,system_i386_wince];
+
+ { all systems supporting exports from programs or units }
+ system_unit_program_exports : set of tsystem = [system_i386_win32,
+ system_i386_wdosx,
+ system_i386_Netware,
+ system_i386_netwlibc,
+ system_arm_wince,
+ system_x86_64_win64,
+ system_ia64_win64]+system_linux;
+
+ cpu2str : array[TSystemCpu] of string =
+ ('','i386','m68k','alpha','powerpc','sparc','vm','ia64','x86_64',
+ 'mips','arm', 'powerpc64');
+
+ var
+ targetinfos : array[tsystem] of psysteminfo;
+ arinfos : array[tar] of parinfo;
+ resinfos : array[tres] of presinfo;
+ asminfos : array[tasm] of pasminfo;
+ dbginfos : array[tdbg] of pdbginfo;
+
+ source_info : tsysteminfo;
+ target_cpu : tsystemcpu;
+ target_info : tsysteminfo;
+ target_asm : tasminfo;
+ target_ar : tarinfo;
+ target_res : tresinfo;
+ target_dbg : tdbginfo;
+ target_cpu_string,
+ target_os_string : string[12]; { for rtl/<X>/,fcl/<X>/, etc. }
+ target_full_string : string[24];
+
+ function set_target(t:tsystem):boolean;
+ function set_target_asm(t:tasm):boolean;
+ function set_target_ar(t:tar):boolean;
+ function set_target_res(t:tres):boolean;
+ function set_target_dbg(t:tdbg):boolean;
+
+ function find_system_by_string(const s : string) : tsystem;
+ function find_asm_by_string(const s : string) : tasm;
+ function find_dbg_by_string(const s : string) : tdbg;
+
+ procedure set_source_info(const ti : tsysteminfo);
+
+ procedure UpdateAlignment(var d:talignmentinfo;const s:talignmentinfo);
+
+ procedure RegisterTarget(const r:tsysteminfo);
+ procedure RegisterRes(const r:tresinfo);
+ procedure RegisterAr(const r:tarinfo);
+ { Register the external linker. This routine is called to setup the
+ class to use for the linker. It returns the tsysteminfo structure
+ updated with the correct linker class for external linking.
+ }
+ procedure RegisterExternalLinker(var system_info: tsysteminfo; c:TAbstractLinkerClass);
+ { Register the internal linker. This routine is called to setup the
+ class to use for the linker. It returns the tsysteminfo structure
+ updated with the correct linker class for internal linking.
+
+ If internal linking is not supported, this class can be set
+ to nil.
+ }
+ procedure RegisterInternalLinker(var system_info : tsysteminfo; c:TAbstractLinkerClass);
+
+ procedure InitSystems;
+
+ {$ifdef FreeBSD}
+ function GetOSRelDate:Longint;
+ {$endif}
+
+implementation
+
+ uses
+ cutils{$ifdef FreeBSD},SysCtl,BaseUnix{$endif};
+
+{****************************************************************************
+ OS runtime version detection utility routine
+****************************************************************************}
+
+{$ifdef FreeBSD}
+function GetOSRelDate:Longint;
+
+var
+ mib : array[0..1] of cint;
+ rval : cint;
+ len : size_t;
+ i : longint;
+ v : longint;
+ oerrno : cint;
+ S : AnsiString;
+
+Begin
+ s:='ab';
+ SetLength(S,50);
+ mib[0] := CTL_KERN;
+ mib[1] := KERN_OSRELDATE;
+ len := 4;
+ oerrno:= fpgeterrno;
+ if (FPsysctl(@mib, 2, pchar(@v), @len, NIL, 0) = -1) Then
+ Begin
+ if (fpgeterrno = ESysENOMEM) Then
+ fpseterrno(oerrno);
+ GetOSRelDate:=0;
+ End
+ else
+ GetOSRelDate:=v;
+End;
+{$endif}
+
+
+{****************************************************************************
+ Target setting
+****************************************************************************}
+
+function set_target(t:tsystem):boolean;
+begin
+ set_target:=false;
+ if assigned(targetinfos[t]) then
+ begin
+ target_info:=targetinfos[t]^;
+ set_target_asm(target_info.assem);
+ set_target_ar(target_info.ar);
+ set_target_res(target_info.res);
+ set_target_dbg(target_info.dbg);
+ target_cpu:=target_info.cpu;
+ target_os_string:=lower(target_info.shortname);
+ target_cpu_string:=cpu2str[target_cpu];
+ target_full_string:=target_cpu_string+'-'+target_os_string;
+ set_target:=true;
+ exit;
+ end;
+end;
+
+
+function set_target_asm(t:tasm):boolean;
+begin
+ set_target_asm:=false;
+ if assigned(asminfos[t]) and
+ ((asminfos[t]^.supported_target=target_info.system) or
+ (asminfos[t]^.supported_target=system_any)) then
+ begin
+ target_asm:=asminfos[t]^;
+ set_target_asm:=true;
+ exit;
+ end;
+end;
+
+
+function set_target_ar(t:tar):boolean;
+begin
+ result:=false;
+ if assigned(arinfos[t]) then
+ begin
+ target_ar:=arinfos[t]^;
+ result:=true;
+ exit;
+ end;
+end;
+
+
+function set_target_res(t:tres):boolean;
+begin
+ result:=false;
+ if assigned(resinfos[t]) then
+ begin
+ target_res:=resinfos[t]^;
+ result:=true;
+ exit;
+ end;
+end;
+
+
+function set_target_dbg(t:tdbg):boolean;
+begin
+ result:=false;
+ if assigned(dbginfos[t]) then
+ begin
+ target_dbg:=dbginfos[t]^;
+ result:=true;
+ exit;
+ end;
+end;
+
+
+function find_system_by_string(const s : string) : tsystem;
+var
+ hs : string;
+ t : tsystem;
+begin
+ result:=system_none;
+ hs:=upper(s);
+ for t:=low(tsystem) to high(tsystem) do
+ if assigned(targetinfos[t]) and
+ (upper(targetinfos[t]^.shortname)=hs) then
+ begin
+ result:=t;
+ exit;
+ end;
+end;
+
+
+function find_asm_by_string(const s : string) : tasm;
+var
+ hs : string;
+ t : tasm;
+begin
+ result:=as_none;
+ hs:=upper(s);
+ for t:=low(tasm) to high(tasm) do
+ if assigned(asminfos[t]) and
+ (asminfos[t]^.idtxt=hs) then
+ begin
+ result:=t;
+ exit;
+ end;
+end;
+
+
+function find_dbg_by_string(const s : string) : tdbg;
+var
+ hs : string;
+ t : tdbg;
+begin
+ result:=dbg_none;
+ hs:=upper(s);
+ for t:=low(tdbg) to high(tdbg) do
+ if assigned(dbginfos[t]) and
+ (dbginfos[t]^.idtxt=hs) then
+ begin
+ result:=t;
+ exit;
+ end;
+end;
+
+
+procedure UpdateAlignment(var d:talignmentinfo;const s:talignmentinfo);
+begin
+ with d do
+ begin
+ { general update rules:
+ minimum: if higher then update
+ maximum: if lower then update or if undefined then update }
+ if s.procalign>procalign then
+ procalign:=s.procalign;
+ if s.loopalign>loopalign then
+ loopalign:=s.loopalign;
+ if s.jumpalign>jumpalign then
+ jumpalign:=s.jumpalign;
+ if s.constalignmin>constalignmin then
+ constalignmin:=s.constalignmin;
+ if (constalignmax=0) or
+ ((s.constalignmax>0) and (s.constalignmax<constalignmax)) then
+ constalignmax:=s.constalignmax;
+ if s.varalignmin>varalignmin then
+ varalignmin:=s.varalignmin;
+ if (varalignmax=0) or
+ ((s.varalignmax>0) and (s.varalignmax<varalignmax)) then
+ varalignmax:=s.varalignmax;
+ if s.localalignmin>localalignmin then
+ localalignmin:=s.localalignmin;
+ if (localalignmax=0) or
+ ((s.localalignmax>0) and (s.localalignmax<localalignmax)) then
+ localalignmax:=s.localalignmax;
+ if s.recordalignmin>recordalignmin then
+ recordalignmin:=s.recordalignmin;
+ if (recordalignmax=0) or
+ ((s.recordalignmax>0) and (s.recordalignmax<recordalignmax)) then
+ recordalignmax:=s.recordalignmax;
+ if (maxCrecordalign=0) or
+ ((s.maxCrecordalign>0) and (s.maxCrecordalign<maxCrecordalign)) then
+ maxCrecordalign:=s.maxCrecordalign;
+ end;
+end;
+
+
+{****************************************************************************
+ Target registration
+****************************************************************************}
+
+procedure RegisterTarget(const r:tsysteminfo);
+var
+ t : tsystem;
+begin
+ t:=r.system;
+ if assigned(targetinfos[t]) then
+ writeln('Warning: Target is already registered!')
+ else
+ Getmem(targetinfos[t],sizeof(tsysteminfo));
+ targetinfos[t]^:=r;
+end;
+
+
+procedure RegisterRes(const r:tresinfo);
+var
+ t : tres;
+begin
+ t:=r.id;
+ if assigned(resinfos[t]) then
+ writeln('Warning: resourcecompiler is already registered!')
+ else
+ Getmem(resinfos[t],sizeof(tresinfo));
+ resinfos[t]^:=r;
+end;
+
+
+procedure RegisterAr(const r:tarinfo);
+var
+ t : tar;
+begin
+ t:=r.id;
+ if assigned(arinfos[t]) then
+ writeln('Warning: ar is already registered!')
+ else
+ Getmem(arinfos[t],sizeof(tarinfo));
+ arinfos[t]^:=r;
+end;
+
+procedure RegisterExternalLinker(var system_info: tsysteminfo; c:TAbstractLinkerClass);
+begin
+ system_info.linkextern := c;
+end;
+
+procedure RegisterInternalLinker(var system_info : tsysteminfo; c:TAbstractLinkerClass);
+begin
+ system_info.link := c;
+end;
+
+
+
+procedure DeregisterInfos;
+var
+ assem : tasm;
+ target : tsystem;
+ ar : tar;
+ res : tres;
+begin
+ for target:=low(tsystem) to high(tsystem) do
+ if assigned(targetinfos[target]) then
+ begin
+ freemem(targetinfos[target],sizeof(tsysteminfo));
+ targetinfos[target]:=nil;
+ end;
+ for assem:=low(tasm) to high(tasm) do
+ if assigned(asminfos[assem]) then
+ begin
+ freemem(asminfos[assem],sizeof(tasminfo));
+ asminfos[assem]:=nil;
+ end;
+ for ar:=low(tar) to high(tar) do
+ if assigned(arinfos[ar]) then
+ begin
+ freemem(arinfos[ar],sizeof(tarinfo));
+ arinfos[ar]:=nil;
+ end;
+ for res:=low(tres) to high(tres) do
+ if assigned(resinfos[res]) then
+ begin
+ freemem(resinfos[res],sizeof(tresinfo));
+ resinfos[res]:=nil;
+ end;
+end;
+
+
+{****************************************************************************
+ Initialization of default target
+****************************************************************************}
+
+procedure default_target(t:tsystem);
+begin
+ set_target(t);
+ if source_info.name='' then
+ source_info:=target_info;
+end;
+
+
+procedure set_source_info(const ti : tsysteminfo);
+begin
+{ can't use message() here (PFV) }
+ if source_info.name<>'' then
+ Writeln('Warning: Source OS Redefined!');
+ source_info:=ti;
+end;
+
+
+procedure InitSystems;
+begin
+{ Now default target, this is dependent on the target cpu define,
+ when the define is the same as the source cpu then we use the source
+ os, else we pick a default }
+{$ifdef i386}
+ {$ifdef cpu86}
+ default_target(source_info.system);
+ {$else cpu86}
+ {$ifdef linux}
+ default_target(system_i386_linux);
+ {$endif}
+ {$ifdef freebsd}
+ default_target(system_i386_freebsd);
+ {$endif}
+ {$endif cpu86}
+{$endif i386}
+
+{$ifdef x86_64}
+ {$ifdef cpux86_64}
+ default_target(source_info.system);
+ {$define source_system_set}
+ {$else cpux86_64}
+ {$ifdef linux}
+ default_target(system_x86_64_linux);
+ {$define source_system_set}
+ {$endif}
+ {$ifdef freebsd}
+ default_target(system_x86_64_freebsd);
+ {$define source_system_set}
+ {$endif}
+ { default is linux }
+ {$ifndef source_system_set}
+ default_target(system_x86_64_linux);
+ {$endif source_system_set}
+ {$endif cpux86_64}
+{$endif x86_64}
+
+{$ifdef m68k}
+ {$ifdef cpu68}
+ default_target(source_info.target);
+ {$else cpu68}
+ default_target(system_m68k_linux);
+ {$endif cpu68}
+{$endif m68k}
+{$ifdef alpha}
+ {$ifdef cpualpha}
+ default_target(source_info.system);
+ {$else cpualpha}
+ default_target(system_alpha_linux);
+ {$endif cpualpha}
+{$endif alpha}
+{$ifdef powerpc}
+ {$ifdef cpupowerpc}
+ default_target(source_info.system);
+ {$else cpupowerpc}
+ default_target(system_powerpc_linux);
+ {$endif cpupowerpc}
+{$endif powerpc}
+{$ifdef POWERPC64}
+ {$ifdef cpupowerpc64}
+ default_target(source_info.system);
+ {$else cpupowerpc64}
+ default_target(system_powerpc64_linux);
+ {$endif cpupowerpc64}
+{$endif POWERPC64}
+{$ifdef sparc}
+ {$ifdef cpusparc}
+ default_target(source_info.system);
+ {$else cpusparc}
+ default_target(system_sparc_linux);
+ {$endif cpusparc}
+{$endif sparc}
+{$ifdef arm}
+ {$ifdef cpuarm}
+ default_target(source_info.system);
+ {$else cpuarm}
+ default_target(system_arm_linux);
+ {$endif cpuarm}
+{$endif arm}
+end;
+
+
+initialization
+ source_info.name:='';
+finalization
+ DeregisterInfos;
+end.
diff --git a/compiler/systems/i_amiga.pas b/compiler/systems/i_amiga.pas
new file mode 100644
index 0000000000..139eff7cfd
--- /dev/null
+++ b/compiler/systems/i_amiga.pas
@@ -0,0 +1,169 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for AmigaOS
+
+ 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 support information structures for the AmigaOS. }
+unit i_amiga;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_m68k_amiga_info : tsysteminfo =
+ (
+ system : system_m68k_Amiga;
+ name : 'Commodore Amiga';
+ shortname : 'amiga';
+ flags : [];
+ cpu : cpu_m68k;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.library';
+ staticlibext : '.a';
+ staticlibprefix : 'lib';
+ sharedlibprefix : '';
+ sharedClibext : '.library';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_amiga;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default;
+ );
+
+ system_powerpc_amiga_info : tsysteminfo =
+ (
+ system : system_powerpc_Amiga;
+ name : 'AmigaOS for PowerPC';
+ shortname : 'amigappc';
+ flags : [];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.library';
+ staticlibext : '.a';
+ staticlibprefix : 'lib';
+ sharedlibprefix : '';
+ sharedClibext : '.library';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_amiga;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_powerpc_sysv;
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU68}
+ {$ifdef AMIGA}
+ set_source_info(system_m68k_Amiga_info);
+ {$endif AMIGA}
+{$endif CPU68}
+{$ifdef CPUPOWERPC}
+ {$ifdef AMIGA}
+// set_source_info(system_powerpc_Amiga_info);
+ {$endif AMIGA}
+{$endif CPUPOWERPC}
+end.
diff --git a/compiler/systems/i_atari.pas b/compiler/systems/i_atari.pas
new file mode 100644
index 0000000000..9ecbcab126
--- /dev/null
+++ b/compiler/systems/i_atari.pas
@@ -0,0 +1,83 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for atari
+
+ 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 support information structures for atari. }
+unit i_atari;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_m68k_atari_info : tsysteminfo =
+ (
+ system : target_m68k_Atari;
+ name : 'Atari ST/STE';
+ shortname : 'atari';
+ flags : [tf_use_8_3];
+ cpu : cpu_m68k;
+ short_name : 'ATARI';
+ unit_env : '';
+ extradefines : '';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ exeext : '.tpp';
+ defext : '';
+ scriptext : '';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : ld_m68k_atari;
+ linkextern : ld_m68k_atari;
+ ar : ar_m68k_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ stackalignment : 2;
+ maxCrecordalignment : 4;
+ stacksize : 8192;
+ DllScanSupported:false;
+ use_function_relative_addresses : false
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu68}
+ {$ifdef atari}
+ set_source_info(system_m68k_atari_info);
+ {$endif atari}
+{$endif cpu68}
+end.
diff --git a/compiler/systems/i_beos.pas b/compiler/systems/i_beos.pas
new file mode 100644
index 0000000000..b10777a401
--- /dev/null
+++ b/compiler/systems/i_beos.pas
@@ -0,0 +1,100 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for BeOS
+
+ 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 support information structures for BeOS. }
+unit i_beos;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_beos_info : tsysteminfo =
+ (
+ system : system_i386_BeOS;
+ name : 'Beos for i386';
+ shortname : 'Beos';
+ flags : [tf_under_development,tf_needs_symbol_size];
+ cpu : cpu_i386;
+ unit_env : 'BEOSUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 8192;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef beos}
+ set_source_info(system_i386_beos_info);
+ {$endif beos}
+{$endif cpu86}
+end.
diff --git a/compiler/systems/i_bsd.pas b/compiler/systems/i_bsd.pas
new file mode 100644
index 0000000000..4ed3c183df
--- /dev/null
+++ b/compiler/systems/i_bsd.pas
@@ -0,0 +1,572 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for FreeBSD/NetBSD
+
+ 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 support information structures for FreeBSD/NetBSD.
+ OpenBSD is only added for i386 for now, though it exists for most
+ other common CPU's too}
+
+unit i_bsd;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_freebsd_info : tsysteminfo =
+ (
+ system : system_i386_FreeBSD;
+ name : 'FreeBSD/ELF for i386';
+ shortname : 'FreeBSD';
+ flags : [tf_pic_uses_got];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+
+ system_x86_64_freebsd_info : tsysteminfo =
+ (
+ system : system_x86_64_freebsd;
+ name : 'FreeBSD for x86-64';
+ shortname : 'FreeBSD';
+ flags : [tf_needs_symbol_size,tf_pic_uses_got{,tf_smartlink_sections}];
+ cpu : cpu_x86_64;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 16;
+ stacksize : 256*1024;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+
+ system_i386_netbsd_info : tsysteminfo =
+ (
+ system : system_i386_NetBSD;
+ name : 'NetBSD for i386';
+ shortname : 'NetBSD';
+ flags : [tf_under_development];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 1;
+ varalignmin : 0;
+ varalignmax : 1;
+ localalignmin : 0;
+ localalignmax : 1;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ system_i386_openbsd_info : tsysteminfo =
+ (
+ system : system_i386_OpenBSD;
+ name : 'OpenBSD for i386';
+ shortname : 'OpenBSD';
+ flags : [tf_under_development];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 1;
+ varalignmin : 0;
+ varalignmax : 1;
+ localalignmin : 0;
+ localalignmax : 1;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ system_m68k_netbsd_info : tsysteminfo =
+ (
+ system : system_m68k_NetBSD;
+ name : 'NetBSD for m68k';
+ shortname : 'NetBSD';
+ flags : [tf_under_development];
+ cpu : cpu_m68k;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 1;
+ varalignmin : 0;
+ varalignmax : 1;
+ localalignmin : 0;
+ localalignmax : 1;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ system_powerpc_netbsd_info : tsysteminfo =
+ (
+ system : system_powerpc_netbsd;
+ name : 'NetBSD for PowerPC';
+ shortname : 'NetBSD';
+ flags : [tf_under_development];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.s';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4 // should be 8 probably
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ { abi_powerpc_sysv doesn't work yet }
+ abi : abi_powerpc_aix;
+ );
+
+
+ system_powerpc_darwin_info : tsysteminfo =
+ (
+ system : system_powerpc_darwin;
+ name : 'Darwin for PowerPC';
+ shortname : 'Darwin';
+ flags : [];
+ cpu : cpu_powerpc;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dylib';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.dylib';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : true;
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_darwin;
+ assemextern : as_darwin;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 24;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : false;
+ abi : abi_powerpc_aix;
+ );
+
+
+
+ system_i386_darwin_info : tsysteminfo =
+ (
+ system : system_i386_darwin;
+ name : 'Darwin for i386';
+ shortname : 'Darwin';
+ flags : [];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dylib';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.dylib';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : true;
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_darwin;
+ assemextern : as_darwin;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef FreeBSD}
+ set_source_info(system_i386_FreeBSD_info);
+ {$endif}
+ {$ifdef NetBSD}
+ set_source_info(system_i386_NetBSD_info);
+ {$endif}
+ {$ifdef OpenBSD}
+ set_source_info(system_i386_NetBSD_info);
+ {$endif}
+ {$ifdef Darwin}
+ set_source_info(system_i386_Darwin_info);
+ {$endif Darwin}
+{$endif cpu86}
+{$ifdef cpux86_64}
+ {$ifdef FreeBSD}
+ set_source_info(system_x86_64_FreeBSD_info);
+ {$endif}
+{$endif}
+{$ifdef cpu68}
+ {$ifdef NetBSD}
+ set_source_info(system_m68k_NetBSD_info);
+ {$endif NetBSD}
+{$endif cpu68}
+{$ifdef cpupowerpc}
+ {$ifdef Darwin}
+ set_source_info(system_powerpc_darwin_info);
+ {$endif Darwin}
+ {$ifdef NetBSD}
+ set_source_info(system_powerpc_netbsd_info);
+ {$endif}
+{$endif cpu68}
+end.
diff --git a/compiler/systems/i_emx.pas b/compiler/systems/i_emx.pas
new file mode 100644
index 0000000000..48d8769c64
--- /dev/null
+++ b/compiler/systems/i_emx.pas
@@ -0,0 +1,114 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for OS/2 via EMX
+
+ 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 support information structures for OS/2 via EMX. }
+unit i_emx;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ res_emxbind_info : tresinfo =
+ (
+ id : res_emxbind;
+ resbin : 'emxbind';
+ rescmd : '-b -r $RES $OBJ'
+ (* Not really used - see TLinkerEMX.SetDefaultInfo in t_emx.pas. *)
+ );
+
+ system_i386_emx_info : tsysteminfo =
+ (
+ system : system_i386_EMX;
+ name : 'OS/2 via EMX';
+ shortname : 'EMX';
+ flags : [tf_need_export,tf_use_8_3];
+ cpu : cpu_i386;
+ unit_env : 'EMXUNITS';
+ extradefines : 'OS2';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.cmd';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : false;
+ assem : as_i386_as_aout;
+ assemextern : as_i386_as_aout;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_emxbind;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 256*1024;
+ DllScanSupported: false;
+ use_function_relative_addresses : false
+ );
+
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef EMX}
+ {$IFNDEF VER1_0}
+ set_source_info(system_i386_emx_info);
+ { OS/2 via EMX can be run under DOS as well }
+ if (OS_Mode=osDOS) or (OS_Mode=osDPMI) then
+ source_info.scriptext := '.bat';
+ {$ENDIF VER1_0}
+ {$endif EMX}
+{$endif CPU86}
+end.
diff --git a/compiler/systems/i_gba.pas b/compiler/systems/i_gba.pas
new file mode 100644
index 0000000000..ef5c1e2013
--- /dev/null
+++ b/compiler/systems/i_gba.pas
@@ -0,0 +1,101 @@
+{
+ This unit implements support information structures for GameBoy Advance
+
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ 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 support information structures for gba. }
+unit i_gba;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_arm_gba_info : tsysteminfo =
+ (
+ system : system_arm_gba;
+ name : 'GameBoy Advance';
+ shortname : 'gba';
+ flags : [tf_needs_symbol_size];
+ cpu : cpu_arm;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '.gba';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef arm}
+ {$ifdef gba}
+ set_source_info(system_arm_gba_info);
+ {$endif gba}
+{$endif arm}
+end.
diff --git a/compiler/systems/i_go32v2.pas b/compiler/systems/i_go32v2.pas
new file mode 100644
index 0000000000..d4989355f4
--- /dev/null
+++ b/compiler/systems/i_go32v2.pas
@@ -0,0 +1,100 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for go32v2
+
+ 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 support information structures for go32v2. }
+unit i_go32v2;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_go32v2_info : tsysteminfo =
+ (
+ system : system_i386_GO32V2;
+ name : 'GO32 V2 DOS extender';
+ shortname : 'Go32v2';
+ flags : [tf_use_8_3];
+ cpu : cpu_i386;
+ unit_env : 'GO32V2UNITS';
+ extradefines : 'DPMI';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : false;
+ assem : as_i386_coff;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported : false;
+ use_function_relative_addresses : true
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef go32v2}
+ set_source_info(system_i386_go32v2_info);
+ {$endif go32v2}
+{$endif cpu86}
+end.
diff --git a/compiler/systems/i_linux.pas b/compiler/systems/i_linux.pas
new file mode 100644
index 0000000000..b1a7b87da5
--- /dev/null
+++ b/compiler/systems/i_linux.pas
@@ -0,0 +1,658 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for linux
+
+ 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 support information structures for linux. }
+unit i_linux;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ res_elf32_info : tresinfo =
+ (
+ id : res_elf;
+ resbin : 'fpcres';
+ rescmd : '-o $OBJ -i $RES'
+ );
+
+ res_elf64_info : tresinfo =
+ (
+ id : res_elf;
+ resbin : 'fpcres';
+ rescmd : '-o $OBJ -i $RES'
+ );
+
+ system_i386_linux_info : tsysteminfo =
+ (
+ system : system_i386_LINUX;
+ name : 'Linux for i386';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_pic_uses_got{,tf_smartlink_sections},tf_needs_symbol_type];
+ cpu : cpu_i386;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ system_x86_6432_linux_info : tsysteminfo =
+ (
+ system : system_x86_6432_LINUX;
+ name : 'Linux for x64_6432';
+ shortname : 'Linux6432';
+ flags : [tf_needs_symbol_size,tf_pic_uses_got{,tf_smartlink_sections}];
+ cpu : cpu_x86_64;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ system_m68k_linux_info : tsysteminfo =
+ (
+ system : system_m68k_linux;
+ name : 'Linux for m68k';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type];
+ cpu : cpu_m68k;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ system_powerpc_linux_info : tsysteminfo =
+ (
+ system : system_powerpc_LINUX;
+ name : 'Linux for PowerPC';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_powerpc_sysv;
+ );
+
+ system_powerpc64_linux_info : tsysteminfo =
+ (
+ system : system_powerpc64_LINUX;
+ name : 'Linux for PowerPC64';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type];
+ cpu : cpu_powerpc64;
+ unit_env : '';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ system_alpha_linux_info : tsysteminfo =
+ (
+ system : system_alpha_LINUX;
+ name : 'Linux for Alpha';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type];
+ cpu : cpu_alpha;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ system_x86_64_linux_info : tsysteminfo =
+ (
+ system : system_x86_64_LINUX;
+ name : 'Linux for x86-64';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_dwarf_cfi,
+ tf_library_needs_pic,tf_needs_symbol_type];
+ cpu : cpu_x86_64;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 16;
+ stacksize : 256*1024;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ system_sparc_linux_info : tsysteminfo =
+ (
+ system : system_SPARC_Linux;
+ name : 'Linux for SPARC';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_library_needs_pic,tf_needs_symbol_type];
+ cpu : cpu_SPARC;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 92;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ system_arm_linux_info : tsysteminfo =
+ (
+ system : system_arm_Linux;
+ name : 'Linux for ARM';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type];
+ cpu : cpu_arm;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef linux}
+ { some FreeBSD versions define linux as well }
+ {$ifndef FreeBSD}
+ set_source_info(system_i386_linux_info);
+ {$endif FreeBSD}
+ {$endif}
+{$endif CPU86}
+{$ifdef CPU68}
+ {$ifdef linux}
+ set_source_info(system_m68k_linux_info);
+ {$endif linux}
+{$endif CPU68}
+{$ifdef CPUX86_64}
+ {$ifdef linux}
+ set_source_info(system_x86_64_linux_info);
+ {$endif linux}
+{$endif CPUX86_64}
+{$ifdef CPUALPHA}
+ {$ifdef linux}
+ set_source_info(system_alpha_linux_info);
+ {$endif linux}
+{$endif CPUALPHA}
+{$ifdef CPUSPARC}
+ {$ifdef linux}
+ set_source_info(system_sparc_linux_info);
+ {$endif linux}
+{$endif CPUSPARC}
+{$ifdef CPUPOWERPC32}
+ {$ifdef linux}
+ set_source_info(system_powerpc_linux_info);
+ {$endif linux}
+{$endif CPUPOWERPC32}
+{$ifdef CPUPOWERPC64}
+ {$ifdef linux}
+ set_source_info(system_powerpc64_linux_info);
+ {$endif linux}
+{$endif CPUPOWERPC64}
+{$ifdef CPUARM}
+ {$ifdef linux}
+ set_source_info(system_arm_linux_info);
+ {$endif linux}
+{$endif CPUARM}
+end.
diff --git a/compiler/systems/i_macos.pas b/compiler/systems/i_macos.pas
new file mode 100644
index 0000000000..cdc387a841
--- /dev/null
+++ b/compiler/systems/i_macos.pas
@@ -0,0 +1,100 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for MacOS
+
+ 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 support information structures for MacOS. }
+unit i_macos;
+
+ interface
+
+ uses
+ systems;
+ const
+ system_powerpc_macos_info : tsysteminfo =
+ (
+ system : system_powerpc_MACOS;
+ name : 'Mac OS for PowerPC';
+ shortname : 'MacOS';
+ flags : [];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '';
+ scriptext : '';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : 'Lib';
+ staticlibext : 'Lib';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : 'Lib';
+ staticClibext : 'Lib';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ p_ext_support : true;
+ Cprefix : '';
+ newline : #13;
+ dirsep : ':';
+ files_case_relevent : false;
+ assem : as_powerpc_mpw;
+ assemextern : as_powerpc_mpw;
+ link : nil;
+ linkextern : nil;
+ ar : ar_mpw_ar;
+ res : res_powerpc_mpw;
+ dbg : dbg_stabs;
+ script : script_mpw;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 8;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_powerpc_aix;
+ );
+
+ implementation
+
+initialization
+{$ifdef cpupowerpc}
+ {$ifdef macos}
+ set_source_info(system_powerpc_macos_info);
+ {$endif macos}
+{$endif cpupowerpc}
+end.
diff --git a/compiler/systems/i_morph.pas b/compiler/systems/i_morph.pas
new file mode 100644
index 0000000000..a5d7bb1cdb
--- /dev/null
+++ b/compiler/systems/i_morph.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 2004 by Free Pascal Development Team
+
+ This unit implements support information structures for MorphOS
+
+ 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 support information structures for the MorphOS. }
+unit i_morph;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_powerpc_MorphOS_info : tsysteminfo =
+ (
+ system : system_powerpc_MorphOS;
+ name : 'MorphOS';
+ shortname : 'MorphOS';
+ flags : [];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.library';
+ staticlibext : '.a';
+ staticlibprefix : 'lib';
+ sharedlibprefix : '';
+ sharedClibext : '.library';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_amiga;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true;
+ abi : abi_powerpc_sysv;
+ );
+
+ implementation
+
+initialization
+{$ifdef CPUPOWERPC}
+ {$ifdef MORPHOS}
+ set_source_info(system_powerpc_MorphOS_info);
+ {$endif MORPHOS}
+{$endif CPUPOWERPC}
+end.
diff --git a/compiler/systems/i_nwl.pas b/compiler/systems/i_nwl.pas
new file mode 100644
index 0000000000..a1abad2f51
--- /dev/null
+++ b/compiler/systems/i_nwl.pas
@@ -0,0 +1,100 @@
+{
+ Copyright (c) 1998-2004 by Peter Vreman
+
+ This unit implements support information structures for Netware (libc) modules
+
+ 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 support information structures for Netware libc modules. }
+unit i_nwl;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_netwlibc_info : tsysteminfo =
+ (
+ system : system_i386_netwlibc;
+ name : 'Netware for i386(libc)';
+ shortname : 'Netwlibc';
+ flags : [];
+ cpu : cpu_i386;
+ unit_env : 'NETWLIBCUNITS';
+ extradefines : 'NETWARE;NETWARE_LIBC';
+ exeext : '.nlm';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.nlm';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.nlm';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #13#10;
+ dirsep : '/';
+ files_case_relevent : false;
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 16384;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef netwlibc}
+ set_source_info(system_i386_netwlibc_info);
+ {$endif netwlibc}
+{$endif CPU86}
+end.
diff --git a/compiler/systems/i_nwm.pas b/compiler/systems/i_nwm.pas
new file mode 100644
index 0000000000..8880accfed
--- /dev/null
+++ b/compiler/systems/i_nwm.pas
@@ -0,0 +1,100 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for Netware modules
+
+ 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 support information structures for Netware modules. }
+unit i_nwm;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_netware_info : tsysteminfo =
+ (
+ system : system_i386_netware;
+ name : 'Netware for i386(clib)';
+ shortname : 'Netware';
+ flags : [];
+ cpu : cpu_i386;
+ unit_env : 'NETWAREUNITS';
+ extradefines : 'NETWARE_CLIB';
+ exeext : '.nlm';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.nlm';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.nlm';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #13#10;
+ dirsep : '/';
+ files_case_relevent : false;
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 16384;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef netware}
+ set_source_info(system_i386_netware_info);
+ {$endif netware}
+{$endif CPU86}
+end.
diff --git a/compiler/systems/i_os2.pas b/compiler/systems/i_os2.pas
new file mode 100644
index 0000000000..adb306689e
--- /dev/null
+++ b/compiler/systems/i_os2.pas
@@ -0,0 +1,114 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for OS/2
+
+ 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 support information structures for OS/2. }
+unit i_os2;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ res_emxbind_info : tresinfo =
+ (
+ id : res_emxbind;
+ resbin : 'emxbind';
+ rescmd : '-b -r $RES $OBJ'
+ (* Not really used - see TLinkeros2.SetDefaultInfo in t_os2.pas. *)
+ );
+
+ system_i386_os2_info : tsysteminfo =
+ (
+ system : system_i386_OS2;
+ name : 'OS/2';
+ shortname : 'OS2';
+ flags : [tf_need_export,tf_use_8_3];
+ cpu : cpu_i386;
+ unit_env : 'OS2UNITS';
+ extradefines : '';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.cmd';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : false;
+ assem : as_i386_as_aout;
+ assemextern : as_i386_as_aout;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_emxbind;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 256*1024;
+ DllScanSupported: false;
+ use_function_relative_addresses : false
+ );
+
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef os2}
+ {$IFNDEF EMX}
+ set_source_info(system_i386_os2_info);
+ {$ENDIF EMX}
+ {$IFDEF VER1_0}
+ set_source_info(system_i386_os2_info);
+ {$ENDIF VER1_0}
+ {$endif os2}
+{$endif CPU86}
+end.
diff --git a/compiler/systems/i_palmos.pas b/compiler/systems/i_palmos.pas
new file mode 100644
index 0000000000..fda9a52eb3
--- /dev/null
+++ b/compiler/systems/i_palmos.pas
@@ -0,0 +1,90 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for PalmOS
+
+ 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 support information structures for PalmOS. }
+unit i_palmos;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_m68k_palmos_info : tsysteminfo =
+ (
+ system : system_m68k_PalmOS;
+ name : 'PalmOS';
+ shortname : 'PalmOS';
+ flags : [tf_code_small,tf_static_a5_based];
+ cpu : cpu_m68k;
+ short_name : 'PALMOS';
+ unit_env : 'PALMUNITS';
+ extradefines : '';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ exeext : '';
+ defext : '';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : ld_m68k_palmos;
+ linkextern : ld_m68k_palmos;
+ ar : ar_m68k_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ stackalignment : 2;
+ maxCrecordalignment : 4;
+ stacksize : 8192;
+ DllScanSupported:false;
+ use_function_relative_addresses : false
+ );
+
+ res_m68k_palmos_info : tresinfo =
+ (
+ id : res_m68k_palmos;
+ resbin : 'pilrc';
+ rescmd : '-I $INC $RES'
+ );
+
+implementation
+
+initialization
+{$ifdef cpu68}
+ {$ifdef palmos}
+ set_source_info(system_m68k_palmos_info);
+ {$endif palmos}
+{$endif cpu68}
+end.
diff --git a/compiler/systems/i_sunos.pas b/compiler/systems/i_sunos.pas
new file mode 100644
index 0000000000..073a3e4bfa
--- /dev/null
+++ b/compiler/systems/i_sunos.pas
@@ -0,0 +1,168 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for solaris
+
+ 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 support information structures for solaris. }
+unit i_sunos;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_solaris_info : tsysteminfo =
+ (
+ system : system_i386_solaris;
+ name : 'Solaris for i386';
+ shortname : 'solaris';
+ flags : [tf_under_development];
+ cpu : cpu_i386;
+ unit_env : 'SOLARISUNITS';
+ extradefines : 'UNIX;LIBC';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 1;
+ varalignmin : 0;
+ varalignmax : 1;
+ localalignmin : 0;
+ localalignmax : 1;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ system_sparc_solaris_info : tsysteminfo =
+ (
+ system : system_sparc_solaris;
+ name : 'Solaris for SPARC';
+ shortname : 'solaris';
+ flags : [tf_needs_symbol_size];
+ cpu : cpu_SPARC;
+ unit_env : 'SOLARISUNITS';
+ extradefines : 'UNIX;LIBC;';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 92;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef solaris}
+ set_source_info(system_i386_solaris_info);
+ {$endif solaris}
+{$endif CPU86}
+{$ifdef CPUSparc}
+ {$ifdef solaris}
+ set_source_info(system_sparc_solaris_info);
+ {$endif solaris}
+{$endif CPUSparc}
+
+end.
diff --git a/compiler/systems/i_watcom.pas b/compiler/systems/i_watcom.pas
new file mode 100644
index 0000000000..751357102b
--- /dev/null
+++ b/compiler/systems/i_watcom.pas
@@ -0,0 +1,102 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for Watcom
+
+ 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 support information structures for Watcom. }
+unit i_watcom;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_watcom_info : tsysteminfo =
+ (
+ system : system_i386_Watcom;
+ name : 'Watcom compatible DOS extenders';
+ shortname : 'WATCOM';
+ flags : [tf_use_8_3];
+ cpu : cpu_i386;
+ unit_env : 'WATCOMUNITS';
+ extradefines : 'DPMI';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.asm';
+ objext : '.obj';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : false;
+ assem : as_i386_wasm;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 16384;
+ DllScanSupported : false;
+ use_function_relative_addresses : true
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef watcom}
+ set_source_info(system_i386_watcom_info);
+ {$endif watcom}
+{$endif cpu86}
+end.
diff --git a/compiler/systems/i_wdosx.pas b/compiler/systems/i_wdosx.pas
new file mode 100644
index 0000000000..75091db330
--- /dev/null
+++ b/compiler/systems/i_wdosx.pas
@@ -0,0 +1,102 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for win32
+
+ 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 support information structures for wdosx. }
+unit i_wdosx;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_wdosx_info : tsysteminfo =
+ (
+ system : system_i386_wdosx;
+ name : 'WDOSX DOS extender';
+ shortname : 'WDOSX';
+ flags : [tf_use_8_3];
+ cpu : cpu_i386;
+ unit_env : 'WDOSXUNITS';
+ extradefines : 'MSWINDOWS';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.rc';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : false;
+ assem : as_i386_pecoffwdosx;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ DllScanSupported:true;
+ use_function_relative_addresses : true
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef WIN32}
+ {$ifdef WDOSX}
+ set_source_info(system_i386_wdosx_info);
+ {$endif WDOSX}
+ {$endif WIN32}
+{$endif CPU86}
+end.
diff --git a/compiler/systems/i_win.pas b/compiler/systems/i_win.pas
new file mode 100644
index 0000000000..b5a7192a5a
--- /dev/null
+++ b/compiler/systems/i_win.pas
@@ -0,0 +1,306 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for win32
+
+ 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 support information structures for win32. }
+unit i_win;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_win32_info : tsysteminfo =
+ (
+ system : system_i386_WIN32;
+ name : 'Win32 for i386';
+ shortname : 'Win32';
+ flags : [];
+ cpu : cpu_i386;
+ unit_env : 'WIN32UNITS';
+ extradefines : 'MSWINDOWS';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.rc';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : true;
+ assem : as_i386_pecoff;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:true;
+ use_function_relative_addresses : true
+ );
+
+ system_x64_win64_info : tsysteminfo =
+ (
+ system : system_x86_64_win64;
+ name : 'Win64 for x64';
+ shortname : 'Win64';
+ flags : [];
+ cpu : cpu_x86_64;
+ unit_env : 'WIN64UNITS';
+ extradefines : 'MSWINDOWS';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.rc';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : true;
+ assem : as_x86_64_pecoff;
+ assemextern : as_x86_64_masm;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 8;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 8;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 16;
+ stacksize : 262144;
+ DllScanSupported:true;
+ use_function_relative_addresses : true
+ );
+
+ system_arm_wince_info : tsysteminfo =
+ (
+ system : system_arm_wince;
+ name : 'WinCE for ARM';
+ shortname : 'WinCE';
+ flags : [];
+ cpu : cpu_arm;
+ unit_env : '';
+ extradefines : 'UNDER_CE';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.rc';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_wince_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:false;
+ use_function_relative_addresses : true
+ );
+
+ system_i386_wince_info : tsysteminfo =
+ (
+ system : system_i386_wince;
+ name : 'WinCE for i386';
+ shortname : 'WinCE';
+ flags : [];
+ cpu : cpu_i386;
+ unit_env : '';
+ extradefines : 'UNDER_CE';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.rc';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ files_case_relevent : true;
+ assem : as_i386_pecoffwince;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ DllScanSupported:true;
+ use_function_relative_addresses : true
+ );
+
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef WIN32}
+ {$ifndef WDOSX}
+ set_source_info(system_i386_win32_info);
+ {$endif WDOSX}
+ {$endif WIN32}
+ {$ifdef WINCE}
+ set_source_info(system_i386_wince_info);
+ {$endif WINCE}
+{$endif CPU86}
+
+{$ifdef CPUX86_64}
+ {$ifdef WIN64}
+ {$ifndef WDOSX}
+ set_source_info(system_x64_win64_info);
+ {$endif WDOSX}
+ {$endif WIN64}
+{$endif CPUX86_64}
+
+{$ifdef CPUARM}
+ {$ifdef WINCE}
+ set_source_info(system_arm_wince_info);
+ {$endif WINCE}
+{$endif CPUARM}
+end.
diff --git a/compiler/systems/mac_crea.txt b/compiler/systems/mac_crea.txt
new file mode 100644
index 0000000000..5372652cbc
--- /dev/null
+++ b/compiler/systems/mac_crea.txt
@@ -0,0 +1,71 @@
+FrŒn: devprograms@apple.com
+Till: <olle.raab@freepascal.org>
+Datum: mŒndag 10 januari 2005 22.33
+€mne: Re: Creator Registration Request
+
+Please include the line below in follow-up emails for this request.
+
+Follow-up: 6855616
+
+Re: Creator Registration Request
+
+Dear Olle Raab,
+
+Thank you for registering your application creator information. We appreciate your continued product development and support of Apple Computer! The following product information has been registered:
+
+Company: Free Pascal Team
+Contact: Olle Raab
+Address: VikingavŠgen 28 A
+S-224 77 Lund
+Sweden
+
+
+Application: Free Pascal Compiler
+Phone: +46-46-120053
+EMail Address: olle.raab@freepascal.org
+
+Application Signatures:
+FPas (Hex) 46506173
+
+This letter serves as your confirmation. Please keep it on file. Additionally, you should review the information for accuracy. If you locate discrepancies, please contact Developer Support at devprograms@apple.com with your corrections.
+
+Thanks for supporting Apple!
+
+Best regards,
+
+Elisa Molson
+Apple Developer Connection
+-----------------------------------
+Spotlight, 64-bit Support, Dashboard, Automator, and more.
+Start developing today with the powerful new technologies in Mac OS X Tiger.
+
+REQUEST ------------------------------------------------------------------------
+
+WEB CREATOR/FILE TYPE Registration Request
+==========================================
+%UNIQUE REGISTRATION%:
+%NAME%: Olle Raab
+%COMPANY%: Free Pascal Team
+%ADDRESS%: VikingavŠgen 28 A
+S-224 77 Lund
+Sweden
+%TELEPHONE%: +46-46-120053
+%E-MAIL%: olle.raab@freepascal.org
+%PRODUCT NAME%: Free Pascal Compiler
+%DEVICE DRIVER%:
+%SIGNATURE (HEX)%: 46506173
+%END
+
+
+DB REFERENCE -------------------------------------------------------------------
+
+TIME IN: 10-Jan-2005 10:45 PST
+TIME OUT: 10-Jan-2005 13:16 PST
+
+Copyright 2005, Apple Computer, Inc.
+
+SECURITY: NON-DISCLOSURE USE ONLY
+
+
+
+
diff --git a/compiler/systems/t_amiga.pas b/compiler/systems/t_amiga.pas
new file mode 100644
index 0000000000..95e9d340b9
--- /dev/null
+++ b/compiler/systems/t_amiga.pas
@@ -0,0 +1,43 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (m68k/powerpc) Amiga target
+
+ 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 t_amiga;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ link,
+ cutils,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_amiga;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterTarget(system_m68k_amiga_info);
+end.
diff --git a/compiler/systems/t_atari.pas b/compiler/systems/t_atari.pas
new file mode 100644
index 0000000000..5833ac8129
--- /dev/null
+++ b/compiler/systems/t_atari.pas
@@ -0,0 +1,43 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Amiga target
+
+ 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 t_atari;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ link,
+ cutils,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_atari;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterTarget(system_m68k_atari_info);
+end.
diff --git a/compiler/systems/t_beos.pas b/compiler/systems/t_beos.pas
new file mode 100644
index 0000000000..5e9ea9f54e
--- /dev/null
+++ b/compiler/systems/t_beos.pas
@@ -0,0 +1,495 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) BeOS target.
+
+ 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 t_beos;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symsym,symdef,
+ import,export,link;
+
+ type
+ timportlibbeos=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ end;
+
+ texportlibbeos=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkerbeos=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean;makelib:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+
+implementation
+
+ uses
+ dos,
+ cutils,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmcpu,cpubase,i_beos;
+
+{*****************************************************************************
+ TIMPORTLIBBEOS
+*****************************************************************************}
+
+procedure timportlibbeos.preparelib(const s : string);
+begin
+end;
+
+
+procedure timportlibbeos.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+end;
+
+
+procedure timportlibbeos.importvariable(vs:tglobalvarsym;const name,module:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+ { reset the mangledname and turn off the dll_var option }
+ vs.set_mangledname(name);
+ exclude(vs.varoptions,vo_is_dll_var);
+end;
+
+
+procedure timportlibbeos.generatelib;
+begin
+end;
+
+
+{*****************************************************************************
+ TEXPORTLIBBEOS
+*****************************************************************************}
+
+procedure texportlibbeos.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibbeos.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Message1(parser_e_no_export_with_index_for_target,'beos');
+ exit;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.concat(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibbeos.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibbeos.generatelib;
+var
+ hp2 : texported_item;
+begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
+ begin
+{$ifdef i386}
+ { place jump in al_procedures }
+ asmlist[al_procedures].concat(Tai_align.Create_op(4,$90));
+ asmlist[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ asmlist[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(tprocsym(hp2.sym).first_procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+ asmlist[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif i386}
+ end;
+ end
+ else
+ Message1(parser_e_no_export_of_variables_for_target,'beos');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERBEOS
+*****************************************************************************}
+
+Constructor TLinkerBeos.Create;
+var
+ s : string;
+ i : integer;
+begin
+ Inherited Create;
+ s:=GetEnv('BELIBRARIES');
+ { convert to correct format in case under unix system }
+ for i:=1 to length(s) do
+ if s[i] = ':' then
+ s[i] := ';';
+ { just in case we have a single path : add the ending ; }
+ { since that is what the compiler expects. }
+ if pos(';',s) = 0 then
+ s:=s+';';
+ LibrarySearchPath.AddPath(s,true); {format:'path1;path2;...'}
+end;
+
+
+procedure TLinkerBeOS.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE `cat $RES`';
+ DllCmd[1]:='ld $OPT $INIT $FINI $SONAME -shared -L. -o $EXE `cat $RES`';
+ DllCmd[2]:='strip --strip-unneeded $EXE';
+(*
+ ExeCmd[1]:='sh $RES $EXE $OPT $STATIC $STRIP -L.';
+{ ExeCmd[1]:='sh $RES $EXE $OPT $DYNLINK $STATIC $STRIP -L.';}
+ DllCmd[1]:='sh $RES $EXE $OPT -L.';
+
+{ DllCmd[1]:='sh $RES $EXE $OPT -L. -g -nostart -soname=$EXE';
+ } DllCmd[2]:='strip --strip-unneeded $EXE';
+{ DynamicLinker:='/lib/ld-beos.so.2';}
+*)
+ end;
+end;
+
+
+function TLinkerBeOS.WriteResponseFile(isdll:boolean;makelib:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : integer;
+ cprtobj,
+ prtobj : string[80];
+ HPath : TStringListItem;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+{ set special options for some targets }
+ linklibc:=(SharedLibFiles.Find('root')<>nil);
+
+ prtobj:='prt0';
+ cprtobj:='cprt0';
+ if (cs_profile in aktmoduleswitches) or
+ (not SharedLibFiles.Empty) then
+ begin
+ AddSharedLibrary('root');
+ linklibc:=true;
+ end;
+
+ if (not linklibc) and makelib then
+ begin
+ linklibc:=true;
+ cprtobj:='dllprt.o';
+ end;
+
+ if linklibc then
+ prtobj:=cprtobj;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+ {
+ if not isdll then
+ LinkRes.Add('ld -o $1 $2 $3 $4 $5 $6 $7 $8 $9 \')
+ else
+ LinkRes.Add('ld -o $1 -e 0 $2 $3 $4 $5 $6 $7 $8 $9\');
+ }
+ LinkRes.Add('-m elf_i386_be -shared -Bsymbolic');
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add(maybequoted('-L'+HPath.Str));
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add(maybequoted('-L'+HPath.Str));
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crti.o',s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crtbegin.o',s) then
+ LinkRes.AddFileName(s);
+{ s:=librarysearchpath.FindFile('start_dyn.o',found)+'start_dyn.o';
+ if found then LinkRes.AddFileName(s+' \');}
+
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+
+ if isdll then
+ LinkRes.AddFileName(FindObjectFile('func.o','',false));
+
+ if librarysearchpath.FindFile('init_term_dyn.o',s) then
+ LinkRes.AddFileName(s);
+ end
+ else
+ begin
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+ end;
+
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+
+{ LinkRes.Add('-lroot \');
+ LinkRes.Add('/boot/develop/tools/gnupro/lib/gcc-lib/i586-beos/2.9-beos-991026/crtend.o \');
+ LinkRes.Add('/boot/develop/lib/x86/crtn.o \');}
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(maybequoted(s))
+ end;
+ end;
+
+ { Write sharedlibraries like -l<lib> }
+ if not SharedLibFiles.Empty then
+ begin
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc is the last lib }
+{ if linklibc then
+ LinkRes.Add('-lroot');}
+{ if linkdynamic and (Info.DynamicLinker<>'') then
+ LinkRes.AddFileName(Info.DynamicLinker);}
+ end;
+ if isdll then
+ LinkRes.Add('-lroot');
+
+ { objects which must be at the end }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crtend.o',s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crtn.o',s) then
+ LinkRes.AddFileName(s);
+ end;
+
+{ Write and Close response }
+ linkres.Add(' ');
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerBeOS.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TcmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in aktglobalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+ If (cs_profile in aktmoduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if cshared Then
+ DynLinkStr:='--shared ' + DynLinkStr;
+ if rlinkpath<>'' Then
+ DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
+ End;
+
+{ Write used files and libraries }
+ WriteResponseFile(false,false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,true);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerBeOS.MakeSharedLibrary:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ StaticStr,
+ StripStr : string[40];
+
+ begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in aktglobalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+ If (cs_profile in aktmoduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if cshared Then
+ DynLinkStr:='--shared ' + DynLinkStr;
+ if rlinkpath<>'' Then
+ DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
+ End;
+{ Write used files and libraries }
+ WriteResponseFile(true,true);
+
+{ Call linker }
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,true);
+
+{ Strip the library ? }
+ if success and (cs_link_strip in aktglobalswitches) then
+ begin
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_beos_info,TLinkerbeos);
+ RegisterImport(system_i386_beos,timportlibbeos);
+ RegisterExport(system_i386_beos,texportlibbeos);
+ RegisterTarget(system_i386_beos_info);
+{$endif i386}
+end.
diff --git a/compiler/systems/t_bsd.pas b/compiler/systems/t_bsd.pas
new file mode 100644
index 0000000000..1d59a6d4ea
--- /dev/null
+++ b/compiler/systems/t_bsd.pas
@@ -0,0 +1,655 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman (original Linux)
+ (c) 2000 by Marco van de Voort (FreeBSD mods)
+
+ This unit implements support import,export,link routines
+ for the (i386)FreeBSD target
+
+ 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 t_bsd;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ cutils,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmcpu,cpubase,symsym,symdef,
+ import,export,link,i_bsd,
+ cgutils,cgbase,cgobj,cpuinfo;
+
+ type
+ tdarwinimported_item = class(timported_item)
+ procdef : tprocdef;
+ end;
+
+ timportlibdarwin=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ procedure generatesmartlib;override;
+ end;
+
+ timportlibbsd=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ end;
+
+ texportlibbsd=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkerbsd=class(texternallinker)
+ private
+ LdSupportsNoResponseFile : boolean;
+ LibrarySuffix : Char;
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+
+
+{*****************************************************************************
+ TIMPORTLIBDARWIN
+*****************************************************************************}
+
+ procedure timportlibdarwin.preparelib(const s : string);
+ begin
+ if asmlist[al_imports]=nil then
+ asmlist[al_imports]:=TAAsmoutput.create;
+ end;
+
+
+ procedure timportlibdarwin.importprocedure(aprocdef:tprocdef;const module : string;index : longint;const name : string);
+ begin
+ { insert sharedlibrary }
+{ current_module.linkothersharedlibs.add(SplitName(module),link_allways); }
+ end;
+
+
+ procedure timportlibdarwin.importvariable(vs:tglobalvarsym;const name,module:string);
+ begin
+ { insert sharedlibrary }
+{ current_module.linkothersharedlibs.add(SplitName(module),link_allways); }
+ { the rest is handled in the nppcld.pas tppcloadnode }
+ vs.set_mangledname(name);
+ end;
+
+
+ procedure timportlibdarwin.generatesmartlib;
+ begin
+ generatelib;
+ end;
+
+
+ procedure timportlibdarwin.generatelib;
+ begin
+ end;
+
+
+{*****************************************************************************
+ TIMPORTLIBBSD
+*****************************************************************************}
+
+procedure timportlibbsd.preparelib(const s : string);
+begin
+end;
+
+
+procedure timportlibbsd.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+end;
+
+
+procedure timportlibbsd.importvariable(vs:tglobalvarsym;const name,module:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+ { reset the mangledname and turn off the dll_var option }
+ vs.set_mangledname(name);
+ exclude(vs.varoptions,vo_is_dll_var);
+end;
+
+
+procedure timportlibbsd.generatelib;
+begin
+end;
+
+
+{*****************************************************************************
+ TEXPORTLIBBSD
+*****************************************************************************}
+
+procedure texportlibbsd.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibbsd.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Message1(parser_e_no_export_with_index_for_target,'*bsd/darwin');
+ exit;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.concat(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibbsd.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibbsd.generatelib;
+var
+ hp2 : texported_item;
+begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
+ begin
+{$ifdef i386}
+ { place jump in al_procedures }
+ asmlist[al_procedures].concat(Tai_align.Create_op(4,$90));
+ asmlist[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ asmlist[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(tprocsym(hp2.sym).first_procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+ asmlist[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif i386}
+{$ifdef powerpc}
+ asmlist[al_procedures].concat(Tai_align.create(16));
+ asmlist[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ asmlist[al_procedures].concat(Taicpu.Op_sym(A_B,objectlibrary.newasmsymbol(tprocsym(hp2.sym).first_procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+ asmlist[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif powerpc}
+ end;
+ end
+ else
+ Message1(parser_e_no_export_of_variables_for_target,'*bsd/darwin');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERLINUX
+*****************************************************************************}
+
+Constructor TLinkerBSD.Create;
+begin
+ Inherited Create;
+ if not Dontlinkstdlibpath Then
+ if (target_info.system <> system_powerpc_darwin) then
+ LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true)
+ else
+ { Mac OS X doesn't have a /lib }
+ LibrarySearchPath.AddPath('/usr/lib',true)
+end;
+
+
+procedure TLinkerBSD.SetDefaultInfo;
+{
+ This will also detect which libc version will be used
+}
+begin
+ LibrarySuffix:=' ';
+ LdSupportsNoResponseFile := (target_info.system in [system_m68k_netbsd,system_powerpc_darwin]);
+ with Info do
+ begin
+ if LdSupportsNoResponseFile then
+ begin
+ if (target_info.system <> system_powerpc_darwin) then
+ begin
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE `cat $RES`';
+ DllCmd[1]:='ld $OPT -shared -L. -o $EXE `cat $RES`'
+ end
+ else
+ begin
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -multiply_defined suppress -L. -o $EXE `cat $RES`';
+ DllCmd[1]:='libtool $OPT -dynamic -init PASCALMAIN -multiply_defined suppress -L. -o $EXE `cat $RES`'
+ end
+ end
+ else
+ begin
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE $RES';
+ DllCmd[1]:='ld $OPT $INIT $FINI $SONAME -shared -L. -o $EXE $RES';
+ end;
+ if (target_info.system <> system_powerpc_darwin) then
+ DllCmd[2]:='strip --strip-unneeded $EXE'
+ else
+ DllCmd[2]:='strip -x $EXE';
+ { first try glibc2 }
+{$ifdef GLIBC2} {Keep linux code in place. FBSD might go to a different
+ glibc too once}
+ DynamicLinker:='/lib/ld-linux.so.2';
+ if FileExists(DynamicLinker) then
+ begin
+ Glibc2:=true;
+ { Check for 2.0 files, else use the glibc 2.1 stub }
+ if FileExists('/lib/ld-2.0.*') then
+ Glibc21:=false
+ else
+ Glibc21:=true;
+ end
+ else
+ DynamicLinker:='/lib/ld-linux.so.1';
+{$else}
+ DynamicLinker:='';
+{$endif}
+ end;
+end;
+
+
+Function TLinkerBSD.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ cprtobj,
+ gprtobj,
+ prtobj : string[80];
+ HPath : TStringListItem;
+ s,s1,s2 : string;
+ linkpthread,
+ linkdynamic,
+ linklibc : boolean;
+ Fl1,Fl2 : Boolean;
+
+begin
+ WriteResponseFile:=False;
+{ set special options for some targets }
+ if target_info.system <> system_powerpc_darwin then
+ begin
+ linkdynamic:=not(SharedLibFiles.empty);
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+ linkpthread:=(SharedLibFiles.Find('pthread')<>nil);
+ if (target_info.system =system_i386_freebsd) and linkpthread Then
+ Begin
+ if not (cs_link_pthread in aktglobalswitches) Then
+ begin
+ {delete pthreads from list, in this case it is in libc_r}
+ SharedLibFiles.Remove(SharedLibFiles.Find('pthread').str);
+ LibrarySuffix:='r';
+ end;
+ End;
+ prtobj:='prt0';
+ cprtobj:='cprt0';
+ gprtobj:='gprt0';
+ if cs_profile in aktmoduleswitches then
+ begin
+ prtobj:=gprtobj;
+ AddSharedLibrary('c');
+ LibrarySuffix:='p';
+ linklibc:=true;
+ end
+ else
+ begin
+ if linklibc then
+ prtobj:=cprtobj;
+ end;
+ end
+ else
+ begin
+ { for darwin: always link dynamically against libc }
+ linklibc := true;
+ if not(isdll) then
+ if not(cs_profile in aktmoduleswitches) then
+ prtobj:='/usr/lib/crt1.o'
+ else
+ prtobj:='/usr/lib/gcrt1.o'
+ else
+ prtobj:='';
+ end;
+
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ if LdSupportsNoResponseFile then
+ LinkRes.Add(maybequoted('-L'+HPath.Str))
+ else
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ if LdSupportsNoResponseFile then
+ LinkRes.Add(maybequoted('-L'+HPath.Str))
+ else
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add('INPUT(');
+ { add objectfiles, start with prt0 always }
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+ { try to add crti and crtbegin if linking to C }
+ if linklibc and
+ (target_info.system <> system_powerpc_darwin) then
+ begin
+ if librarysearchpath.FindFile('crtbegin.o',s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crti.o',s) then
+ LinkRes.AddFileName(s);
+ end;
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add(')');
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(maybequoted(s))
+ end;
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add(')');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if not SharedLibFiles.Empty then
+ begin
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add('INPUT(');
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ linkdynamic:=false; { libc will include the ld-linux for us }
+ end;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc then
+ Begin
+ If LibrarySuffix=' ' Then
+ LinkRes.Add('-lc')
+ else
+ LinkRes.Add('-lc_'+LibrarySuffix);
+ If LibrarySuffix='r' Then
+ LinkRes.Add('-lc');
+ end;
+ { when we have -static for the linker the we also need libgcc }
+ if (cs_link_staticflag in aktglobalswitches) then
+ LinkRes.Add('-lgcc');
+ if linkdynamic and (Info.DynamicLinker<>'') then
+ LinkRes.AddFileName(Info.DynamicLinker);
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add(')');
+ end;
+ { objects which must be at the end }
+ if linklibc and
+ (target_info.system <> system_powerpc_darwin) then
+ begin
+ Fl1:=librarysearchpath.FindFile('crtend.o',s1);
+ Fl2:=librarysearchpath.FindFile('crtn.o',s2);
+ if Fl1 or Fl2 then
+ begin
+ LinkRes.Add('INPUT(');
+ If Fl1 Then
+ LinkRes.AddFileName(s1);
+ If Fl2 Then
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+ { ignore the fact that our relocations are in non-writable sections, }
+ { will be fixed once we have pic support }
+ if isdll and
+ (target_info.system = system_powerpc_darwin) then
+ LinkRes.Add('-read_only_relocs suppress');
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerBSD.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ GCSectionsStr,
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ GCSectionsStr:='';
+ if (cs_link_staticflag in aktglobalswitches) then
+ begin
+ if (target_info.system=system_m68k_netbsd) and
+ ((cs_link_on_target in aktglobalswitches) or
+ (target_info.system=source_info.system)) then
+ StaticStr:='-Bstatic'
+ else
+ StaticStr:='-static';
+ end;
+ if (cs_link_strip in aktglobalswitches) then
+ if (target_info.system <> system_powerpc_darwin) then
+ StripStr:='-s'
+ else
+ StripStr:='-x';
+
+ if (cs_link_smart in aktglobalswitches) and
+ (tf_smartlink_sections in target_info.flags) then
+ GCSectionsStr:='--gc-sections';
+
+ If (cs_profile in aktmoduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+
+ if CShared Then
+ DynLinKStr:=DynLinkStr+' --shared';
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,LdSupportsNoResponseFile);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerBSD.MakeSharedLibrary:boolean;
+var
+ InitStr,
+ FiniStr,
+ SoNameStr : string[80];
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile(true);
+
+ InitStr:='-init FPC_LIB_START';
+ FiniStr:='-fini FPC_LIB_EXIT';
+ SoNameStr:='-soname '+SplitFileName(current_module.sharedlibfilename^);
+
+{ Call linker }
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$INIT',InitStr);
+ Replace(cmdstr,'$FINI',FiniStr);
+ Replace(cmdstr,'$SONAME',SoNameStr);
+
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,LdSupportsNoResponseFile);
+
+{ Strip the library ? }
+ if success and (cs_link_strip in aktglobalswitches) then
+ begin
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef x86_64}
+ RegisterExternalLinker(system_x86_64_FreeBSD_info,TLinkerBSD);
+ RegisterImport(system_x86_64_freebsd,timportlibbsd);
+ RegisterExport(system_x86_64_freebsd,texportlibbsd);
+ RegisterTarget(system_x86_64_freebsd_info);
+{$endif}
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_FreeBSD_info,TLinkerBSD);
+ RegisterExternalLinker(system_i386_NetBSD_info,TLinkerBSD);
+ RegisterExternalLinker(system_i386_OpenBSD_info,TLinkerBSD);
+ RegisterImport(system_i386_freebsd,timportlibbsd);
+ RegisterExport(system_i386_freebsd,texportlibbsd);
+ RegisterTarget(system_i386_freebsd_info);
+ RegisterImport(system_i386_netbsd,timportlibbsd);
+ RegisterExport(system_i386_netbsd,texportlibbsd);
+ RegisterTarget(system_i386_netbsd_info);
+ RegisterImport(system_i386_openbsd,timportlibbsd);
+ RegisterExport(system_i386_openbsd,texportlibbsd);
+ RegisterTarget(system_i386_openbsd_info);
+{$endif i386}
+{$ifdef m68k}
+// RegisterExternalLinker(system_m68k_FreeBSD_info,TLinkerBSD);
+ RegisterExternalLinker(system_m68k_NetBSD_info,TLinkerBSD);
+ RegisterImport(system_m68k_netbsd,timportlibbsd);
+ RegisterExport(system_m68k_netbsd,texportlibbsd);
+ RegisterTarget(system_m68k_netbsd_info);
+{$endif m68k}
+{$ifdef powerpc}
+// RegisterExternalLinker(system_m68k_FreeBSD_info,TLinkerBSD);
+ RegisterExternalLinker(system_powerpc_darwin_info,TLinkerBSD);
+ RegisterImport(system_powerpc_darwin,timportlibdarwin);
+ RegisterExport(system_powerpc_darwin,texportlibbsd);
+ RegisterTarget(system_powerpc_darwin_info);
+ RegisterExternalLinker(system_powerpc_netbsd_info,TLinkerBSD);
+ RegisterImport(system_powerpc_netbsd,timportlibbsd);
+ RegisterExport(system_powerpc_netbsd,texportlibbsd);
+ RegisterTarget(system_powerpc_netbsd_info);
+{$endif powerpc}
+end.
diff --git a/compiler/systems/t_emx.pas b/compiler/systems/t_emx.pas
new file mode 100644
index 0000000000..44427e627f
--- /dev/null
+++ b/compiler/systems/t_emx.pas
@@ -0,0 +1,516 @@
+{
+ Copyright (c) 1998-2002 by Daniel Mantione
+ Portions Copyright (c) 1998-2002 Eberhard Mattes
+
+ Unit to write out import libraries and def files for OS/2 via EMX
+
+ 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.
+
+ ****************************************************************************
+}
+{
+ A lot of code in this unit has been ported from C to Pascal from the
+ emximp utility, part of the EMX development system. Emximp is copyrighted
+ by Eberhard Mattes. Note: Eberhard doesn't know much about the Pascal
+ port, please send questions to Daniel Mantione
+ <d.s.p.mantione@twi.tudelft.nl>.
+}
+unit t_emx;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ strings,
+ dos,
+ cutils,cclasses,
+ globtype,comphook,systems,symconst,symsym,symdef,
+ globals,verbose,fmodule,script,
+ import,link,i_emx,ppu;
+
+ type
+ TImportLibEMX=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure generatelib;override;
+ end;
+
+ TLinkerEMX=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+const profile_flag:boolean=false;
+
+const n_ext = 1;
+ n_abs = 2;
+ n_text = 4;
+ n_data = 6;
+ n_bss = 8;
+ n_imp1 = $68;
+ n_imp2 = $6a;
+
+type reloc=packed record {This is the layout of a relocation table
+ entry.}
+ address:longint; {Fixup location}
+ remaining:longint;
+ {Meaning of bits for remaining:
+ 0..23: Symbol number or segment
+ 24: Self-relative fixup if non-zero
+ 25..26: Fixup size (0: 1 byte, 1: 2, 2: 4 bytes)
+ 27: Reference to symbol or segment
+ 28..31 Not used}
+ end;
+
+ nlist=packed record {This is the layout of a symbol table entry.}
+ strofs:longint; {Offset in string table}
+ typ:byte; {Type of the symbol}
+ other:byte; {Other information}
+ desc:word; {More information}
+ value:longint; {Value (address)}
+ end;
+
+ a_out_header=packed record
+ magic:word; {Magic word, must be $0107}
+ machtype:byte; {Machine type}
+ flags:byte; {Flags}
+ text_size:longint; {Length of text, in bytes}
+ data_size:longint; {Length of initialized data, in bytes}
+ bss_size:longint; {Length of uninitialized data, in bytes}
+ sym_size:longint; {Length of symbol table, in bytes}
+ entry:longint; {Start address (entry point)}
+ trsize:longint; {Length of relocation info for text, bytes}
+ drsize:longint; {Length of relocation info for data, bytes}
+ end;
+
+ ar_hdr=packed record
+ ar_name:array[0..15] of char;
+ ar_date:array[0..11] of char;
+ ar_uid:array[0..5] of char;
+ ar_gid:array[0..5] of char;
+ ar_mode:array[0..7] of char;
+ ar_size:array[0..9] of char;
+ ar_fmag:array[0..1] of char;
+ end;
+
+var aout_str_size:longint;
+ aout_str_tab:array[0..2047] of byte;
+ aout_sym_count:longint;
+ aout_sym_tab:array[0..5] of nlist;
+
+ aout_text:array[0..63] of byte;
+ aout_text_size:longint;
+
+ aout_treloc_tab:array[0..1] of reloc;
+ aout_treloc_count:longint;
+
+ aout_size:longint;
+ seq_no:longint;
+
+ ar_member_size:longint;
+
+ out_file:file;
+
+procedure write_ar(const name:string;size:longint);
+
+var ar:ar_hdr;
+ time:datetime;
+ dummy:word;
+ numtime:longint;
+ tmp:string[19];
+
+
+begin
+ ar_member_size:=size;
+ fillchar(ar.ar_name,sizeof(ar.ar_name),' ');
+ move(name[1],ar.ar_name,length(name));
+ getdate(time.year,time.month,time.day,dummy);
+ gettime(time.hour,time.min,time.sec,dummy);
+ packtime(time,numtime);
+ str(numtime,tmp);
+ fillchar(ar.ar_date,sizeof(ar.ar_date),' ');
+ move(tmp[1],ar.ar_date,length(tmp));
+ ar.ar_uid:='0 ';
+ ar.ar_gid:='0 ';
+ ar.ar_mode:='100666'#0#0;
+ str(size,tmp);
+ fillchar(ar.ar_size,sizeof(ar.ar_size),' ');
+ move(tmp[1],ar.ar_size,length(tmp));
+ ar.ar_fmag:='`'#10;
+ blockwrite(out_file,ar,sizeof(ar));
+end;
+
+procedure finish_ar;
+
+var a:byte;
+
+begin
+ a:=0;
+ if odd(ar_member_size) then
+ blockwrite(out_file,a,1);
+end;
+
+procedure aout_init;
+
+begin
+ aout_str_size:=sizeof(longint);
+ aout_sym_count:=0;
+ aout_text_size:=0;
+ aout_treloc_count:=0;
+end;
+
+function aout_sym(const name:string;typ,other:byte;desc:word;
+ value:longint):longint;
+
+begin
+ if aout_str_size+length(name)+1>sizeof(aout_str_tab) then
+ internalerror(200504241);
+ if aout_sym_count>=sizeof(aout_sym_tab) div sizeof(aout_sym_tab[0]) then
+ internalerror(200504242);
+ aout_sym_tab[aout_sym_count].strofs:=aout_str_size;
+ aout_sym_tab[aout_sym_count].typ:=typ;
+ aout_sym_tab[aout_sym_count].other:=other;
+ aout_sym_tab[aout_sym_count].desc:=desc;
+ aout_sym_tab[aout_sym_count].value:=value;
+ strPcopy(@aout_str_tab[aout_str_size],name);
+ aout_str_size:=aout_str_size+length(name)+1;
+ aout_sym:=aout_sym_count;
+ inc(aout_sym_count);
+end;
+
+procedure aout_text_byte(b:byte);
+
+begin
+ if aout_text_size>=sizeof(aout_text) then
+ internalerror(200504243);
+ aout_text[aout_text_size]:=b;
+ inc(aout_text_size);
+end;
+
+procedure aout_text_dword(d:longint);
+
+type li_ar=array[0..3] of byte;
+
+begin
+ aout_text_byte(li_ar(d)[0]);
+ aout_text_byte(li_ar(d)[1]);
+ aout_text_byte(li_ar(d)[2]);
+ aout_text_byte(li_ar(d)[3]);
+end;
+
+procedure aout_treloc(address,symbolnum,pcrel,len,ext:longint);
+
+begin
+ if aout_treloc_count>=sizeof(aout_treloc_tab) div sizeof(reloc) then
+ internalerror(200504244);
+ aout_treloc_tab[aout_treloc_count].address:=address;
+ aout_treloc_tab[aout_treloc_count].remaining:=symbolnum+pcrel shl 24+
+ len shl 25+ext shl 27;
+ inc(aout_treloc_count);
+end;
+
+procedure aout_finish;
+
+begin
+ while (aout_text_size and 3)<>0 do
+ aout_text_byte ($90);
+ aout_size:=sizeof(a_out_header)+aout_text_size+aout_treloc_count*
+ sizeof(reloc)+aout_sym_count*sizeof(aout_sym_tab[0])+aout_str_size;
+end;
+
+procedure aout_write;
+
+var ao:a_out_header;
+
+begin
+ ao.magic:=$0107;
+ ao.machtype:=0;
+ ao.flags:=0;
+ ao.text_size:=aout_text_size;
+ ao.data_size:=0;
+ ao.bss_size:=0;
+ ao.sym_size:=aout_sym_count*sizeof(aout_sym_tab[0]);
+ ao.entry:=0;
+ ao.trsize:=aout_treloc_count*sizeof(reloc);
+ ao.drsize:=0;
+ blockwrite(out_file,ao,sizeof(ao));
+ blockwrite(out_file,aout_text,aout_text_size);
+ blockwrite(out_file,aout_treloc_tab,sizeof(reloc)*aout_treloc_count);
+ blockwrite(out_file,aout_sym_tab,sizeof(aout_sym_tab[0])*aout_sym_count);
+ longint((@aout_str_tab)^):=aout_str_size;
+ blockwrite(out_file,aout_str_tab,aout_str_size);
+end;
+
+procedure TImportLibEMX.preparelib(const s:string);
+
+{This code triggers a lot of bugs in the compiler.
+const armag='!<arch>'#10;
+ ar_magic:array[1..length(armag)] of char=armag;}
+const ar_magic:array[1..8] of char='!<arch>'#10;
+var
+ libname : string;
+begin
+ LibName:=FixFileName(S + Target_Info.StaticCLibExt);
+ seq_no:=1;
+ current_module.linkotherstaticlibs.add(libname,link_allways);
+ assign(out_file,current_module.outputpath^+libname);
+ rewrite(out_file,1);
+ blockwrite(out_file,ar_magic,sizeof(ar_magic));
+end;
+
+procedure TImportLibEMX.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+{func = Name of function to import.
+ module = Name of DLL to import from.
+ index = Index of function in DLL. Use 0 to import by name.
+ name = Name of function in DLL. Ignored when index=0;}
+var tmp1,tmp2,tmp3:string;
+ sym_mcount,sym_import:longint;
+ fixup_mcount,fixup_import:longint;
+ func : string;
+begin
+ { force the current mangledname }
+ include(aprocdef.procoptions,po_has_mangledname);
+ func:=aprocdef.mangledname;
+
+ aout_init;
+ tmp2:=func;
+ if profile_flag and not (copy(func,1,4)='_16_') then
+ begin
+ {sym_entry:=aout_sym(func,n_text+n_ext,0,0,aout_text_size);}
+ sym_mcount:=aout_sym('__mcount',n_ext,0,0,0);
+ {Use, say, "_$U_DosRead" for "DosRead" to import the
+ non-profiled function.}
+ tmp2:='__$U_'+func;
+ sym_import:=aout_sym(tmp2,n_ext,0,0,0);
+ aout_text_byte($55); {push ebp}
+ aout_text_byte($89); {mov ebp, esp}
+ aout_text_byte($e5);
+ aout_text_byte($e8); {call _mcount}
+ fixup_mcount:=aout_text_size;
+ aout_text_dword(0-(aout_text_size+4));
+ aout_text_byte($5d); {pop ebp}
+ aout_text_byte($e9); {jmp _$U_DosRead}
+ fixup_import:=aout_text_size;
+ aout_text_dword(0-(aout_text_size+4));
+
+ aout_treloc(fixup_mcount,sym_mcount,1,2,1);
+ aout_treloc (fixup_import, sym_import,1,2,1);
+ end;
+ str(seq_no,tmp1);
+ tmp1:='IMPORT#'+tmp1;
+ if name='' then
+ begin
+ str(index,tmp3);
+ tmp3:=func+'='+module+'.'+tmp3;
+ end
+ else
+ tmp3:=func+'='+module+'.'+name;
+ aout_sym(tmp2,n_imp1+n_ext,0,0,0);
+ aout_sym(tmp3,n_imp2+n_ext,0,0,0);
+ aout_finish;
+ write_ar(tmp1,aout_size);
+ aout_write;
+ finish_ar;
+ inc(seq_no);
+end;
+
+procedure TImportLibEMX.GenerateLib;
+
+begin
+ close(out_file);
+end;
+
+
+{****************************************************************************
+ TLinkerEMX
+****************************************************************************}
+
+Constructor TLinkerEMX.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerEMX.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $OPT -o $OUT @$RES';
+ ExeCmd[2]:='emxbind -b $STRIP $APPTYPE $RSRC -k$STACKKB -h$HEAPMB -o $EXE $OUT -aim -s$DOSHEAPKB';
+ if source_info.script = script_dos then
+ ExeCmd[3]:='del $OUT';
+ end;
+end;
+
+
+Function TLinkerEMX.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TStringListItem;
+ s : string;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ { add objectfiles, start with prt0 always }
+ LinkRes.AddFileName(FindObjectFile('prt0','',false));
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(s);
+ end;
+
+ { Write staticlibraries }
+ { No group !! This will not work correctly PM }
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(s)
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerEMX.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ i : longint;
+ AppTypeStr,
+ StripStr: string[40];
+ RsrcStr : string;
+ DS: DirStr;
+ NS: NameStr;
+ ES: ExtStr;
+ OutName: PathStr;
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ FSplit (current_module.exefilename^, DS, NS, ES);
+ OutName := DS + NS + '.out';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr := '-s'
+ else
+ StripStr := '';
+ if (usewindowapi) or (AppType = app_gui) then
+ AppTypeStr := '-p'
+ else if AppType = app_fs then
+ AppTypeStr := '-f'
+ else AppTypeStr := '-w';
+ if not (Current_module.ResourceFiles.Empty) then
+ RsrcStr := '-r ' + Current_module.ResourceFiles.GetFirst
+ else
+ RsrcStr := '';
+(* Only one resource file supported, discard everything else
+ (should be already empty anyway, though). *)
+ Current_module.ResourceFiles.Clear;
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ success:=false;
+ for i:=1 to 3 do
+ begin
+ SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ { Is this really required? Not anymore according to my EMX docs }
+ Replace(cmdstr,'$HEAPMB',tostr((1048575) shr 20));
+ {Size of the stack when an EMX program runs in OS/2.}
+ Replace(cmdstr,'$STACKKB',tostr((stacksize+1023) shr 10));
+ {When an EMX program runs in DOS, the heap and stack share the
+ same memory pool. The heap grows upwards, the stack grows downwards.}
+ Replace(cmdstr,'$DOSHEAPKB',tostr((stacksize+1023) shr 10));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$APPTYPE',AppTypeStr);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RSRC',RsrcStr);
+ Replace(cmdstr,'$OUT',maybequoted(OutName));
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ if i<>3 then
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,(i=1),false)
+ else
+ success:=DoExec(binstr,cmdstr,(i=1),true);
+ end;
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_emx_info,TLinkerEMX);
+ RegisterImport(system_i386_emx,TImportLibEMX);
+ RegisterRes(res_emxbind_info);
+ RegisterTarget(system_i386_emx_info);
+end.
diff --git a/compiler/systems/t_gba.pas b/compiler/systems/t_gba.pas
new file mode 100644
index 0000000000..c937ca2a6d
--- /dev/null
+++ b/compiler/systems/t_gba.pas
@@ -0,0 +1,300 @@
+{
+ This unit implements support import,export,link routines
+ for the (arm) GameBoy Advance target
+
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ 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 t_gba;
+
+{$i fpcdefs.inc}
+
+
+interface
+
+ uses
+ symsym,symdef,
+ import,export,link;
+
+ type
+ tlinkergba=class(texternallinker)
+ private
+ libctype:(libc5,glibc2,glibc21,uclibc);
+ Function WriteResponseFile : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+implementation
+
+
+ uses
+ cutils,cclasses,verbose,systems,globtype,globals,
+ symconst,script,fmodule,dos,aasmbase,aasmtai,aasmcpu,
+ cpubase,cgobj,i_gba;
+
+
+
+{*****************************************************************************
+ TLINKERLINUX
+*****************************************************************************}
+
+Constructor TLinkerGba.Create;
+begin
+ Inherited Create;
+ if not Dontlinkstdlibpath Then
+ LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
+end;
+
+
+procedure TLinkerGba.SetDefaultInfo;
+{
+ This will also detect which libc version will be used
+}
+begin
+ with Info do
+ begin
+ //ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE $RES';
+ // Here we call ld with right options for GBA
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -Ttext 0x08000000 -Tbss 0x03000000 -L. -o $EXE $RES';
+ DllCmd[1]:='ld $OPT $INIT $FINI $SONAME -shared -L. -o $EXE $RES';
+ DllCmd[2]:='strip --strip-unneeded $EXE';
+ DynamicLinker:='/lib/ld-linux.so.2';
+ libctype:=glibc2;
+ end;
+end;
+
+
+Function TLinkerGba.WriteResponseFile: Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ cprtobj,
+ gprtobj,
+ prtobj : string[80];
+ HPath : TStringListItem;
+ s,s1,s2 : string;
+ found1,
+ found2,
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+{ set special options for some targets }
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+ prtobj:='prt0';
+ case libctype of
+ glibc21:
+ begin
+ cprtobj:='cprt21';
+ gprtobj:='gprt21';
+ end;
+ uclibc:
+ begin
+ cprtobj:='ucprt0';
+ gprtobj:='ugprt0';
+ end
+ else
+ cprtobj:='cprt0';
+ gprtobj:='gprt0';
+ end;
+
+ if cs_profile in aktmoduleswitches then
+ begin
+ prtobj:=gprtobj;
+ if not(libctype in [glibc2,glibc21]) then
+ AddSharedLibrary('gmon');
+ AddSharedLibrary('c');
+ linklibc:=true;
+ end
+ else
+ begin
+ if linklibc then
+ prtobj:=cprtobj;
+ end;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT(');
+ { add objectfiles, start with prt0 always }
+ if prtobj<>'' then
+ LinkRes.AddFileName(maybequoted(FindObjectFile(prtobj,'',false)));
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crtbegin.o',s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crti.o',s) then
+ LinkRes.AddFileName(s);
+ end;
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ LinkRes.Add(')');
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(maybequoted(s))
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if not SharedLibFiles.Empty then
+ begin
+ LinkRes.Add('INPUT(');
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc then
+ LinkRes.Add('-lc');
+ { when we have -static for the linker the we also need libgcc }
+ if (cs_link_staticflag in aktglobalswitches) then
+ LinkRes.Add('-lgcc');
+ LinkRes.Add(')');
+ end;
+
+ { objects which must be at the end }
+ if linklibc and (libctype<>uclibc) then
+ begin
+ found1:=librarysearchpath.FindFile('crtend.o',s1);
+ found2:=librarysearchpath.FindFile('crtn.o',s2);
+ if found1 or found2 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found1 then
+ LinkRes.AddFileName(s1);
+ if found2 then
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerGba.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ GCSectionsStr,
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ GCSectionsStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in aktglobalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+ if (cs_link_smart in aktglobalswitches) and
+ (tf_smartlink_sections in target_info.flags) then
+ GCSectionsStr:='--gc-sections';
+ If (cs_profile in aktmoduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if cshared Then
+ DynLinkStr:='--shared ' + DynLinkStr;
+ if rlinkpath<>'' Then
+ DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
+ End;
+
+{ Write used files and libraries }
+ WriteResponseFile;
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_arm_gba_info,TLinkerGba);
+ RegisterTarget(system_arm_gba_info);
+end.
diff --git a/compiler/systems/t_go32v2.pas b/compiler/systems/t_go32v2.pas
new file mode 100644
index 0000000000..c627d5cb82
--- /dev/null
+++ b/compiler/systems/t_go32v2.pas
@@ -0,0 +1,364 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Go32v2 target
+
+ 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 t_go32v2;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ link,
+ cutils,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_go32v2,ogcoff;
+
+ type
+ tlinkergo32v2=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ Function WriteScript(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+{****************************************************************************
+ TLinkerGo32v2
+****************************************************************************}
+
+Constructor TLinkerGo32v2.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerGo32v2.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $SCRIPT $OPT $STRIP -o $EXE $RES';
+ end;
+end;
+
+
+Function TLinkerGo32v2.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add('-(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(GetShortName(s))
+ end;
+ LinkRes.Add('-)');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+Function TLinkerGo32v2.WriteScript(isdll:boolean) : Boolean;
+Var
+ scriptres : TLinkRes;
+ HPath : TStringListItem;
+ s : string;
+begin
+ WriteScript:=False;
+
+ { Open link.res file }
+ ScriptRes:=TLinkRes.Create(outputexedir+Info.ScriptName);
+ ScriptRes.Add('OUTPUT_FORMAT("coff-go32-exe")');
+ ScriptRes.Add('ENTRY(start)');
+
+ ScriptRes.Add('SECTIONS');
+ ScriptRes.Add('{');
+ ScriptRes.Add(' .text 0x1000+SIZEOF_HEADERS : {');
+ ScriptRes.Add(' . = ALIGN(16);');
+ { add objectfiles, start with prt0 always }
+ ScriptRes.Add(' '+GetShortName(FindObjectFile('prt0','',false))+'(.text)');
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ ScriptRes.Add(' . = ALIGN(16);');
+ ScriptRes.Add(' '+GetShortName(s)+'(.text)');
+ end;
+ end;
+ ScriptRes.Add(' *(.text)');
+ ScriptRes.Add(' etext = . ; _etext = .;');
+ ScriptRes.Add(' . = ALIGN(0x200);');
+ ScriptRes.Add(' }');
+ ScriptRes.Add(' .data ALIGN(0x200) : {');
+ ScriptRes.Add(' djgpp_first_ctor = . ;');
+ ScriptRes.Add(' *(.ctor)');
+ ScriptRes.Add(' djgpp_last_ctor = . ;');
+ ScriptRes.Add(' djgpp_first_dtor = . ;');
+ ScriptRes.Add(' *(.dtor)');
+ ScriptRes.Add(' djgpp_last_dtor = . ;');
+ ScriptRes.Add(' *(.data)');
+ ScriptRes.Add(' *(.gcc_exc)');
+ ScriptRes.Add(' ___EH_FRAME_BEGIN__ = . ;');
+ ScriptRes.Add(' *(.eh_fram)');
+ ScriptRes.Add(' ___EH_FRAME_END__ = . ;');
+ ScriptRes.Add(' LONG(0)');
+ ScriptRes.Add(' edata = . ; _edata = .;');
+ ScriptRes.Add(' . = ALIGN(0x200);');
+ ScriptRes.Add(' }');
+ ScriptRes.Add(' .bss SIZEOF(.data) + ADDR(.data) :');
+ ScriptRes.Add(' {');
+ ScriptRes.Add(' _object.2 = . ;');
+ ScriptRes.Add(' . += 24 ;');
+ ScriptRes.Add(' *(.bss)');
+ ScriptRes.Add(' *(COMMON)');
+ ScriptRes.Add(' end = . ; _end = .;');
+ ScriptRes.Add(' . = ALIGN(0x200);');
+ ScriptRes.Add(' }');
+ ScriptRes.Add(' }');
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ ScriptRes.Add('SEARCH_DIR("'+GetShortName(HPath.Str)+'")');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ ScriptRes.Add('SEARCH_DIR("'+GetShortName(HPath.Str)+'")');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+{ Write and Close response }
+ ScriptRes.WriteToDisk;
+ ScriptRes.Free;
+
+ WriteScript:=True;
+end;
+
+
+
+function TLinkerGo32v2.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ StripStr : string[40];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+
+ { Write used files and libraries and our own ld script }
+ WriteScript(false);
+ WriteResponsefile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ if source_info.system=system_i386_go32v2 then
+ Replace(cmdstr,'$RES','@'+maybequoted(outputexedir+Info.ResName))
+ else
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$SCRIPT','--script='+maybequoted(outputexedir+Info.ScriptName));
+ success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ begin
+ RemoveFile(outputexedir+Info.ResName);
+ RemoveFile(outputexedir+Info.ScriptName);
+ end;
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{$ifdef notnecessary}
+procedure tlinkergo32v2.postprocessexecutable(const n : string);
+type
+ tcoffheader=packed record
+ mach : word;
+ nsects : word;
+ time : longint;
+ sympos : longint;
+ syms : longint;
+ opthdr : word;
+ flag : word;
+ end;
+ tcoffsechdr=packed record
+ name : array[0..7] of char;
+ vsize : longint;
+ rvaofs : longint;
+ datalen : longint;
+ datapos : longint;
+ relocpos : longint;
+ lineno1 : longint;
+ nrelocs : word;
+ lineno2 : word;
+ flags : longint;
+ end;
+ psecfill=^TSecfill;
+ TSecfill=record
+ fillpos,
+ fillsize : longint;
+ next : psecfill;
+ end;
+var
+ f : file;
+ coffheader : tcoffheader;
+ firstsecpos,
+ maxfillsize,
+ l : longint;
+ coffsec : tcoffsechdr;
+ secroot,hsecroot : psecfill;
+ zerobuf : pointer;
+begin
+ { when -s is used quit, because there is no .exe }
+ if cs_link_extern in aktglobalswitches then
+ exit;
+ { open file }
+ assign(f,n);
+ {$I-}
+ reset(f,1);
+ if ioresult<>0 then
+ Message1(execinfo_f_cant_open_executable,n);
+ { read headers }
+ seek(f,2048);
+ blockread(f,coffheader,sizeof(tcoffheader));
+ { read section info }
+ maxfillsize:=0;
+ firstsecpos:=0;
+ secroot:=nil;
+ for l:=1to coffheader.nSects do
+ begin
+ blockread(f,coffsec,sizeof(tcoffsechdr));
+ if coffsec.datapos>0 then
+ begin
+ if secroot=nil then
+ firstsecpos:=coffsec.datapos;
+ new(hsecroot);
+ hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
+ hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
+ hsecroot^.next:=secroot;
+ secroot:=hsecroot;
+ if secroot^.fillsize>maxfillsize then
+ maxfillsize:=secroot^.fillsize;
+ end;
+ end;
+ if firstsecpos>0 then
+ begin
+ l:=firstsecpos-filepos(f);
+ if l>maxfillsize then
+ maxfillsize:=l;
+ end
+ else
+ l:=0;
+ { get zero buffer }
+ getmem(zerobuf,maxfillsize);
+ fillchar(zerobuf^,maxfillsize,0);
+ { zero from sectioninfo until first section }
+ blockwrite(f,zerobuf^,l);
+ { zero section alignments }
+ while assigned(secroot) do
+ begin
+ seek(f,secroot^.fillpos);
+ blockwrite(f,zerobuf^,secroot^.fillsize);
+ hsecroot:=secroot;
+ secroot:=secroot^.next;
+ dispose(hsecroot);
+ end;
+ freemem(zerobuf,maxfillsize);
+ close(f);
+ {$I+}
+ i:=ioresult;
+ postprocessexecutable:=true;
+end;
+{$endif}
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_go32v2_info,TLinkerGo32v2);
+ RegisterInternalLinker(system_i386_go32v2_info,TCoffLinker);
+ RegisterTarget(system_i386_go32v2_info);
+end.
diff --git a/compiler/systems/t_linux.pas b/compiler/systems/t_linux.pas
new file mode 100644
index 0000000000..ba47cd141e
--- /dev/null
+++ b/compiler/systems/t_linux.pas
@@ -0,0 +1,755 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Linux target
+
+ 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 t_linux;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symsym,symdef,ppu,
+ import,export,link;
+
+ type
+ timportliblinux=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ end;
+
+ texportliblinux=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkerlinux=class(texternallinker)
+ private
+ libctype:(libc5,glibc2,glibc21,uclibc);
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ function postprocessexecutable(const fn : string;isdll:boolean):boolean;
+ end;
+
+
+implementation
+
+ uses
+ cutils,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,dos
+ ,aasmbase,aasmtai,aasmcpu,cpubase,cgobj
+ ,i_linux
+ ;
+
+{*****************************************************************************
+ TIMPORTLIBLINUX
+*****************************************************************************}
+
+procedure timportliblinux.preparelib(const s : string);
+begin
+end;
+
+
+procedure timportliblinux.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+end;
+
+
+procedure timportliblinux.importvariable(vs:tglobalvarsym;const name,module:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+ { reset the mangledname and turn off the dll_var option }
+ vs.set_mangledname(name);
+ exclude(vs.varoptions,vo_is_dll_var);
+end;
+
+
+procedure timportliblinux.generatelib;
+begin
+end;
+
+
+{*****************************************************************************
+ TEXPORTLIBLINUX
+*****************************************************************************}
+
+procedure texportliblinux.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportliblinux.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Message1(parser_e_no_export_with_index_for_target,'linux');
+ exit;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.concat(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportliblinux.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportliblinux.generatelib;
+var
+ hp2 : texported_item;
+begin
+ new_section(asmlist[al_procedures],sec_code,'',0);
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
+ begin
+ { place jump in al_procedures }
+ asmlist[al_procedures].concat(tai_align.create(target_info.alignment.procalign));
+ asmlist[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ cg.a_jmp_name(asmlist[al_procedures],tprocsym(hp2.sym).first_procdef.mangledname);
+ asmlist[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+ end;
+ end
+ else
+ message1(parser_e_no_export_of_variables_for_target,'linux');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERLINUX
+*****************************************************************************}
+
+Constructor TLinkerLinux.Create;
+begin
+ Inherited Create;
+ if not Dontlinkstdlibpath Then
+{$ifdef x86_64}
+ LibrarySearchPath.AddPath('/lib64;/usr/lib64;/usr/X11R6/lib64',true);
+{$else}
+{$ifdef powerpc64}
+ LibrarySearchPath.AddPath('/lib64;/usr/lib64;/usr/X11R6/lib64',true);
+{$else powerpc64}
+ LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
+{$endif powerpc64}
+{$endif x86_64}
+end;
+
+
+procedure TLinkerLinux.SetDefaultInfo;
+{
+ This will also detect which libc version will be used
+}
+
+const
+{$ifdef i386} platform_select='-b elf32-i386 -m elf_i386';{$endif}
+{$ifdef x86_64} platform_select='-b elf64-x86-64 -m elf_x86_64';{$endif}
+{$ifdef powerpc}platform_select='-b elf32-powerpc -m elf32ppclinux';{$endif}
+{$ifdef POWERPC64} platform_select='-b elf64-powerpc -m elf64ppc';{$endif}
+{$ifdef sparc} platform_select='-b elf32-sparc -m elf32_sparc';{$endif}
+{$ifdef arm} platform_select='';{$endif} {unknown :( }
+{$ifdef m68k} platform_select='';{$endif} {unknown :( }
+
+{$ifdef m68k}
+var
+ St : SearchRec;
+{$endif m68k}
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld '+platform_select+' $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE $RES';
+ DllCmd[1]:='ld '+platform_select+' $OPT $INIT $FINI $SONAME -shared -L. -o $EXE $RES';
+ DllCmd[2]:='strip --strip-unneeded $EXE';
+{$ifdef m68k}
+ libctype:=glibc2;
+ FindFirst('/lib/ld*',AnyFile,st);
+ while DosError=0 do
+ begin
+ if copy(st.name,1,5)='ld-2.' then
+ begin
+ DynamicLinker:='/lib/'+St.name;
+ if st.name[6]<>'0' then
+ libctype:=glibc21;
+ break;
+ end;
+ FindNext(St);
+ end;
+ FindClose(St);
+{$endif m68k}
+
+{$ifdef i386}
+ { first try glibc2 }
+ DynamicLinker:='/lib/ld-linux.so.2';
+ if FileExists(DynamicLinker) then
+ { Check for 2.0 files, else use the glibc 2.1 stub }
+ if FileExists('/lib/ld-2.0.*') then
+ libctype:=glibc2
+ else
+ libctype:=glibc21
+ else
+ if fileexists('/lib/ld-uClibc.so.0') then
+ begin
+ libctype:=uclibc;
+ dynamiclinker:='/lib/ld-uClibc.so.0';
+ end
+ else if fileexists('/lib/ld-linux.so.1') then
+ DynamicLinker:='/lib/ld-linux.so.1'
+ else
+ libctype:=glibc21;
+{$endif i386}
+
+{$ifdef x86_64}
+ DynamicLinker:='/lib64/ld-linux-x86-64.so.2';
+ libctype:=glibc2;
+{$endif x86_64}
+
+{$ifdef sparc}
+ DynamicLinker:='/lib/ld-linux.so.2';
+ libctype:=glibc2;
+{$endif sparc}
+
+{$ifdef powerpc}
+ DynamicLinker:='/lib/ld.so.1';
+ libctype:=glibc2;
+{$endif powerpc}
+
+{$ifdef powerpc64}
+ DynamicLinker:='/lib64/ld64.so.1';
+ libctype:=glibc2;
+{$endif powerpc64}
+
+{$ifdef arm}
+ DynamicLinker:='/lib/ld-linux.so.2';
+ libctype:=glibc2;
+{$endif arm}
+ end;
+end;
+
+
+Function TLinkerLinux.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ cprtobj,
+ gprtobj,
+ prtobj : string[80];
+ HPath : TStringListItem;
+ s,s1,s2 : string;
+ found1,
+ found2,
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+{ set special options for some targets }
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+ if isdll then
+ begin
+ prtobj:='dllprt0';
+ cprtobj:='dllprt0';
+ gprtobj:='dllprt0';
+ end
+ else
+ begin
+ prtobj:='prt0';
+ case libctype of
+ glibc21:
+ begin
+ cprtobj:='cprt21';
+ gprtobj:='gprt21';
+ end;
+ uclibc:
+ begin
+ cprtobj:='ucprt0';
+ gprtobj:='ugprt0';
+ end
+ else
+ cprtobj:='cprt0';
+ gprtobj:='gprt0';
+ end;
+ end;
+ if cs_profile in aktmoduleswitches then
+ begin
+ prtobj:=gprtobj;
+ if not(libctype in [glibc2,glibc21]) then
+ AddSharedLibrary('gmon');
+ AddSharedLibrary('c');
+ linklibc:=true;
+ end
+ else
+ begin
+ if linklibc then
+ prtobj:=cprtobj;
+ end;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT(');
+ { add objectfiles, start with prt0 always }
+ if prtobj<>'' then
+ LinkRes.AddFileName(maybequoted(FindObjectFile(prtobj,'',false)));
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crtbegin.o',s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crti.o',s) then
+ LinkRes.AddFileName(s);
+ end;
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ LinkRes.Add(')');
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(maybequoted(s))
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if not SharedLibFiles.Empty then
+ begin
+ LinkRes.Add('INPUT(');
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc then
+ LinkRes.Add('-lc');
+ { when we have -static for the linker the we also need libgcc }
+ if (cs_link_staticflag in aktglobalswitches) then
+ LinkRes.Add('-lgcc');
+ LinkRes.Add(')');
+ end;
+
+ { objects which must be at the end }
+ if linklibc and (libctype<>uclibc) then
+ begin
+ found1:=librarysearchpath.FindFile('crtend.o',s1);
+ found2:=librarysearchpath.FindFile('crtn.o',s2);
+ if found1 or found2 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found1 then
+ LinkRes.AddFileName(s1);
+ if found2 then
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+ {Entry point.}
+ linkres.add('ENTRY(_start)');
+
+ {Sections.}
+{
+ commented out because it cause problems on several machines with different ld versions (FK)
+ linkres.add('SECTIONS');
+ linkres.add('{');
+ {Read-only sections, merged into text segment:}
+ linkres.add(' PROVIDE (__executable_start = 0x010000); . = 0x010000 +0x100;');
+ linkres.add(' .interp : { *(.interp) }');
+ linkres.add(' .hash : { *(.hash) }');
+ linkres.add(' .dynsym : { *(.dynsym) }');
+ linkres.add(' .dynstr : { *(.dynstr) }');
+ linkres.add(' .gnu.version : { *(.gnu.version) }');
+ linkres.add(' .gnu.version_d : { *(.gnu.version_d) }');
+ linkres.add(' .gnu.version_r : { *(.gnu.version_r) }');
+ linkres.add(' .rel.dyn :');
+ linkres.add(' {');
+ linkres.add(' *(.rel.init)');
+ linkres.add(' *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)');
+ linkres.add(' *(.rel.fini)');
+ linkres.add(' *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)');
+ linkres.add(' *(.rel.data.rel.ro*)');
+ linkres.add(' *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)');
+ linkres.add(' *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)');
+ linkres.add(' *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)');
+ linkres.add(' *(.rel.got)');
+ linkres.add(' *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)');
+ linkres.add(' }');
+ linkres.add(' .rela.dyn :');
+ linkres.add(' {');
+ linkres.add(' *(.rela.init)');
+ linkres.add(' *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)');
+ linkres.add(' *(.rela.fini)');
+ linkres.add(' *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)');
+ linkres.add(' *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)');
+ linkres.add(' *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)');
+ linkres.add(' *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)');
+ linkres.add(' *(.rela.got)');
+ linkres.add(' *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)');
+ linkres.add(' }');
+ linkres.add(' .rel.plt : { *(.rel.plt) }');
+ linkres.add(' .rela.plt : { *(.rela.plt) }');
+ linkres.add(' .init :');
+ linkres.add(' {');
+ linkres.add(' KEEP (*(.init))');
+ linkres.add(' } =0x90909090');
+ linkres.add(' .plt : { *(.plt) }');
+ linkres.add(' .text :');
+ linkres.add(' {');
+ linkres.add(' *(.text .stub .text.* .gnu.linkonce.t.*)');
+ linkres.add(' KEEP (*(.text.*personality*))');
+ {.gnu.warning sections are handled specially by elf32.em.}
+ linkres.add(' *(.gnu.warning)');
+ linkres.add(' } =0x90909090');
+ linkres.add(' .fini :');
+ linkres.add(' {');
+ linkres.add(' KEEP (*(.fini))');
+ linkres.add(' } =0x90909090');
+ linkres.add(' PROVIDE (_etext = .);');
+ linkres.add(' .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }');
+ {Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up.}
+ linkres.add(' . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1)); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000);');
+ linkres.add(' .dynamic : { *(.dynamic) }');
+ linkres.add(' .got : { *(.got) }');
+ linkres.add(' .got.plt : { *(.got.plt) }');
+ linkres.add(' .data :');
+ linkres.add(' {');
+ linkres.add(' *(.data .data.* .gnu.linkonce.d.*)');
+ linkres.add(' KEEP (*(.gnu.linkonce.d.*personality*))');
+ linkres.add(' }');
+ linkres.add(' _edata = .;');
+ linkres.add(' PROVIDE (edata = .);');
+{$ifdef zsegment_threadvars}
+ linkres.add(' _z = .;');
+ linkres.add(' .threadvar 0 : AT (_z) { *(.threadvar .threadvar.* .gnu.linkonce.tv.*) }');
+ linkres.add(' PROVIDE (_threadvar_size = SIZEOF(.threadvar));');
+ linkres.add(' . = _z + SIZEOF (.threadvar);');
+{$else}
+ linkres.add(' .threadvar : { *(.threadvar .threadvar.* .gnu.linkonce.tv.*) }');
+{$endif}
+ linkres.add(' __bss_start = .;');
+ linkres.add(' .bss :');
+ linkres.add(' {');
+ linkres.add(' *(.dynbss)');
+ linkres.add(' *(.bss .bss.* .gnu.linkonce.b.*)');
+ linkres.add(' *(COMMON)');
+ {Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.}
+ linkres.add(' . = ALIGN(32 / 8);');
+ linkres.add(' }');
+ linkres.add(' . = ALIGN(32 / 8);');
+ linkres.add(' _end = .;');
+ linkres.add(' PROVIDE (end = .);');
+ linkres.add(' . = DATA_SEGMENT_END (.);');
+ {Stabs debugging sections.}
+ linkres.add(' .stab 0 : { *(.stab) }');
+ linkres.add(' .stabstr 0 : { *(.stabstr) }');
+ linkres.add('}');
+}
+
+{ Write and Close response }
+ LinkRes.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerLinux.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ GCSectionsStr,
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ GCSectionsStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in aktglobalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+ if (af_smartlink_sections in target_asm.flags) and
+ (tf_smartlink_sections in target_info.flags) then
+ GCSectionsStr:='--gc-sections';
+ If (cs_profile in aktmoduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if cshared Then
+ DynLinkStr:='--shared ' + DynLinkStr;
+ if rlinkpath<>'' Then
+ DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
+ End;
+
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ if (success) then
+ success:=PostProcessExecutable(current_module.exefilename^,false);
+
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerLinux.MakeSharedLibrary:boolean;
+var
+ InitStr,
+ FiniStr,
+ SoNameStr : string[80];
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile(true);
+
+ { Create some replacements }
+ InitStr:='-init FPC_LIB_START';
+ FiniStr:='-fini FPC_LIB_EXIT';
+ SoNameStr:='-soname '+SplitFileName(current_module.sharedlibfilename^);
+
+{ Call linker }
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$INIT',InitStr);
+ Replace(cmdstr,'$FINI',FiniStr);
+ Replace(cmdstr,'$SONAME',SoNameStr);
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+
+{ Strip the library ? }
+ if success and (cs_link_strip in aktglobalswitches) then
+ begin
+ { only remove non global symbols and debugging info for a library }
+ Info.DllCmd[2]:='strip --discard-all --strip-debug $EXE';
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+function tlinkerLinux.postprocessexecutable(const fn : string;isdll:boolean):boolean;
+
+Var
+ cmdstr: string;
+ found : boolean;
+ hp : tused_unit;
+
+begin
+ postprocessexecutable:=True;
+ if target_res.id=res_elf then
+ begin
+ found:=((current_module.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
+ if not found then
+ begin
+ hp:=tused_unit(usedunits.first);
+ While Assigned(hp) and not Found do
+ begin
+ Found:=((hp.u.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
+ hp:=tused_unit(hp.next);
+ end;
+ end;
+ if found then
+ begin
+ cmdstr:=' -f -i '+maybequoted(fn);
+ postprocessexecutable:=DoExec(FindUtil(utilsprefix+'fpcres'),cmdstr,false,false);
+ end;
+ end;
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_linux_info,TLinkerLinux);
+ RegisterImport(system_i386_linux,timportliblinux);
+ RegisterExport(system_i386_linux,texportliblinux);
+ RegisterTarget(system_i386_linux_info);
+ RegisterRes(res_elf32_info);
+
+ RegisterExternalLinker(system_x86_6432_linux_info,TLinkerLinux);
+ RegisterImport(system_x86_6432_linux,timportliblinux);
+ RegisterExport(system_x86_6432_linux,texportliblinux);
+ RegisterTarget(system_x86_6432_linux_info);
+{$endif i386}
+{$ifdef m68k}
+ RegisterExternalLinker(system_m68k_linux_info,TLinkerLinux);
+ RegisterImport(system_m68k_linux,timportliblinux);
+ RegisterExport(system_m68k_linux,texportliblinux);
+ RegisterTarget(system_m68k_linux_info);
+{$endif m68k}
+{$ifdef powerpc}
+ RegisterExternalLinker(system_powerpc_linux_info,TLinkerLinux);
+ RegisterImport(system_powerpc_linux,timportliblinux);
+ RegisterExport(system_powerpc_linux,texportliblinux);
+ RegisterTarget(system_powerpc_linux_info);
+{$endif powerpc}
+{$ifdef powerpc64}
+ RegisterExternalLinker(system_powerpc64_linux_info,TLinkerLinux);
+ RegisterImport(system_powerpc64_linux,timportliblinux);
+ RegisterExport(system_powerpc64_linux,texportliblinux);
+ RegisterTarget(system_powerpc64_linux_info);
+{$endif powerpc64}
+{$ifdef alpha}
+ RegisterExternalLinker(system_alpha_linux_info,TLinkerLinux);
+ RegisterImport(system_alpha_linux,timportliblinux);
+ RegisterExport(system_alpha_linux,texportliblinux);
+ RegisterTarget(system_alpha_linux_info);
+{$endif alpha}
+{$ifdef x86_64}
+ RegisterExternalLinker(system_x86_64_linux_info,TLinkerLinux);
+ RegisterImport(system_x86_64_linux,timportliblinux);
+ RegisterExport(system_x86_64_linux,texportliblinux);
+ RegisterTarget(system_x86_64_linux_info);
+ RegisterRes(res_elf64_info);
+{$endif x86_64}
+{$ifdef SPARC}
+ RegisterExternalLinker(system_sparc_linux_info,TLinkerLinux);
+ RegisterImport(system_SPARC_linux,timportliblinux);
+ RegisterExport(system_SPARC_linux,texportliblinux);
+ RegisterTarget(system_SPARC_linux_info);
+{$endif SPARC}
+{$ifdef ARM}
+ RegisterExternalLinker(system_arm_linux_info,TLinkerLinux);
+ RegisterImport(system_arm_linux,timportliblinux);
+ RegisterExport(system_arm_linux,texportliblinux);
+ RegisterTarget(system_arm_linux_info);
+{$endif ARM}
+end.
diff --git a/compiler/systems/t_macos.pas b/compiler/systems/t_macos.pas
new file mode 100644
index 0000000000..115fbbc330
--- /dev/null
+++ b/compiler/systems/t_macos.pas
@@ -0,0 +1,273 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines for MacOS.
+
+ 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 t_macos;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ import,symsym,symdef,link;
+
+ type
+ timportlibmacos=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkermpw=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+implementation
+
+ uses
+ cutils,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_macos,
+ symconst;
+
+{*****************************************************************************
+ TIMPORTLIBMACOS
+*****************************************************************************}
+
+procedure timportlibmacos.preparelib(const s : string);
+begin
+end;
+
+
+procedure timportlibmacos.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+end;
+
+
+procedure timportlibmacos.importvariable(vs:tglobalvarsym;const name,module:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+ { reset the mangledname and turn off the dll_var option }
+ vs.set_mangledname(name);
+ exclude(vs.varoptions,vo_is_dll_var);
+end;
+
+
+procedure timportlibmacos.generatelib;
+begin
+end;
+
+{*****************************************************************************
+ TLINKERMPW
+*****************************************************************************}
+
+Constructor TLinkerMPW.Create;
+begin
+ Inherited Create;
+ //LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
+end;
+
+
+procedure TLinkerMPW.SetDefaultInfo;
+
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='Execute $RES'; {The link.res file contains the whole link command.}
+ //ExeCmd[1]:='PPCLink $OPT $DYNLINK $STATIC $STRIP -tocdataref off -dead on -o $EXE -@filelist $RES';
+ //DllCmd[1]:='PPCLink $OPT $INIT $FINI $SONAME -shared -o $EXE -@filelist $RES';
+ end;
+end;
+
+
+Function TLinkerMPW.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ s,heapsizestr: string;
+
+begin
+ WriteResponseFile:=False;
+ { Open link.res file }
+ linkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ with linkRes do
+ begin
+ {#182 is escape char in MPW (analog to backslash in unix). The space}
+ {ensures there is whitespace separating items.}
+ Add('PPCLink '#182);
+
+ { Add MPW standard libraries}
+ if apptype = app_cui then
+ Add('"{PPCLibraries}PPCSIOW.o" '#182);
+
+ {Even GUI apps must link to PPCToolLibs, because of the System unit
+ which can be used by MPW tools as well as by GUI apps.}
+ Add('"{PPCLibraries}PPCToolLibs.o" '#182);
+ Add('"{SharedLibraries}InterfaceLib" '#182);
+ Add('"{SharedLibraries}StdCLib" '#182);
+ Add('"{SharedLibraries}MathLib" '#182);
+ Add('"{PPCLibraries}StdCRuntime.o" '#182);
+ Add('"{PPCLibraries}PPCCRuntime.o" '#182);
+
+ {Add main objectfiles}
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ Add(s+' '#182);
+ end;
+
+ {Add last lines of the link command}
+ if apptype = app_tool then
+ Add('-t "MPST" -c "MPS " '#182);
+
+ if apptype = app_cui then {If SIOW, to avoid some warnings.}
+ Add('-ignoredups __start -ignoredups .__start -ignoredups main -ignoredups .main -ignoredups qd '#182);
+
+ Add('-tocdataref off -sym on -dead on -o '+ ScriptFixFileName(current_module.exefilename^));
+
+ Add('Exit If "{Status}" != 0');
+
+ if heapsize = 0 then
+ heapsizestr:= HexStr(384000, 8)
+ else
+ heapsizestr:= HexStr(heapsize, 8);
+
+ {Add a SIZE resource on the fly. It controls:
+ * backgrounding is enabled, to facilitate debuging with Power Mac Debugger
+ * it is signaled it is a 32 bit app. (perhaps not nessecary on PowerPC)
+ * heapsize }
+ if apptype <> app_tool then
+ begin
+ Add('Echo "data ''SIZE'' (-1) '#182'{ $'#182'"1080 ' + heapsizestr + ' ' + heapsizestr +
+ #182'" '#182'};" | Rez -a -o ' + ScriptFixFileName(current_module.exefilename^));
+ Add('Exit If "{Status}" != 0');
+ end;
+
+ {Add mac resources}
+ if apptype = app_cui then
+ begin
+ Add('Rez -a "{RIncludes}"SIOW.r -o ' + ScriptFixFileName(current_module.exefilename^));
+ Add('Exit If "{Status}" != 0');
+ end;
+
+ while not (current_module.ResourceFiles.Empty) do
+ begin
+ s := Current_module.ResourceFiles.GetFirst;
+ if Copy(s,Length(s)-1,Length(s)) = '.r' then
+ Add('Rez -a ' + s + ' -o ' + ScriptFixFileName(current_module.exefilename^))
+ else
+ Add('DeRez ' + s + ' | Rez -a -o ' + ScriptFixFileName(current_module.exefilename^));
+ Add('Exit If "{Status}" != 0');
+ end;
+
+ end;
+
+ { Write and Close response }
+ linkres.writetodisk;
+ linkres.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerMPW.MakeExecutable:boolean;
+var
+ binstr : string;
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ StaticStr,
+ StripStr : string[40];
+
+ s: string;
+
+begin
+ //TODO Only external link in MPW is possible, otherwise yell.
+
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='';
+(*
+ StaticStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in aktglobalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+ If (cs_profile in aktmoduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+*)
+
+{ Prepare linking }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(current_module.exefilename^)));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+
+ WriteResponseFile(false);
+
+ success:= true;
+ if cs_link_on_target in aktglobalswitches then
+ success:=DoExec('SetFile', ' -c ''MPS '' -t ''TEXT'' ' +
+ ScriptFixFileName(outputexedir+Info.ResName),true,false);
+
+{ Call linker }
+ if success then
+ success:=DoExec('Execute',CmdStr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef m68k}
+ RegisterTarget(system_m68k_macos_info);
+ RegisterImport(system_m68k_macos,timportlibmacos);
+{$endif m68k}
+{$ifdef powerpc}
+ RegisterExternalLinker(system_powerpc_macos_info,TLinkerMPW);
+ RegisterTarget(system_powerpc_macos_info);
+ RegisterImport(system_powerpc_macos,timportlibmacos);
+{$endif powerpc}
+end.
diff --git a/compiler/systems/t_morph.pas b/compiler/systems/t_morph.pas
new file mode 100644
index 0000000000..0657f808ab
--- /dev/null
+++ b/compiler/systems/t_morph.pas
@@ -0,0 +1,269 @@
+{
+ Copyright (c) 2004 by Free Pascal Development Team
+
+ This unit implements support import, export, link routines
+ for the MorphOS (PowerPC) target
+
+ 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 t_morph;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ link,
+ cutils,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_morph;
+
+ type
+ PlinkerMorphOS=^TlinkerMorphOS;
+ TlinkerMorphOS=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create; override;
+ procedure SetDefaultInfo; override;
+ function MakeExecutable:boolean; override;
+ end;
+
+{$IFDEF MORPHOS}
+{ * PathConv is implemented in the system unit! * }
+function PathConv(path: string): string; external name 'PATHCONV';
+{$ELSE}
+function PathConv(path: string): string;
+begin
+ PathConv:=path;
+end;
+{$ENDIF}
+
+{****************************************************************************
+ TLinkerMorphOS
+****************************************************************************}
+
+Constructor TLinkerMorphOS.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerMorphOS.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ if (cs_link_on_target in aktglobalswitches) then
+ begin
+ ExeCmd[1]:='ld $OPT -o $EXE $RES';
+ ExeCmd[2]:='strip --strip-unneeded --remove-section .comment $EXE';
+ end
+ else
+ begin
+ ExeCmd[1]:='fpcvlink -b elf32amiga $OPT $STRIP -o $EXE -T $RES';
+ end;
+ end;
+end;
+
+
+Function TLinkerMorphOS.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TStringListItem;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if (cs_link_on_target in aktglobalswitches) then
+ s:=ScriptFixFileName(s);
+ LinkRes.Add('-L'+s);
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if s<>'' then
+ LinkRes.Add('SEARCH_DIR('+PathConv(maybequoted(s))+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT (');
+ { add objectfiles, start with prt0 always }
+ s:=FindObjectFile('prt0','',false);
+ LinkRes.AddFileName(s);
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ { vlink doesn't use SEARCH_DIR for object files }
+ if not(cs_link_on_target in aktglobalswitches) then
+ s:=FindObjectFile(s,'',false);
+ LinkRes.AddFileName(PathConv(maybequoted(s)));
+ end;
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ { vlink doesn't need, and doesn't support GROUP }
+ if (cs_link_on_target in aktglobalswitches) then
+ begin
+ LinkRes.Add(')');
+ LinkRes.Add('GROUP(');
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(PathConv(maybequoted(s)));
+ end;
+ end;
+
+ if (cs_link_on_target in aktglobalswitches) then
+ begin
+ LinkRes.Add(')');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+ end
+ else
+ begin
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ LinkRes.Add('lib'+s+target_info.staticlibext);
+ end;
+ LinkRes.Add(')');
+ end;
+
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+
+end;
+
+
+function TLinkerMorphOS.MakeExecutable:boolean;
+var
+ binstr : string;
+ cmdstr : TCmdStr;
+ success : boolean;
+ StripStr: string[40];
+begin
+
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+ if not (cs_link_on_target in aktglobalswitches) then
+ begin
+ StripStr:='';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s -P __abox__';
+ end;
+
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ if not(cs_link_on_target in aktglobalswitches) then
+ begin
+ Replace(cmdstr,'$EXE',PathConv(maybequoted(ScriptFixFileName(current_module.exefilename^))));
+ Replace(cmdstr,'$RES',PathConv(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
+ Replace(cmdstr,'$STRIP',StripStr);
+ end
+ else
+ begin
+ Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(current_module.exefilename^)));
+ Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
+ end;
+ success:=DoExec(FindUtil(BinStr),cmdstr,true,false);
+
+{ Stripping Enabled? }
+ { For MorphOS a separate strip command is needed, to avoid stripping }
+ { __abox__ symbol, which is required to be present in current MorphOS }
+ { executables. }
+ if (cs_link_on_target in aktglobalswitches) then
+ begin
+ if success and (cs_link_strip in aktglobalswitches) then
+ begin
+ SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+ end;
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_powerpc_morphos_info,TLinkerMorphOS);
+ RegisterTarget(system_powerpc_morphos_info);
+end.
diff --git a/compiler/systems/t_nwl.pas b/compiler/systems/t_nwl.pas
new file mode 100644
index 0000000000..78e1ba0d93
--- /dev/null
+++ b/compiler/systems/t_nwl.pas
@@ -0,0 +1,645 @@
+{
+ Copyright (c) 1998-2004 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Netware libc target
+
+ 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.
+
+ Currently generating NetWare-NLM's only work under Linux and win32.
+ (see http://home.arcor.de/armin.diehl/fpcnw for binutils working
+ with win32) while not included in fpc-releases.
+
+ The following compiler-swiches are supported for NetWare:
+ $DESCRIPTION : NLM-Description, will be displayed at load-time
+ $M : For Stack-Size, Heap-Size will be ignored
+ 32K is the accepted minimum
+ $VERSION x.x.x : Sets Major, Minor and Revision
+ $SCREENNAME : Sets the ScreenName
+ $THREADNAME : Sets current threadname
+
+ Additional parameters for the nlmvonv-inputfile can be passed with
+ -k, i.e. -kREENTRANT will add the option REENTRANT to the nlmconv
+ inputfile. A ; will be converted into a newline
+
+ Exports will be handled like in win32:
+ procedure bla; cdecl;
+ begin
+ end;
+
+ exports foo name 'Bar';
+
+ The path to the import-Files must be specified by the library-path.
+ All external modules are defined as autoload. (Note: the import-files have
+ to be in unix-format for exe2nlm)
+ By default, the most import files are included in freepascal.
+
+ e.g. function getgrnam(name:Pchar):Pgroup;cdecl;external 'libc' 'getgrnam';
+ sets IMPORT @libc.imp and MODULE libc.
+ To avoid setting the autoload, use ! in the name, e.g.
+ procedure EnterDebugger;cdecl;external '!netware' name 'EnterDebugger';
+
+ Function simply defined as external work without generating autoload and
+ IMPORT but you will get a warning from nlmconv.
+
+ If you dont have nlmconv, compile gnu-binutils with
+ ./configure --enable-targets=i386-netware
+ make all
+
+ Debugging is possible with gdb and a converter from gdb to ndi available
+ at http://home.arcor.de/armin.diehl/gdbnw
+
+ A sample program:
+
+ Program Hello;
+ (*$DESCRIPTION HelloWorldNlm*)
+ (*$VERSION 1.2.3*)
+ (*$ScreenName Hello*)
+ (*$M 60000,60000*)
+ begin
+ writeLn ('hello world');
+ end.
+
+ compile with:
+ ppc386 -Tnetwlibc hello
+
+ Libraries are supported but this needs at least netware 5.1 sp6,
+ 6.0 sp3 or netware 6.5
+
+ In case there is a xdc file with the same name as the nlm name,
+ this file will be used for nlmconv. Otherwise a temp xdc will
+ be created and used.
+
+****************************************************************************
+}
+unit t_nwl;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+{$ifdef netwlibc}
+{$define netware}
+{$endif}
+
+ uses
+ cutils,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmcpu,cpubase,symsym,symdef,
+ import,export,link,i_nwl
+ {$ifdef netware} ,dos {$endif}
+ ;
+
+ type
+ timportlibnetwlibc=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ end;
+
+ texportlibnetwlibc=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkernetwlibc=class(texternallinker)
+ private
+ NLMConvLinkFile: TLinkRes; {for second pass, fist pass is ld}
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeNetwareLoadableModule (isLib : boolean):boolean;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+Const tmpLinkFileName = '~link~tmp.o';
+ minStackSize = 32768;
+
+{*****************************************************************************
+ TIMPORTLIBNETWARE
+*****************************************************************************}
+
+procedure timportlibnetwlibc.preparelib(const s : string);
+begin
+end;
+
+
+procedure timportlibnetwlibc.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+end;
+
+
+procedure timportlibnetwlibc.importvariable(vs:tglobalvarsym;const name,module:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+ { reset the mangledname and turn off the dll_var option }
+ vs.set_mangledname(name);
+ exclude(vs.varoptions,vo_is_dll_var);
+end;
+
+
+procedure timportlibnetwlibc.generatelib;
+begin
+end;
+
+
+{*****************************************************************************
+ TEXPORTLIBNETWARE
+*****************************************************************************}
+
+procedure texportlibnetwlibc.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibnetwlibc.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Comment(V_Error,'can''t export with index under netware');
+ exit;
+ end;
+ { use pascal name is none specified }
+ if (hp.options and eo_name)=0 then
+ begin
+ hp.name:=stringdup(hp.sym.name);
+ hp.options:=hp.options or eo_name;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.insert(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibnetwlibc.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibnetwlibc.generatelib;
+var
+ hp2 : texported_item;
+begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
+ begin
+{$ifdef i386}
+ { place jump in al_procedures }
+ asmlist[al_procedures].concat(Tai_align.Create_op(4,$90));
+ asmlist[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ asmlist[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(tprocsym(hp2.sym).first_procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+ asmlist[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif i386}
+ end;
+ end
+ else
+ //Comment(V_Error,'Exporting of variables is not supported under netware');
+ Message1(parser_e_no_export_of_variables_for_target,'netware');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERNETWARE
+*****************************************************************************}
+
+Constructor TLinkerNetwlibc.Create;
+begin
+ Inherited Create;
+end;
+
+
+procedure TLinkerNetwlibc.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ {$ifndef netware}
+ ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T $RES $STRIP -o $TMPOBJ';
+ ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T$RES';
+ {$else}
+ {for running on netware we need absolute pathes since ld has another working directory}
+ ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T '+FExpand(outputexedir+Info.ResName)+' $STRIP -o '+Fexpand(outputexedir+tmpLinkFileName);
+ ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T'+FExpand(outputexedir+'n'+Info.ResName);
+ {$endif}
+ end;
+end;
+
+
+Function TLinkerNetwlibc.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ s,s2,s3 : string;
+ ProgNam : string [80];
+ NlmNam : string [80];
+ hp2 : texported_item; { for exports }
+ p : byte;
+begin
+ WriteResponseFile:=False;
+
+ ProgNam := current_module.exefilename^;
+ i:=Pos(target_info.exeext,ProgNam);
+ if i>0 then
+ Delete(ProgNam,i,255);
+ NlmNam := ProgNam + target_info.exeext;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName); {for ld}
+ NLMConvLinkFile:=TLinkRes.Create(outputexedir+'n'+Info.ResName); {for nlmconv, written in CreateExeFile}
+
+ p := Pos ('"', Description);
+ while (p > 0) do
+ begin
+ delete (Description,p,1);
+ p := Pos ('"', Description);
+ end;
+ if Description <> '' then
+ NLMConvLinkFile.Add('DESCRIPTION "' + Description + '"');
+ NLMConvLinkFile.Add('VERSION '+tostr(dllmajor)+','+tostr(dllminor)+','+tostr(dllrevision));
+
+ p := Pos ('"', nwscreenname);
+ while (p > 0) do
+ begin
+ delete (nwscreenname,p,1);
+ p := Pos ('"', nwscreenname);
+ end;
+ p := Pos ('"', nwthreadname);
+ while (p > 0) do
+ begin
+ delete (nwthreadname,p,1);
+ p := Pos ('"', nwthreadname);
+ end;
+ p := Pos ('"', nwcopyright);
+ while (p > 0) do
+ begin
+ delete (nwcopyright,p,1);
+ p := Pos ('"', nwcopyright);
+ end;
+
+ if nwscreenname <> '' then
+ NLMConvLinkFile.Add('SCREENNAME "' + nwscreenname + '"');
+ if nwthreadname <> '' then
+ NLMConvLinkFile.Add('THREADNAME "' + nwthreadname + '"');
+ if nwcopyright <> '' then
+ NLMConvLinkFile.Add('COPYRIGHT "' + nwcopyright + '"');
+
+ if stacksize < minStackSize then stacksize := minStackSize;
+ str (stacksize, s);
+ NLMConvLinkFile.Add ('STACKSIZE '+s);
+ {$ifndef netware}
+ NLMConvLinkFile.Add ('INPUT '+outputexedir+tmpLinkFileName);
+ {$else}
+ NLMConvLinkFile.Add ('INPUT '+FExpand(outputexedir+tmpLinkFileName));
+ {$endif}
+
+ { add objectfiles, start with nwpre always }
+ LinkRes.Add ('INPUT(');
+ s2 := FindObjectFile('nwplibc','',false);
+ if s2 = '' then
+ s2 := FindObjectFile('libcpre.gcc','',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+
+ if isDll then {needed to provide main}
+ s2 := FindObjectFile('nwl_dlle','',false)
+ else
+ s2 := FindObjectFile('nwl_main','',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+
+ { main objectfiles, add to linker input }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ s2 := FindObjectFile (s,'',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ end;
+ end;
+ LinkRes.Add (')');
+
+ { output file (nlm), add to nlmconv }
+ {$ifndef netware}
+ NLMConvLinkFile.Add ('OUTPUT ' + NlmNam);
+ {$else}
+ NLMConvLinkFile.Add ('OUTPUT ' + FExpand(NlmNam));
+ {$endif}
+
+ { start and stop-procedures }
+ NLMConvLinkFile.Add ('START _LibCPrelude');
+ NLMConvLinkFile.Add ('EXIT _LibCPostlude');
+ NLMConvLinkFile.Add ('CHECK _LibCCheckUnload');
+ NLMConvLinkFile.Add ('REENTRANT'); { needed by older libc versions }
+
+ if not (cs_link_strip in aktglobalswitches) then
+ begin
+ NLMConvLinkFile.Add ('DEBUG');
+ Comment(V_Debug,'DEBUG');
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add ('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=lower (StaticLibFiles.GetFirst);
+ if s<>'' then
+ begin
+ {ad: that's a hack !
+ whith -XX we get the .a files as static libs (in addition to the
+ imported libraries}
+ if (pos ('.a',s) <> 0) OR (pos ('.A', s) <> 0) then
+ begin
+ S2 := FindObjectFile(s,'',false);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ Comment(V_Debug,'adding Object File (StaticLibFiles) '+S2);
+ end else
+ begin
+ i:=Pos(target_info.staticlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ S := S + '.imp'; S2 := '';
+ librarysearchpath.FindFile(S,S2);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+s2);
+ s2 := FExpand (S2);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S2);
+ Comment(V_Debug,'IMPORT @'+s2);
+ end;
+ end
+ end;
+ LinkRes.Add (')');
+ end;
+
+ if not SharedLibFiles.Empty then
+ begin
+ While not SharedLibFiles.Empty do
+ begin
+ {becuase of upper/lower case mix, we may get duplicate
+ names but nlmconv ignores that.
+ Here we are setting the import-files for nlmconv. I.e. for
+ the module libc or libc.nlm we add IMPORT @libc.imp and also
+ the module libc.nlm (autoload)
+ If a lib name begins with !, only the IMPORT will be generated
+ ? may it be better to set autoload's via StaticLibFiles ? }
+ S:=lower (SharedLibFiles.GetFirst);
+ if s<>'' then
+ begin
+ s2:=s;
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ if s[1] = '!' then
+ begin // special, with ! only the imp will be included but no module is autoloaded, needed i.e. for netware.imp inlcuded in libc ndk
+ delete (s,1,1);
+ S := S + '.imp';
+ librarysearchpath.FindFile(S,S3);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+S3);
+ S3 := FExpand (S3);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S3);
+ Comment(V_Debug,'IMPORT @'+S3);
+ end else
+ begin
+ S := S + '.imp';
+ librarysearchpath.FindFile(S,S3);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+S3);
+ S3 := FExpand (S3);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S3);
+ NLMConvLinkFile.Add('MODULE '+s2);
+ Comment(V_Debug,'MODULE '+S2);
+ Comment(V_Debug,'IMPORT @'+S3);
+ end;
+ end
+ end;
+ end;
+
+ { write exports }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if not hp2.is_var then
+ begin
+ { Export the Symbol }
+ Comment(V_Debug,'EXPORT '+hp2.name^);
+ NLMConvLinkFile.Add ('EXPORT '+hp2.name^);
+ end
+ else
+ { really, i think it is possible }
+ {Comment(V_Error,'Exporting of variables is not supported under netware');}
+ Message1(parser_e_no_export_of_variables_for_target,'netware');
+ hp2:=texported_item(hp2.next);
+ end;
+
+{ Write and Close response for ld, response for nlmconv is in NLMConvLinkFile(not written) }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+{ pass options from -k to nlmconv, ; is interpreted as newline }
+ s := ParaLinkOptions;
+ while(Length(s) > 0) and (s[1] = ' ') do
+ delete (s,1,1);
+ p := pos ('"',s);
+ while p > 0 do
+ begin
+ delete (s,p,1);
+ p := pos ('"',s);
+ end;
+
+ p := pos (';',s);
+ while p > 0 do
+ begin
+ s2 := copy(s,1,p-1);
+ comment (V_Debug,'adding "'+s2+'" to nlmvonv input');
+ NLMConvLinkFile.Add(s2);
+ delete (s,1,p);
+ p := pos (';',s);
+ end;
+ if s <> '' then
+ begin
+ comment (V_Debug,'adding "'+s+'" to nlmvonv input');
+ NLMConvLinkFile.Add(s);
+ end;
+
+ WriteResponseFile:=True;
+end;
+
+Const
+ xdc : Array[0..127] of char = (
+ 'B','A','G','F',#2,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
+ #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#2,#0,#0,#0,#0,#0,#0,#0,#16,#0,#0,
+ #0,#7,'M','P','K','_','B','a','g',#0,#0,#0,#0,#0,#0,#0,#0,#11,'M','T',
+ ' ','S','a','f','e',' ','N','L','M',#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
+ #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
+ #0,#0,#0,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0);
+
+
+function TLinkerNetwlibc.MakeNetwareLoadableModule (isLib : boolean):boolean;
+var
+ binstr : String;
+ cmdstr : TcmdStr;
+ xdcname : string;
+ success : boolean;
+ StripStr : string[2];
+ xdcpresent,usexdc : boolean;
+ f : file;
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='';
+
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+
+{ Write used files and libraries and create Headerfile for
+ nlmconv in NLMConvLinkFile }
+ WriteResponseFile(isLib);
+ if isLib then
+ NLMConvLinkFile.Add('FLAG_ON 1024'); {0x400 Specifies whether the NLM is a shared library.}
+
+{ if we have a xdc file, dont touch it, otherwise create a new
+ one and remove it after nlmconv }
+ xdcname := ForceExtension(current_module.exefilename^,'.xdc');
+ xdcpresent := FileExists (xdcname);
+ if not xdcpresent then
+ begin
+ assign (f,xdcname);
+ rewrite(f,1);
+ if ioresult = 0 then
+ begin
+ blockwrite (f,xdc,sizeof(xdc));
+ close(f);
+ usexdc := (IOResult = 0);
+ end else
+ usexdc := false;
+ end else
+ usexdc := true;
+
+ if usexdc then
+ NLMConvLinkFile.Add('XDCDATA '+xdcname);
+
+{ Call linker, this will generate a new object file that will be passed
+ to nlmconv. Otherwise we could not create nlms without debug info }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$TMPOBJ',maybequoted(outputexedir+tmpLinkFileName));
+ Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
+ success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+{ Call nlmconv }
+ if success then
+ begin
+ NLMConvLinkFile.writetodisk;
+ NLMConvLinkFile.Free;
+ SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+'n'+Info.ResName));
+ Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
+ success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ begin
+ RemoveFile(outputexedir+'n'+Info.ResName);
+ RemoveFile(outputexedir+tmpLinkFileName);
+ if not xdcpresent then
+ if usexdc then
+ RemoveFile (xdcname);
+ end;
+ end;
+
+ MakeNetwareLoadableModule:=success; { otherwise a recursive call to link method }
+end;
+
+function TLinkerNetwlibc.MakeExecutable:boolean;
+begin
+ MakeExecutable := MakeNetwareLoadableModule (false);
+end;
+
+
+function TLinkerNetwlibc.MakeSharedLibrary:boolean;
+begin
+ MakeSharedLibrary := MakeNetwareLoadableModule (true);
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+
+initialization
+ RegisterExternalLinker(system_i386_netwlibc_info,TLinkerNetwlibc);
+ RegisterImport(system_i386_netwlibc,TImportLibNetwlibc);
+ RegisterExport(system_i386_netwlibc,TExportLibNetwlibc);
+ RegisterTarget(system_i386_netwlibc_info);
+end.
diff --git a/compiler/systems/t_nwm.pas b/compiler/systems/t_nwm.pas
new file mode 100644
index 0000000000..d231a67c98
--- /dev/null
+++ b/compiler/systems/t_nwm.pas
@@ -0,0 +1,576 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Netware target
+
+ 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.
+
+ Currently generating NetWare-NLM's only work under Linux and win32.
+ (see http://home.arcor.de/armin.diehl/fpcnw for binutils working
+ with win32) while not included in fpc-releases.
+
+ The following compiler-swiches are supported for NetWare:
+ $DESCRIPTION : NLM-Description, will be displayed at load-time
+ $M : For Stack-Size, Heap-Size will be ignored
+ 32K is the accepted minimum
+ $VERSION x.x.x : Sets Major, Minor and Revision
+ $SCREENNAME : Sets the ScreenName
+ $THREADNAME : Sets current threadname
+
+ Displaying copyright does not work with nlmconv from gnu bunutils
+ version less that 2.13
+
+ Additional parameters for the nlmvonv-inputfile can be passed with
+ -k, i.e. -kREENTRANT will add the option REENTRANT to the nlmconv
+ inputfile. A ; will be converted into a newline
+
+ Exports will be handled like in win32:
+ procedure bla;
+ begin
+ end;
+
+ exports foo name 'Bar';
+
+ The path to the import-Files must be specified by the library-path.
+ All external modules are defined as autoload. (Note: the import-files have
+ to be in unix-format for exe2nlm)
+ By default, the most import files are included in freepascal.
+
+ i.e. Procedure ConsolePrintf (p:pchar); cdecl; external 'clib.nlm';
+ sets IMPORT @clib.imp and MODULE clib.
+
+ Function simply defined as external work without generating autoload but
+ you will get a warnung from nlmconv.
+
+ If you dont have nlmconv, compile gnu-binutils with
+ ./configure --enable-targets=i386-linux,i386-netware
+ make all
+
+ Debugging is possible with gdb and a converter from gdb to ndi available
+ at http://home.arcor.de/armin.diehl/gdbnw
+
+ A sample program:
+
+ Program Hello;
+ (*$DESCRIPTION HelloWorldNlm*)
+ (*$VERSION 1.2.3*)
+ (*$ScreenName Hello*)
+ (*$M 60000,60000*)
+ begin
+ writeLn ('hello world');
+ end.
+
+ compile with:
+ ppc386 -Tnetware hello
+
+ ToDo:
+ - No duplicate imports and autoloads
+ - libc support (needs new target)
+
+****************************************************************************
+}
+unit t_nwm;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ cutils,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmcpu,cpubase,symsym,symdef,
+ import,export,link,i_nwm
+ {$ifdef netware} ,dos {$endif}
+ ;
+
+ type
+ timportlibnetware=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ end;
+
+ texportlibnetware=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkernetware=class(texternallinker)
+ private
+ NLMConvLinkFile: TLinkRes; {for second pass, fist pass is ld}
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+Const tmpLinkFileName = 'link~tmp._o_';
+ minStackSize = 32768;
+
+{*****************************************************************************
+ TIMPORTLIBNETWARE
+*****************************************************************************}
+
+procedure timportlibnetware.preparelib(const s : string);
+begin
+end;
+
+
+procedure timportlibnetware.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+end;
+
+
+procedure timportlibnetware.importvariable(vs:tglobalvarsym;const name,module:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+ { reset the mangledname and turn off the dll_var option }
+ vs.set_mangledname(name);
+ exclude(vs.varoptions,vo_is_dll_var);
+end;
+
+
+procedure timportlibnetware.generatelib;
+begin
+end;
+
+
+{*****************************************************************************
+ TEXPORTLIBNETWARE
+*****************************************************************************}
+
+procedure texportlibnetware.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibnetware.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Comment(V_Error,'can''t export with index under netware');
+ exit;
+ end;
+ { use pascal name is none specified }
+ if (hp.options and eo_name)=0 then
+ begin
+ hp.name:=stringdup(hp.sym.name);
+ hp.options:=hp.options or eo_name;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.insert(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibnetware.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibnetware.generatelib;
+var
+ hp2 : texported_item;
+begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
+ begin
+{$ifdef i386}
+ { place jump in al_procedures }
+ asmlist[al_procedures].concat(Tai_align.Create_op(4,$90));
+ asmlist[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ asmlist[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(tprocsym(hp2.sym).first_procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+ asmlist[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif i386}
+ end;
+ end
+ else
+ //Comment(V_Error,'Exporting of variables is not supported under netware');
+ Message1(parser_e_no_export_of_variables_for_target,'netware');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERNETWARE
+*****************************************************************************}
+
+Constructor TLinkerNetware.Create;
+begin
+ Inherited Create;
+end;
+
+
+procedure TLinkerNetware.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ {$ifndef netware}
+ ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T $RES $STRIP -o $TMPOBJ';
+ ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T$RES';
+ {$else}
+ {for running on netware we need absolute pathes since ld has another working directory}
+ ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T '+FExpand(outputexedir+Info.ResName)+' $STRIP -o '+Fexpand(outputexedir+tmpLinkFileName);
+ ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T'+FExpand(outputexedir+'n'+Info.ResName);
+ {$endif}
+ end;
+end;
+
+
+Function TLinkerNetware.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ s,s2,s3 : string;
+ ProgNam : string [80];
+ NlmNam : string [80];
+ hp2 : texported_item; { for exports }
+ p : byte;
+begin
+ WriteResponseFile:=False;
+
+ ProgNam := current_module.exefilename^;
+ i:=Pos(target_info.exeext,ProgNam);
+ if i>0 then
+ Delete(ProgNam,i,255);
+ NlmNam := ProgNam + target_info.exeext;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName); {for ld}
+ NLMConvLinkFile:=TLinkRes.Create(outputexedir+'n'+Info.ResName); {for nlmconv, written in CreateExeFile}
+
+ p := Pos ('"', Description);
+ while (p > 0) do
+ begin
+ delete (Description,p,1);
+ p := Pos ('"', Description);
+ end;
+ if Description <> '' then
+ NLMConvLinkFile.Add('DESCRIPTION "' + Description + '"');
+ NLMConvLinkFile.Add('VERSION '+tostr(dllmajor)+','+tostr(dllminor)+','+tostr(dllrevision));
+
+ p := Pos ('"', nwscreenname);
+ while (p > 0) do
+ begin
+ delete (nwscreenname,p,1);
+ p := Pos ('"', nwscreenname);
+ end;
+ p := Pos ('"', nwthreadname);
+ while (p > 0) do
+ begin
+ delete (nwthreadname,p,1);
+ p := Pos ('"', nwthreadname);
+ end;
+ p := Pos ('"', nwcopyright);
+ while (p > 0) do
+ begin
+ delete (nwcopyright,p,1);
+ p := Pos ('"', nwcopyright);
+ end;
+
+ if nwscreenname <> '' then
+ NLMConvLinkFile.Add('SCREENNAME "' + nwscreenname + '"');
+ if nwthreadname <> '' then
+ NLMConvLinkFile.Add('THREADNAME "' + nwthreadname + '"');
+ if nwcopyright <> '' then
+ NLMConvLinkFile.Add('COPYRIGHT "' + nwcopyright + '"');
+
+ if stacksize < minStackSize then stacksize := minStackSize;
+ str (stacksize, s);
+ NLMConvLinkFile.Add ('STACKSIZE '+s);
+ {$ifndef netware}
+ NLMConvLinkFile.Add ('INPUT '+outputexedir+tmpLinkFileName);
+ {$else}
+ NLMConvLinkFile.Add ('INPUT '+FExpand(outputexedir+tmpLinkFileName));
+ {$endif}
+
+ { add objectfiles, start with nwpre always }
+ LinkRes.Add ('INPUT(');
+ s2 := FindObjectFile('nwpre','',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+
+ { main objectfiles, add to linker input }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ s2 := FindObjectFile (s,'',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ end;
+ end;
+ LinkRes.Add (')');
+
+ { output file (nlm), add to nlmconv }
+ {$ifndef netware}
+ NLMConvLinkFile.Add ('OUTPUT ' + NlmNam);
+ {$else}
+ NLMConvLinkFile.Add ('OUTPUT ' + FExpand(NlmNam));
+ {$endif}
+
+ { start and stop-procedures }
+ NLMConvLinkFile.Add ('START _Prelude'); { defined in rtl/netware/nwpre.as }
+ NLMConvLinkFile.Add ('EXIT _Stop'); { nwpre.as }
+ NLMConvLinkFile.Add ('CHECK FPC_NW_CHECKFUNCTION'); { system.pp }
+
+ if not (cs_link_strip in aktglobalswitches) then
+ begin
+ NLMConvLinkFile.Add ('DEBUG');
+ Comment(V_Debug,'DEBUG');
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add ('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=lower (StaticLibFiles.GetFirst);
+ if s<>'' then
+ begin
+ {ad: that's a hack !
+ whith -XX we get the .a files as static libs (in addition to the
+ imported libraries}
+ if (pos ('.a',s) <> 0) OR (pos ('.A', s) <> 0) then
+ begin
+ S2 := FindObjectFile(s,'',false);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ Comment(V_Debug,'adding Object File (StaticLibFiles) '+S2);
+ end else
+ begin
+ i:=Pos(target_info.staticlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ S := S + '.imp'; S2 := '';
+ librarysearchpath.FindFile(S,S2);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+s2);
+ s2 := FExpand (S2);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S2);
+ Comment(V_Debug,'IMPORT @'+s2);
+ end;
+ end
+ end;
+ LinkRes.Add (')');
+ end;
+
+ if not SharedLibFiles.Empty then
+ begin
+ While not SharedLibFiles.Empty do
+ begin
+ {becuase of upper/lower case mix, we may get duplicate
+ names but nlmconv ignores that.
+ Here we are setting the import-files for nlmconv. I.e. for
+ the module clib or clib.nlm we add IMPORT @clib.imp and also
+ the module clib.nlm (autoload)
+ ? may it be better to set autoload's via StaticLibFiles ? }
+ S:=lower (SharedLibFiles.GetFirst);
+ if s<>'' then
+ begin
+ s2:=s;
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ if s[1] = '!' then
+ begin // special, with ! only the imp will be included but no module is autoloaded, needed i.e. for netware.imp
+ S := copy(S,2,255) + '.imp';
+ librarysearchpath.FindFile(S,S3);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+S3);
+ S3 := FExpand (S3);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S3);
+ Comment(V_Debug,'IMPORT @'+S3);
+ end else
+ begin
+ S := S + '.imp';
+ librarysearchpath.FindFile(S,S3);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+S3);
+ S3 := FExpand (S3);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S3);
+ NLMConvLinkFile.Add('MODULE '+s2);
+ Comment(V_Debug,'MODULE '+S2);
+ Comment(V_Debug,'IMPORT @'+S3);
+ end;
+ end;
+ end;
+ end;
+
+ { write exports }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if not hp2.is_var then
+ begin
+ { Export the Symbol }
+ Comment(V_Debug,'EXPORT '+hp2.name^);
+ NLMConvLinkFile.Add ('EXPORT '+hp2.name^);
+ end
+ else
+ { really, i think it is possible }
+ Message1(parser_e_no_export_of_variables_for_target,'netware');
+ hp2:=texported_item(hp2.next);
+ end;
+
+{ Write and Close response for ld, response for nlmconv is in NLMConvLinkFile(not written) }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+{ pass options from -k to nlmconv, ; is interpreted as newline }
+ s := ParaLinkOptions;
+ while(Length(s) > 0) and (s[1] = ' ') do
+ delete (s,1,1);
+ p := pos ('"',s);
+ while p > 0 do
+ begin
+ delete (s,p,1);
+ p := pos ('"',s);
+ end;
+
+ p := pos (';',s);
+ while p > 0 do
+ begin
+ s2 := copy(s,1,p-1);
+ comment (V_Debug,'adding "'+s2+'" to nlmvonv input');
+ NLMConvLinkFile.Add(s2);
+ delete (s,1,p);
+ p := pos (';',s);
+ end;
+ if s <> '' then
+ begin
+ comment (V_Debug,'adding "'+s+'" to nlmvonv input');
+ NLMConvLinkFile.Add(s);
+ end;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerNetware.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ StripStr : string[2];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='';
+
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+
+{ Write used files and libraries and create Headerfile for
+ nlmconv in NLMConvLinkFile }
+ WriteResponseFile(false);
+
+{ Call linker, this will generate a new object file that will be passed
+ to nlmconv. Otherwise we could not create nlms without debug info }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$TMPOBJ',maybequoted(outputexedir+tmpLinkFileName));
+ Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
+ success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+{ Call nlmconv }
+ if success then
+ begin
+ NLMConvLinkFile.writetodisk;
+ NLMConvLinkFile.Free;
+ SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+'n'+Info.ResName));
+ Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
+ success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ begin
+ RemoveFile(outputexedir+'n'+Info.ResName);
+ RemoveFile(outputexedir+tmpLinkFileName);
+ end;
+ end;
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+
+initialization
+ RegisterExternalLinker(system_i386_netware_info,TLinkerNetware);
+ RegisterImport(system_i386_netware,TImportLibNetware);
+ RegisterExport(system_i386_netware,TExportLibNetware);
+ RegisterTarget(system_i386_netware_info);
+end.
diff --git a/compiler/systems/t_os2.pas b/compiler/systems/t_os2.pas
new file mode 100644
index 0000000000..ed86fe5e21
--- /dev/null
+++ b/compiler/systems/t_os2.pas
@@ -0,0 +1,516 @@
+{
+ Copyright (c) 1998-2002 by Daniel Mantione
+ Portions Copyright (c) 1998-2002 Eberhard Mattes
+
+ Unit to write out import libraries and def files for OS/2
+
+ 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.
+
+ ****************************************************************************
+}
+{
+ A lot of code in this unit has been ported from C to Pascal from the
+ emximp utility, part of the EMX development system. Emximp is copyrighted
+ by Eberhard Mattes. Note: Eberhard doesn't know much about the Pascal
+ port, please send questions to Daniel Mantione
+ <d.s.p.mantione@twi.tudelft.nl>.
+}
+unit t_os2;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ strings,
+ dos,
+ cutils,cclasses,
+ globtype,systems,symconst,symdef,
+ globals,verbose,fmodule,script,
+ import,link,i_os2;
+
+ type
+ timportlibos2=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkeros2=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+const profile_flag:boolean=false;
+
+const n_ext = 1;
+ n_abs = 2;
+ n_text = 4;
+ n_data = 6;
+ n_bss = 8;
+ n_imp1 = $68;
+ n_imp2 = $6a;
+
+type reloc=packed record {This is the layout of a relocation table
+ entry.}
+ address:longint; {Fixup location}
+ remaining:longint;
+ {Meaning of bits for remaining:
+ 0..23: Symbol number or segment
+ 24: Self-relative fixup if non-zero
+ 25..26: Fixup size (0: 1 byte, 1: 2, 2: 4 bytes)
+ 27: Reference to symbol or segment
+ 28..31 Not used}
+ end;
+
+ nlist=packed record {This is the layout of a symbol table entry.}
+ strofs:longint; {Offset in string table}
+ typ:byte; {Type of the symbol}
+ other:byte; {Other information}
+ desc:word; {More information}
+ value:longint; {Value (address)}
+ end;
+
+ a_out_header=packed record
+ magic:word; {Magic word, must be $0107}
+ machtype:byte; {Machine type}
+ flags:byte; {Flags}
+ text_size:longint; {Length of text, in bytes}
+ data_size:longint; {Length of initialized data, in bytes}
+ bss_size:longint; {Length of uninitialized data, in bytes}
+ sym_size:longint; {Length of symbol table, in bytes}
+ entry:longint; {Start address (entry point)}
+ trsize:longint; {Length of relocation info for text, bytes}
+ drsize:longint; {Length of relocation info for data, bytes}
+ end;
+
+ ar_hdr=packed record
+ ar_name:array[0..15] of char;
+ ar_date:array[0..11] of char;
+ ar_uid:array[0..5] of char;
+ ar_gid:array[0..5] of char;
+ ar_mode:array[0..7] of char;
+ ar_size:array[0..9] of char;
+ ar_fmag:array[0..1] of char;
+ end;
+
+var aout_str_size:longint;
+ aout_str_tab:array[0..2047] of byte;
+ aout_sym_count:longint;
+ aout_sym_tab:array[0..5] of nlist;
+
+ aout_text:array[0..63] of byte;
+ aout_text_size:longint;
+
+ aout_treloc_tab:array[0..1] of reloc;
+ aout_treloc_count:longint;
+
+ aout_size:longint;
+ seq_no:longint;
+
+ ar_member_size:longint;
+
+ out_file:file;
+
+procedure write_ar(const name:string;size:longint);
+
+var ar:ar_hdr;
+ time:datetime;
+ dummy:word;
+ numtime:longint;
+ tmp:string[19];
+
+
+begin
+ ar_member_size:=size;
+ fillchar(ar.ar_name,sizeof(ar.ar_name),' ');
+ move(name[1],ar.ar_name,length(name));
+ getdate(time.year,time.month,time.day,dummy);
+ gettime(time.hour,time.min,time.sec,dummy);
+ packtime(time,numtime);
+ str(numtime,tmp);
+ fillchar(ar.ar_date,sizeof(ar.ar_date),' ');
+ move(tmp[1],ar.ar_date,length(tmp));
+ ar.ar_uid:='0 ';
+ ar.ar_gid:='0 ';
+ ar.ar_mode:='100666'#0#0;
+ str(size,tmp);
+ fillchar(ar.ar_size,sizeof(ar.ar_size),' ');
+ move(tmp[1],ar.ar_size,length(tmp));
+ ar.ar_fmag:='`'#10;
+ blockwrite(out_file,ar,sizeof(ar));
+end;
+
+procedure finish_ar;
+
+var a:byte;
+
+begin
+ a:=0;
+ if odd(ar_member_size) then
+ blockwrite(out_file,a,1);
+end;
+
+procedure aout_init;
+
+begin
+ aout_str_size:=sizeof(longint);
+ aout_sym_count:=0;
+ aout_text_size:=0;
+ aout_treloc_count:=0;
+end;
+
+function aout_sym(const name:string;typ,other:byte;desc:word;
+ value:longint):longint;
+
+begin
+ if aout_str_size+length(name)+1>sizeof(aout_str_tab) then
+ internalerror(200504245);
+ if aout_sym_count>=sizeof(aout_sym_tab) div sizeof(aout_sym_tab[0]) then
+ internalerror(200504246);
+ aout_sym_tab[aout_sym_count].strofs:=aout_str_size;
+ aout_sym_tab[aout_sym_count].typ:=typ;
+ aout_sym_tab[aout_sym_count].other:=other;
+ aout_sym_tab[aout_sym_count].desc:=desc;
+ aout_sym_tab[aout_sym_count].value:=value;
+ strPcopy(@aout_str_tab[aout_str_size],name);
+ aout_str_size:=aout_str_size+length(name)+1;
+ aout_sym:=aout_sym_count;
+ inc(aout_sym_count);
+end;
+
+procedure aout_text_byte(b:byte);
+
+begin
+ if aout_text_size>=sizeof(aout_text) then
+ internalerror(200504247);
+ aout_text[aout_text_size]:=b;
+ inc(aout_text_size);
+end;
+
+procedure aout_text_dword(d:longint);
+
+type li_ar=array[0..3] of byte;
+
+begin
+ aout_text_byte(li_ar(d)[0]);
+ aout_text_byte(li_ar(d)[1]);
+ aout_text_byte(li_ar(d)[2]);
+ aout_text_byte(li_ar(d)[3]);
+end;
+
+procedure aout_treloc(address,symbolnum,pcrel,len,ext:longint);
+
+begin
+ if aout_treloc_count>=sizeof(aout_treloc_tab) div sizeof(reloc) then
+ internalerror(200504248);
+ aout_treloc_tab[aout_treloc_count].address:=address;
+ aout_treloc_tab[aout_treloc_count].remaining:=symbolnum+pcrel shl 24+
+ len shl 25+ext shl 27;
+ inc(aout_treloc_count);
+end;
+
+procedure aout_finish;
+
+begin
+ while (aout_text_size and 3)<>0 do
+ aout_text_byte ($90);
+ aout_size:=sizeof(a_out_header)+aout_text_size+aout_treloc_count*
+ sizeof(reloc)+aout_sym_count*sizeof(aout_sym_tab[0])+aout_str_size;
+end;
+
+procedure aout_write;
+
+var ao:a_out_header;
+
+begin
+ ao.magic:=$0107;
+ ao.machtype:=0;
+ ao.flags:=0;
+ ao.text_size:=aout_text_size;
+ ao.data_size:=0;
+ ao.bss_size:=0;
+ ao.sym_size:=aout_sym_count*sizeof(aout_sym_tab[0]);
+ ao.entry:=0;
+ ao.trsize:=aout_treloc_count*sizeof(reloc);
+ ao.drsize:=0;
+ blockwrite(out_file,ao,sizeof(ao));
+ blockwrite(out_file,aout_text,aout_text_size);
+ blockwrite(out_file,aout_treloc_tab,sizeof(reloc)*aout_treloc_count);
+ blockwrite(out_file,aout_sym_tab,sizeof(aout_sym_tab[0])*aout_sym_count);
+ longint((@aout_str_tab)^):=aout_str_size;
+ blockwrite(out_file,aout_str_tab,aout_str_size);
+end;
+
+procedure timportlibos2.preparelib(const s:string);
+
+{This code triggers a lot of bugs in the compiler.
+const armag='!<arch>'#10;
+ ar_magic:array[1..length(armag)] of char=armag;}
+const ar_magic:array[1..8] of char='!<arch>'#10;
+var
+ libname : string;
+begin
+ libname:=FixFileName(S + Target_Info.StaticCLibExt);
+ seq_no:=1;
+ current_module.linkotherstaticlibs.add(libname,link_allways);
+ assign(out_file,current_module.outputpath^+libname);
+ rewrite(out_file,1);
+ blockwrite(out_file,ar_magic,sizeof(ar_magic));
+end;
+
+procedure timportlibos2.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+{func = Name of function to import.
+ module = Name of DLL to import from.
+ index = Index of function in DLL. Use 0 to import by name.
+ name = Name of function in DLL. Ignored when index=0;}
+var tmp1,tmp2,tmp3:string;
+ sym_mcount,sym_import:longint;
+ fixup_mcount,fixup_import:longint;
+ func : string;
+begin
+ { force the current mangledname }
+ include(aprocdef.procoptions,po_has_mangledname);
+ func:=aprocdef.mangledname;
+
+ aout_init;
+ tmp2:=func;
+ if profile_flag and not (copy(func,1,4)='_16_') then
+ begin
+ {sym_entry:=aout_sym(func,n_text+n_ext,0,0,aout_text_size);}
+ sym_mcount:=aout_sym('__mcount',n_ext,0,0,0);
+ {Use, say, "_$U_DosRead" for "DosRead" to import the
+ non-profiled function.}
+ tmp2:='__$U_'+func;
+ sym_import:=aout_sym(tmp2,n_ext,0,0,0);
+ aout_text_byte($55); {push ebp}
+ aout_text_byte($89); {mov ebp, esp}
+ aout_text_byte($e5);
+ aout_text_byte($e8); {call _mcount}
+ fixup_mcount:=aout_text_size;
+ aout_text_dword(0-(aout_text_size+4));
+ aout_text_byte($5d); {pop ebp}
+ aout_text_byte($e9); {jmp _$U_DosRead}
+ fixup_import:=aout_text_size;
+ aout_text_dword(0-(aout_text_size+4));
+
+ aout_treloc(fixup_mcount,sym_mcount,1,2,1);
+ aout_treloc (fixup_import, sym_import,1,2,1);
+ end;
+ str(seq_no,tmp1);
+ tmp1:='IMPORT#'+tmp1;
+ if name='' then
+ begin
+ str(index,tmp3);
+ tmp3:=func+'='+module+'.'+tmp3;
+ end
+ else
+ tmp3:=func+'='+module+'.'+name;
+ aout_sym(tmp2,n_imp1+n_ext,0,0,0);
+ aout_sym(tmp3,n_imp2+n_ext,0,0,0);
+ aout_finish;
+ write_ar(tmp1,aout_size);
+ aout_write;
+ finish_ar;
+ inc(seq_no);
+end;
+
+procedure timportlibos2.generatelib;
+
+begin
+ close(out_file);
+end;
+
+
+{****************************************************************************
+ TLinkeros2
+****************************************************************************}
+
+Constructor TLinkeros2.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkeros2.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $OPT -o $OUT @$RES';
+ ExeCmd[2]:='emxbind -b $STRIP $APPTYPE $RSRC -k$STACKKB -h1 -o $EXE $OUT -ai -s8';
+ if Source_Info.Script = script_dos then
+ ExeCmd[3]:='del $OUT';
+ end;
+end;
+
+
+Function TLinkeros2.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TStringListItem;
+ s : string;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ { add objectfiles, start with prt0 always }
+ LinkRes.AddFileName(FindObjectFile('prt0','',false));
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(s);
+ end;
+
+ { Write staticlibraries }
+ { No group !! This will not work correctly PM }
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(s)
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkeros2.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ i : longint;
+ AppTypeStr,
+ StripStr: string[40];
+ RsrcStr : string;
+ DS: DirStr;
+ NS: NameStr;
+ ES: ExtStr;
+ OutName: PathStr;
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ FSplit (current_module.exefilename^, DS, NS, ES);
+ OutName := DS + NS + '.out';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr := '-s'
+ else
+ StripStr := '';
+ if (usewindowapi) or (AppType = app_gui) then
+ AppTypeStr := '-p'
+ else if AppType = app_fs then
+ AppTypeStr := '-f'
+ else AppTypeStr := '-w';
+ if not (Current_module.ResourceFiles.Empty) then
+ RsrcStr := '-r ' + Current_module.ResourceFiles.GetFirst
+ else
+ RsrcStr := '';
+(* Only one resource file supported, discard everything else
+ (should be already empty anyway, though). *)
+ Current_module.ResourceFiles.Clear;
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ success:=false;
+ for i:=1 to 3 do
+ begin
+ SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ { Is this really required? Not anymore according to my EMX docs }
+ Replace(cmdstr,'$HEAPMB',tostr((1048575) shr 20));
+ {Size of the stack when an EMX program runs in OS/2.}
+ Replace(cmdstr,'$STACKKB',tostr((stacksize+1023) shr 10));
+ {When an EMX program runs in DOS, the heap and stack share the
+ same memory pool. The heap grows upwards, the stack grows downwards.}
+ Replace(cmdstr,'$DOSHEAPKB',tostr((stacksize+1023) shr 10));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$APPTYPE',AppTypeStr);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RSRC',RsrcStr);
+ Replace(cmdstr,'$OUT',maybequoted(OutName));
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ if i<>3 then
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,(i=1),false)
+ else
+ success:=DoExec(binstr,cmdstr,(i=1),true);
+ end;
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_os2_info,TLinkerOS2);
+ RegisterImport(system_i386_os2,TImportLibOS2);
+{ RegisterRes(res_emxbind_info);}
+ RegisterTarget(system_i386_os2_info);
+end.
diff --git a/compiler/systems/t_palmos.pas b/compiler/systems/t_palmos.pas
new file mode 100644
index 0000000000..b2e4a6e2eb
--- /dev/null
+++ b/compiler/systems/t_palmos.pas
@@ -0,0 +1,212 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Amiga target
+
+ 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 t_palmos;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ link;
+
+ type
+ tlinkerPalmOS=class(texternallinker)
+ private
+ Function WriteResponseFile : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+implementation
+
+ uses
+ cutils,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_palmos;
+
+{****************************************************************************
+ TLinkerPalmOS
+****************************************************************************}
+
+Constructor TLinkerPalmOS.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerPalmOS.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ldpalm $OPT $STRIP -N -dy -T $SCRIPT -o $EXE @$RES';
+ ExeCmd[2]:='build-prc $EXE.prc "$APPNAME" $APPID $EXE *.bin';
+ end;
+end;
+
+
+Function TLinkerPalmOS.WriteResponseFile : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : PStringQueueItem;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ { add objectfiles, start with crt0 always }
+ { using crt0, we should stick C compatible }
+ LinkRes.AddFileName(FindObjectFile('crt0',''));
+
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(s);
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add('-(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(s)
+ end;
+ LinkRes.Add('-)');
+ end;
+
+ { currently the PalmOS target must be linked always against the C lib }
+ LinkRes.Add('-lcrt');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ linklibc:=true;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerPalmOS.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : string;
+ success : boolean;
+ StripStr : string[40];
+ i : longint;
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module^.exefilename^);
+
+ { Create some replacements }
+ StripStr:='';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+
+ { Write used files and libraries }
+ WriteResponseFile;
+
+{ Call linker }
+ success:=false;
+ for i:=1 to 2 do
+ begin
+ SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ Replace(cmdstr,'$EXE',MaybeQuote(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$SCRIPT',FindUtil('palm.ld'));
+ Replace(cmdstr,'$APPNAME',palmos_applicationname);
+ Replace(cmdstr,'$APPID',palmos_applicationid);
+ success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
+ if not success then
+ break;
+ end;
+ end;
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef m68k}
+ RegisterTarget(target_m68k_palmos_info);
+ RegisterRes(res_m68k_palmos_info);
+{$endif m68k}
+end.
diff --git a/compiler/systems/t_sunos.pas b/compiler/systems/t_sunos.pas
new file mode 100644
index 0000000000..d600f5d9a0
--- /dev/null
+++ b/compiler/systems/t_sunos.pas
@@ -0,0 +1,490 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) solaris target
+
+ 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 t_sunos;
+
+{$i fpcdefs.inc}
+
+interface
+
+{ copy from t_linux
+// Up to now we use gld since the solaris ld seems not support .res-files}
+{-$DEFINE LinkTest} { DON't del link.res and write Info }
+{$DEFINE GnuLd} {The other is not implemented }
+
+implementation
+
+ uses
+ cutils,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmcpu,cpubase,symsym,symdef,
+ cgobj,
+ import,export,link,i_sunos;
+
+ type
+ timportlibsolaris=class(timportlib)
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ end;
+
+ texportlibsolaris=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkersolaris=class(texternallinker)
+ private
+ Glibc2,
+ Glibc21 : boolean;
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+
+{*****************************************************************************
+ TIMPORTLIBsolaris
+*****************************************************************************}
+
+procedure timportlibsolaris.preparelib(const s : string);
+begin
+{$ifDef LinkTest}
+ WriteLN('Prepare import: ',s);
+{$EndIf}
+end;
+
+
+procedure timportlibsolaris.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
+begin
+ { insert sharedlibrary }
+{$ifDef LinkTest}
+ WriteLN('Import: f:',func,' m:',module,' n:',name);
+{$EndIf}
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+end;
+
+
+procedure timportlibsolaris.importvariable(vs:tglobalvarsym;const name,module:string);
+begin
+ { insert sharedlibrary }
+ current_module.linkothersharedlibs.add(SplitName(module),link_allways);
+ { reset the mangledname and turn off the dll_var option }
+ vs.set_mangledname(name);
+ exclude(vs.varoptions,vo_is_dll_var);
+end;
+
+
+procedure timportlibsolaris.generatelib;
+begin
+end;
+
+
+{*****************************************************************************
+ TEXPORTLIBsolaris
+*****************************************************************************}
+
+procedure texportlibsolaris.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibsolaris.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Message1(parser_e_no_export_with_index_for_target,'solaris');
+ exit;
+ end;
+ { use pascal name is none specified }
+ if (hp.options and eo_name)=0 then
+ begin
+ hp.name:=stringdup(hp.sym.name);
+ hp.options:=hp.options or eo_name;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.insert(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibsolaris.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibsolaris.generatelib;
+var
+ hp2 : texported_item;
+begin
+ new_section(asmlist[al_procedures],sec_code,'',0);
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
+ begin
+ { place jump in al_procedures }
+ asmlist[al_procedures].concat(tai_align.create(target_info.alignment.procalign));
+ asmlist[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ cg.a_jmp_name(asmlist[al_procedures],tprocsym(hp2.sym).first_procdef.mangledname);
+ asmlist[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+ end;
+ end
+ else
+ Message1(parser_e_no_export_of_variables_for_target,'linux');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERsolaris
+*****************************************************************************}
+
+Constructor TLinkersolaris.Create;
+begin
+ Inherited Create;
+ if NOT Dontlinkstdlibpath Then
+ LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib;/opt/sfw/lib',true);
+{$ifdef LinkTest}
+ if (cs_link_staticflag in aktglobalswitches) then WriteLN('ForceLinkStaticFlag');
+ if (cs_link_static in aktglobalswitches) then WriteLN('LinkStatic-Flag');
+ if (cs_link_shared in aktglobalswitches) then WriteLN('LinkSynamicFlag');
+{$EndIf}
+end;
+
+
+procedure TLinkersolaris.SetDefaultInfo;
+{
+ This will also detect which libc version will be used
+}
+begin
+ Glibc2:=false;
+ Glibc21:=false;
+ with Info do
+ begin
+{$IFDEF GnuLd}
+ ExeCmd[1]:='gld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
+ DllCmd[1]:='gld $OPT -shared -L. -o $EXE $RES';
+ DllCmd[2]:='strip --strip-unneeded $EXE';
+ DynamicLinker:=''; { Gnu uses the default }
+ Glibc21:=false;
+{$ELSE}
+ Not Implememted
+{$ENDIF}
+(* Linux Stuff not needed?
+ { first try glibc2 } // muss noch gendert werden
+ if FileExists(DynamicLinker) then
+ begin
+ Glibc2:=true;
+ { Check for 2.0 files, else use the glibc 2.1 stub }
+ if FileExists('/lib/ld-2.0.*') then
+ Glibc21:=false
+ else
+ Glibc21:=true;
+ end
+ else
+ DynamicLinker:='/lib/ld-linux.so.1';
+*)
+ end;
+
+end;
+
+
+Function TLinkersolaris.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ cprtobj,
+ gprtobj,
+ prtobj : string[80];
+ HPath : TStringListItem;
+ s,s2 : string;
+ linkdynamic,
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+{ set special options for some targets }
+ linkdynamic:=not(SharedLibFiles.empty);
+{ linkdynamic:=false; // da nicht getestet }
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+ prtobj:='prt0';
+ cprtobj:='cprt0';
+ gprtobj:='gprt0';
+ if cs_profile in aktmoduleswitches then
+ begin
+ prtobj:=gprtobj;
+ if not glibc2 then
+ AddSharedLibrary('gmon');
+ AddSharedLibrary('c');
+ linklibc:=true;
+ end
+ else
+ begin
+ if linklibc then
+ prtobj:=cprtobj
+ else
+ AddSharedLibrary('c'); { quick hack: this solaris implementation needs alwys libc }
+ end;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT(');
+ { add objectfiles, start with prt0 always }
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then { Needed in solaris? }
+ begin
+{ if librarysearchpath.FindFile('crtbegin.o',s) then
+ LinkRes.AddFileName(s);}
+ if librarysearchpath.FindFile('crti.o',s) then
+ LinkRes.AddFileName(s);
+ end;
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ LinkRes.Add(')');
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(maybequoted(s))
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if not SharedLibFiles.Empty then
+ begin
+ LinkRes.Add('INPUT(');
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ linkdynamic:=false; { libc will include the ld-solaris (war ld-linux) for us }
+ end;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc then
+ LinkRes.Add('-lc');
+ { when we have -static for the linker the we also need libgcc }
+ if (cs_link_staticflag in aktglobalswitches) then begin
+ LinkRes.Add('-lgcc');
+ end;
+ if linkdynamic and (Info.DynamicLinker<>'') then { gld has a default, DynamicLinker is not set in solaris }
+ LinkRes.AddFileName(Info.DynamicLinker);
+ LinkRes.Add(')');
+ end;
+ { objects which must be at the end }
+ if linklibc then {needed in solaris ? }
+ begin
+ if {librarysearchpath.FindFile('crtend.o',s1) or}
+ librarysearchpath.FindFile('crtn.o',s2) then
+ begin
+ LinkRes.Add('INPUT(');
+{ LinkRes.AddFileName(s1);}
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkersolaris.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in aktglobalswitches) then
+ StaticStr:='-Bstatic';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+ If (cs_profile in aktmoduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ { solaris sets DynamicLinker, but gld will (hopefully) defaults to -Bdynamic and add the default-linker }
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
+
+{ Remove ReponseFile }
+{$IFNDEF LinkTest}
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+{$ENDIF}
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkersolaris.MakeSharedLibrary:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile(true);
+
+{ Call linker }
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+
+{ Strip the library ? }
+ if success and (cs_link_strip in aktglobalswitches) then
+ begin
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(utilsprefix+FindUtil(binstr),cmdstr,true,false);
+ end;
+
+{ Remove ReponseFile }
+{$IFNDEF LinkTest}
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+{$ENDIF}
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_solaris_info,TLinkersolaris);
+ RegisterImport(system_i386_solaris,TImportLibsolaris);
+ RegisterExport(system_i386_solaris,TExportLibsolaris);
+ RegisterTarget(system_i386_solaris_info);
+{$endif i386}
+
+{$ifdef sparc}
+ RegisterExternalLinker(system_sparc_solaris_info,TLinkersolaris);
+ RegisterImport(system_sparc_solaris,TImportLibsolaris);
+ RegisterExport(system_sparc_solaris,TExportLibsolaris);
+ RegisterTarget(system_sparc_solaris_info);
+{$endif sparc}
+end.
diff --git a/compiler/systems/t_watcom.pas b/compiler/systems/t_watcom.pas
new file mode 100644
index 0000000000..ba9886e6bf
--- /dev/null
+++ b/compiler/systems/t_watcom.pas
@@ -0,0 +1,178 @@
+{
+ Copyright (c) 2003 by Wiktor Sywula
+
+ This unit implements support import, export, link routines
+ for the (i386) Watcom target
+
+ 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 t_watcom;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ link,
+ cclasses,cutils,strings,globtype,globals,
+ systems,verbose,script,fmodule,i_watcom;
+
+
+ type
+ tlinkerwatcom=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+{ function MakeSharedLibrary:boolean;override;}
+ end;
+
+
+{****************************************************************************
+ TLinkerWatcom
+****************************************************************************}
+
+Constructor TLinkerWatcom.Create;
+begin
+ Inherited Create;
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerWatcom.SetDefaultInfo;
+begin
+ with Info do
+ ExeCmd[1]:='wlink system causeway option quiet option nocaseexact $OPT $STRIP name $EXE @$RES';
+end;
+
+Function TLinkerWatcom.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write object files, start with prt0 }
+ LinkRes.Add('file '+GetShortName(FindObjectFile('prt0','',false)));
+ if not ObjectFiles.Empty then
+ While not ObjectFiles.Empty do
+ begin
+ S:=ObjectFiles.GetFirst;
+ LinkRes.AddFileName('file '+GetShortName(s));
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName('file '+GetShortName(s));
+ end;
+
+(*
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.Get;
+ if s<>'c' then
+ begin
+ i:=Pos(target_os.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+*)
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerWatcom.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ StripStr : string[40];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='debug dwarf all';
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='';
+
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ RemoveFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+{function TLinkerWatcom.MakeSharedLibrary:boolean;
+begin
+ MakeSharedLibrary:=false;
+end;}
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_watcom_info,TLinkerWatcom);
+ RegisterTarget(system_i386_watcom_info);
+end.
diff --git a/compiler/systems/t_wdosx.pas b/compiler/systems/t_wdosx.pas
new file mode 100644
index 0000000000..4eaa9eaf68
--- /dev/null
+++ b/compiler/systems/t_wdosx.pas
@@ -0,0 +1,84 @@
+{
+ Copyright (c) 2001-2002 Pavel ??????
+
+ This unit implements support import,export,link routines
+ for the (i386) WDOSX target
+
+ 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 t_wdosx;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ cutils,
+ fmodule,globals,systems,
+ import,export,link,t_win,i_wdosx;
+
+ type
+ timportlibwdosx=class(timportlibwin32)
+ end;
+
+ texportlibwdosx=texportlibwin32;
+
+ tlinkerwdosx=class(tlinkerwin32)
+ public
+ function MakeExecutable:boolean;override;
+ end;
+
+ tDLLScannerWdosx=class(tDLLScannerWin32)
+ end;
+
+
+{*****************************************************************************
+ TIMPORTLIBWDOSX
+*****************************************************************************}
+
+{*****************************************************************************
+ TLINKERWDOSX
+*****************************************************************************}
+function TLinkerWdosx.MakeExecutable:boolean;
+var
+ b: boolean;
+begin
+ b := Inherited MakeExecutable;
+ if b then
+ DoExec(FindUtil('stubit'),current_module.exefilename^,false,false);
+ Result := b;
+end;
+
+{****************************************************************************
+ TDLLScannerWdosx
+****************************************************************************}
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_wdosx_info,TLinkerWdosx);
+ RegisterImport(system_i386_wdosx,TImportLibWdosx);
+ RegisterExport(system_i386_wdosx,TExportLibWdosx);
+ RegisterDLLScanner(system_i386_wdosx,TDLLScannerWdosx);
+ {RegisterAr(ar_gnu_arw_info);}
+ {RegisterRes(res_gnu_windres_info);}
+ RegisterTarget(system_i386_wdosx_info);
+end.
diff --git a/compiler/systems/t_win.pas b/compiler/systems/t_win.pas
new file mode 100644
index 0000000000..3d6e435ae7
--- /dev/null
+++ b/compiler/systems/t_win.pas
@@ -0,0 +1,1673 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Win32 target
+
+ 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 t_win;
+
+{$i fpcdefs.inc}
+
+interface
+ uses
+ dos,
+ cutils,cclasses,
+ aasmbase,aasmtai,aasmcpu,fmodule,globtype,globals,systems,verbose,
+ symconst,symdef,symsym,
+ script,gendef,
+ cpubase,
+ import,export,link,cgobj,i_win;
+
+
+ const
+ MAX_DEFAULT_EXTENSIONS = 3;
+
+ type
+ tStr4=array[1..MAX_DEFAULT_EXTENSIONS] of string[4];
+ pStr4=^tStr4;
+
+ twin32imported_item = class(timported_item)
+ procdef : tprocdef;
+ end;
+
+ timportlibwin32=class(timportlib)
+ private
+ procedure win32importproc(aprocdef:tprocdef;const func,module : string;index : longint;const name : string);
+ procedure importvariable_str(const s:string;const name,module:string);
+ procedure importprocedure_str(const func,module:string;index:longint;const name:string);
+ public
+ procedure preparelib(const s:string);override;
+ procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
+ procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
+ procedure generatelib;override;
+ procedure generatenasmlib;virtual;
+ procedure generatesmartlib;override;
+ end;
+
+ texportlibwin32=class(texportlib)
+ st : string;
+ EList_indexed:tList;
+ EList_nonindexed:tList;
+ procedure preparelib(const s:string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure exportfromlist(hp : texported_item);
+ procedure generatelib;override;
+ procedure generatenasmlib;virtual;
+ end;
+
+ tlinkerwin32=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ Function PostProcessExecutable(const fn:string;isdll:boolean) : Boolean;
+ public
+ Constructor Create;override;
+ Procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+ tDLLScannerWin32=class(tDLLScanner)
+ private
+ cstring : array[0..127]of char;
+ function DOSstubOK(var x:cardinal):boolean;
+ function FindDLL(const s:string;var founddll:string):boolean;
+ function ExtractDllName(Const Name : string) : string;
+ public
+ function isSuitableFileType(x:cardinal):longbool;override;
+ function GetEdata(HeaderEntry:cardinal):longbool;override;
+ function Scan(const binname:string):longbool;override;
+ end;
+
+implementation
+
+ uses
+ cpuinfo,cgutils,dbgbase;
+
+
+ const
+ res_gnu_windres_info : tresinfo =
+ (
+ id : res_gnu_windres;
+ resbin : 'windres';
+ rescmd : '--include $INC -O coff -o $OBJ $RES'
+ );
+
+ res_gnu_wince_windres_info : tresinfo =
+ (
+ id : res_gnu_wince_windres;
+ resbin : 'windres';
+ rescmd : '--include $INC -O coff -o $OBJ $RES'
+ );
+
+{*****************************************************************************
+ TIMPORTLIBWIN32
+*****************************************************************************}
+
+ procedure timportlibwin32.preparelib(const s : string);
+ begin
+ if asmlist[al_imports]=nil then
+ asmlist[al_imports]:=TAAsmoutput.create;
+ end;
+
+
+ procedure timportlibwin32.win32importproc(aprocdef:tprocdef;const func,module : string;index : longint;const name : string);
+ var
+ hp1 : timportlist;
+ hp2 : twin32imported_item;
+ hs : string;
+ begin
+ { procdef or funcname must be give, not both }
+ if assigned(aprocdef) and (func<>'') then
+ internalerror(200411161);
+ { append extension if required }
+ hs:=AddExtension(module,target_info.sharedlibext);
+ { search for the module }
+ hp1:=timportlist(current_module.imports.first);
+ while assigned(hp1) do
+ begin
+ if hs=hp1.dllname^ then
+ break;
+ hp1:=timportlist(hp1.next);
+ end;
+ { generate a new item ? }
+ if not(assigned(hp1)) then
+ begin
+ hp1:=timportlist.create(hs);
+ current_module.imports.concat(hp1);
+ end;
+ { search for reuse of old import item }
+ if assigned(aprocdef) then
+ begin
+ hp2:=twin32imported_item(hp1.imported_items.first);
+ while assigned(hp2) do
+ begin
+ if (hp2.procdef=aprocdef) then
+ break;
+ hp2:=twin32imported_item(hp2.next);
+ end;
+ end
+ else
+ begin
+ hp2:=twin32imported_item(hp1.imported_items.first);
+ while assigned(hp2) do
+ begin
+ if (hp2.func^=func) then
+ break;
+ hp2:=twin32imported_item(hp2.next);
+ end;
+ end;
+ if not assigned(hp2) then
+ begin
+ hp2:=twin32imported_item.create(func,name,index);
+ hp2.procdef:=aprocdef;
+ hp1.imported_items.concat(hp2);
+ end;
+ end;
+
+
+ procedure timportlibwin32.importprocedure(aprocdef:tprocdef;const module : string;index : longint;const name : string);
+ begin
+ win32importproc(aprocdef,'',module,index,name);
+ end;
+
+
+ procedure timportlibwin32.importprocedure_str(const func,module : string;index : longint;const name : string);
+ begin
+ win32importproc(nil,func,module,index,name);
+ end;
+
+
+ procedure timportlibwin32.importvariable(vs:tglobalvarsym;const name,module:string);
+ begin
+ importvariable_str(vs.mangledname,name,module);
+ end;
+
+
+ procedure timportlibwin32.importvariable_str(const s:string;const name,module:string);
+ var
+ hp1 : timportlist;
+ hp2 : twin32imported_item;
+ hs : string;
+ begin
+ hs:=AddExtension(module,target_info.sharedlibext);
+ { search for the module }
+ hp1:=timportlist(current_module.imports.first);
+ while assigned(hp1) do
+ begin
+ if hs=hp1.dllname^ then
+ break;
+ hp1:=timportlist(hp1.next);
+ end;
+ { generate a new item ? }
+ if not(assigned(hp1)) then
+ begin
+ hp1:=timportlist.create(hs);
+ current_module.imports.concat(hp1);
+ end;
+ hp2:=twin32imported_item.create_var(s,name);
+ hp2.procdef:=nil;
+ hp1.imported_items.concat(hp2);
+ end;
+
+ procedure timportlibwin32.generatenasmlib;
+ var
+ hp1 : timportlist;
+ hp2 : twin32imported_item;
+ begin
+ new_section(asmlist[al_imports],sec_code,'',0);
+ hp1:=timportlist(current_module.imports.first);
+ while assigned(hp1) do
+ begin
+ hp2:=twin32imported_item(hp1.imported_items.first);
+ while assigned(hp2) do
+ begin
+ asmlist[al_imports].concat(tai_directive.create(asd_extern,hp2.func^));
+ asmlist[al_imports].concat(tai_directive.create(asd_nasm_import,hp2.func^+' '+hp1.dllname^+' '+hp2.name^));
+ hp2:=twin32imported_item(hp2.next);
+ end;
+ hp1:=timportlist(hp1.next);
+ end;
+ end;
+
+
+ procedure timportlibwin32.generatesmartlib;
+ var
+ hp1 : timportlist;
+ mangledstring : string;
+ importname : string;
+ suffix : integer;
+ hp2 : twin32imported_item;
+ lhead,lname,lcode, {$ifdef ARM} lpcode, {$endif ARM}
+ lidata4,lidata5 : tasmlabel;
+ href : treference;
+ begin
+ if (target_asm.id in [as_i386_masm,as_i386_tasm,as_i386_nasmwin32]) then
+ begin
+ generatenasmlib;
+ exit;
+ end;
+ hp1:=timportlist(current_module.imports.first);
+ while assigned(hp1) do
+ begin
+ { Get labels for the sections }
+ objectlibrary.getdatalabel(lhead);
+ objectlibrary.getdatalabel(lname);
+ objectlibrary.getaddrlabel(lidata4);
+ objectlibrary.getaddrlabel(lidata5);
+ { create header for this importmodule }
+ asmlist[al_imports].concat(Tai_cutobject.Create_begin);
+ new_section(asmlist[al_imports],sec_idata2,'',0);
+ asmlist[al_imports].concat(Tai_label.Create(lhead));
+ { pointer to procedure names }
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(lidata4));
+ { two empty entries follow }
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+ { pointer to dll name }
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(lname));
+ { pointer to fixups }
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(lidata5));
+ { first write the name references }
+ new_section(asmlist[al_imports],sec_idata4,'',0);
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+ asmlist[al_imports].concat(Tai_label.Create(lidata4));
+ { then the addresses and create also the indirect jump }
+ new_section(asmlist[al_imports],sec_idata5,'',0);
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+ asmlist[al_imports].concat(Tai_label.Create(lidata5));
+
+ { create procedures }
+ hp2:=twin32imported_item(hp1.imported_items.first);
+ while assigned(hp2) do
+ begin
+ { insert cuts }
+ asmlist[al_imports].concat(Tai_cutobject.Create);
+ { create indirect jump }
+ if not hp2.is_var then
+ begin
+ objectlibrary.getjumplabel(lcode);
+ {$ifdef ARM}
+ objectlibrary.getjumplabel(lpcode);
+ {$endif ARM}
+ { place jump in al_procedures, insert a code section in the
+ al_imports to reduce the amount of .s files (PFV) }
+ new_section(asmlist[al_imports],sec_code,'',0);
+ if assigned(hp2.procdef) then
+ mangledstring:=hp2.procdef.mangledname
+ else
+ mangledstring:=hp2.func^;
+ asmlist[al_imports].concat(Tai_symbol.Createname_global(mangledstring,AT_FUNCTION,0));
+ asmlist[al_imports].concat(Tai_function_name.Create(''));
+ {$ifdef ARM}
+ reference_reset_symbol(href,lpcode,0);
+ asmlist[al_imports].concat(Taicpu.op_reg_ref(A_LDR,NR_R12,href));
+ reference_reset_base(href,NR_R12,0);
+ asmlist[al_imports].concat(Taicpu.op_reg_ref(A_LDR,NR_R15,href));
+ asmlist[al_imports].concat(Tai_label.Create(lpcode));
+ reference_reset_symbol(href,lcode,0);
+ asmlist[al_imports].concat(tai_const.create_sym_offset(href.symbol,href.offset));
+ {$else ARM}
+ reference_reset_symbol(href,lcode,0);
+ asmlist[al_imports].concat(Taicpu.Op_ref(A_JMP,S_NO,href));
+ asmlist[al_imports].concat(Tai_align.Create_op(4,$90));
+ {$endif ARM}
+ end;
+ { create head link }
+ new_section(asmlist[al_imports],sec_idata7,'',0);
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(lhead));
+ { fixup }
+ objectlibrary.getjumplabel(tasmlabel(hp2.lab));
+ new_section(asmlist[al_imports],sec_idata4,'',0);
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(hp2.lab));
+ { add jump field to al_imports }
+ new_section(asmlist[al_imports],sec_idata5,'',0);
+ if hp2.is_var then
+ asmlist[al_imports].concat(Tai_symbol.Createname_global(hp2.func^,AT_FUNCTION,0))
+ else
+ asmlist[al_imports].concat(Tai_label.Create(lcode));
+ if (cs_debuginfo in aktmoduleswitches) then
+ begin
+ if assigned(hp2.name) then
+ begin
+ importname:='__imp_'+hp2.name^;
+ suffix:=0;
+ while assigned(objectlibrary.getasmsymbol(importname)) do
+ begin
+ inc(suffix);
+ importname:='__imp_'+hp2.name^+'_'+tostr(suffix);
+ end;
+ asmlist[al_imports].concat(tai_symbol.createname(importname,AT_FUNCTION,4));
+ end
+ else
+ begin
+ importname:='__imp_by_ordinal'+tostr(hp2.ordnr);
+ suffix:=0;
+ while assigned(objectlibrary.getasmsymbol(importname)) do
+ begin
+ inc(suffix);
+ importname:='__imp_by_ordinal'+tostr(hp2.ordnr)+'_'+tostr(suffix);
+ end;
+ asmlist[al_imports].concat(tai_symbol.createname(importname,AT_FUNCTION,4));
+ end;
+ end;
+ if hp2.name^<>'' then
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(hp2.lab))
+ else
+ asmlist[al_imports].concat(Tai_const.Create_32bit(longint($80000000) or longint(hp2.ordnr)));
+ { finally the import information }
+ new_section(asmlist[al_imports],sec_idata6,'',0);
+ asmlist[al_imports].concat(Tai_label.Create(hp2.lab));
+ asmlist[al_imports].concat(Tai_const.Create_16bit(hp2.ordnr));
+ asmlist[al_imports].concat(Tai_string.Create(hp2.name^+#0));
+ asmlist[al_imports].concat(Tai_align.Create_op(2,0));
+ hp2:=twin32imported_item(hp2.next);
+ end;
+
+ { write final section }
+ asmlist[al_imports].concat(Tai_cutobject.Create_end);
+ { end of name references }
+ new_section(asmlist[al_imports],sec_idata4,'',0);
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+ { end if addresses }
+ new_section(asmlist[al_imports],sec_idata5,'',0);
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+ { dllname }
+ new_section(asmlist[al_imports],sec_idata7,'',0);
+ asmlist[al_imports].concat(Tai_label.Create(lname));
+ asmlist[al_imports].concat(Tai_string.Create(hp1.dllname^+#0));
+
+ hp1:=timportlist(hp1.next);
+ end;
+ end;
+
+
+ procedure timportlibwin32.generatelib;
+ var
+ hp1 : timportlist;
+ hp2 : twin32imported_item;
+ l1,l2,l3,l4 {$ifdef ARM} ,l5 {$endif ARM} : tasmlabel;
+ mangledstring : string;
+ importname : string;
+ suffix : integer;
+ href : treference;
+ begin
+ if (target_asm.id in [as_i386_masm,as_i386_tasm,as_i386_nasmwin32]) then
+ begin
+ generatenasmlib;
+ exit;
+ end;
+ hp1:=timportlist(current_module.imports.first);
+ while assigned(hp1) do
+ begin
+ { align al_procedures for the jumps }
+ new_section(asmlist[al_imports],sec_code,'',sizeof(aint));
+ { Get labels for the sections }
+ objectlibrary.getjumplabel(l1);
+ objectlibrary.getjumplabel(l2);
+ objectlibrary.getjumplabel(l3);
+ new_section(asmlist[al_imports],sec_idata2,'',0);
+ { pointer to procedure names }
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(l2));
+ { two empty entries follow }
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+ { pointer to dll name }
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(l1));
+ { pointer to fixups }
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(l3));
+
+ { only create one section for each else it will
+ create a lot of idata* }
+
+ { first write the name references }
+ new_section(asmlist[al_imports],sec_idata4,'',0);
+ asmlist[al_imports].concat(Tai_label.Create(l2));
+
+ hp2:=twin32imported_item(hp1.imported_items.first);
+ while assigned(hp2) do
+ begin
+ objectlibrary.getjumplabel(tasmlabel(hp2.lab));
+ if hp2.name^<>'' then
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(hp2.lab))
+ else
+ asmlist[al_imports].concat(Tai_const.Create_32bit(longint($80000000) or hp2.ordnr));
+ hp2:=twin32imported_item(hp2.next);
+ end;
+ { finalize the names ... }
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+
+ { then the addresses and create also the indirect jump }
+ new_section(asmlist[al_imports],sec_idata5,'',0);
+ asmlist[al_imports].concat(Tai_label.Create(l3));
+ hp2:=twin32imported_item(hp1.imported_items.first);
+ while assigned(hp2) do
+ begin
+ if not hp2.is_var then
+ begin
+ objectlibrary.getjumplabel(l4);
+ {$ifdef ARM}
+ objectlibrary.getjumplabel(l5);
+ {$endif ARM}
+ { create indirect jump and }
+ { place jump in al_procedures }
+ new_section(asmlist[al_imports],sec_code,'',0);
+ if assigned(hp2.procdef) then
+ mangledstring:=hp2.procdef.mangledname
+ else
+ mangledstring:=hp2.func^;
+ asmlist[al_imports].concat(Tai_symbol.Createname_global(mangledstring,AT_FUNCTION,0));
+ asmlist[al_imports].concat(tai_function_name.create(''));
+ {$ifdef ARM}
+ reference_reset_symbol(href,l5,0);
+ asmlist[al_imports].concat(Taicpu.op_reg_ref(A_LDR,NR_R12,href));
+ reference_reset_base(href,NR_R12,0);
+ asmlist[al_imports].concat(Taicpu.op_reg_ref(A_LDR,NR_R15,href));
+ asmlist[al_imports].concat(Tai_label.Create(l5));
+ reference_reset_symbol(href,l4,0);
+ asmlist[al_imports].concat(tai_const.create_sym_offset(href.symbol,href.offset));
+ {$else ARM}
+ reference_reset_symbol(href,l4,0);
+ asmlist[al_imports].concat(Taicpu.Op_ref(A_JMP,S_NO,href));
+ asmlist[al_imports].concat(Tai_align.Create_op(4,$90));
+ {$endif ARM}
+ { add jump field to al_imports }
+ new_section(asmlist[al_imports],sec_idata5,'',0);
+ if (cs_debuginfo in aktmoduleswitches) then
+ begin
+ if assigned(hp2.name) then
+ begin
+ importname:='__imp_'+hp2.name^;
+ suffix:=0;
+ while assigned(objectlibrary.getasmsymbol(importname)) do
+ begin
+ inc(suffix);
+ importname:='__imp_'+hp2.name^+'_'+tostr(suffix);
+ end;
+ asmlist[al_imports].concat(tai_symbol.createname(importname,AT_FUNCTION,4));
+ end
+ else
+ begin
+ importname:='__imp_by_ordinal'+tostr(hp2.ordnr);
+ suffix:=0;
+ while assigned(objectlibrary.getasmsymbol(importname)) do
+ begin
+ inc(suffix);
+ importname:='__imp_by_ordinal'+tostr(hp2.ordnr)+'_'+tostr(suffix);
+ end;
+ asmlist[al_imports].concat(tai_symbol.createname(importname,AT_FUNCTION,4));
+ end;
+ end;
+ asmlist[al_imports].concat(Tai_label.Create(l4));
+ end
+ else
+ begin
+ asmlist[al_imports].concat(Tai_symbol.Createname_global(hp2.func^,AT_DATA,0));
+ end;
+ asmlist[al_imports].concat(Tai_const.Create_rva_sym(hp2.lab));
+ hp2:=twin32imported_item(hp2.next);
+ end;
+ { finalize the addresses }
+ asmlist[al_imports].concat(Tai_const.Create_32bit(0));
+
+ { finally the import information }
+ new_section(asmlist[al_imports],sec_idata6,'',0);
+ hp2:=twin32imported_item(hp1.imported_items.first);
+ while assigned(hp2) do
+ begin
+ asmlist[al_imports].concat(Tai_label.Create(hp2.lab));
+ { the ordinal number }
+ asmlist[al_imports].concat(Tai_const.Create_16bit(hp2.ordnr));
+ asmlist[al_imports].concat(Tai_string.Create(hp2.name^+#0));
+ asmlist[al_imports].concat(Tai_align.Create_op(2,0));
+ hp2:=twin32imported_item(hp2.next);
+ end;
+ { create import dll name }
+ new_section(asmlist[al_imports],sec_idata7,'',0);
+ asmlist[al_imports].concat(Tai_label.Create(l1));
+ asmlist[al_imports].concat(Tai_string.Create(hp1.dllname^+#0));
+
+ hp1:=timportlist(hp1.next);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TEXPORTLIBWIN32
+*****************************************************************************}
+
+ procedure texportlibwin32.preparelib(const s:string);
+ begin
+ if asmlist[al_exports]=nil then
+ asmlist[al_exports]:=TAAsmoutput.create;
+ EList_indexed:=tList.Create;
+ EList_nonindexed:=tList.Create;
+ objectlibrary.getdatalabel(edatalabel);
+ end;
+
+
+ procedure texportlibwin32.exportvar(hp : texported_item);
+ begin
+ { same code used !! PM }
+ exportprocedure(hp);
+ end;
+
+ var
+ Gl_DoubleIndex:boolean;
+ Gl_DoubleIndexValue:longint;
+
+ function IdxCompare(Item1, Item2: Pointer): Integer;
+ var
+ I1:texported_item absolute Item1;
+ I2:texported_item absolute Item2;
+ begin
+ Result:=I1.index-I2.index;
+ if(Result=0)and(Item1<>Item2)then
+ begin
+ Gl_DoubleIndex:=true;
+ Gl_DoubleIndexValue:=I1.index;
+ end;
+ end;
+
+
+ procedure texportlibwin32.exportprocedure(hp : texported_item);
+ begin
+ if ((hp.options and eo_index)<>0)and((hp.index<=0) or (hp.index>$ffff)) then
+ begin
+ message1(parser_e_export_invalid_index,tostr(hp.index));
+ exit;
+ end;
+ if hp.options and eo_index=eo_index then
+ EList_indexed.Add(hp)
+ else
+ EList_nonindexed.Add(hp);
+ end;
+
+
+ procedure texportlibwin32.exportfromlist(hp : texported_item);
+ //formerly texportlibwin32.exportprocedure
+ { must be ordered at least for win32 !! }
+ var
+ hp2 : texported_item;
+ begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if hp2=nil then
+ current_module._exports.concat(hp)
+ else
+ begin
+ if hp2.name^=hp.name^ then
+ begin
+ { this is not allowed !! }
+ message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ current_module._exports.insertbefore(hp,hp2);
+ end;
+ end;
+
+
+ procedure texportlibwin32.generatelib;
+ var
+ ordinal_base,ordinal_max,ordinal_min : longint;
+ current_index : longint;
+ entries,named_entries : longint;
+ name_label,dll_name_label,export_address_table : tasmlabel;
+ export_name_table_pointers,export_ordinal_table : tasmlabel;
+ hp,hp2 : texported_item;
+ temtexport : TLinkedList;
+ address_table,name_table_pointers,
+ name_table,ordinal_table : TAAsmoutput;
+ i,autoindex,ni_high : longint;
+ hole : boolean;
+
+ begin
+ Gl_DoubleIndex:=false;
+ ELIst_indexed.Sort(@IdxCompare);
+
+ if Gl_DoubleIndex then
+ begin
+ message1(parser_e_export_ordinal_double,tostr(Gl_DoubleIndexValue));
+ EList_indexed.Free;
+ EList_nonindexed.Free;
+ exit;
+ end;
+
+ autoindex:=1;
+ while EList_nonindexed.Count>0 do
+ begin
+ hole:=(EList_indexed.Count>0)and(texported_item(EList_indexed.Items[0]).index>1);
+ if not hole then
+ for i:=autoindex to pred(EList_indexed.Count)do
+ if texported_item(EList_indexed.Items[i]).index-texported_item(EList_indexed.Items[pred(i)]).index>1 then
+ begin
+ autoindex:=succ(texported_item(EList_indexed.Items[pred(i)]).index);
+ hole:=true;
+ break;
+ end;
+ ni_high:=pred(EList_nonindexed.Count);
+ if not hole then
+ begin
+ autoindex:=succ(EList_indexed.Count);
+ EList_indexed.Add(EList_nonindexed.Items[ni_high]);
+ end
+ else
+ EList_indexed.Insert(pred(AutoIndex),EList_nonindexed.Items[ni_high]);
+ EList_nonindexed.Delete(ni_high);
+ texported_item(EList_indexed.Items[pred(AutoIndex)]).index:=autoindex;
+ end;
+ EList_nonindexed.Free;
+ for i:=0 to pred(EList_indexed.Count)do
+ exportfromlist(texported_item(EList_indexed.Items[i]));
+ EList_indexed.Free;
+
+ if (target_asm.id in [as_i386_masm,as_i386_tasm,as_i386_nasmwin32]) then
+ begin
+ generatenasmlib;
+ exit;
+ end;
+
+ hp:=texported_item(current_module._exports.first);
+ if not assigned(hp) then
+ exit;
+
+ ordinal_max:=0;
+ ordinal_min:=$7FFFFFFF;
+ entries:=0;
+ named_entries:=0;
+ objectlibrary.getjumplabel(dll_name_label);
+ objectlibrary.getjumplabel(export_address_table);
+ objectlibrary.getjumplabel(export_name_table_pointers);
+ objectlibrary.getjumplabel(export_ordinal_table);
+
+ { count entries }
+ while assigned(hp) do
+ begin
+ inc(entries);
+ if (hp.index>ordinal_max) then
+ ordinal_max:=hp.index;
+ if (hp.index>0) and (hp.index<ordinal_min) then
+ ordinal_min:=hp.index;
+ if assigned(hp.name) then
+ inc(named_entries);
+ hp:=texported_item(hp.next);
+ end;
+
+ { no support for higher ordinal base yet !! }
+ ordinal_base:=1;
+ current_index:=ordinal_base;
+ { we must also count the holes !! }
+ entries:=ordinal_max-ordinal_base+1;
+
+ new_section(asmlist[al_exports],sec_edata,'',0);
+ { create label to reference from main so smartlink will include
+ the .edata section }
+ asmlist[al_exports].concat(Tai_symbol.Create_global(edatalabel,0));
+ { export flags }
+ asmlist[al_exports].concat(Tai_const.Create_32bit(0));
+ { date/time stamp }
+ asmlist[al_exports].concat(Tai_const.Create_32bit(0));
+ { major version }
+ asmlist[al_exports].concat(Tai_const.Create_16bit(0));
+ { minor version }
+ asmlist[al_exports].concat(Tai_const.Create_16bit(0));
+ { pointer to dll name }
+ asmlist[al_exports].concat(Tai_const.Create_rva_sym(dll_name_label));
+ { ordinal base normally set to 1 }
+ asmlist[al_exports].concat(Tai_const.Create_32bit(ordinal_base));
+ { number of entries }
+ asmlist[al_exports].concat(Tai_const.Create_32bit(entries));
+ { number of named entries }
+ asmlist[al_exports].concat(Tai_const.Create_32bit(named_entries));
+ { address of export address table }
+ asmlist[al_exports].concat(Tai_const.Create_rva_sym(export_address_table));
+ { address of name pointer pointers }
+ asmlist[al_exports].concat(Tai_const.Create_rva_sym(export_name_table_pointers));
+ { address of ordinal number pointers }
+ asmlist[al_exports].concat(Tai_const.Create_rva_sym(export_ordinal_table));
+ { the name }
+ asmlist[al_exports].concat(Tai_label.Create(dll_name_label));
+ if st='' then
+ asmlist[al_exports].concat(Tai_string.Create(current_module.modulename^+target_info.sharedlibext+#0))
+ else
+ asmlist[al_exports].concat(Tai_string.Create(st+target_info.sharedlibext+#0));
+
+ { export address table }
+ address_table:=TAAsmoutput.create;
+ address_table.concat(Tai_align.Create_op(4,0));
+ address_table.concat(Tai_label.Create(export_address_table));
+ name_table_pointers:=TAAsmoutput.create;
+ name_table_pointers.concat(Tai_align.Create_op(4,0));
+ name_table_pointers.concat(Tai_label.Create(export_name_table_pointers));
+ ordinal_table:=TAAsmoutput.create;
+ ordinal_table.concat(Tai_align.Create_op(4,0));
+ ordinal_table.concat(Tai_label.Create(export_ordinal_table));
+ name_table:=TAAsmoutput.Create;
+ name_table.concat(Tai_align.Create_op(4,0));
+ { write each address }
+ hp:=texported_item(current_module._exports.first);
+ while assigned(hp) do
+ begin
+ if (hp.options and eo_name)<>0 then
+ begin
+ objectlibrary.getjumplabel(name_label);
+ name_table_pointers.concat(Tai_const.Create_rva_sym(name_label));
+ ordinal_table.concat(Tai_const.Create_16bit(hp.index-ordinal_base));
+ name_table.concat(Tai_align.Create_op(2,0));
+ name_table.concat(Tai_label.Create(name_label));
+ name_table.concat(Tai_string.Create(hp.name^+#0));
+ end;
+ hp:=texported_item(hp.next);
+ end;
+ { order in increasing ordinal values }
+ { into temtexport list }
+ temtexport:=TLinkedList.Create;
+ hp:=texported_item(current_module._exports.first);
+ while assigned(hp) do
+ begin
+ current_module._exports.remove(hp);
+ hp2:=texported_item(temtexport.first);
+ while assigned(hp2) and (hp.index>hp2.index) do
+ hp2:=texported_item(hp2.next);
+ if hp2=nil then
+ temtexport.concat(hp)
+ else
+ temtexport.insertbefore(hp,hp2);
+ hp:=texported_item(current_module._exports.first);;
+ end;
+
+ { write the export adress table }
+ current_index:=ordinal_base;
+ hp:=texported_item(temtexport.first);
+ while assigned(hp) do
+ begin
+ { fill missing values }
+ while current_index<hp.index do
+ begin
+ address_table.concat(Tai_const.Create_32bit(0));
+ inc(current_index);
+ end;
+ case hp.sym.typ of
+ globalvarsym :
+ address_table.concat(Tai_const.Createname_rva(tglobalvarsym(hp.sym).mangledname));
+ typedconstsym :
+ address_table.concat(Tai_const.Createname_rva(ttypedconstsym(hp.sym).mangledname));
+ procsym :
+ address_table.concat(Tai_const.Createname_rva(tprocsym(hp.sym).first_procdef.mangledname));
+ end;
+ inc(current_index);
+ hp:=texported_item(hp.next);
+ end;
+
+ asmlist[al_exports].concatlist(address_table);
+ asmlist[al_exports].concatlist(name_table_pointers);
+ asmlist[al_exports].concatlist(ordinal_table);
+ asmlist[al_exports].concatlist(name_table);
+ address_table.Free;
+ name_table_pointers.free;
+ ordinal_table.free;
+ name_table.free;
+ temtexport.free;
+ end;
+
+ procedure texportlibwin32.generatenasmlib;
+ var
+ hp : texported_item;
+ p : pchar;
+ s : string;
+ begin
+ new_section(asmlist[al_exports],sec_code,'',0);
+ hp:=texported_item(current_module._exports.first);
+ while assigned(hp) do
+ begin
+ case hp.sym.typ of
+ globalvarsym :
+ s:=tglobalvarsym(hp.sym).mangledname;
+ typedconstsym :
+ s:=ttypedconstsym(hp.sym).mangledname;
+ procsym :
+ s:=tprocsym(hp.sym).first_procdef.mangledname;
+ else
+ s:='';
+ end;
+ p:=strpnew(#9+'export '+s+' '+hp.name^+' '+tostr(hp.index));
+ {asmlist[al_exports].concat(tai_direct.create(p));}
+ hp:=texported_item(hp.next);
+ end;
+ end;
+
+
+{****************************************************************************
+ TLINKERWIN32
+****************************************************************************}
+
+
+Constructor TLinkerWin32.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+Procedure TLinkerWin32.SetDefaultInfo;
+var
+ targetopts: string;
+begin
+ with Info do
+ begin
+ {$ifdef ARM}
+ targetopts:='-m armpe';
+ {$else ARM}
+ targetopts:='-b pe-i386 -m i386pe';
+ {$endif ARM}
+ ExeCmd[1]:='ld '+targetopts+' $OPT $STRIP $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
+ DllCmd[1]:='ld '+targetopts+' $OPT $STRIP --dll $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
+ { ExeCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF';
+ use short forms to avoid 128 char limitation problem }
+ ExeCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
+ ExeCmd[3]:='ld '+targetopts+' $OPT $STRIP $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
+ { DllCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF'; }
+ DllCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
+ DllCmd[3]:='ld '+targetopts+' $OPT $STRIP --dll $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
+ end;
+end;
+
+
+
+Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ HPath : TStringListItem;
+ s,s2 : string;
+ i : integer;
+ linklibcygwin : boolean;
+begin
+ WriteResponseFile:=False;
+ linklibcygwin:=(SharedLibFiles.Find('cygwin')<>nil);
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+MaybeQuoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+ HPath:=TStringListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+MaybeQuoted(HPath.Str)+')');
+ HPath:=TStringListItem(HPath.Next);
+ end;
+
+ { add objectfiles, start with prt0 always }
+ { profiling of shared libraries is currently not supported }
+ LinkRes.Add('INPUT(');
+ if isdll then
+ LinkRes.AddFileName(MaybeQuoted(FindObjectFile('wdllprt0','',false)))
+ else
+ if (cs_profile in aktmoduleswitches) then
+ LinkRes.AddFileName(MaybeQuoted(FindObjectFile('gprt0','',false)))
+ else
+ begin
+ if linklibcygwin then
+ LinkRes.AddFileName(MaybeQuoted(FindObjectFile('wcygprt0','',false)))
+ else
+ LinkRes.AddFileName(MaybeQuoted(FindObjectFile('wprt0','',false)));
+ end;
+
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(MaybeQuoted(s));
+ end;
+ LinkRes.Add(')');
+
+
+ { Write staticlibraries }
+ if (not StaticLibFiles.Empty) or (cs_profile in aktmoduleswitches) then
+ begin
+ LinkRes.Add('GROUP(');
+ if (cs_profile in aktmoduleswitches) then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ LinkRes.Add('-lgmon');
+ LinkRes.Add('-lkernel32');
+ end;
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(MaybeQuoted(s));
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { Write sharedlibraries }
+ if not SharedLibFiles.Empty then
+ begin
+ LinkRes.Add('INPUT(') ;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if FindLibraryFile(s,target_info.staticClibprefix,target_info.staticClibext,s2) then
+ begin
+ LinkRes.Add(MaybeQuoted(s2));
+ continue;
+ end;
+ if pos(target_info.sharedlibprefix,s)=1 then
+ s:=copy(s,length(target_info.sharedlibprefix)+1,255);
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end;
+ LinkRes.Add(')');
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerWin32.MakeExecutable:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ cmds,i : longint;
+ AsBinStr : string[80];
+ StripStr,
+ RelocStr,
+ AppTypeStr,
+ ImageBaseStr : string[40];
+begin
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ RelocStr:='';
+ AppTypeStr:='';
+ ImageBaseStr:='';
+ StripStr:='';
+ AsBinStr:=FindUtil(utilsprefix+'as');
+ if RelocSection then
+ RelocStr:='--base-file base.$$$';
+ if target_info.system in [system_arm_wince,system_i386_wince] then
+ begin
+ AppTypeStr:='--subsystem wince';
+ if apptype <> app_gui then
+ AppTypeStr:=AppTypeStr + ' --entry=mainCRTStartup';
+ end
+ else
+ if apptype=app_gui then
+ AppTypeStr:='--subsystem windows';
+ if assigned(DLLImageBase) then
+ ImageBaseStr:='--image-base=0x'+DLLImageBase^;
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ success:=false;
+ if RelocSection or (not Deffile.empty) then
+ cmds:=3
+ else
+ cmds:=1;
+ for i:=1 to cmds do
+ begin
+ SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$APPTYPE',AppTypeStr);
+ Replace(cmdstr,'$ASBIN',AsbinStr);
+ Replace(cmdstr,'$RELOC',RelocStr);
+ Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ if not DefFile.Empty then
+ begin
+ DefFile.WriteFile;
+ Replace(cmdstr,'$DEF','-d '+maybequoted(deffile.fname));
+ end
+ else
+ Replace(cmdstr,'$DEF','');
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,(i=1),false);
+ if not success then
+ break;
+ end;
+ end;
+
+{ Post process }
+ if success then
+ success:=PostProcessExecutable(current_module.exefilename^,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ begin
+ RemoveFile(outputexedir+Info.ResName);
+ RemoveFile('base.$$$');
+ RemoveFile('exp.$$$');
+ RemoveFile('deffile.$$$');
+ end;
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerWin32.MakeSharedLibrary:boolean;
+var
+ binstr : String;
+ cmdstr : TCmdStr;
+ success : boolean;
+ cmds,
+ i : longint;
+ AsBinStr : string[80];
+ StripStr,
+ RelocStr,
+ AppTypeStr,
+ ImageBaseStr : string[40];
+begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_extern in aktglobalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Create some replacements }
+ RelocStr:='';
+ AppTypeStr:='';
+ ImageBaseStr:='';
+ StripStr:='';
+ AsBinStr:=FindUtil(utilsprefix+'as');
+ if RelocSection then
+ RelocStr:='--base-file base.$$$';
+ if apptype=app_gui then
+ AppTypeStr:='--subsystem windows';
+ if assigned(DLLImageBase) then
+ ImageBaseStr:='--image-base=0x'+DLLImageBase^;
+ if (cs_link_strip in aktglobalswitches) then
+ StripStr:='-s';
+
+{ Write used files and libraries }
+ WriteResponseFile(true);
+
+{ Call linker }
+ success:=false;
+ if RelocSection or (not Deffile.empty) then
+ cmds:=3
+ else
+ cmds:=1;
+ for i:=1 to cmds do
+ begin
+ SplitBinCmd(Info.DllCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$APPTYPE',AppTypeStr);
+ Replace(cmdstr,'$ASBIN',AsbinStr);
+ Replace(cmdstr,'$RELOC',RelocStr);
+ Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ if not DefFile.Empty then
+ begin
+ DefFile.WriteFile;
+ Replace(cmdstr,'$DEF','-d '+maybequoted(deffile.fname));
+ end
+ else
+ Replace(cmdstr,'$DEF','');
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,(i=1),false);
+ if not success then
+ break;
+ end;
+ end;
+
+{ Post process }
+ if success then
+ success:=PostProcessExecutable(current_module.sharedlibfilename^,true);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_extern in aktglobalswitches) then
+ begin
+ RemoveFile(outputexedir+Info.ResName);
+ RemoveFile('base.$$$');
+ RemoveFile('exp.$$$');
+ RemoveFile('deffile.$$$');
+ end;
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+
+function tlinkerwin32.postprocessexecutable(const fn : string;isdll:boolean):boolean;
+type
+ tdosheader = packed record
+ e_magic : word;
+ e_cblp : word;
+ e_cp : word;
+ e_crlc : word;
+ e_cparhdr : word;
+ e_minalloc : word;
+ e_maxalloc : word;
+ e_ss : word;
+ e_sp : word;
+ e_csum : word;
+ e_ip : word;
+ e_cs : word;
+ e_lfarlc : word;
+ e_ovno : word;
+ e_res : array[0..3] of word;
+ e_oemid : word;
+ e_oeminfo : word;
+ e_res2 : array[0..9] of word;
+ e_lfanew : longint;
+ end;
+ tpeheader = packed record
+ PEMagic : array[0..3] of char;
+ Machine : word;
+ NumberOfSections : word;
+ TimeDateStamp : longint;
+ PointerToSymbolTable : longint;
+ NumberOfSymbols : longint;
+ SizeOfOptionalHeader : word;
+ Characteristics : word;
+ Magic : word;
+ MajorLinkerVersion : byte;
+ MinorLinkerVersion : byte;
+ SizeOfCode : longint;
+ SizeOfInitializedData : longint;
+ SizeOfUninitializedData : longint;
+ AddressOfEntryPoint : longint;
+ BaseOfCode : longint;
+ BaseOfData : longint;
+ ImageBase : longint;
+ SectionAlignment : longint;
+ FileAlignment : longint;
+ MajorOperatingSystemVersion : word;
+ MinorOperatingSystemVersion : word;
+ MajorImageVersion : word;
+ MinorImageVersion : word;
+ MajorSubsystemVersion : word;
+ MinorSubsystemVersion : word;
+ Reserved1 : longint;
+ SizeOfImage : longint;
+ SizeOfHeaders : longint;
+ CheckSum : longint;
+ Subsystem : word;
+ DllCharacteristics : word;
+ SizeOfStackReserve : longint;
+ SizeOfStackCommit : longint;
+ SizeOfHeapReserve : longint;
+ SizeOfHeapCommit : longint;
+ LoaderFlags : longint;
+ NumberOfRvaAndSizes : longint;
+ DataDirectory : array[1..$80] of byte;
+ end;
+ tcoffsechdr=packed record
+ name : array[0..7] of char;
+ vsize : longint;
+ rvaofs : longint;
+ datalen : longint;
+ datapos : longint;
+ relocpos : longint;
+ lineno1 : longint;
+ nrelocs : word;
+ lineno2 : word;
+ flags : longint;
+ end;
+ psecfill=^TSecfill;
+ TSecfill=record
+ fillpos,
+ fillsize : longint;
+ next : psecfill;
+ end;
+var
+ f : file;
+ cmdstr : string;
+ dosheader : tdosheader;
+ peheader : tpeheader;
+ firstsecpos,
+ maxfillsize,
+ l,peheaderpos : longint;
+ coffsec : tcoffsechdr;
+ secroot,hsecroot : psecfill;
+ zerobuf : pointer;
+begin
+ postprocessexecutable:=false;
+ { when -s is used or it's a dll then quit }
+ if (cs_link_extern in aktglobalswitches) then
+ begin
+ case apptype of
+ app_native :
+ cmdstr:='--subsystem native';
+ app_gui :
+ cmdstr:='--subsystem gui';
+ app_cui :
+ cmdstr:='--subsystem console';
+ end;
+ if dllversion<>'' then
+ cmdstr:=cmdstr+' --version '+dllversion;
+ cmdstr:=cmdstr+' --input '+maybequoted(fn);
+ cmdstr:=cmdstr+' --stack '+tostr(stacksize);
+ DoExec(FindUtil(utilsprefix+'postw32'),cmdstr,false,false);
+ postprocessexecutable:=true;
+ exit;
+ end;
+ { open file }
+ assign(f,fn);
+ {$I-}
+ reset(f,1);
+ if ioresult<>0 then
+ Message1(execinfo_f_cant_open_executable,fn);
+ { read headers }
+ blockread(f,dosheader,sizeof(tdosheader));
+ peheaderpos:=dosheader.e_lfanew;
+ seek(f,peheaderpos);
+ blockread(f,peheader,sizeof(tpeheader));
+ { write info }
+ Message1(execinfo_x_codesize,tostr(peheader.SizeOfCode));
+ Message1(execinfo_x_initdatasize,tostr(peheader.SizeOfInitializedData));
+ Message1(execinfo_x_uninitdatasize,tostr(peheader.SizeOfUninitializedData));
+ { change stack size (PM) }
+ { I am not sure that the default value is adequate !! }
+ peheader.SizeOfStackReserve:=stacksize;
+ { change the header }
+ { sub system }
+ { gui=2 }
+ { cui=3 }
+ { wincegui=9 }
+ if target_info.system in [system_arm_wince,system_i386_wince] then
+ peheader.Subsystem:=9
+ else
+ case apptype of
+ app_native :
+ peheader.Subsystem:=1;
+ app_gui :
+ peheader.Subsystem:=2;
+ app_cui :
+ peheader.Subsystem:=3;
+ end;
+ if dllversion<>'' then
+ begin
+ peheader.MajorImageVersion:=dllmajor;
+ peheader.MinorImageVersion:=dllminor;
+ end;
+ { reset timestamp }
+ peheader.TimeDateStamp:=0;
+ { write header back }
+ seek(f,peheaderpos);
+ blockwrite(f,peheader,sizeof(tpeheader));
+ if ioresult<>0 then
+ Message1(execinfo_f_cant_process_executable,fn);
+ seek(f,peheaderpos);
+ blockread(f,peheader,sizeof(tpeheader));
+ { write the value after the change }
+ Message1(execinfo_x_stackreserve,tostr(peheader.SizeOfStackReserve));
+ Message1(execinfo_x_stackcommit,tostr(peheader.SizeOfStackCommit));
+ { read section info }
+ maxfillsize:=0;
+ firstsecpos:=0;
+ secroot:=nil;
+ for l:=1 to peheader.NumberOfSections do
+ begin
+ blockread(f,coffsec,sizeof(tcoffsechdr));
+ if coffsec.datapos>0 then
+ begin
+ if secroot=nil then
+ firstsecpos:=coffsec.datapos;
+ new(hsecroot);
+ hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
+ hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
+ hsecroot^.next:=secroot;
+ secroot:=hsecroot;
+ if secroot^.fillsize>maxfillsize then
+ maxfillsize:=secroot^.fillsize;
+ end;
+ end;
+ if firstsecpos>0 then
+ begin
+ l:=firstsecpos-filepos(f);
+ if l>maxfillsize then
+ maxfillsize:=l;
+ end
+ else
+ l:=0;
+ { get zero buffer }
+ getmem(zerobuf,maxfillsize);
+ fillchar(zerobuf^,maxfillsize,0);
+ { zero from sectioninfo until first section }
+ blockwrite(f,zerobuf^,l);
+ { zero section alignments }
+ while assigned(secroot) do
+ begin
+ seek(f,secroot^.fillpos);
+ blockwrite(f,zerobuf^,secroot^.fillsize);
+ hsecroot:=secroot;
+ secroot:=secroot^.next;
+ dispose(hsecroot);
+ end;
+ freemem(zerobuf,maxfillsize);
+ close(f);
+ {$I+}
+ if ioresult<>0 then;
+ postprocessexecutable:=true;
+end;
+
+
+{****************************************************************************
+ TDLLScannerWin32
+****************************************************************************}
+
+ function tDLLScannerWin32.DOSstubOK(var x:cardinal):boolean;
+ begin
+ blockread(f,TheWord,2,loaded);
+ if loaded<>2 then
+ DOSstubOK:=false
+ else
+ begin
+ DOSstubOK:=(TheWord='MZ');
+ seek(f,$3C);
+ blockread(f,x,4,loaded);
+ if(loaded<>4)or(longint(x)>filesize(f))then
+ DOSstubOK:=false;
+ end;
+ end;
+
+ function TDLLScannerWin32.FindDLL(const s:string;var founddll:string):boolean;
+ var
+ sysdir : string;
+ Found : boolean;
+ begin
+ Found:=false;
+ { Look for DLL in:
+ 1. Current dir
+ 2. Library Path
+ 3. windir,windir/system,windir/system32 }
+ Found:=FindFile(s,'.'+source_info.DirSep,founddll);
+ if (not found) then
+ Found:=librarysearchpath.FindFile(s,founddll);
+ if (not found) then
+ begin
+ sysdir:=FixPath(GetEnv('windir'),false);
+ Found:=FindFile(s,sysdir+';'+sysdir+'system'+source_info.DirSep+';'+sysdir+'system32'+source_info.DirSep,founddll);
+ end;
+ if (not found) then
+ begin
+ message1(exec_w_libfile_not_found,s);
+ FoundDll:=s;
+ end;
+ FindDll:=Found;
+ end;
+
+
+ function tDLLScannerWin32.ExtractDllName(Const Name : string) : string;
+ var n : string;
+ begin
+ n:=Upper(SplitExtension(Name));
+ if (n='.DLL') or (n='.DRV') or (n='.EXE') then
+ ExtractDllName:=Name
+ else
+ ExtractDllName:=Name+target_info.sharedlibext;
+ end;
+
+
+
+function tDLLScannerWin32.isSuitableFileType(x:cardinal):longbool;
+ begin
+ seek(f,x);
+ blockread(f,TheWord,2,loaded);
+ isSuitableFileType:=(loaded=2)and(TheWord='PE');
+ end;
+
+
+function tDLLScannerWin32.GetEdata(HeaderEntry:cardinal):longbool;
+ type
+ TObjInfo=packed record
+ ObjName:array[0..7]of char;
+ VirtSize,
+ VirtAddr,
+ RawSize,
+ RawOffset,
+ Reloc,
+ LineNum:cardinal;
+ RelCount,
+ LineCount:word;
+ flags:cardinal;
+ end;
+ var
+ i:cardinal;
+ ObjOfs:cardinal;
+ Obj:TObjInfo;
+ APE_obj,APE_Optsize:word;
+ ExportRVA:cardinal;
+ delta:cardinal;
+ const
+ IMAGE_SCN_CNT_CODE=$00000020;
+ var
+ _d:dirstr;
+ _n:namestr;
+ _e:extstr;
+ function isUsedFunction(name:pchar):longbool;
+ var
+ hp:tExternalsItem;
+ begin
+ isUsedFunction:=false;
+ hp:=tExternalsItem(current_module.Externals.first);
+ while assigned(hp)do
+ begin
+ if(assigned(hp.data))and(not hp.found)then
+ if hp.data^=StrPas(name)then
+ begin
+ isUsedFunction:=true;
+ hp.found:=true;
+ exit;
+ end;
+ hp:=tExternalsItem(hp.next);
+ end;
+ end;
+
+ procedure Store(index:cardinal;name:pchar;isData:longbool);
+ begin
+ if not isUsedFunction(name)then
+ exit;
+ if not(current_module.uses_imports) then
+ begin
+ current_module.uses_imports:=true;
+ importlib.preparelib(current_module.modulename^);
+ end;
+ if IsData then
+ timportlibwin32(importlib).importvariable_str(name,_n,name)
+ else
+ timportlibwin32(importlib).importprocedure_str(name,_n,index,name);
+ end;
+
+ procedure ProcessEdata;
+ type
+ a8=array[0..7]of char;
+ function GetSectionName(rva:cardinal;var Flags:cardinal):a8;
+ var
+ i:cardinal;
+ LocObjOfs:cardinal;
+ LocObj:TObjInfo;
+ begin
+ GetSectionName:='';
+ Flags:=0;
+ LocObjOfs:=APE_OptSize+HeaderOffset+24;
+ for i:=1 to APE_obj do
+ begin
+ seek(f,LocObjOfs);
+ blockread(f,LocObj,sizeof(LocObj));
+ if(rva>=LocObj.VirtAddr)and(rva<=LocObj.VirtAddr+LocObj.RawSize)then
+ begin
+ GetSectionName:=a8(LocObj.ObjName);
+ Flags:=LocObj.flags;
+ end;
+ end;
+ end;
+ var
+ j,Fl:cardinal;
+ ulongval,procEntry:cardinal;
+ Ordinal:word;
+ isData:longbool;
+ ExpDir:packed record
+ flag,
+ stamp:cardinal;
+ Major,
+ Minor:word;
+ Name,
+ Base,
+ NumFuncs,
+ NumNames,
+ AddrFuncs,
+ AddrNames,
+ AddrOrds:cardinal;
+ end;
+ begin
+ with Obj do
+ begin
+ seek(f,RawOffset+delta);
+ blockread(f,ExpDir,sizeof(ExpDir));
+ fsplit(impname,_d,_n,_e);
+ for j:=0 to pred(ExpDir.NumNames)do
+ begin
+{ Don't know why but this gives serious problems with overflow checking on }
+{$IFOPT Q+}
+{$DEFINE OVERFLOW_CHECK_WAS_ON}
+{$ENDIF}
+{$Q-}
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrOrds+j*2);
+ blockread(f,Ordinal,2);
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrFuncs+cardinal(Ordinal)*4);
+ blockread(f,ProcEntry,4);
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrNames+j*4);
+ blockread(f,ulongval,4);
+ seek(f,RawOffset-VirtAddr+ulongval);
+ blockread(f,cstring,sizeof(cstring));
+ isData:=GetSectionName(procentry,Fl)='';
+{$IFDEF OVERFLOW_CHECK_WAS_ON}
+{$Q+}
+{$ENDIF}
+ if not isData then
+ isData:=Fl and IMAGE_SCN_CNT_CODE<>IMAGE_SCN_CNT_CODE;
+ Store(succ(Ordinal),cstring,isData);
+ end;
+ end;
+ end;
+ begin
+ GetEdata:=false;
+ seek(f,HeaderEntry+120);
+ blockread(f,ExportRVA,4);
+ seek(f,HeaderEntry+6);
+ blockread(f,APE_Obj,2);
+ seek(f,HeaderEntry+20);
+ blockread(f,APE_OptSize,2);
+ ObjOfs:=APE_OptSize+HeaderOffset+24;
+ for i:=1 to APE_obj do
+ begin
+ seek(f,ObjOfs);
+ blockread(f,Obj,sizeof(Obj));
+ inc(ObjOfs,sizeof(Obj));
+ with Obj do
+ if(VirtAddr<=ExportRva)and(ExportRva<VirtAddr+VirtSize)then
+ begin
+ delta:=ExportRva-VirtAddr;
+ ProcessEdata;
+ GetEdata:=true;
+ end;
+ end;
+ end;
+
+function tDLLScannerWin32.scan(const binname:string):longbool;
+ var
+ OldFileMode:longint;
+ hs,
+ foundimp : string;
+ begin
+ Scan:=false;
+ { is there already an import library the we will use that one }
+ if FindLibraryFile(binname,target_info.staticClibprefix,target_info.staticClibext,foundimp) then
+ exit;
+ { check if we can find the dll }
+ hs:=AddExtension(binname,target_info.sharedlibext);
+ if not FindDll(hs,impname) then
+ exit;
+ { read the dll file }
+ assign(f,impname);
+ OldFileMode:=filemode;
+ filemode:=0;
+ reset(f,1);
+ filemode:=OldFileMode;
+ if not DOSstubOK(HeaderOffset)then
+ scan:=false
+ else if not isSuitableFileType(HeaderOffset)then
+ scan:=false
+ else
+ scan:=GetEdata(HeaderOffset);
+ close(f);
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_win32_info,TLinkerWin32);
+ RegisterImport(system_i386_win32,TImportLibWin32);
+ RegisterExport(system_i386_win32,TExportLibWin32);
+ RegisterDLLScanner(system_i386_win32,TDLLScannerWin32);
+ RegisterRes(res_gnu_windres_info);
+ RegisterTarget(system_i386_win32_info);
+
+ RegisterExternalLinker(system_i386_wince_info,TLinkerWin32);
+ RegisterImport(system_i386_wince,TImportLibWin32);
+ RegisterExport(system_i386_wince,TExportLibWin32);
+ RegisterDLLScanner(system_i386_wince,TDLLScannerWin32);
+ RegisterTarget(system_i386_wince_info);
+{$endif i386}
+{$ifdef x86_64}
+ RegisterExternalLinker(system_x64_win64_info,TLinkerWin32);
+ RegisterImport(system_x86_64_win64,TImportLibWin32);
+ RegisterExport(system_x86_64_win64,TExportLibWin32);
+ RegisterDLLScanner(system_x86_64_win64,TDLLScannerWin32);
+ RegisterRes(res_gnu_windres_info);
+ RegisterTarget(system_x64_win64_info);
+{$endif x86_64}
+{$ifdef arm}
+ RegisterExternalLinker(system_arm_wince_info,TLinkerWin32);
+ RegisterImport(system_arm_wince,TImportLibWin32);
+ RegisterExport(system_arm_wince,TExportLibWin32);
+ RegisterRes(res_gnu_wince_windres_info);
+ RegisterTarget(system_arm_wince_info);
+{$endif arm}
+end.
diff --git a/compiler/tgobj.pas b/compiler/tgobj.pas
new file mode 100644
index 0000000000..6412f3e99e
--- /dev/null
+++ b/compiler/tgobj.pas
@@ -0,0 +1,625 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the base object for temp. 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.
+
+ ****************************************************************************
+}
+{#@abstract(Temporary reference allocator unit)
+ Temporary reference allocator unit. This unit contains
+ all which is related to allocating temporary memory
+ space on the stack, as required, by the code generator.
+}
+
+unit tgobj;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ globals,globtype,
+ symtype,
+ cpubase,cpuinfo,cgbase,cgutils,
+ aasmbase,aasmtai;
+
+ type
+ ptemprecord = ^ttemprecord;
+ ttemprecord = record
+ temptype : ttemptype;
+ pos : longint;
+ size : longint;
+ def : tdef;
+ next : ptemprecord;
+ nextfree : ptemprecord; { for faster freeblock checking }
+{$ifdef EXTDEBUG}
+ posinfo,
+ releaseposinfo : tfileposinfo;
+{$endif}
+ end;
+
+
+ {# Generates temporary variables }
+ ttgobj = class
+ private
+ { contains all free temps using nextfree links }
+ tempfreelist : ptemprecord;
+ function alloctemp(list: taasmoutput; size,alignment : longint; temptype : ttemptype; def:tdef) : longint;
+ procedure freetemp(list: taasmoutput; pos:longint;temptypes:ttemptypeset);
+ public
+ { contains all temps }
+ templist : ptemprecord;
+ { Offsets of the first/last temp }
+ firsttemp,
+ lasttemp : longint;
+ direction : shortint;
+ constructor create;
+ {# Clear and free the complete linked list of temporary memory
+ locations. The list is set to nil.}
+ procedure resettempgen;
+ {# Sets the first offset from the frame pointer or stack pointer where
+ the temporary references will be allocated. It is to note that this
+ value should always be negative.
+
+ @param(l start offset where temps will start in stack)
+ }
+ procedure setfirsttemp(l : longint);
+
+ procedure gettemp(list: taasmoutput; size : longint;temptype:ttemptype;var ref : treference);
+ procedure gettemptyped(list: taasmoutput; def:tdef;temptype:ttemptype;var ref : treference);
+ procedure ungettemp(list: taasmoutput; const ref : treference);
+
+ function sizeoftemp(list: taasmoutput; const ref: treference): longint;
+ function changetemptype(list: taasmoutput; const ref:treference;temptype:ttemptype):boolean;
+
+ {# Returns TRUE if the reference ref is allocated in temporary volatile memory space,
+ otherwise returns FALSE.
+
+ @param(ref reference to verify)
+ }
+ function istemp(const ref : treference) : boolean;
+ {# Frees a reference @var(ref) which was allocated in the volatile temporary memory space.
+ The freed space can later be reallocated and reused. If this reference
+ is not in the temporary memory, it is simply not freed.
+ }
+ procedure ungetiftemp(list: taasmoutput; const ref : treference);
+
+ { Allocate space for a local }
+ procedure getlocal(list: taasmoutput; size : longint;def:tdef;var ref : treference);
+ procedure UnGetLocal(list: taasmoutput; const ref : treference);
+ end;
+
+ var
+ tg: ttgobj;
+
+ procedure location_freetemp(list:taasmoutput; const l : tlocation);
+
+
+implementation
+
+ uses
+ cutils,
+ systems,verbose,
+ procinfo
+ ;
+
+
+ const
+ FreeTempTypes = [tt_free,tt_freenoreuse];
+
+{$ifdef EXTDEBUG}
+ TempTypeStr : array[ttemptype] of string[18] = (
+ '<none>',
+ 'free','normal','persistant',
+ 'noreuse','freenoreuse'
+ );
+{$endif EXTDEBUG}
+
+ Used2Free : array[ttemptype] of ttemptype = (
+ tt_none,
+ tt_none,tt_free,tt_free,
+ tt_freenoreuse,tt_none
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure location_freetemp(list:taasmoutput; const l : tlocation);
+ begin
+ if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ tg.ungetiftemp(list,l.reference);
+ end;
+
+
+{*****************************************************************************
+ TTGOBJ
+*****************************************************************************}
+
+ constructor ttgobj.create;
+
+ begin
+ tempfreelist:=nil;
+ templist:=nil;
+ { we could create a new child class for this but I don't if it is worth the effort (FK) }
+{$ifdef powerpc}
+ direction:=1;
+{$else powerpc}
+{$ifdef POWERPC64}
+ direction:=1;
+{$else POWERPC64}
+ direction:=-1;
+{$endif POWERPC64}
+{$endif powerpc}
+ end;
+
+
+ procedure ttgobj.resettempgen;
+ var
+ hp : ptemprecord;
+{$ifdef EXTDEBUG}
+ currpos,
+ lastpos : longint;
+{$endif EXTDEBUG}
+ begin
+{$ifdef EXTDEBUG}
+ lastpos:=lasttemp;
+{$endif EXTDEBUG}
+ { Clear the old templist }
+ while assigned(templist) do
+ begin
+{$ifdef EXTDEBUG}
+ if not(templist^.temptype in FreeTempTypes) then
+ begin
+ Comment(V_Warning,'tgobj: (ResetTempgen) temp at pos '+tostr(templist^.pos)+
+ ' with size '+tostr(templist^.size)+' and type '+TempTypeStr[templist^.temptype]+
+ ' from pos '+tostr(templist^.posinfo.line)+':'+tostr(templist^.posinfo.column)+
+ ' not freed at the end of the procedure');
+ end;
+ if direction=1 then
+ currpos:=templist^.pos+templist^.size
+ else
+ currpos:=templist^.pos;
+ if currpos<>lastpos then
+ begin
+ Comment(V_Warning,'tgobj: (ResetTempgen) temp at pos '+tostr(templist^.pos)+
+ ' with size '+tostr(templist^.size)+' and type '+TempTypeStr[templist^.temptype]+
+ ' from pos '+tostr(templist^.posinfo.line)+':'+tostr(templist^.posinfo.column)+
+ ' was expected at position '+tostr(lastpos));
+ end;
+ if direction=1 then
+ lastpos:=templist^.pos
+ else
+ lastpos:=templist^.pos+templist^.size;
+{$endif EXTDEBUG}
+ hp:=templist;
+ templist:=hp^.next;
+ dispose(hp);
+ end;
+ templist:=nil;
+ tempfreelist:=nil;
+ firsttemp:=0;
+ lasttemp:=0;
+ end;
+
+
+ procedure ttgobj.setfirsttemp(l : longint);
+ begin
+ { this is a negative value normally }
+ if l*direction>=0 then
+ begin
+ if odd(l) then
+ inc(l,direction);
+ end
+ else
+ internalerror(200204221);
+ firsttemp:=l;
+ lasttemp:=l;
+ end;
+
+
+ function ttgobj.AllocTemp(list: taasmoutput; size,alignment : longint; temptype : ttemptype;def : tdef) : longint;
+ var
+ tl,htl,
+ bestslot,bestprev,
+ hprev,hp : ptemprecord;
+ bestsize : longint;
+ freetype : ttemptype;
+ begin
+ AllocTemp:=0;
+ bestprev:=nil;
+ bestslot:=nil;
+ tl:=nil;
+ bestsize:=0;
+
+ if size=0 then
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'tgobj: (AllocTemp) temp of size 0 requested, allocating 4 bytes');
+{$endif}
+ size:=4;
+ end;
+
+ freetype:=Used2Free[temptype];
+ if freetype=tt_none then
+ internalerror(200208201);
+ size:=align(size,alignment);
+ { First check the tmpfreelist, but not when
+ we don't want to reuse an already allocated block }
+ if assigned(tempfreelist) and
+ (temptype<>tt_noreuse) then
+ begin
+ hprev:=nil;
+ hp:=tempfreelist;
+ while assigned(hp) do
+ begin
+{$ifdef EXTDEBUG}
+ if not(hp^.temptype in FreeTempTypes) then
+ Comment(V_Warning,'tgobj: (AllocTemp) temp at pos '+tostr(hp^.pos)+ ' in freelist is not set to tt_free !');
+{$endif}
+ { Check only slots that are
+ - free
+ - share the same type
+ - contain enough space
+ - has a correct alignment }
+ if (hp^.temptype=freetype) and
+ (hp^.def=def) and
+ (hp^.size>=size) and
+ (hp^.pos=align(hp^.pos,alignment)) then
+ begin
+ { Slot is the same size then leave immediatly }
+ if (hp^.size=size) then
+ begin
+ bestprev:=hprev;
+ bestslot:=hp;
+ bestsize:=size;
+ break;
+ end
+ else
+ begin
+ if (bestsize=0) or (hp^.size<bestsize) then
+ begin
+ bestprev:=hprev;
+ bestslot:=hp;
+ bestsize:=hp^.size;
+ end;
+ end;
+ end;
+ hprev:=hp;
+ hp:=hp^.nextfree;
+ end;
+ end;
+ { Reuse an old temp ? }
+ if assigned(bestslot) then
+ begin
+ if bestsize=size then
+ begin
+ tl:=bestslot;
+ { Remove from the tempfreelist }
+ if assigned(bestprev) then
+ bestprev^.nextfree:=tl^.nextfree
+ else
+ tempfreelist:=tl^.nextfree;
+ end
+ else
+ begin
+ { Duplicate bestlost and the block in the list }
+ new(tl);
+ move(bestslot^,tl^,sizeof(ttemprecord));
+ tl^.next:=bestslot^.next;
+ bestslot^.next:=tl;
+ { Now we split the block in 2 parts. Depending on the direction
+ we need to resize the newly inserted block or the old reused block.
+ For direction=1 we can use tl for the new block. For direction=-1 we
+ will be reusing bestslot and resize the new block, that means we need
+ to swap the pointers }
+ if direction=-1 then
+ begin
+ htl:=tl;
+ tl:=bestslot;
+ bestslot:=htl;
+ { Update the tempfreelist to point to the new block }
+ if assigned(bestprev) then
+ bestprev^.nextfree:=bestslot
+ else
+ tempfreelist:=bestslot;
+ end;
+ { Create new block and resize the old block }
+ tl^.size:=size;
+ tl^.nextfree:=nil;
+ { Resize the old block }
+ dec(bestslot^.size,size);
+ inc(bestslot^.pos,size);
+ end;
+ tl^.temptype:=temptype;
+ tl^.def:=def;
+ tl^.nextfree:=nil;
+ end
+ else
+ begin
+ { create a new temp, we need to allocate at least a minimum of
+ 4 bytes, else we get two temps at the same position resulting
+ in problems when finding the corresponding temprecord }
+ if size<4 then
+ size:=4;
+ { now we can create the templist entry }
+ new(tl);
+ tl^.temptype:=temptype;
+ tl^.def:=def;
+
+ { Extend the temp }
+ if direction=-1 then
+ begin
+ lasttemp:=(-align(-lasttemp,alignment))-size;
+ tl^.pos:=lasttemp;
+ end
+ else
+ begin
+ tl^.pos:=align(lasttemp,alignment);
+ lasttemp:=tl^.pos+size;
+ end;
+
+ tl^.size:=size;
+ tl^.next:=templist;
+ tl^.nextfree:=nil;
+ templist:=tl;
+ end;
+{$ifdef EXTDEBUG}
+ tl^.posinfo:=aktfilepos;
+ if assigned(tl^.def) then
+ list.concat(tai_tempalloc.allocinfo(tl^.pos,tl^.size,'allocated with type '+TempTypeStr[tl^.temptype]+' for def '+tl^.def.typename))
+ else
+ list.concat(tai_tempalloc.allocinfo(tl^.pos,tl^.size,'allocated with type '+TempTypeStr[tl^.temptype]));
+{$else}
+ list.concat(tai_tempalloc.alloc(tl^.pos,tl^.size));
+{$endif}
+ AllocTemp:=tl^.pos;
+ end;
+
+
+ procedure ttgobj.FreeTemp(list: taasmoutput; pos:longint;temptypes:ttemptypeset);
+ var
+ hp,hnext,hprev,hprevfree : ptemprecord;
+ begin
+ hp:=templist;
+ hprev:=nil;
+ hprevfree:=nil;
+ while assigned(hp) do
+ begin
+ if (hp^.pos=pos) then
+ begin
+ { check if already freed }
+ if hp^.temptype in FreeTempTypes then
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'tgobj: (FreeTemp) temp at pos '+tostr(pos)+ ' is already free !');
+ list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp is already freed'));
+{$endif}
+ exit;
+ end;
+ { check type that are allowed to be released }
+ if not(hp^.temptype in temptypes) then
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Debug,'tgobj: (Freetemp) temp at pos '+tostr(pos)+ ' has different type ('+TempTypeStr[hp^.temptype]+'), not releasing');
+ list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp has wrong type ('+TempTypeStr[hp^.temptype]+') not releasing'));
+{$endif}
+ exit;
+ end;
+ list.concat(tai_tempalloc.dealloc(hp^.pos,hp^.size));
+ { set this block to free }
+ hp^.temptype:=Used2Free[hp^.temptype];
+ { Update tempfreelist }
+ if assigned(hprevfree) then
+ begin
+ { Concat blocks when the previous block is free and
+ there is no block assigned for a tdef }
+ if assigned(hprev) and
+ (hp^.temptype=tt_free) and
+ not assigned(hp^.def) and
+ (hprev^.temptype=tt_free) and
+ not assigned(hprev^.def) then
+ begin
+ inc(hprev^.size,hp^.size);
+ if direction=1 then
+ hprev^.pos:=hp^.pos;
+ hprev^.next:=hp^.next;
+ dispose(hp);
+ hp:=hprev;
+ end
+ else
+ hprevfree^.nextfree:=hp;
+ end
+ else
+ begin
+ hp^.nextfree:=tempfreelist;
+ tempfreelist:=hp;
+ end;
+ { Concat blocks when the next block is free and
+ there is no block assigned for a tdef }
+ hnext:=hp^.next;
+ if assigned(hnext) and
+ (hp^.temptype=tt_free) and
+ not assigned(hp^.def) and
+ (hnext^.temptype=tt_free) and
+ not assigned(hnext^.def) then
+ begin
+ inc(hp^.size,hnext^.size);
+ if direction=1 then
+ hp^.pos:=hnext^.pos;
+ hp^.nextfree:=hnext^.nextfree;
+ hp^.next:=hnext^.next;
+ dispose(hnext);
+ end;
+ { Stop }
+ exit;
+ end;
+ if (hp^.temptype=tt_free) then
+ hprevfree:=hp;
+ hprev:=hp;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure ttgobj.gettemp(list: taasmoutput; size : longint;temptype:ttemptype;var ref : treference);
+ var
+ varalign : longint;
+ begin
+ varalign:=size_2_align(size);
+ varalign:=used_align(varalign,aktalignment.localalignmin,aktalignment.localalignmax);
+ { can't use reference_reset_base, because that will let tgobj depend
+ on cgobj (PFV) }
+ fillchar(ref,sizeof(ref),0);
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=alloctemp(list,size,varalign,temptype,nil);
+ end;
+
+
+ procedure ttgobj.gettemptyped(list: taasmoutput; def:tdef;temptype:ttemptype;var ref : treference);
+ var
+ varalign : longint;
+ begin
+ varalign:=def.alignment;
+ varalign:=used_align(varalign,aktalignment.localalignmin,aktalignment.localalignmax);
+ { can't use reference_reset_base, because that will let tgobj depend
+ on cgobj (PFV) }
+ fillchar(ref,sizeof(ref),0);
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=alloctemp(list,def.size,varalign,temptype,def);
+ end;
+
+
+ function ttgobj.istemp(const ref : treference) : boolean;
+ begin
+ { ref.index = R_NO was missing
+ led to problems with local arrays
+ with lower bound > 0 (PM) }
+ if direction = 1 then
+ begin
+ istemp:=(ref.base=current_procinfo.framepointer) and
+ (ref.index=NR_NO) and
+ (ref.offset>=firsttemp);
+ end
+ else
+ begin
+ istemp:=(ref.base=current_procinfo.framepointer) and
+ (ref.index=NR_NO) and
+ (ref.offset<firsttemp);
+ end;
+ end;
+
+
+ function ttgobj.sizeoftemp(list: taasmoutput; const ref: treference): longint;
+ var
+ hp : ptemprecord;
+ begin
+ SizeOfTemp := -1;
+ hp:=templist;
+ while assigned(hp) do
+ begin
+ if (hp^.pos=ref.offset) then
+ begin
+ sizeoftemp := hp^.size;
+ exit;
+ end;
+ hp := hp^.next;
+ end;
+{$ifdef EXTDEBUG}
+ comment(v_debug,'tgobj: (SizeOfTemp) temp at pos '+tostr(ref.offset)+' not found !');
+ list.concat(tai_tempalloc.allocinfo(ref.offset,0,'temp not found'));
+{$endif}
+ end;
+
+
+ function ttgobj.ChangeTempType(list: taasmoutput; const ref:treference;temptype:ttemptype):boolean;
+ var
+ hp : ptemprecord;
+ begin
+ ChangeTempType:=false;
+ hp:=templist;
+ while assigned(hp) do
+ begin
+ if (hp^.pos=ref.offset) then
+ begin
+ if hp^.temptype<>tt_free then
+ begin
+{$ifdef EXTDEBUG}
+ if hp^.temptype=temptype then
+ Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
+ ' at pos '+tostr(ref.offset)+ ' is already of the correct type !');
+ list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'type changed to '+TempTypeStr[temptype]));
+{$endif}
+ ChangeTempType:=true;
+ hp^.temptype:=temptype;
+ end
+ else
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
+ ' at pos '+tostr(ref.offset)+ ' is already freed !');
+ list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp is already freed'));
+{$endif}
+ end;
+ exit;
+ end;
+ hp:=hp^.next;
+ end;
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
+ ' at pos '+tostr(ref.offset)+ ' not found !');
+ list.concat(tai_tempalloc.allocinfo(ref.offset,0,'temp not found'));
+{$endif}
+ end;
+
+
+ procedure ttgobj.UnGetTemp(list: taasmoutput; const ref : treference);
+ begin
+ FreeTemp(list,ref.offset,[tt_normal,tt_noreuse,tt_persistent]);
+ end;
+
+
+ procedure ttgobj.UnGetIfTemp(list: taasmoutput; const ref : treference);
+ begin
+ if istemp(ref) then
+ FreeTemp(list,ref.offset,[tt_normal]);
+ end;
+
+
+ procedure ttgobj.getlocal(list: taasmoutput; size : longint;def:tdef;var ref : treference);
+ var
+ varalign : longint;
+ begin
+ varalign:=def.alignment;
+ varalign:=used_align(varalign,aktalignment.localalignmin,aktalignment.localalignmax);
+ { can't use reference_reset_base, because that will let tgobj depend
+ on cgobj (PFV) }
+ fillchar(ref,sizeof(ref),0);
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=alloctemp(list,size,varalign,tt_persistent,nil);
+ end;
+
+
+ procedure ttgobj.UnGetLocal(list: taasmoutput; const ref : treference);
+ begin
+ FreeTemp(list,ref.offset,[tt_persistent]);
+ end;
+
+
+end.
diff --git a/compiler/tokens.pas b/compiler/tokens.pas
new file mode 100644
index 0000000000..53c8f69f2f
--- /dev/null
+++ b/compiler/tokens.pas
@@ -0,0 +1,538 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Tokens used by the compiler
+
+ 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 tokens;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype;
+
+type
+ ttoken=(NOTOKEN,
+ { operators, which can also be overloaded }
+ _PLUS,
+ _MINUS,
+ _STAR,
+ _SLASH,
+ _EQUAL,
+ _GT,
+ _LT,
+ _GTE,
+ _LTE,
+ _SYMDIF,
+ _STARSTAR,
+ _OP_AS,
+ _OP_IN,
+ _OP_IS,
+ _OP_OR,
+ _OP_AND,
+ _OP_DIV,
+ _OP_MOD,
+ _OP_NOT,
+ _OP_SHL,
+ _OP_SHR,
+ _OP_XOR,
+ _ASSIGNMENT,
+ { special chars }
+ _CARET,
+ _UNEQUAL,
+ _LECKKLAMMER,
+ _RECKKLAMMER,
+ _POINT,
+ _COMMA,
+ _LKLAMMER,
+ _RKLAMMER,
+ _COLON,
+ _SEMICOLON,
+ _KLAMMERAFFE,
+ _POINTPOINT,
+ _POINTPOINTPOINT,
+ _PIPE,
+ _AMPERSAND,
+ _EOF,
+ _ID,
+ _NOID,
+ _REALNUMBER,
+ _INTCONST,
+ _CSTRING,
+ _CCHAR,
+ _CWSTRING,
+ _CWCHAR,
+ { C like operators }
+ _PLUSASN,
+ _MINUSASN,
+ _ANDASN,
+ _ORASN,
+ _STARASN,
+ _SLASHASN,
+ _MODASN,
+ _DIVASN,
+ _NOTASN,
+ _XORASN,
+ { Normal words -- ATTENTION: These words must be sorted: }
+ { first in length order, then in alphabetical order. }
+ _C,
+ _AS,
+ _AT,
+ _DO,
+ _IF,
+ _IN,
+ _IS,
+ _OF,
+ _ON,
+ _OR,
+ _TO,
+ _AND,
+ _ASM,
+ _DIV,
+ _END,
+ _FAR,
+ _FOR,
+ _MOD,
+ _NIL,
+ _NOT,
+ _OUT,
+ _SET,
+ _SHL,
+ _SHR,
+ _TRY,
+ _VAR,
+ _XOR,
+ _CASE,
+ _CVAR,
+ _ELSE,
+ _EXIT,
+ _FAIL,
+ _FILE,
+ _GOTO,
+ _NAME,
+ _NEAR,
+ _READ,
+ _SELF,
+ _SYSV,
+ _THEN,
+ _TRUE,
+ _TYPE,
+ _UNIT,
+ _UNIV,
+ _USES,
+ _WITH,
+ _ALIAS,
+ _ARRAY,
+ _BEGIN,
+ _BREAK,
+ _CDECL,
+ _CLASS,
+ _CONST,
+ _FALSE,
+ _FAR16,
+ _INDEX,
+ _LABEL,
+ _RAISE,
+ _UNTIL,
+ _WHILE,
+ _WRITE,
+ _DISPID,
+ _DOWNTO,
+ _EXCEPT,
+ _EXPORT,
+ _INLINE,
+ _LEGACY,
+ _OBJECT,
+ _PACKED,
+ _PASCAL,
+ _PUBLIC,
+ _RECORD,
+ _REPEAT,
+ _RESULT,
+ _STATIC,
+ _STORED,
+ _STRICT,
+ _STRING,
+ _SYSTEM,
+ _ASMNAME,
+ _CPPDECL,
+ _DEFAULT,
+ _DYNAMIC,
+ _EXPORTS,
+ _FINALLY,
+ _FORWARD,
+ _IOCHECK,
+ _LIBRARY,
+ _MESSAGE,
+ _PACKAGE,
+ _PRIVATE,
+ _PROGRAM,
+ _R12BASE,
+ _STDCALL,
+ _SYSCALL,
+ _VARARGS,
+ _VIRTUAL,
+ _ABSOLUTE,
+ _ABSTRACT,
+ _BASESYSV,
+ _CONTAINS,
+ _CONTINUE,
+ _CPPCLASS,
+ _EXTERNAL,
+ _FUNCTION,
+ _LOCATION,
+ _MWPASCAL,
+ _OPERATOR,
+ _OVERLOAD,
+ _OVERRIDE,
+ _PLATFORM,
+ _PROPERTY,
+ _REGISTER,
+ _REQUIRES,
+ _RESIDENT,
+ _SAFECALL,
+ _SYSVBASE,
+ _ASSEMBLER,
+ _INHERITED,
+ _INTERFACE,
+ _INTERRUPT,
+ _NODEFAULT,
+ _OTHERWISE,
+ _PROCEDURE,
+ _PROTECTED,
+ _PUBLISHED,
+ _SOFTFLOAT,
+ _THREADVAR,
+ _DEPRECATED,
+ _DESTRUCTOR,
+ _IMPLEMENTS,
+ _INTERNPROC,
+ _OLDFPCCALL,
+ _OPENSTRING,
+ _CONSTRUCTOR,
+ _INTERNCONST,
+ _REINTRODUCE,
+ _SHORTSTRING,
+ _COMPILERPROC,
+ _FINALIZATION,
+ _NOSTACKFRAME,
+ _DISPINTERFACE,
+ _UNIMPLEMENTED,
+ _IMPLEMENTATION,
+ _INITIALIZATION,
+ _RESOURCESTRING
+ );
+
+const
+ tokenlenmin = 1;
+ tokenlenmax = 14;
+
+ { last operator which can be overloaded, the first_overloaded should
+ be declared directly after NOTOKEN }
+ first_overloaded = succ(NOTOKEN);
+ last_overloaded = _ASSIGNMENT;
+
+type
+ tokenrec=record
+ str : string[tokenlenmax];
+ special : boolean;
+ keyword : tmodeswitch;
+ op : ttoken;
+ end;
+
+ ttokenarray=array[ttoken] of tokenrec;
+ ptokenarray=^ttokenarray;
+
+ tokenidxrec=record
+ first,last : ttoken;
+ end;
+
+ ptokenidx=^ttokenidx;
+ ttokenidx=array[tokenlenmin..tokenlenmax,'A'..'Z'] of tokenidxrec;
+
+const
+ arraytokeninfo : ttokenarray =(
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ { Operators which can be overloaded }
+ (str:'+' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'-' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'*' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'/' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'>' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'<' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'>=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'<=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'><' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'**' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'as' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'in' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'is' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'or' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'and' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'div' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'mod' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'not' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'shl' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'shr' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'xor' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:':=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ { Special chars }
+ (str:'^' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'<>' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'[' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:']' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'.' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:',' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'(' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:')' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:':' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:';' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'@' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'..' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'...' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'|' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'&' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'end of file' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'identifier' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'non identifier';special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const real' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'ordinal const' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const string' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const char' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const wstring' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const wchar' ;special:true ;keyword:m_none;op:NOTOKEN),
+ { C like operators }
+ (str:'+=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'-=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'&=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'|=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'*=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'/=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ { Normal words -- ATTENTION: These words must be sorted: }
+ { first in length order, then in alphabetical order. }
+ (str:'C' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'AS' ;special:false;keyword:m_class;op:_OP_AS),
+ (str:'AT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DO' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'IF' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'IN' ;special:false;keyword:m_all;op:_OP_IN),
+ (str:'IS' ;special:false;keyword:m_class;op:_OP_IS),
+ (str:'OF' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'ON' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OR' ;special:false;keyword:m_all;op:_OP_OR),
+ (str:'TO' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'AND' ;special:false;keyword:m_all;op:_OP_AND),
+ (str:'ASM' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'DIV' ;special:false;keyword:m_all;op:_OP_DIV),
+ (str:'END' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'FAR' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FOR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'MOD' ;special:false;keyword:m_all;op:_OP_MOD),
+ (str:'NIL' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'NOT' ;special:false;keyword:m_all;op:_OP_NOT),
+ (str:'OUT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SET' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'SHL' ;special:false;keyword:m_all;op:_OP_SHL),
+ (str:'SHR' ;special:false;keyword:m_all;op:_OP_SHR),
+ (str:'TRY' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'VAR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'XOR' ;special:false;keyword:m_all;op:_OP_XOR),
+ (str:'CASE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'CVAR' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ELSE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'EXIT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FAIL' ;special:false;keyword:m_none;op:NOTOKEN), { only set within constructors PM }
+ (str:'FILE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'GOTO' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'NAME' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'NEAR' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'READ' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SELF' ;special:false;keyword:m_none;op:NOTOKEN), {set inside methods only PM }
+ (str:'SYSV' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'THEN' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'TRUE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'TYPE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'UNIT' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'UNIV' ;special:false;keyword:m_mac;op:NOTOKEN),
+ (str:'USES' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'WITH' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'ALIAS' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ARRAY' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'BEGIN' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'BREAK' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CDECL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CLASS' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'CONST' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'FALSE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'FAR16' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'INDEX' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'LABEL' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'RAISE' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'UNTIL' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'WHILE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'WRITE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DISPID' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DOWNTO' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'EXCEPT' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'EXPORT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'INLINE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'LEGACY' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'OBJECT' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'PACKED' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'PASCAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PUBLIC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'RECORD' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'REPEAT' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'RESULT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STATIC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STORED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STRICT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STRING' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'SYSTEM' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ASMNAME' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CPPDECL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DEFAULT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DYNAMIC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'EXPORTS' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'FINALLY' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'FORWARD' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'IOCHECK' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'LIBRARY' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'MESSAGE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PACKAGE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PRIVATE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PROGRAM' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'R12BASE' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'STDCALL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SYSCALL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'VARARGS' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'VIRTUAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ABSOLUTE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ABSTRACT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'BASESYSV' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'CONTAINS' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CONTINUE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CPPCLASS' ;special:false;keyword:m_fpc;op:NOTOKEN),
+ (str:'EXTERNAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FUNCTION' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'LOCATION' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'MWPASCAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OPERATOR' ;special:false;keyword:m_fpc;op:NOTOKEN),
+ (str:'OVERLOAD' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OVERRIDE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PLATFORM' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PROPERTY' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'REGISTER' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'REQUIRES' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'RESIDENT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SAFECALL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SYSVBASE' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'ASSEMBLER' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'INHERITED' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'INTERFACE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'INTERRUPT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'NODEFAULT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OTHERWISE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'PROCEDURE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'PROTECTED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PUBLISHED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SOFTFLOAT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'THREADVAR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'DEPRECATED' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'DESTRUCTOR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'IMPLEMENTS' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'INTERNPROC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OLDFPCCALL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OPENSTRING' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CONSTRUCTOR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'INTERNCONST' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'REINTRODUCE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SHORTSTRING' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'COMPILERPROC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FINALIZATION' ;special:false;keyword:m_initfinal;op:NOTOKEN),
+ (str:'NOSTACKFRAME' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DISPINTERFACE' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'UNIMPLEMENTED' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'IMPLEMENTATION';special:false;keyword:m_all;op:NOTOKEN),
+ (str:'INITIALIZATION';special:false;keyword:m_initfinal;op:NOTOKEN),
+ (str:'RESOURCESTRING';special:false;keyword:m_class;op:NOTOKEN)
+ );
+
+
+var
+ tokeninfo:ptokenarray;
+ tokenidx:ptokenidx;
+
+procedure inittokens;
+procedure donetokens;
+procedure create_tokenidx;
+
+
+implementation
+
+procedure create_tokenidx;
+{ create an index with the first and last token for every possible token
+ length, so a search only will be done in that small part }
+var
+ t : ttoken;
+ i : longint;
+ c : char;
+begin
+ fillchar(tokenidx^,sizeof(tokenidx^),0);
+ for t:=low(ttoken) to high(ttoken) do
+ begin
+ if not arraytokeninfo[t].special then
+ begin
+ i:=length(arraytokeninfo[t].str);
+ c:=arraytokeninfo[t].str[1];
+ if ord(tokenidx^[i,c].first)=0 then
+ tokenidx^[i,c].first:=t;
+ tokenidx^[i,c].last:=t;
+ end;
+ end;
+end;
+
+
+procedure inittokens;
+begin
+ if tokenidx = nil then
+ begin
+ tokeninfo:=@arraytokeninfo;
+ new(tokenidx);
+ create_tokenidx;
+ end;
+end;
+
+
+procedure donetokens;
+begin
+ if tokenidx <> nil then
+ begin
+ tokeninfo:=nil;
+ dispose(tokenidx);
+ tokenidx:=nil;
+ end;
+end;
+
+end.
diff --git a/compiler/utils/Makefile b/compiler/utils/Makefile
new file mode 100644
index 0000000000..0d14063a26
--- /dev/null
+++ b/compiler/utils/Makefile
@@ -0,0 +1,2021 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2005/10/20]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-emx i386-watcom i386-netwlibc i386-wince m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd x86_64-win64 arm-linux arm-wince powerpc64-linux
+BSDs = freebsd netbsd openbsd darwin
+UNIXs = linux $(BSDs) solaris qnx
+LIMIT83fs = go32v2 os2 emx watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=../..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPC:=$(shell $(FPCPROG) -PB)
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifneq ($(words $(FPC_COMPILERINFO)),5)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSO)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTO)
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+export OS_TARGET OS_SOURCE CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_PROGRAMS+=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+override INSTALL_FPCPACKAGE=y
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+STATICLIBPREFIX=libp
+RSTEXT=.rst
+ifeq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+endif
+ifeq ($(OS_TARGET),darwin)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+endif
+else
+ifeq ($(OS_TARGET),go32v1)
+PPUEXT=.pp1
+OEXT=.o1
+ASMEXT=.s1
+SMARTEXT=.sl1
+STATICLIBEXT=.a1
+SHAREDLIBEXT=.so1
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+SHORTSUFFIX=wat
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+PPUEXT=.ppw
+OEXT=.ow
+ASMEXT=.sw
+SMARTEXT=.slw
+STATICLIBEXT=.aw
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+PPUEXT=.ppo
+ASMEXT=.so2
+OEXT=.oo2
+AOUTEXT=.out
+SMARTEXT=.sl2
+STATICLIBPREFIX=
+STATICLIBEXT=.ao2
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+PPUEXT=.ppu
+ASMEXT=.asm
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),atari)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nw
+endif
+ifeq ($(OS_TARGET),netwlibc)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nwl
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+endif
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),win32)
+ifeq ($(CROSSBINDIR),)
+ASNAME=asw
+LDNAME=ldw
+ARNAME=arw
+endif
+endif
+endif
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+PPAS=ppas$(SRCBATCHEXT)
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ifndef UPXPROG
+ifeq ($(OS_TARGET),go32v2)
+UPXPROG:=1
+endif
+ifeq ($(OS_TARGET),win32)
+UPXPROG:=1
+endif
+ifdef UPXPROG
+UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(UPXPROG),)
+UPXPROG=
+else
+UPXPROG:=$(firstword $(UPXPROG))
+endif
+else
+UPXPROG=
+endif
+endif
+export UPXPROG
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(CPU_TARGET)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX) -Xc
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+else
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+else
+FPCCPUOPT:=
+endif
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-OG2p3
+endif
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifeq ($(OS_TARGET),linux)
+ifeq ($(FPC_VERSION),1.0.6)
+override FPCOPTDEF+=HASUNIX
+endif
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+EXECPPAS:=@$(PPAS)
+endif
+endif
+.PHONY: fpc_exes
+ifndef CROSSINSTALL
+ifneq ($(TARGET_PROGRAMS),)
+override EXEFILES=$(addsuffix $(EXEEXT),$(TARGET_PROGRAMS))
+override EXEOFILES:=$(addsuffix $(OEXT),$(TARGET_PROGRAMS)) $(addprefix $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_PROGRAMS)))
+override ALLTARGET+=fpc_exes
+override INSTALLEXEFILES+=$(EXEFILES)
+override CLEANEXEFILES+=$(EXEFILES) $(EXEOFILES)
+ifeq ($(OS_TARGET),os2)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))
+endif
+ifeq ($(OS_TARGET),emx)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))
+endif
+endif
+endif
+fpc_exes: $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(EXEFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release
+$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)
+ @$(ECHOREDIR) Compiled > $(FPCMADE)
+fpc_all: $(FPCMADE)
+fpc_smart:
+ $(MAKE) all LINKSMART=1 CREATESMART=1
+fpc_debug:
+ $(MAKE) all DEBUG=1
+fpc_release:
+ $(MAKE) all RELEASE=1
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res
+$(COMPILER_UNITTARGETDIR):
+ $(MKDIRTREE) $(COMPILER_UNITTARGETDIR)
+$(COMPILER_TARGETDIR):
+ $(MKDIRTREE) $(COMPILER_TARGETDIR)
+%$(PPUEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(PPUEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.lpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.dpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%.res: %.rc
+ windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+ $(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILES)
+endif
+ $(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+ $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+ $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+ $(MKDIR) $(INSTALL_LIBDIR)
+ $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+ ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+ $(MKDIR) $(INSTALL_DATADIR)
+ $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+ $(MKDIR) $(INSTALL_SOURCEDIR)
+ $(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+ $(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+ $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+ -$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+ -$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+ -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+ -$(DELTREE) units
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+ -$(DEL) *.o *.ppu *.a
+endif
+ -$(DELTREE) *$(SMARTEXT)
+ -$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+ -$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+ -$(DEL) *$(DEBUGSYMEXT)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+ @$(ECHO)
+ @$(ECHO) == Package info ==
+ @$(ECHO) Package Name..... $(PACKAGE_NAME)
+ @$(ECHO) Package Version.. $(PACKAGE_VERSION)
+ @$(ECHO)
+ @$(ECHO) == Configuration info ==
+ @$(ECHO)
+ @$(ECHO) FPC.......... $(FPC)
+ @$(ECHO) FPC Version.. $(FPC_VERSION)
+ @$(ECHO) Source CPU... $(CPU_SOURCE)
+ @$(ECHO) Target CPU... $(CPU_TARGET)
+ @$(ECHO) Source OS.... $(OS_SOURCE)
+ @$(ECHO) Target OS.... $(OS_TARGET)
+ @$(ECHO) Full Source.. $(FULL_SOURCE)
+ @$(ECHO) Full Target.. $(FULL_TARGET)
+ @$(ECHO) SourceSuffix. $(SOURCESUFFIX)
+ @$(ECHO) TargetSuffix. $(TARGETSUFFIX)
+ @$(ECHO)
+ @$(ECHO) == Directory info ==
+ @$(ECHO)
+ @$(ECHO) Required pkgs... $(REQUIRE_PACKAGES)
+ @$(ECHO)
+ @$(ECHO) Basedir......... $(BASEDIR)
+ @$(ECHO) FPCDir.......... $(FPCDIR)
+ @$(ECHO) CrossBinDir..... $(CROSSBINDIR)
+ @$(ECHO) UnitsDir........ $(UNITSDIR)
+ @$(ECHO) PackagesDir..... $(PACKAGESDIR)
+ @$(ECHO)
+ @$(ECHO) GCC library..... $(GCCLIBDIR)
+ @$(ECHO) Other library... $(OTHERLIBDIR)
+ @$(ECHO)
+ @$(ECHO) == Tools info ==
+ @$(ECHO)
+ @$(ECHO) As........ $(AS)
+ @$(ECHO) Ld........ $(LD)
+ @$(ECHO) Ar........ $(AR)
+ @$(ECHO) Rc........ $(RC)
+ @$(ECHO)
+ @$(ECHO) Mv........ $(MVPROG)
+ @$(ECHO) Cp........ $(CPPROG)
+ @$(ECHO) Rm........ $(RMPROG)
+ @$(ECHO) GInstall.. $(GINSTALL)
+ @$(ECHO) Echo...... $(ECHO)
+ @$(ECHO) Shell..... $(SHELL)
+ @$(ECHO) Date...... $(DATE)
+ @$(ECHO) FPCMake... $(FPCMAKE)
+ @$(ECHO) PPUMove... $(PPUMOVE)
+ @$(ECHO) Upx....... $(UPXPROG)
+ @$(ECHO) Zip....... $(ZIPPROG)
+ @$(ECHO)
+ @$(ECHO) == Object info ==
+ @$(ECHO)
+ @$(ECHO) Target Loaders........ $(TARGET_LOADERS)
+ @$(ECHO) Target Units.......... $(TARGET_UNITS)
+ @$(ECHO) Target Implicit Units. $(TARGET_IMPLICITUNITS)
+ @$(ECHO) Target Programs....... $(TARGET_PROGRAMS)
+ @$(ECHO) Target Dirs........... $(TARGET_DIRS)
+ @$(ECHO) Target Examples....... $(TARGET_EXAMPLES)
+ @$(ECHO) Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+ @$(ECHO)
+ @$(ECHO) Clean Units......... $(CLEAN_UNITS)
+ @$(ECHO) Clean Files......... $(CLEAN_FILES)
+ @$(ECHO)
+ @$(ECHO) Install Units....... $(INSTALL_UNITS)
+ @$(ECHO) Install Files....... $(INSTALL_FILES)
+ @$(ECHO)
+ @$(ECHO) == Install info ==
+ @$(ECHO)
+ @$(ECHO) DateStr.............. $(DATESTR)
+ @$(ECHO) ZipName.............. $(ZIPNAME)
+ @$(ECHO) ZipPrefix............ $(ZIPPREFIX)
+ @$(ECHO) ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+ @$(ECHO) ZipSuffix............ $(ZIPSUFFIX)
+ @$(ECHO) FullZipName.......... $(FULLZIPNAME)
+ @$(ECHO) Install FPC Package.. $(INSTALL_FPCPACKAGE)
+ @$(ECHO)
+ @$(ECHO) Install base dir..... $(INSTALL_BASEDIR)
+ @$(ECHO) Install binary dir... $(INSTALL_BINDIR)
+ @$(ECHO) Install library dir.. $(INSTALL_LIBDIR)
+ @$(ECHO) Install units dir.... $(INSTALL_UNITDIR)
+ @$(ECHO) Install source dir... $(INSTALL_SOURCEDIR)
+ @$(ECHO) Install doc dir...... $(INSTALL_DOCDIR)
+ @$(ECHO) Install example dir.. $(INSTALL_EXAMPLEDIR)
+ @$(ECHO) Install data dir..... $(INSTALL_DATADIR)
+ @$(ECHO)
+ @$(ECHO) Dist destination dir. $(DIST_DESTDIR)
+ @$(ECHO) Dist zip name........ $(DIST_ZIPNAME)
+ @$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+ fpc_makefile_dirs
+fpc_makefile:
+ $(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+ifndef DATA2INC
+DATA2INC:=$(strip $(wildcard $(addsuffix /data2inc$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATA2INC),)
+DATA2INC= __missing_command_DATA2INC
+else
+DATA2INC:=$(firstword $(DATA2INC))
+endif
+endif
+export DATA2INC
+all: fpc_all
+debug: fpc_debug
+smart: fpc_smart
+release: fpc_release
+units: fpc_units
+examples:
+shared:
+install: fpc_install
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+distinstall:
+zipinstall:
+zipsourceinstall:
+zipexampleinstall:
+zipdistinstall:
+clean: fpc_clean
+distclean: fpc_distclean
+cleanall: fpc_cleanall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+ppu$(PPUEXT): ppu.pas
+ppufiles$(EXEEXT): ppufiles.pp ppu$(PPUEXT)
+ppudump$(EXEEXT): ppudump.pp ppu$(PPUEXT)
+ppumove$(EXEEXT): ppumove.pp ppu$(PPUEXT)
+fpcsubst$(EXEEXT): fpcsubst.pp usubst.pp
+fpcmkcfg$(EXEEXT): fpcmkcfg.pp usubst.pp fpccfg.inc
+ifneq ($(DATA2INC),)
+fpccfg.inc: fpc.cft
+ $(DATA2INC) -b -s fpc.cft fpccfg.inc DefaultConfig
+endif
+unexport PPUFILES PPUMOVE
diff --git a/compiler/utils/Makefile.fpc b/compiler/utils/Makefile.fpc
new file mode 100644
index 0000000000..1aacfc3c25
--- /dev/null
+++ b/compiler/utils/Makefile.fpc
@@ -0,0 +1,52 @@
+#
+# Makefile.fpc for Free Pascal Compiler Utils
+#
+
+[target]
+programs=fpc fppkg ppufiles ppudump ppumove fpcsubst fpcmkcfg
+rst=fppkg fpcmkcfg fpcsubst
+
+[clean]
+units=ppu crc usubst
+
+[compiler]
+unitdir=..
+sourcedir=..
+
+[install]
+fpcpackage=y
+
+[require]
+tools=data2inc
+
+[default]
+fpcdir=../..
+
+
+[rules]
+#
+# PPU Tools
+#
+ppu$(PPUEXT): ppu.pas
+
+ppufiles$(EXEEXT): ppufiles.pp ppu$(PPUEXT)
+
+ppudump$(EXEEXT): ppudump.pp ppu$(PPUEXT)
+
+ppumove$(EXEEXT): ppumove.pp ppu$(PPUEXT)
+
+fpcsubst$(EXEEXT): fpcsubst.pp usubst.pp
+
+fpcmkcfg$(EXEEXT): fpcmkcfg.pp usubst.pp fpccfg.inc
+
+ifneq ($(DATA2INC),)
+fpccfg.inc: fpc.cft
+ $(DATA2INC) -b -s fpc.cft fpccfg.inc DefaultConfig
+endif
+
+#
+# Don't export some tools, which are found in the current dir if it's in
+# the path, so are not valid for the subdirs
+#
+
+unexport PPUFILES PPUMOVE
diff --git a/compiler/utils/README b/compiler/utils/README
new file mode 100644
index 0000000000..ab7a13eefa
--- /dev/null
+++ b/compiler/utils/README
@@ -0,0 +1,20 @@
+This dirctory contains some utilities that are used during the
+development of the Free Pascal Compiler.
+
+msg2inc : Convert a compiler message file (errorX.msg) to .inc files to
+ include it as the default language in the compiler. It can
+ also convert the .msg to .tex for inclusion the documentation
+
+nasmconv : Convert a Nasm insns.dat to i386tab.inc so it can be used with
+ the compiler
+
+makecfg : This script will make the samplecfg for linux installations
+
+msgdif : analyzes the differences between two msg files
+ msgdif errore.msg errord.msg
+ will print out new error msg, removed old ones
+ and will create a new file new.msg that will
+ contain the new error messages (supposing TeX comment is after
+ the message line itself)
+ removed messages are prepended by "%%% "
+ (they can be useful in case on error enum renaming !)
diff --git a/compiler/utils/fixlog.pp b/compiler/utils/fixlog.pp
new file mode 100644
index 0000000000..4f5a7a932a
--- /dev/null
+++ b/compiler/utils/fixlog.pp
@@ -0,0 +1,174 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Remove all revision logs from source files after X revisions or
+ older than date X
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program fixlog;
+
+{$mode objfpc}
+{$H+}
+
+uses
+ sysutils;
+
+const
+ bufsize = 32*1024;
+
+var
+ maxrevs,myear,mmonth,mday : integer;
+
+procedure Date2Int(const date:string;var year,month,day:integer);
+begin
+ year:=StrToInt(Copy(date,1,4));
+ month:=StrToInt(Copy(date,6,2));
+ day:=StrToInt(Copy(date,9,2));
+ if (year=0) or (month=0) or (day=0) then
+ begin
+ writeln('wrong date "',date,'", use yyyy/mm/dd');
+ halt(2);
+ end;
+end;
+
+
+procedure dofile(const fn:string);
+var
+ t,f : text;
+ s : string;
+ skip, truncated : boolean;
+ year,month,day,
+ found,revs,i : integer;
+ fbuf,tbuf : pointer;
+begin
+ getmem(fbuf,bufsize);
+ getmem(tbuf,bufsize);
+ write('processing ',fn,': ');
+ assign(t,fn);
+ assign(f,'fixlog.tmp');
+ {$I-}
+ reset(t);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ writeln('error!');
+ exit;
+ end;
+ rewrite(f);
+ settextbuf(t,tbuf^,bufsize);
+ settextbuf(f,fbuf^,bufsize);
+ found:=0;
+ revs:=0;
+ skip:=false;
+ truncated:=false;
+ while not eof(t) do
+ begin
+ readln(t,s);
+ case found of
+ 0 :
+ begin
+ if pos('$Log: ',s)>0 then
+ found:=1;
+ skip:=false;
+ writeln(f,s);
+ end;
+ 1 :
+ begin
+ i:=pos('Revision',s);
+ if i>0 then
+ begin
+ inc(revs);
+ if revs>maxrevs then
+ begin
+ skip:=true;
+ truncated:=true;
+ found:=2;
+ end
+ else
+ begin
+ inc(i,10);
+ while (i<length(s)) and (s[i]<>' ') do
+ inc(i);
+ while (i<length(s)) and (s[i]=' ') do
+ inc(i);
+ if (i<length(s)) and (s[i] in ['0'..'9']) then
+ begin
+ Date2Int(Copy(s,i,10),year,month,day);
+ if (year<Myear) or
+ ((year=MYear) and (month<Mmonth)) or
+ ((year=MYear) and (month=Mmonth) and (day<Mday)) then
+ begin
+ skip:=true;
+ truncated:=true;
+ found:=2;
+// write(year,'/',month,'/',day,' date');
+ end;
+ end;
+ end;
+ end
+ else
+ if pos('}',s)>0 then
+ begin
+ skip:=false;
+ found:=0;
+ end;
+ if not skip then
+ writeln(f,s);
+ end;
+ 2 :
+ begin
+ if pos('}',s)>0 then
+ begin
+ skip:=false;
+ found:=0;
+ end;
+ if not skip then
+ writeln(f,s);
+ end;
+ end;
+ end;
+ close(t);
+ close(f);
+ if revs=0 then
+ writeln(' no log found')
+ else
+ if truncated then
+ writeln(revs-1,' revisions')
+ else
+ writeln(revs,' revisions');
+ erase(t);
+ rename(f,fn);
+ freemem(tbuf);
+ freemem(fbuf);
+end;
+
+var
+ dir : tsearchrec;
+ i : integer;
+ path : string;
+begin
+ writeln('fixlog v1.01 (C) 1999-2002 Peter Vreman');
+ if paramcount<3 then
+ begin
+ writeln('usage: fixlog <revisions> <yyyy-mm-dd> <files> [files]');
+ halt(1);
+ end;
+ MaxRevs:=StrToInt(ParamStr(1));
+ Date2Int(ParamStr(2),MYear,MMonth,MDay);
+ for i:=3 to paramcount do
+ begin
+ path:=ExtractFilePath(paramstr(i));
+ if findfirst(paramstr(i),faAnyFile,dir)=0 then
+ repeat
+ dofile(path+dir.name);
+ until findnext(dir)<>0;
+ findclose(dir);
+ end;
+end.
diff --git a/compiler/utils/fixmsg.pp b/compiler/utils/fixmsg.pp
new file mode 100644
index 0000000000..6bd1cfbe2c
--- /dev/null
+++ b/compiler/utils/fixmsg.pp
@@ -0,0 +1,66 @@
+type
+ trtabrec=record
+ name : string[12];
+ idx : longint;
+ end;
+
+const
+ trtab : array[0..10] of trtabrec=(
+ (name:'general';idx:1000),
+ (name:'scan';idx:2000),
+ (name:'parser';idx:3000),
+ (name:'type';idx:4000),
+ (name:'sym';idx:5000),
+ (name:'cg';idx:6000),
+ (name:'asmr';idx:7000),
+ (name:'asmw';idx:8000),
+ (name:'exec';idx:9000),
+ (name:'unit';idx:10000),
+ (name:'option';idx:11000)
+ );
+
+var
+ t,f : text;
+ s,hs : string;
+ i,j,k : longint;
+begin
+ assign(t,paramstr(1));
+ reset(t);
+ assign(f,'New.msg');
+ rewrite(f);
+ while not eof(t) do
+ begin
+ readln(t,s);
+ if (s<>'') and not(s[1] in ['#','%']) then
+ begin
+ for i:=0 to 10 do
+ if Copy(s,1,length(trtab[i].name))=trtab[i].name then
+ begin
+ j:=pos('=',s);
+ if j>0 then
+ begin
+ inc(j);
+ if s[j] in ['0'..'9'] then
+ begin
+ k:=j;
+ while (s[k] in ['0'..'9']) do
+ inc(k);
+ if s[k]='_' then
+ inc(k);
+ delete(s,j,k-j);
+ end;
+ str(trtab[i].idx,hs);
+ while length(hs)<5 do
+ hs:='0'+hs;
+ hs:=hs+'_';
+ inc(trtab[i].idx);
+ insert(hs,s,j);
+ end;
+ break;
+ end;
+ end;
+ writeln(f,s);
+ end;
+ close(f);
+ close(t);
+end.
diff --git a/compiler/utils/fixnasm.pp b/compiler/utils/fixnasm.pp
new file mode 100644
index 0000000000..01041ede83
--- /dev/null
+++ b/compiler/utils/fixnasm.pp
@@ -0,0 +1,99 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Convert insns.dat from Nasm to an i386ins.dat for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program fixnasm;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+const
+ spaces=' ';
+var
+ t,f : text;
+ para,bytes,flags,
+ opcode,lastop,
+ s : string;
+ i,j : longint;
+begin
+ writeln('Fixing insns.dat -> i386ins.dat');
+ assign(t,'insns.dat');
+ reset(t);
+ assign(f,'insns.new');
+ rewrite(f);
+ lastop:='';
+ while not eof(t) do
+ begin
+ readln(t,s);
+ if (s<>'') and (s[1]<>';') then
+ begin
+ i:=pos(' ',s);
+ j:=pos(',',s);
+ if (j>0) and (j<i) then
+ opcode:=Copy(s,1,j-1)
+ else
+ opcode:=Copy(s,1,i-1);
+ if opcode<>lastop then
+ begin
+ writeln(f,'');
+ writeln(f,'[',Copy(s,1,i-1),']');
+ writeln(f,'(Ch_All, Ch_None, Ch_None)');
+ lastop:=opcode;
+ end;
+ while (i<length(s)) and (s[i+1]=' ') do
+ inc(i);
+ Delete(s,1,i);
+ i:=pos(' ',s);
+ para:=Copy(s,1,i-1);
+ para:=para+Copy(spaces,1,22-length(para));
+ while (i<length(s)) and (s[i+1]=' ') do
+ inc(i);
+ Delete(s,1,i);
+ i:=pos(' ',s);
+ bytes:=Copy(s,1,i-1);
+ bytes:=bytes+Copy(spaces,1,32-length(bytes));
+ while (i<length(s)) and (s[i+1]=' ') do
+ inc(i);
+ Delete(s,1,i);
+ i:=pos(' ',s);
+ if i=0 then
+ i:=255;
+ flags:=Copy(s,1,i-1);
+ writeln(f,para,bytes,flags);
+ end
+ else
+ writeln(f,s);
+ end;
+ close(f);
+ close(t);
+end.
diff --git a/compiler/utils/fixtab.pp b/compiler/utils/fixtab.pp
new file mode 100644
index 0000000000..89410c5836
--- /dev/null
+++ b/compiler/utils/fixtab.pp
@@ -0,0 +1,367 @@
+program FixTab;
+uses Dos;
+
+const
+ {Files}
+ InputExt='';
+ OutputExt='*';
+
+
+var
+{General}
+ InFile,
+ OutFile : string[80];
+ ParaFile : word;
+{Specific}
+const
+ TabSize : longint=8;
+ DosEol : boolean=false;
+ Verbose : boolean=false;
+
+{****************************************************************************
+ Routines
+****************************************************************************}
+
+const
+{$IFDEF LINUX}
+ PathCh='/';
+{$ELSE}
+ PathCh='\';
+{$ENDIF}
+
+Function SplitPath(Const HStr:String):String;
+var
+ i : byte;
+begin
+ i:=Length(Hstr);
+ while (i>0) and (Hstr[i]<>PathCh) do
+ dec(i);
+ SplitPath:=Copy(Hstr,1,i);
+end;
+
+
+
+Function SplitFileName(Const HStr:String):String;
+var
+ i : byte;
+begin
+ i:=Length(Hstr);
+ while (i>0) and (Hstr[i]<>PathCh) do
+ dec(i);
+ SplitFileName:=Copy(Hstr,i+1,255);
+end;
+
+
+
+Function SplitName(Const HStr:String):String;
+var
+ i,j : byte;
+begin
+ i:=Length(Hstr);
+ j:=i;
+ while (i>0) and (Hstr[i]<>PathCh) do
+ dec(i);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j<=i then
+ j:=255;
+ SplitName:=Copy(Hstr,i+1,j-(i+1));
+end;
+
+
+
+Function SplitExtension(Const HStr:String):String;
+var
+ j,i : byte;
+begin
+ i:=Length(Hstr);
+ j:=i;
+ while (i>0) and (Hstr[i]<>PathCh) do
+ dec(i);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j<=i then
+ j:=254;
+ SplitExtension:=Copy(Hstr,j+1,255);
+end;
+
+
+
+Function AddExtension(Const HStr,ext:String):String;
+begin
+ if (Ext<>'') and (SplitExtension(HStr)='') then
+ AddExtension:=Hstr+'.'+Ext
+ else
+ AddExtension:=Hstr;
+end;
+
+
+
+Function ForceExtension(Const HStr,ext:String):String;
+var
+ j : byte;
+begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ j:=255;
+ ForceExtension:=Copy(Hstr,1,j-1)+'.'+Ext;
+end;
+
+
+function UCase(Const Hstr:string):string;
+var
+ i : byte;
+begin
+ for i:=1to Length(Hstr) do
+ UCase[i]:=Upcase(Hstr[i]);
+ UCase[0]:=chr(Length(Hstr));
+end;
+
+
+
+Function ESpace(HStr:String;len:byte):String;
+begin
+ while length(Hstr)<Len do
+ begin
+ inc(byte(Hstr[0]));
+ Hstr[Length(Hstr)]:=' ';
+ end;
+ ESpace:=Hstr;
+end;
+
+{****************************************************************************
+ Main Stuff
+****************************************************************************}
+
+var
+ Done : array[0..1023] of string[32];
+ Total : word;
+Function FileDone(const fn:string):boolean;
+var
+ i : word;
+begin
+ i:=0;
+ while (i<Total) and (Done[i]<>fn) do
+ inc(i);
+ if Done[i]=fn then
+ FileDone:=true
+ else
+ begin
+ Done[Total]:=fn;
+ inc(Total);
+ FileDone:=false;
+ end;
+end;
+
+
+
+procedure Convert(fn,nfn:string);
+type
+ inbuftype=array[0..31999] of char;
+ outbuftype=array[0..63999] of char;
+var
+ f,g : file;
+ inbuf : ^inbuftype;
+ outbuf : ^outbuftype;
+ Curr,
+ TabCol,
+ col,
+ i,last,
+ innum,
+ outnum : longint;
+
+ procedure WriteBuf;
+ begin
+ if i>last then
+ begin
+ move(InBuf^[last],OutBuf^[OutNum],i-last);
+ inc(OutNum,(i-last));
+ end;
+ Last:=i+1;
+ end;
+
+begin
+{Create New FileName}
+ if SplitExtension(nfn)='*' then
+ nfn:=AddExtension(SplitPath(nfn)+SplitName(nfn),SplitExtension(fn));
+ if SplitName(nfn)='*' then
+ begin
+ if SplitPath(nfn)='' then
+ nfn:=AddExtension(SplitPath(fn)+SplitName(fn),SplitExtension(nfn))
+ else
+ nfn:=AddExtension(SplitPath(nfn)+SplitName(fn),SplitExtension(nfn));
+ end;
+{Done?}
+ if FileDone(nfn) then
+ exit;
+{Open Files}
+ Write('Converting '+ESpace(fn,30)+' ');
+ if fn=nfn then
+ assign(g,ForceExtension(fn,'$T$'))
+ else
+ begin
+ Write('-> '+ESpace(nfn,30)+' ');
+ assign(g,nfn);
+ end;
+ new(inbuf);
+ new(outbuf);
+ assign(f,fn);
+ {$I-}
+ reset(f,1);
+ {$I+}
+ if ioresult<>0 then
+ exit;
+ {$I-}
+ rewrite(g,1);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ close(f);
+ exit;
+ end;
+ Curr:=0;
+ col:=1;
+ last:=0;
+ repeat
+ blockread(f,InBuf^,sizeof(InBufType),innum);
+ outnum:=0;
+ if innum>0 then
+ begin
+ i:=0;
+ while (i<innum) do
+ begin
+ case InBuf^[i] of
+ #9 : begin
+ WriteBuf;
+ OutBuf^[OutNum]:=' ';
+ inc(OutNum);
+ inc(Col);
+ TabCol:=(((Col-1) div TabSize)+1)*TabSize;
+ while (Col<TabCol) do
+ begin
+ OutBuf^[OutNum]:=' ';
+ inc(OutNum);
+ inc(Col);
+ end;
+ end;
+ #13 : begin
+ WriteBuf;
+ while (outnum>0) and (outbuf^[outnum-1] in [' ',#9]) do
+ dec(outnum);
+ end;
+ #10 : begin
+ WriteBuf;
+ while (outnum>0) and (outbuf^[outnum-1] in [' ',#9]) do
+ dec(outnum);
+ if DosEol then
+ begin
+ OutBuf^[OutNum]:=#13;
+ inc(OutNum);
+ end;
+ OutBuf^[OutNum]:=#10;
+ inc(OutNum);
+ col:=0;
+ inc(Curr);
+ if (curr and 31)=0 then
+ Write(Curr:5,#8#8#8#8#8);
+ end;
+ else
+ inc(col);
+ end;
+ inc(i);
+ end;
+ WriteBuf;
+ last:=0;
+ end;
+ blockwrite(g,OutBuf^,outnum);
+ until innum=0;
+ WriteLn(Curr,' Lines');
+ close(g);
+ close(f);
+ if fn=nfn then
+ begin
+ erase(f);
+ rename(g,fn);
+ end;
+ dispose(outbuf);
+ dispose(inbuf);
+end;
+
+
+{****************************************************************************
+ General Stuff
+****************************************************************************}
+
+procedure getpara;
+var
+ ch : char;
+ para : string[128];
+ i,j : word;
+
+ procedure helpscreen;
+ begin
+ writeln('Usage : '+SplitName(ParamStr(0))+' [Options] <InFile(s)>'#10);
+ writeln('<Options> can be : -O<OutFile> Specify OutFile Mask');
+ WriteLn(' -D Use MsDos #13#10 Eols');
+ writeln(' -T<size> Set Size of Tabs');
+ writeln(' -V be more verbose');
+ writeln(' -? or -H This HelpScreen');
+ halt(1);
+ end;
+
+begin
+ for i:=1to paramcount do
+ begin
+ para:=ucase(paramstr(i));
+ if (para[1]='-') then
+ begin
+ ch:=para[2];
+ delete(para,1,2);
+ case ch of
+ 'O' : OutFile:=AddExtension(Para,OutputExt);
+ 'D' : DosEol:=true;
+ 'T' : Val(Para,TabSize,j);
+ 'V' : verbose:=true;
+ '?','H' : helpscreen;
+ end;
+ end
+ else
+ begin
+ if ParaFile=0 then
+ ParaFile:=i;
+ end;
+ end;
+ if (ParaFile=0) then
+ HelpScreen;
+ if OutFile='' then
+ OutFile:=ForceExtension('*',OutPutExt);
+end;
+
+
+
+var
+ Dir : SearchRec;
+ i : word;
+begin
+ GetPara;
+{Main}
+ if Verbose then
+ begin
+ Writeln('fixtab v1.01 (C) 1999-2002 Peter Vreman');
+ Writeln('TabSize ',TabSize);
+ if DosEol then
+ WriteLn('Using MsDos Eols');
+ end;
+ for i:=ParaFile to ParamCount do
+ begin
+ InFile:=AddExtension(ParamStr(i),InputExt);
+ FindFirst(InFile,$20,Dir);
+ while (DosError=0) do
+ begin
+ Convert(SplitPath(InFile)+Dir.Name,OutFile);
+ FindNext(Dir);
+ end;
+ end;
+end.
diff --git a/compiler/utils/fpc.cft b/compiler/utils/fpc.cft
new file mode 100644
index 0000000000..e858c909c4
--- /dev/null
+++ b/compiler/utils/fpc.cft
@@ -0,0 +1,204 @@
+#
+# Config file generated by fpcmkcfg on %BUILDDATE% - %BUILDTIME%
+# Example fpc.cfg for Free Pascal Compiler
+#
+
+# ----------------------
+# Defines (preprocessor)
+# ----------------------
+
+#
+# nested #IFNDEF, #IFDEF, #ENDIF, #ELSE, #DEFINE, #UNDEF are allowed
+#
+# -d is the same as #DEFINE
+# -u is the same as #UNDEF
+#
+
+#
+# Some examples (for switches see below, and the -? helppages)
+#
+# Try compiling with the -dRELEASE or -dDEBUG on the commandline
+#
+
+# For a release compile with optimizes and strip debuginfo
+#IFDEF RELEASE
+ -OG2p3
+ -Xs
+ #WRITE Compiling Release Version
+#ENDIF
+
+# For a debug version compile with debuginfo and all codegeneration checks on
+#IFDEF DEBUG
+ -g
+ -Crtoi
+ #WRITE Compiling Debug Version
+#ENDIF
+
+# ----------------
+# Parsing switches
+# ----------------
+
+# Pascal language mode
+# -Mfpc free pascal dialect (default)
+# -Mobjfpc switch some Delphi 2 extensions on
+# -Mdelphi tries to be Delphi compatible
+# -Mtp tries to be TP/BP 7.0 compatible
+# -Mgpc tries to be gpc compatible
+# -Mmacpas tries to be compatible to the macintosh pascal dialects
+#
+# Turn on Object Pascal extensions by default
+#-Mobjfpc
+
+# Assembler reader mode
+# -Rdefault use default assembler
+# -Ratt read AT&T style assembler
+# -Rintel read Intel style assembler
+#
+# All assembler blocks are AT&T styled by default
+#-Ratt
+
+# Semantic checking
+# -S2 same as -Mobjfpc
+# -Sc supports operators like C (*=,+=,/= and -=)
+# -Sa include assertion code.
+# -Sd same as -Mdelphi
+# -Se<x> compiler stops after the <x> errors (default is 1)
+# -Sg allow LABEL and GOTO
+# -Sh Use ansistrings
+# -Si support C++ styled INLINE
+# -SI<x> set interface style to <x>
+# -SIcomCOM compatible interface (default)
+# -SIcorbaCORBA compatible interface
+# -Sm support macros like C (global)
+# -So same as -Mtp
+# -Sp same as -Mgpc
+# -Ss constructor name must be init (destructor must be done)
+# -St allow static keyword in objects
+#
+# Allow goto, inline, C-operators, C-vars
+-Sgic
+
+# ---------------
+# Code generation
+# ---------------
+
+# Uncomment the next line if you always want static/dynamic units by default
+# (can be overruled with -CD, -CS at the commandline)
+#-CS
+#-CD
+
+# Set the default heapsize to 8Mb
+#-Ch8000000
+
+# Set default codegeneration checks (iocheck, overflow, range, stack)
+#-Ci
+#-Co
+#-Cr
+#-Ct
+
+# Optimizer switches for i386 compiler
+# -Og generate smaller code
+# -OG generate faster code (default)
+# -Or keep certain variables in registers (still BUGGY!!!)
+# -Ou enable uncertain optimizations (see docs)
+# -O1 level 1 optimizations (quick optimizations)
+# -O2 level 2 optimizations (-O1 + slower optimizations)
+# -O3 level 3 optimizations (same as -O2u)
+# -Op target processor
+# -Op1 set target processor to 386/486
+# -Op2 set target processor to Pentium/PentiumMMX (tm)
+# -Op3 set target processor to PPro/PII/c6x86/K6 (tm)
+
+# Optimize always for Size and PII
+#-OG2p3
+
+
+# -----------------------
+# Set Filenames and Paths
+# -----------------------
+
+# Both slashes and backslashes are allowed in paths
+
+# path to the messagefile, not necessary anymore but can be used to override
+# the default language
+#-Fr%basepath%/msg/errore.msg
+#-Fr%basepath%/msg/errorn.msg
+#-Fr%basepath%/msg/errores.msg
+#-Fr%basepath%/msg/errord.msg
+#-Fr%basepath%/msg/errorr.msg
+
+# path to the gcclib
+#-Fl%basepath%/lib
+
+# searchpath for includefiles
+#-Fi/pp/inc;/pp/rtl/inc
+
+# searchpath for includefiles
+# release them only if you know what you do
+# because this could cause a rebuild of the runtime library
+# if you tell them compiler/ide to build the project (FK)
+#-Fi%basepath%/source/rtl/inc;%basepath%/source/rtl/i386
+
+# searchpath for objectfiles
+#-Fo%basepath%/source/rtl/inc;%basepath%/source/rtl/i386
+
+# searchpath for units and other system dependent things
+-Fu%basepath%/units/$FPCTARGET/
+-Fu%basepath%/units/$FPCTARGET/*
+-Fu%basepath%/units/$FPCTARGET/rtl
+
+# searchpath for libraries
+#-Fl%basepath%/lib
+#-Fl/lib;/usr/lib
+
+# searchpath for tools
+-FD%basepath%/bin/$FPCTARGET
+
+
+# -------------
+# Linking
+# -------------
+
+# generate always debugging information for GDB (slows down the compiling
+# process)
+# -gc generate checks for pointers
+# -gd use dbx
+# -gg use gsym
+# -gh use heap trace unit (for memory leak debugging)
+# -gl use line info unit to show more info for backtraces
+# -gv generates programs tracable with valgrind
+# -gw generate dwarf debugging info
+#
+# Enable debuginfo and use the line info unit by default
+#-gl
+
+# always pass an option to the linker
+#-k-s
+
+# Always strip debuginfo from the executable
+-Xs
+
+
+# -------------
+# Miscellaneous
+# -------------
+
+# Write always a nice FPC logo ;)
+-l
+
+# Verbosity
+# e : Show errors (default) d : Show debug info
+# w : Show warnings u : Show unit info
+# n : Show notes t : Show tried/used files
+# h : Show hints m : Show defined macros
+# i : Show general info p : Show compiled procedures
+# l : Show linenumbers c : Show conditionals
+# a : Show everything 0 : Show nothing (except errors)
+# b : Show all procedure r : Rhide/GCC compatibility mode
+# declarations if an error x : Executable info (Win32 only)
+# occurs
+#
+# Display Info, Warnings, Notes and Hints
+-viwn
+# If you don't want so much verbosity use
+#-vw
diff --git a/compiler/utils/fpc.mpw b/compiler/utils/fpc.mpw
new file mode 100644
index 0000000000..8ae99a7ee6
--- /dev/null
+++ b/compiler/utils/fpc.mpw
@@ -0,0 +1,2 @@
+# MPW script which mimics the fpc wrapper application
+ppcppc {Parameters}
diff --git a/compiler/utils/fpc.pp b/compiler/utils/fpc.pp
new file mode 100644
index 0000000000..01511f7419
--- /dev/null
+++ b/compiler/utils/fpc.pp
@@ -0,0 +1,205 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ This file is the "loader" for the Free Pascal compiler
+
+ 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.
+
+ ****************************************************************************}
+program fpc;
+
+{$mode objfpc}{$H+}
+
+ uses
+ Sysutils;
+
+ const
+{$ifdef UNIX}
+ exeext='';
+{$else UNIX}
+ {$ifdef AMIGA}
+ exeext='';
+ {$else}
+ {$ifdef MORPHOS}
+ exeext='';
+ {$else}
+ {$ifdef NETWARE}
+ exeext='.nlm';
+ {$else}
+ exeext='.exe';
+ {$endif NETWARE}
+ {$endif MORPHOS}
+ {$endif AMIGA}
+{$endif UNIX}
+
+
+ procedure error(const s : string);
+ begin
+ writeln('Error: ',s);
+ halt(1);
+ end;
+
+
+ function SplitPath(Const HStr:String):String;
+ var
+ i : longint;
+ begin
+ i:=Length(Hstr);
+ while (i>0) and not(Hstr[i] in ['\','/']) do
+ dec(i);
+ SplitPath:=Copy(Hstr,1,i);
+ end;
+
+
+ function FileExists ( Const F : String) : Boolean;
+ var
+ Info : TSearchRec;
+ begin
+ FileExists:= findfirst(F,fareadonly+faarchive+fahidden,info)=0;
+ findclose(Info);
+ end;
+
+ procedure findexe(var ppcbin:string);
+ var
+ path : string;
+ begin
+ { add .exe extension }
+ ppcbin:=ppcbin+exeext;
+
+ { get path of fpc.exe }
+ path:=splitpath(paramstr(0));
+ if FileExists(path+ppcbin) then
+ ppcbin:=path+ppcbin
+ else
+ begin
+ path:=FileSearch(ppcbin,getenvironmentvariable('PATH'));
+ if path<>'' then
+ ppcbin:=path;
+
+ end;
+ end;
+
+ var
+ s : ansistring;
+ processorname,
+ ppcbin,
+ versionStr,
+ processorstr : string;
+ ppccommandline : ansistring;
+ i : longint;
+ errorvalue : Longint;
+ begin
+ ppccommandline:='';
+{$ifdef i386}
+ ppcbin:='ppc386';
+ processorname:='i386';
+{$endif i386}
+{$ifdef m68k}
+ ppcbin:='ppc68k';
+ processorname:='m68k';
+{$endif m68k}
+{$ifdef alpha}
+ ppcbin:='ppcapx';
+ processorname:='alpha';
+{$endif alpha}
+{$ifdef powerpc}
+ ppcbin:='ppcppc';
+ processorname:='powerpc';
+{$endif powerpc}
+{$ifdef arm}
+ ppcbin:='ppcarm';
+ processorname:='arm';
+{$endif arm}
+{$ifdef sparc}
+ ppcbin:='ppcsparc';
+ processorname:='sparc';
+{$endif sparc}
+{$ifdef x86_64}
+ ppcbin:='ppcx64';
+ processorname:='x86_64';
+{$endif x86_64}
+{$ifdef ia64}
+ ppcbin:='ppcia64';
+ processorname:='ia64';
+{$endif ia64}
+ versionstr:=''; { Default is just the name }
+ for i:=1 to paramcount do
+ begin
+ s:=paramstr(i);
+ if pos('-V',s)=1 then
+ versionstr:=copy(s,3,length(s)-2)
+ else
+ begin
+ if pos('-P',s)=1 then
+ begin
+ processorstr:=copy(s,3,length(s)-2);
+ { -PB is a special code that will show the
+ default compiler and exit immediatly. It's
+ main usage is for Makefile }
+ if processorstr='B' then
+ begin
+ { report the full name of the ppcbin }
+ findexe(ppcbin);
+ writeln(ppcbin);
+ halt(0);
+ end
+ { -PP is a special code that will show the
+ processor and exit immediatly. It's
+ main usage is for Makefile }
+ else if processorstr='P' then
+ begin
+ { report the processor }
+ writeln(processorname);
+ halt(0);
+ end
+ else if processorstr='i386' then
+ ppcbin:='ppc386'
+ else if processorstr='m68k' then
+ ppcbin:='ppc68k'
+ else if processorstr='alpha' then
+ ppcbin:='ppcapx'
+ else if processorstr='powerpc' then
+ ppcbin:='ppcppc'
+ else if processorstr='arm' then
+ ppcbin:='ppcarm'
+ else if processorstr='sparc' then
+ ppcbin:='ppcsparc'
+ else if processorstr='ia64' then
+ ppcbin:='ppcia64'
+ else if processorstr='x86_64' then
+ ppcbin:='ppcx64'
+ else error('Illegal processor type "'+processorstr+'"');
+ end
+ else
+ ppccommandline:=ppccommandline+s+' ';
+ end;
+ end;
+
+ if versionstr<>'' then
+ ppcbin:=ppcbin+'-'+versionstr;
+ { find the full path to the specified exe }
+ findexe(ppcbin);
+
+ { call ppcXXX }
+ try
+ errorvalue:=ExecuteProcess(ppcbin,ppccommandline);
+ except
+ on e : exception do
+ error(ppcbin+' can''t be executed, error message: '+e.message);
+ end;
+ if errorvalue<>0 then
+ error(ppcbin+' returned an error exitcode (normal if you did not specify a source file to be compiled)');
+ halt(errorvalue);
+ end.
diff --git a/compiler/utils/fpccfg.inc b/compiler/utils/fpccfg.inc
new file mode 100644
index 0000000000..103f32ab70
--- /dev/null
+++ b/compiler/utils/fpccfg.inc
@@ -0,0 +1,224 @@
+{$ifdef Delphi}
+const DefaultConfig : array[0..24] of string[240]=(
+{$else Delphi}
+const DefaultConfig : array[0..24,1..240] of char=(
+{$endif Delphi}
+ '#'#013#010+
+ '# Config file generated by fpcmkcfg on %BUILDDATE% - %BUILDTIME%'#013#010+
+ '# Example fpc.cfg for Free Pascal Compiler'#013#010+
+ '#'#013#010+
+ #013#010+
+ '# ----------------------'#013#010+
+ '# Defines (preprocessor)'#013#010+
+ '# ----------------------'#013#010+
+ #013#010+
+ '#'#013#010+
+ '# nested #IFNDEF, #IFDEF, #ENDIF, #ELSE',', #DEFINE, #UNDEF are allowed'+
+ #013#010+
+ '#'#013#010+
+ '# -d is the same as #DEFINE'#013#010+
+ '# -u is the same as #UNDEF'#013#010+
+ '#'#013#010+
+ #013#010+
+ '#'#013#010+
+ '# Some examples (for switches see below, and the -? helppages)'#013#010+
+ '#'#013#010+
+ '# Try compiling with the -dRELEASE or -dDEBUG on the commandline'#013#010+
+ '#'#013#010+
+ #013#010+
+ '# F','or a release compile with optimizes and strip debuginfo'#013#010+
+ '#IFDEF RELEASE'#013#010+
+ ' -OG2p3'#013#010+
+ ' -Xs'#013#010+
+ ' #WRITE Compiling Release Version'#013#010+
+ '#ENDIF'#013#010+
+ #013#010+
+ '# For a debug version compile with debuginfo and all codegeneration ch'+
+ 'ecks on'#013#010+
+ '#IFDEF DEBUG'#013#010+
+ ' -g'#013#010+
+ ' -Cr','toi'#013#010+
+ ' #WRITE Compiling Debug Version'#013#010+
+ '#ENDIF'#013#010+
+ #013#010+
+ '# ----------------'#013#010+
+ '# Parsing switches'#013#010+
+ '# ----------------'#013#010+
+ #013#010+
+ '# Pascal language mode'#013#010+
+ '# -Mfpc free pascal dialect (default)'#013#010+
+ '# -Mobjfpc switch some Delphi 2 extensions on'#013#010+
+ '# ',' -Mdelphi tries to be Delphi compatible'#013#010+
+ '# -Mtp tries to be TP/BP 7.0 compatible'#013#010+
+ '# -Mgpc tries to be gpc compatible'#013#010+
+ '# -Mmacpas tries to be compatible to the macintosh pascal diale'+
+ 'cts'#013#010+
+ '#'#013#010+
+ '# Turn on Object ','Pascal extensions by default'#013#010+
+ '#-Mobjfpc'#013#010+
+ #013#010+
+ '# Assembler reader mode'#013#010+
+ '# -Rdefault use default assembler'#013#010+
+ '# -Ratt read AT&T style assembler'#013#010+
+ '# -Rintel read Intel style assembler'#013#010+
+ '#'#013#010+
+ '# All assembler blocks are AT&T style','d by default'#013#010+
+ '#-Ratt'#013#010+
+ #013#010+
+ '# Semantic checking'#013#010+
+ '# -S2 same as -Mobjfpc'#013#010+
+ '# -Sc supports operators like C (*=,+=,/= and -=)'#013#010+
+ '# -Sa include assertion code.'#013#010+
+ '# -Sd same as -Mdelphi'#013#010+
+ '# -Se<x> ',' compiler stops after the <x> errors (default is 1)'+
+ #013#010+
+ '# -Sg allow LABEL and GOTO'#013#010+
+ '# -Sh Use ansistrings'#013#010+
+ '# -Si support C++ styled INLINE'#013#010+
+ '# -SI<x> set interface style to <x>'#013#010+
+ '# -SIcomCOM c','ompatible interface (default)'#013#010+
+ '# -SIcorbaCORBA compatible interface'#013#010+
+ '# -Sm support macros like C (global)'#013#010+
+ '# -So same as -Mtp'#013#010+
+ '# -Sp same as -Mgpc'#013#010+
+ '# -Ss constructor name must be init ','(destructor must be '+
+ 'done)'#013#010+
+ '# -St allow static keyword in objects'#013#010+
+ '#'#013#010+
+ '# Allow goto, inline, C-operators, C-vars'#013#010+
+ '-Sgic'#013#010+
+ #013#010+
+ '# ---------------'#013#010+
+ '# Code generation'#013#010+
+ '# ---------------'#013#010+
+ #013#010+
+ '# Uncomment the next line if you always want sta','tic/dynamic units by'+
+ ' default'#013#010+
+ '# (can be overruled with -CD, -CS at the commandline)'#013#010+
+ '#-CS'#013#010+
+ '#-CD'#013#010+
+ #013#010+
+ '# Set the default heapsize to 8Mb'#013#010+
+ '#-Ch8000000'#013#010+
+ #013#010+
+ '# Set default codegeneration checks (iocheck, overflow, range, stack)'#013+
+ #010+
+ '#-Ci'#013#010+
+ '#-Co'#013#010+
+ '#-Cr'#013#010+
+ '#-','Ct'#013#010+
+ #013#010+
+ '# Optimizer switches for i386 compiler'#013#010+
+ '# -Og generate smaller code'#013#010+
+ '# -OG generate faster code (default)'#013#010+
+ '# -Or keep certain variables in registers (still BUGGY!!!)'#013#010+
+ '# -Ou enable uncertain optimizations (s','ee docs)'#013#010+
+ '# -O1 level 1 optimizations (quick optimizations)'#013#010+
+ '# -O2 level 2 optimizations (-O1 + slower optimizations)'#013#010+
+ '# -O3 level 3 optimizations (same as -O2u)'#013#010+
+ '# -Op target processor'#013#010+
+ '# -Op1 set target pr','ocessor to 386/486'#013#010+
+ '# -Op2 set target processor to Pentium/PentiumMMX (tm)'#013#010+
+ '# -Op3 set target processor to PPro/PII/c6x86/K6 (tm)'#013#010+
+ #013#010+
+ '# Optimize always for Size and PII'#013#010+
+ '#-OG2p3'#013#010+
+ #013#010+
+ #013#010+
+ '# -----------------------'#013#010+
+ '# Set Filenames and P','aths'#013#010+
+ '# -----------------------'#013#010+
+ #013#010+
+ '# Both slashes and backslashes are allowed in paths'#013#010+
+ #013#010+
+ '# path to the messagefile, not necessary anymore but can be used to ov'+
+ 'erride'#013#010+
+ '# the default language'#013#010+
+ '#-Fr%basepath%/msg/errore.msg'#013#010+
+ '#-Fr%basepath%/ms','g/errorn.msg'#013#010+
+ '#-Fr%basepath%/msg/errores.msg'#013#010+
+ '#-Fr%basepath%/msg/errord.msg'#013#010+
+ '#-Fr%basepath%/msg/errorr.msg'#013#010+
+ #013#010+
+ '# path to the gcclib'#013#010+
+ '#-Fl%basepath%/lib'#013#010+
+ #013#010+
+ '# searchpath for includefiles'#013#010+
+ '#-Fi/pp/inc;/pp/rtl/inc'#013#010+
+ #013#010+
+ '# searchpath for includefile','s'#013#010+
+ '# release them only if you know what you do'#013#010+
+ '# because this could cause a rebuild of the runtime library'#013#010+
+ '# if you tell them compiler/ide to build the project (FK)'#013#010+
+ '#-Fi%basepath%/source/rtl/inc;%basepath%/source/rtl/i386'#013#010+
+ #013#010+
+ '# searchpath',' for objectfiles'#013#010+
+ '#-Fo%basepath%/source/rtl/inc;%basepath%/source/rtl/i386'#013#010+
+ #013#010+
+ '# searchpath for units and other system dependent things'#013#010+
+ '-Fu%basepath%/units/$FPCTARGET/'#013#010+
+ '-Fu%basepath%/units/$FPCTARGET/*'#013#010+
+ '-Fu%basepath%/units/$FPCTARGET/rtl'#013#010+
+ #013,#010+
+ '# searchpath for libraries'#013#010+
+ '#-Fl%basepath%/lib'#013#010+
+ '#-Fl/lib;/usr/lib'#013#010+
+ #013#010+
+ '# searchpath for tools'#013#010+
+ '-FD%basepath%/bin/$FPCTARGET'#013#010+
+ #013#010+
+ #013#010+
+ '# -------------'#013#010+
+ '# Linking'#013#010+
+ '# -------------'#013#010+
+ #013#010+
+ '# generate always debugging information for GDB (slows down the c','omp'+
+ 'iling'#013#010+
+ '# process)'#013#010+
+ '# -gc generate checks for pointers'#013#010+
+ '# -gd use dbx'#013#010+
+ '# -gg use gsym'#013#010+
+ '# -gh use heap trace unit (for memory leak debugging)'#013#010+
+ '# -gl use line info unit to show mor','e info for backtrace'+
+ 's'#013#010+
+ '# -gv generates programs tracable with valgrind'#013#010+
+ '# -gw generate dwarf debugging info'#013#010+
+ '#'#013#010+
+ '# Enable debuginfo and use the line info unit by default'#013#010+
+ '#-gl'#013#010+
+ #013#010+
+ '# always pass an option to the linker'#013,#010+
+ '#-k-s'#013#010+
+ #013#010+
+ '# Always strip debuginfo from the executable'#013#010+
+ '-Xs'#013#010+
+ #013#010+
+ #013#010+
+ '# -------------'#013#010+
+ '# Miscellaneous'#013#010+
+ '# -------------'#013#010+
+ #013#010+
+ '# Write always a nice FPC logo ;)'#013#010+
+ '-l'#013#010+
+ #013#010+
+ '# Verbosity'#013#010+
+ '# e : Show errors (default) d : Show debug info'#013#010+
+ '# w',' : Show warnings u : Show unit info'#013#010+
+ '# n : Show notes t : Show tried/used files'#013#010+
+ '# h : Show hints m : Show defined macros'#013#010+
+ '# i : Show general info p : Show compiled pr','ocedures'#013+
+ #010+
+ '# l : Show linenumbers c : Show conditionals'#013#010+
+ '# a : Show everything 0 : Show nothing (except errors'+
+ ')'#013#010+
+ '# b : Show all procedure r : Rhide/GCC compatibility mod'+
+ 'e'#013#010+
+ '# declaration','s if an error x : Executable info (Win32 on'+
+ 'ly)'#013#010+
+ '# occurs'#013#010+
+ '#'#013#010+
+ '# Display Info, Warnings, Notes and Hints'#013#010+
+ '-viwn'#013#010+
+ '# If you don'#039't want so much verbosity use'#013#010+
+ '#-vw'#013#010
+);
diff --git a/compiler/utils/fpcmkcfg.pp b/compiler/utils/fpcmkcfg.pp
new file mode 100644
index 0000000000..802885b70d
--- /dev/null
+++ b/compiler/utils/fpcmkcfg.pp
@@ -0,0 +1,230 @@
+{$mode objfpc}
+{$H+}
+{
+ This file is part of Free Pascal Build tools
+ Copyright (c) 2005 by Michael Van Canneyt
+
+ Create a configuration file
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program fpcmkcfg;
+
+uses usubst,SysUtils,Classes;
+
+{
+ The fpccfg.inc file must be built from a template with the bin2obj
+ command. it needs options:
+ bin2obj -a -o fpccfg.inc -c DefaultConfig fpc.cft
+ where fpc.cft is the template file.
+}
+
+{$i fpccfg.inc}
+
+Const
+ BuildVersion={$I %FPCVERSION%};
+ BuildTarget={$I %FPCTARGET%};
+
+
+Resourcestring
+ SUsage00 = 'Usage: %s [options]';
+ SUsage10 = 'Where options is one or more of';
+ SUSage20 = ' -t filename Template file name. Default is built-in';
+ SUSage30 = ' -o filename Set output file. Default is standard output.';
+ SUsage40 = ' -d name=value define name=value pair.';
+ SUsage50 = ' -h show this help and exit.';
+ SUsage60 = ' -u name remove name from list of name/value pairs.';
+ SUsage70 = ' -l filename read name/value pairs from filename';
+ SUsage80 = ' -b show builtin template and exit.';
+ SUsage90 = ' -v be verbose.';
+ SErrUnknownOption = 'Error: Unknown option.';
+ SErrArgExpected = 'Error: Option "%s" requires an argument.';
+ SErrNoSuchFile = 'Error: File "%s" does not exist.';
+ SErrBackupFailed = 'Error: Backup of file "%s" to "%s" failed.';
+ SErrDelBackupFailed = 'Error: Delete of old backup file "%s" failed.';
+ SWarnIgnoringFile = 'Warning: Ignoring non-existent file: ';
+ SWarnIgnoringPair = 'Warning: ignoring wrong name/value pair: ';
+ SStats = 'Replaced %d placeholders in %d lines.';
+ SSubstInLine = 'Replaced %s placeholders in line %d.';
+
+
+Var
+ Verbose : Boolean;
+ SkipBackup : Boolean;
+ List,Cfg : TStringList;
+ TemplateFileName,
+ OutputFileName : String;
+
+
+
+
+procedure Init;
+
+begin
+ Verbose:=False;
+ List:=TStringList.Create;
+ AddToList(List,'FPCVERSION',BuildVersion);
+ AddToList(List,'FPCTARGET',BuildTarget);
+ AddToList(List,'PWD',GetCurrentDir);
+ AddToList(List,'BUILDDATE',DateToStr(Date));
+ AddToList(List,'BUILDTIME',TimeToStr(Time));
+ Cfg:=TStringList.Create;
+ Cfg.Text:=StrPas(Addr(DefaultConfig));
+end;
+
+Procedure Done;
+
+begin
+ FreeAndNil(List);
+ FreeAndNil(Cfg);
+end;
+
+Procedure Usage;
+
+begin
+ Writeln(Format(SUsage00,[ExtractFileName(Paramstr(0))]));
+ Writeln(SUsage10);
+ Writeln(SUsage20);
+ Writeln(SUsage30);
+ Writeln(SUsage40);
+ Writeln(SUsage50);
+ Writeln(SUsage60);
+ Writeln(SUsage70);
+ Writeln(SUsage80);
+ Writeln(SUsage90);
+ Halt(1);
+end;
+
+Procedure UnknownOption(Const S : String);
+
+begin
+ Writeln(SErrUnknownOption,S);
+ Usage;
+end;
+
+Procedure ShowBuiltIn;
+
+Var
+ I : Integer;
+
+
+begin
+ For I:=0 to Cfg.Count-1 do
+ Writeln(Cfg[I]);
+end;
+
+
+Procedure ProcessCommandline;
+
+Var
+ I : Integer;
+ S : String;
+
+ Function GetOptArg : String;
+
+ begin
+ If I=ParamCount then
+ begin
+ Writeln(StdErr,Format(SErrArgExpected,[S]));
+ Halt(1);
+ end;
+ inc(I);
+ Result:=ParamStr(I);
+ end;
+
+begin
+ I:=1;
+ While( I<=ParamCount) do
+ begin
+ S:=Paramstr(i);
+ If Length(S)<=1 then
+ UnknownOption(S)
+ else
+ case S[2] of
+ 'v' : Verbose:=True;
+ 'h' : Usage;
+ 'b' : begin
+ ShowBuiltin;
+ halt(0);
+ end;
+ 't' : TemplateFileName:=GetOptArg;
+ 'd' : AddPair(List,GetOptArg);
+ 'u' : AddPair(List,GetOptArg+'=');
+ 'o' : OutputFileName:=GetoptArg;
+ 's' : SkipBackup:=True;
+ else
+ UnknownOption(S);
+ end;
+ Inc(I);
+ end;
+ If (TemplateFileName<>'') then
+ begin
+ If Not FileExists(TemplateFileName) then
+ begin
+ Writeln(StdErr,Format(SErrNoSuchFile,[TemplateFileName]));
+ Halt(1);
+ end;
+ Cfg.LoadFromFile(TemplateFileName);
+ AddToList(List,'TEMPLATEFILE',TemplateFileName);
+ end
+ else
+ AddToList(List,'TEMPLATEFILE','builtin');
+end;
+
+
+Procedure CreateFile;
+
+Var
+ Fout : Text;
+ S,BFN : String;
+ I,RCount : INteger;
+
+begin
+ If (OutputFileName<>'')
+ and FileExists(OutputFileName)
+ and not SkipBackup then
+ begin
+ BFN:=ChangeFileExt(OutputFileName,'.bak');
+ If FileExists(BFN) and not DeleteFile(BFN) then
+ begin
+ Writeln(StdErr,Format(SErrDelBackupFailed,[BFN]));
+ Halt(1);
+ end;
+ If not RenameFile(OutputFileName,BFN) then
+ begin
+ Writeln(StdErr,Format(SErrBackupFailed,[OutputFileName,BFN]));
+ Halt(1);
+ end;
+ end;
+ Assign(Fout,OutputFileName);
+ Rewrite(FOut);
+ Try
+ RCount:=0;
+ For I:=0 to Cfg.Count-1 do
+ begin
+ S:=Cfg[i];
+ Inc(RCount,DoSubstitutions(List,S));
+ Writeln(FOut,S);
+ end;
+ If Verbose then
+ Writeln(StdErr,Format(SStats,[RCount,Cfg.Count]));
+ Finally
+ Close(Fout);
+ end;
+end;
+
+begin
+ Init;
+ Try
+ ProcessCommandLine;
+ CreateFile;
+ Finally
+ Done;
+ end;
+end.
diff --git a/compiler/utils/fpcsubst.pp b/compiler/utils/fpcsubst.pp
new file mode 100644
index 0000000000..cb82a162bf
--- /dev/null
+++ b/compiler/utils/fpcsubst.pp
@@ -0,0 +1,241 @@
+{$Mode objfpc}
+{$H+}
+program fpcsubst;
+
+uses SysUtils,Classes,Usubst;
+
+Const
+ BuildVersion={$I %FPCVERSION%};
+ BuildTarget={$I %FPCTARGET%};
+
+Resourcestring
+ SUsage00 = 'Usage: %s [options]';
+ SUsage10 = 'Where options is one or more of';
+ SUSage20 = ' -i filename Set input file. Default is standard input';
+ SUSage30 = ' -o filename Set output file. Default is standard output.';
+ SUsage40 = ' -d name=value define name=value pair.';
+ SUsage50 = ' -h show this help and exit.';
+ SUsage60 = ' -u name remove name from list of name/value pairs.';
+ SUsage70 = ' -l filename read name/value pairs from filename';
+ SUsage80 = ' -b show builtin list and exit.';
+ SUsage90 = ' -v be verbose.';
+ SErrUnknownOption = 'Error: Unknown option.';
+ SErrArgExpected = 'Error: Option "%s" requires an argument.';
+ SErrNoSuchFile = 'Error: File "%s" does not exist.';
+ SErrBackupFailed = 'Error: Backup of file "%s" to "%s" failed.';
+ SErrDelBackupFailed = 'Error: Delete of old backup file "%s" failed.';
+ SWarnIgnoringFile = 'Warning: Ignoring non-existent file: ';
+ SWarnIgnoringPair = 'Warning: ignoring wrong name/value pair: ';
+ SStats = 'Replaced %d placeholders in %d lines.';
+ SSubstInLine = 'Replaced %s placeholders in line %d.';
+
+
+Var
+ List : TStringList;
+ InputFileName : String;
+ OutputFileName : String;
+ Verbose : Boolean;
+ SkipBackup : Boolean;
+
+
+
+
+
+procedure Init;
+
+begin
+ Verbose:=False;
+ List:=TStringList.Create;
+ AddToList(List,'FPCVERSION',BuildVersion);
+ AddToList(List,'FPCTARGET',BuildTarget);
+ AddToList(List,'PWD',GetCurrentDir);
+ AddToList(List,'BUILDDATE',DateToStr(Date));
+ AddToList(List,'BUILDTIME',TimeToStr(Time));
+end;
+
+Procedure Done;
+
+begin
+ FreeAndNil(List);
+end;
+
+Procedure Usage;
+
+begin
+ Writeln(Format(SUsage00,[ExtractFileName(Paramstr(0))]));
+ Writeln(SUsage10);
+ Writeln(SUsage20);
+ Writeln(SUsage30);
+ Writeln(SUsage40);
+ Writeln(SUsage50);
+ Writeln(SUsage60);
+ Writeln(SUsage70);
+ Writeln(SUsage80);
+ Writeln(SUsage90);
+ Halt(1);
+end;
+
+Procedure ShowBuiltIns;
+
+var
+ I : Integer;
+
+begin
+ for I:=0 to List.Count-1 do
+ Writeln(List[i]);
+end;
+
+
+
+
+Procedure AddFromFile(FN : String);
+
+Var
+ F : Text;
+ S : String;
+
+begin
+ If Not FileExists(FN) then
+ begin
+ Writeln(StdErr,SWarnIgnoringFile,FN);
+ Exit;
+ end;
+ Assign(F,FN);
+ Reset(F);
+ Try
+ While not EOF(F) do
+ begin
+ ReadLn(F,S);
+ If (Length(S)>0) and (not (S[1] in ['#',';'])) then
+ If not AddPair(List,S) then
+ If Verbose then
+ Writeln(StdErr,SWarnIgnoringPair,S)
+ end;
+ finally
+ Close(F);
+ end;
+end;
+
+Procedure UnknownOption(Const S : String);
+
+begin
+ Writeln(SErrUnknownOption,S);
+ Usage;
+end;
+
+Procedure ProcessCommandline;
+
+Var
+ I : Integer;
+ S : String;
+
+ Function GetOptArg : String;
+
+ begin
+ If I=ParamCount then
+ begin
+ Writeln(StdErr,Format(SErrArgExpected,[S]));
+ Halt(1);
+ end;
+ inc(I);
+ Result:=ParamStr(I);
+ end;
+
+begin
+ I:=1;
+ While( I<=ParamCount) do
+ begin
+ S:=Paramstr(i);
+ If (Length(S)<=1) or (S[1]<>'-') then
+ UnknownOption(S)
+ else
+ case S[2] of
+ 'v' : Verbose:=True;
+ 'h' : Usage;
+ 'b' : begin
+ ShowBuiltins;
+ halt(0);
+ end;
+ 'l' : AddFromFile(GetOptArg);
+ 'd' : AddPair(List,GetOptArg);
+ 'u' : AddPair(List,GetOptArg+'=');
+ 'i' : InputFileName:=GetOptArg;
+ 'o' : OutputFileName:=GetoptArg;
+ 's' : SkipBackup:=True;
+ else
+ UnknownOption(S);
+ end;
+ Inc(I);
+ end;
+end;
+
+
+
+Procedure DoFile;
+
+Var
+ Fin,Fout : Text;
+ S,BFN : String;
+ N,LCount,RCount : Integer;
+
+
+begin
+ If (InputFileName<>'') and not FileExists(InputFIleName) then
+ begin
+ Writeln(StdErr,Format(SErrNoSuchFile,[InputFileName]));
+ Halt(1)
+ end;
+ If (OutputFileName<>'')
+ and FileExists(OutputFileName)
+ and not SkipBackup then
+ begin
+ BFN:=ChangeFileExt(OutputFileName,'.bak');
+ If FileExists(BFN) and not DeleteFile(BFN) then
+ begin
+ Writeln(StdErr,Format(SErrDelBackupFailed,[BFN]));
+ Halt(1);
+ end;
+ If not RenameFile(OutputFileName,BFN) then
+ begin
+ Writeln(StdErr,Format(SErrBackupFailed,[OutputFileName,BFN]));
+ Halt(1);
+ end;
+ end;
+ Assign(Fin,InputFileName);
+ Assign(Fout,OutputFileName);
+ Reset(Fin);
+ Try
+ Rewrite(FOut);
+ Try
+ LCount:=0;
+ RCount:=0;
+ While Not EOF(Fin) do
+ begin
+ Inc(LCount);
+ ReadLn(Fin,S);
+ N:=DoSubstitutions(List,S);
+ If Verbose and (N>0) then
+ Writeln(StdErr,Format(SSubstInLine,[N,LCount]));
+ Inc(RCount,N);
+ Writeln(Fout,S);
+ end;
+ If Verbose then
+ Writeln(StdErr,Format(SStats,[RCount,LCount]));
+ Finally
+ Close(Fout);
+ end;
+ Finally
+ Close(Fin);
+ end;
+
+end;
+
+begin
+ Init;
+ Try
+ ProcessCommandLine;
+ DoFile;
+ Finally
+ Done;
+ end;
+end.
diff --git a/compiler/utils/fpimpdef.pp b/compiler/utils/fpimpdef.pp
new file mode 100644
index 0000000000..323cb3be95
--- /dev/null
+++ b/compiler/utils/fpimpdef.pp
@@ -0,0 +1,98 @@
+{$APPTYPE CONSOLE}
+program FPimpdef;
+{$DEFINE STANDALONE}
+{$IFNDEF FPC}
+uses
+ dmisc,
+ ImpDef;
+{$ELSE}
+uses
+ DOS,
+ ImpDef;
+{$ENDIF}
+var
+binname:string;
+function Ofound(const short,full:string):longint;
+var
+ i:longint;
+begin
+ Ofound:=-1;
+ for i:=1 to ParamCount do
+ if(paramstr(i)=short)or(paramstr(i)=full)then
+ begin
+ Ofound:=i;
+ exit;
+ end;
+end;
+function GetOption(const short,full:string):string;
+var
+ i:longint;
+begin
+ i:=Ofound(short,full);
+ if i>0 then
+ GetOption:=paramstr(succ(i))
+ else
+ GetOption:='';
+end;
+procedure help_info;
+var
+ fn:string[255];
+ jj:cardinal;
+begin
+ fn:=paramstr(0);
+ for jj:=length(fn)downto 1 do
+ if fn[jj] in [':','\','/']then
+ begin
+ fn:=copy(fn,succ(jj),255);
+ break;
+ end;
+ writeln('Usage: ',fn,' [options]');
+ writeln('Options:');
+ writeln('-i | --input <file> - set input file;');
+ writeln('-o | --output <file> - set output .def file');
+ writeln('-l | --library <file> - set output static library');
+ writeln('-s | --assembler <name> - use <name> for assembler (default asw)');
+ writeln('-r | --archiver <name> - use <name> for archiver (default arw)');
+ writeln('-h | --help - show this screen');
+ halt;
+end;
+{$ifndef UNIX}
+procedure AddExt(var s:string);
+ var
+ s1:string;
+ i:longint;
+ begin
+ s1:=copy(s,length(s)-3,4);
+ for i:=1 to length(s1)do
+ s1[i]:=upcase(s1[i]);
+ if s1<>'.EXE'then
+ s:=s+'.EXE';
+ end;
+{$endif}
+var
+ EnvPath:string;
+begin
+binname:=GetOption('-i','--input');
+if(binname='')or(Ofound('-h','--help')>0)then
+ help_info;
+ as_name:=GetOption('-s','--assembler');
+ if as_name='' then
+ as_name:='as';
+ ar_name:=GetOption('-r','--archiver');
+ if ar_name='' then
+ ar_name:='ar';
+{$ifndef UNIX}
+ AddExt(as_name);
+ AddExt(ar_name);
+{$endif}
+ EnvPath:=GetEnv('Path');
+ if EnvPath='' then
+ EnvPath:=GetEnv('PATH');
+ as_name:=FSearch(as_name,EnvPath);
+ ar_name:=FSearch(ar_name,EnvPath);
+if not makedef(binname,GetOption('-o','--output'),GetOption('-l','--library'))then
+ begin
+ writeln('Export names not found');
+ halt(1);
+ end;
+end.
diff --git a/compiler/utils/fppkg.pp b/compiler/utils/fppkg.pp
new file mode 100644
index 0000000000..eed82ff964
--- /dev/null
+++ b/compiler/utils/fppkg.pp
@@ -0,0 +1,963 @@
+program fppkg;
+
+{$mode objfpc}{$H+}
+
+uses
+ Classes, SysUtils, TypInfo
+ { add your units here };
+
+Resourcestring
+ // SErrInValidArgument = 'Invalid command-line argument at position %d : %s';
+ SErrNeedArgument = 'Option at position %d (%s) needs an argument';
+ SErrMissingConfig = 'Missing configuration Makefile.fpc or fpmake.pp';
+ SErrRunning = 'The FPC make tool encountered the following error: %s';
+ SErrFailedToCompileFPCMake = 'Could not compile fpmake driver program';
+ SLogGeneratingFPMake = 'Generating fpmake.pp';
+ SLogCompilingFPMake = 'Compiling fpmake.pp: ';
+ SLogRunningFPMake = 'Running fpmake';
+
+Type
+
+ TRunMode = (rmHelp,rmCompile,rmBuild,rmInstall,rmArchive,rmClean,rmDownload);
+
+ { TMakeTool }
+
+ TMakeTool = Class(TObject)
+ Private
+ FConvertOnly,
+ FLogging : Boolean;
+ FCompiler : String;
+ FRunMode : TRunMode;
+ FHaveMakefile : Boolean;
+ FHaveFpmake : Boolean;
+ FFPMakeSrc : String;
+ FFPMakeBin : String;
+ Procedure Log(Msg : String);
+ Procedure Error(Msg : String);
+ Procedure Error(Fmt : String; Args : Array of const);
+ Function GetCompiler : String;
+ Public
+ Procedure ProcessCommandLine;
+ procedure CreateFPMake;
+ procedure CompileFPMake(Extra : Boolean);
+ Function RunFPMake : Integer;
+ Procedure Run;
+ end;
+
+ EMakeToolError = Class(Exception);
+
+
+ { TMakeFileConverter }
+ TSectionType = (stNone,stPackage,stTarget,stclean,stinstall,stCompiler,
+ stDefault,stRequire,stRules,stPrerules);
+
+ TMakeFileConverter = Class(TObject)
+ FSection : TSectionType;
+ FPackageName,
+ FpackageDir,
+ FPackageOptions,
+ FPackageDeps,
+ FBuilDUnit,
+ FSubName,
+ FPackageVersion : String;
+ // Reading;
+ procedure DoPackageLine(Const S : String);
+ Procedure DoTargetLine(Line : String; Var T,R,D : TStrings);
+ Procedure DoInstallLine(Line : String; Var IFL : TStrings);
+ procedure DoCleanLine(Line : String; Var CFL : TStrings);
+ procedure DoRequireLine(Line : String);
+ procedure DoCompilerLine(Line : String;Var SD : TStrings);
+ // Writing;
+ procedure WriteOSCPUCheck(Src: TStrings;OS,CPU : String);
+ procedure StartPackage(Src : TStrings; Dir,OS : String);
+ procedure EndPackage(Src : TStrings; Dir,OS : String);
+ procedure DoTargets(Src,T,R,SD : TStrings; Dir,Prefix : String);
+ procedure DoCleans(Src,CFL : TStrings);
+ procedure DoInstalls(Src,IFL : TStrings);
+ Procedure StartInstaller(Src : TStrings);
+ Procedure EndInstaller(Src : TStrings);
+ Function GetLine (L : TStrings; Var I : Integer) : String;
+ Public
+ procedure ConvertFile(const AFileName: String; Src: TStrings; Dir,OS : String);
+ Procedure ConvertFile(Const Source,Dest: String);
+ end;
+
+{ Auxiliary functions }
+
+Function GetWord(var S : String; Sep : Char) : String;
+
+Var
+ L : Integer;
+
+begin
+ L:=Pos(Sep,S);
+ If (L=0) then
+ L:=Length(S)+1;
+ Result:=Copy(S,1,L-1);
+ Delete(S,1,L);
+ S:=Trim(S);
+end;
+
+Function GetWord(var S : String) : String;
+
+begin
+ Result:=GetWord(S,' ');
+end;
+
+
+Function IsCPU (S: String) : Boolean;
+
+begin
+ Result:=Pos(lowercase(S)+',','i386,powerpc,arm,alpha,sparc,')<>0
+end;
+
+Function GetOSCPU(L : String; var OS,CPU : String) : String;
+
+ Procedure Add(Var A : String; ad : String);
+
+ begin
+ If (A<>'') then
+ A:=A+',';
+ A:=A+ad;
+ end;
+
+
+Var
+ S : String;
+
+begin
+ OS:='';
+ CPU:='';
+ S:=GetWord(L,',');
+ While (S<>'') do
+ begin
+ If (S<>'all') then
+ If IsCPU(S) then
+ Add(CPU,S)
+ else
+ Add(OS,S);
+ S:=GetWord(L,',');
+ end;
+end;
+
+
+{ TMakeFileConverter }
+
+procedure TMakeFileConverter.StartInstaller(Src: TStrings);
+
+begin
+ With Src do
+ begin
+ Add('{$mode objfpc}{$H+}');
+ Add('program fpmake;');
+
+ Add('');
+ Add(' { Generated automatically by '+ExtractFileName(Paramstr(0))+' on '+DateToStr(Sysutils.Date)+' }');
+ Add('');
+ Add('uses fpmkunit;');
+ Add('');
+ Add('Var');
+ Add(' T : TTarget;');
+ Add('');
+ Add('begin');
+ Add(' With Installer do ');
+ Add(' begin');
+ end;
+end;
+
+procedure TMakeFileConverter.EndInstaller(Src: TStrings);
+begin
+ With Src do
+ begin
+ Add(' Run;');
+ Add(' end;');
+ Add('end.');
+ Add('');
+ end;
+end;
+
+Function TMakeFileConverter.GetLine (L : TStrings; Var I : Integer) : String;
+
+Var
+ P : Integer;
+ OK : Boolean;
+
+begin
+ OK:=False;
+ Result:='';
+ Repeat
+ Result:=Result+L[i];
+ P:=Pos('#',Result);
+ If (P>0) then
+ Result:=Copy(Result,1,P-1);
+ Result:=Trim(Result);
+ P:=Length(Result);
+ If (P>0) and (Result[P]='\') then
+ Result:=Copy(Result,1,P-1)
+ else
+ OK:=(Result<>'');
+ if Not OK then
+ Inc(I);
+ Until OK or (I>L.Count-1);
+end;
+
+Function SplitNamevalue(Const S : String; Var AName,AValue : String) : boolean;
+
+var
+ L : Integer;
+
+begin
+ L:=Pos('=',S);
+ Result:=(L<>0);
+ If Result then
+ begin
+ AName:=LowerCase(trim(Copy(S,1,L-1)));
+ AValue:=S;
+ Delete(AValue,1,L);
+ AValue:=Trim(Avalue);
+ end
+ else
+ begin
+ AName:='';
+ AValue:='';
+ end;
+end;
+
+
+procedure TMakeFileConverter.StartPackage(Src : TStrings; Dir,OS : String);
+
+Var
+ S : String;
+
+begin
+ With Src do
+ begin
+ Add(' { ');
+ Add(' '+FPackageName);
+ Add(' } ');
+ Add(' StartPackage('''+FPackageName+''');');
+ If (Dir<>'') then
+ Add(' Directory:='''+ExcludeTrailingPathDelimiter(Dir)+''';');
+ If (OS<>'') and (OS<>'all') then
+ Add(' OS:=['+OS+'];');
+ If (FPackageVersion<>'') then
+ Add(' Version:='''+FPackageVersion+''';');
+ If (FPackageOptions<>'') then
+ Add(' Options:='''+FPackageOptions+''';');
+ If (FPackageDeps<>'') then
+ begin
+ S:=GetWord(FPackageDeps);
+ While S<>'' do
+ begin
+ Add(' Dependencies.Add('''+S+''');');
+ S:=GetWord(FPackageDeps);
+ end;
+ end;
+ end;
+end;
+
+procedure TMakeFileConverter.EndPackage(Src : TStrings; Dir,OS : String);
+
+begin
+ Src.add(' EndPackage;');
+ FPackageName:='';
+ FPackageVersion:='';
+ FPackageOptions:='';
+ FBuilDUnit:='';
+ FPackageDeps:='';
+end;
+
+
+procedure TMakeFileConverter.DoPackageLine(Const S : String);
+
+Var V,N : String;
+
+begin
+ SplitNameValue(S,N,V);
+ If (N='name') then
+ FPackageName:=V
+ else If (N='version') then
+ FPackageVersion:=V
+ else If (N='main') then
+ begin
+ FPackageName:='sub';
+ FSubName:=V;
+ end
+ else
+ Writeln(StdErr,'Unknown name/value pair in package section :',N);
+end;
+
+
+{
+ Convert various entries of type
+ XXYY_OSN=words
+ to entries of type
+ prefix_word=OS1,OS2,OS3
+ OS is never empty, 'all' is default.
+ }
+Procedure AddStrings(Var L : TStrings; Values,Prefix,OS : String) ;
+
+Var
+ S,O : String;
+ i : integer;
+
+begin
+ If (L=Nil) then
+ L:=TstringList.Create;
+ If prefix<>'' then
+ prefix:=prefix+'_';
+ S:=GetWord(Values);
+ While (S<>'') do
+ begin
+ S:=Prefix+S;
+ I:=L.IndexOfName(S);
+ If (I<>-1) then
+ begin
+ O:=L.Values[S];
+ If (O='all') then
+ O:='';
+ If (O<>'') then
+ O:=O+',';
+ O:=O+OS;
+ L.Values[S]:=O;
+ end
+ else
+ L.Add(S+'='+OS);
+ S:=GetWord(Values);
+ end;
+end;
+
+
+procedure TMakeFileConverter.DoTargetLine(Line : String; Var T,R,D : TStrings);
+
+Var
+ V,N,OS : String;
+ P : Integer;
+
+begin
+ SplitNameValue(Line,N,V);
+ P:=Pos('_',N);
+ If (P=0) then
+ OS:='all'
+ else
+ begin
+ OS:=N;
+ Delete(OS,1,P);
+ N:=Copy(N,1,P-1);
+ end;
+ If (N='dirs') then
+ AddStrings(D,V,'',OS)
+ else If (N='units') then
+ AddStrings(T,V,'unit',OS)
+ else If (N='implicitunits') then
+ AddStrings(T,V,'unit',OS)
+ else If (N='programs') then
+ AddStrings(T,V,'program',OS)
+ else If (N='examples') then
+ AddStrings(T,V,'exampleunit',OS)
+ else If (N='rsts') then
+ AddStrings(R,V,'',OS)
+ else
+ Writeln(StdErr,'Unknown name/value pair in target section : ',Line);
+end;
+
+procedure TMakeFileConverter.DoInstallLine(Line : String; Var IFL : TStrings);
+
+Var
+ S,V,N,OS : String;
+ P : Integer;
+
+begin
+ SplitNameValue(Line,N,V);
+ P:=Pos('_',N);
+ If (P=0) then
+ OS:='all'
+ else
+ begin
+ OS:=N;
+ Delete(OS,1,P);
+ N:=Copy(N,1,P-1);
+ end;
+ If (N='fpcpackage') then
+ P:=0 // temporary, needs fixing.
+ else If (N='buildunit') then
+ FBuildUnit:=V // temporary, needs fixing.
+ else If (N='units') then
+ begin
+ S:=GetWord(V);
+ While (S<>'') do
+ begin
+ AddStrings(IFL,S+'.o','',OS);
+ AddStrings(IFL,S+'.ppu','',OS);
+ S:=GetWord(V);
+ end;
+ end
+ else
+ Writeln(StdErr,'Unknown name/value pair in install section : ',N);
+end;
+
+procedure TMakeFileConverter.DoCleanLine(Line : String; Var CFL : TStrings);
+
+Var
+ V,N,S,OS : String;
+ P : Integer;
+
+begin
+ SplitNameValue(Line,N,V);
+ P:=Pos('_',N);
+ If (P=0) then
+ OS:='all'
+ else
+ begin
+ OS:=N;
+ Delete(OS,1,P);
+ N:=Copy(N,1,P-1);
+ end;
+ If (N='fpcpackage') then
+ P:=0 // temporary, needs fixing.
+ else If (N='units') then
+ begin
+ S:=GetWord(V);
+ While (S<>'') do
+ begin
+ AddStrings(CFL,S+'.o','',OS);
+ AddStrings(CFL,S+'.ppu','',OS);
+ S:=GetWord(V);
+ end;
+ end
+ else
+ Writeln(StdErr,'Unknown name/value pair in clean section : ',N);
+end;
+
+procedure TMakeFileConverter.DoRequireLine(Line : String);
+
+Var
+ V,N,OS : String;
+ P : Integer;
+
+begin
+ SplitNameValue(Line,N,V);
+ P:=Pos('_',N);
+ If (P=0) then
+ OS:='all'
+ else
+ begin
+ OS:=N;
+ Delete(OS,1,P);
+ N:=Copy(N,1,P-1);
+ end;
+ if (N='packages') then
+ FPackageDeps:=V
+ else If (N='libc') and (Upcase(V)='Y') then
+ P:=0 // Set options ?
+ else
+ Writeln(StdErr,'Unknown name/value pair in require section : ',N);
+end;
+
+
+procedure TMakeFileConverter.DoCompilerLine(Line : String;Var SD : TStrings);
+
+Var
+ V,N,OS : String;
+ P : Integer;
+
+begin
+ SplitNameValue(Line,N,V);
+ P:=Pos('_',N);
+ If (P=0) then
+ OS:='all'
+ else
+ begin
+ OS:=N;
+ Delete(OS,1,P);
+ N:=Copy(N,1,P-1);
+ end;
+ If (N='includedir') then
+ FPackageOptions:=Trim(FPackageOptions+' -Fi'+V)
+ else If (N='options') then
+ FPackageOptions:=Trim(FPackageOptions+' '+V)
+ else If (N='targetdir') then
+ P:=0 // Ignore
+ else if (N='sourcedir') or (N='unitdir') then
+ begin
+ If (SD=Nil) then
+ SD:=TStringList.Create;
+ SD.Add(OS+'='+V);
+ end
+ else
+ Writeln(StdErr,'Unknown name/value pair in compiler section : ',N);
+end;
+
+Function SearchInDirs(Prefix,AName, Dirs : String) : string;
+
+Var
+ D,S : String;
+
+begin
+ S:=GetWord(Dirs);
+ Result:='';
+ While (Result='') and (S<>'') do
+ begin
+ D:=Prefix+S+PathDelim;
+ If FileExists(D+AName+'.pp') or FileExists(D+AName+'.pas') then
+ Result:=S;
+ S:=GetWord(Dirs);
+ end;
+end;
+
+procedure TMakeFileConverter.DoTargets(Src,T,R,SD : TStrings; Dir,Prefix : String);
+
+Var
+ I,J,P : Integer;
+ Pre,N,V,D,DOS,OS,CPU : String;
+ Res : Boolean;
+
+begin
+ If (Dir<>'') then
+ Dir:=IncludeTrailingPathDelimiter(Dir);
+ If (Prefix<>'') then
+ Prefix:=IncludeTrailingPathDelimiter(Prefix);
+ Dir:=Prefix+Dir;
+ Res:=False;
+ If Assigned(T) then
+ For I:=0 to T.Count-1 do
+ begin
+ T.GetNamevalue(I,N,V);
+ P:=Pos('_',N);
+ If (P<>0) then
+ begin
+ Pre:=Copy(N,1,P-1);
+ Delete(N,1,P);
+ end;
+ If Assigned(R) then
+ Res:=R.IndexOfName(N)<>-1;
+ GetOSCPU(V,OS,CPU);
+ Pre[1]:=Upcase(Pre[1]);
+ Src.Add(' T:=Targets.Add'+Pre+'('''+Prefix+N+''');');
+ If (CPU<>'') then
+ Src.Add(' T.CPU:=['+CPU+'];');
+ If (OS<>'') then
+ Src.Add(' T.OS:=['+OS+'];');
+ If res then
+ Src.add(' T.ResourceStrings:=True;');
+ If (CompareText(FBuildUnit,N)=0) then
+ Src.add(' T.Install:=False;');
+ if Assigned(SD) then
+ for J:=0 to SD.Count-1 do
+ begin
+ SD.GetNameValue(J,DOS,D);
+ If (DOS<>'all') then
+ Src.Add(' if (Defaults.OS='+DOS+') then');
+ Src.add(' T.Directory:='''+SearchInDirs(Dir,N,D)+''';');
+ end;
+ end;
+end;
+
+procedure TMakeFileConverter.WriteOSCPUCheck(Src: TStrings;OS,CPU : String);
+
+Var
+ S : String;
+
+begin
+ If (CPU<>'') then
+ S:='(Defaults.CPU='+CPU+')';
+ If (OS<>'') then
+ begin
+ IF (S<>'') then
+ S:=S+' OR ';
+ S:=S+'(Defaults.OS='+CPU+')';
+ end;
+ If (S<>'') then
+ Src.Add(' If '+S+' then');
+end;
+
+procedure TMakeFileConverter.DoInstalls(Src,IFL : TStrings);
+
+Var
+ I,J,P : Integer;
+ Pre,N,V,D,DOS,OS,CPU : String;
+
+begin
+ If Assigned(IFL) then
+ For I:=0 to IFL.Count-1 do
+ begin
+ IFL.GetNamevalue(I,N,V);
+ GetOSCPU(V,OS,CPU);
+ WriteOSCPUCheck(Src,OS,CPU);
+ Src.add(' InstallFiles.Add('''+N+''');');
+ end;
+end;
+
+procedure TMakeFileConverter.DoCleans(Src,CFL : TStrings);
+
+Var
+ I,J,P : Integer;
+ N,V,DOS,OS,CPU : String;
+
+
+begin
+ If Assigned(CFL) then
+ For I:=0 to CFL.Count-1 do
+ begin
+ CFL.GetNamevalue(I,N,V);
+ GetOSCPU(V,OS,CPU);
+ WriteOSCPUCheck(Src,OS,CPU);
+ Src.add(' CleanFiles.Add('''+N+''');');
+ end;
+end;
+
+
+
+procedure TMakeFileConverter.ConvertFile(const AFileName: String; Src: TStrings; Dir,OS : String);
+
+ Function IsSection(var S : String) : Boolean;
+
+ Var
+ L : Integer;
+
+ begin
+ L:=Length(S);
+ Result:=(L>0) and (S[1]='[') and (S[L]=']');
+ If Result then
+ S:=trim(Copy(S,2,L-2));
+ end;
+
+Var
+ R,L,T,D,S,SD,IFL,CFL : TStrings;
+ I,J : Integer;
+ Prefix,Line,DN : String;
+ B : Boolean;
+
+begin
+ Writeln('Converting '+AFileName);
+ T:=Nil;
+ D:=Nil;
+ S:=Nil;
+ SD:=Nil;
+ R:=Nil;
+ IFL:=Nil;
+ CFL:=Nil;
+ FPackageOptions:='';
+ FPackageDir:='';
+ L:=TStringList.Create;
+ try
+ L.LoadFromFile(AFileName);
+ I:=0;
+ While (I<L.Count) do
+ begin
+ Line:=GetLine(L,I);
+ If IsSection(Line) then
+ begin
+ J:=GetEnumValue(TypeInfo(TSectionType),'st'+Line);
+ If (J=-1) then
+ begin
+ FSection:=stNone;
+ Writeln(stdErr,'Unsupported section: ',Line);
+ end
+ else
+ FSection:=TSectiontype(J);
+ end
+ else
+ case FSection of
+ stPackage : DoPackageLine(Line);
+ stTarget : DoTargetLine(Line,T,R,D);
+ stInstall : DoInstallLine(Line,IFL);
+ stClean : DoCleanLine(Line,CFL);
+ stCompiler : DoCompilerLine(Line,SD);
+ strequire : DoRequireLine(Line);
+ end;
+ inc(I);
+ end;
+ // If there are only 'dir' entries, then there is no package name.
+ B:=False;
+ if (FPackageName<>'') then
+ begin
+ Prefix:='';
+ B:=FPackageName<>'sub';
+ If B then
+ StartPackage(Src,Dir,OS)
+ else
+ Prefix:=Dir;
+ DoTargets(Src,T,R,SD,Dir,Prefix);
+ DoInstalls(Src,IFL);
+ DoCleans(Src,CFL);
+ end;
+ If Assigned(D) then
+ begin
+ If (Dir<>'') then
+ Dir:=IncludeTrailingPathDelimiter(Dir);
+ For I:=0 to D.Count-1 do
+ begin
+ D.GetNameValue(I,DN,Line);
+ If (Line<>'all') and (Line<>'') then
+ OS:=Line;
+ DN:=Dir+DN+PathDelim;
+ If FileExists(DN+'Makefile.fpc') then
+ ConvertFile(DN+'Makefile.fpc',Src,DN,OS);
+ end;
+ end;
+ If B then
+ EndPackage(Src,Dir,OS);
+ Finally
+ S.Free;
+ IFL.Free;
+ CFL.Free;
+ D.Free;
+ SD.Free;
+ T.Free;
+ L.Free;
+ end;
+end;
+
+procedure TMakeFileConverter.ConvertFile(const Source, Dest: String);
+
+Var
+ L : TStrings;
+
+begin
+ L:=TStringList.Create;
+ Try
+ StartInstaller(L);
+ ConvertFile(Source,L,'','');
+ EndInstaller(L);
+ L.SaveToFile(Dest);
+ Finally
+ L.Free;
+ end;
+end;
+
+{ TMakeTool }
+
+procedure TMakeTool.CompileFPMake(Extra: Boolean);
+
+Var
+ O,C : String;
+
+begin
+ C:=GetCompiler;
+ O:=FFPmakeSrc;
+ If Extra then
+ O:='-Fafpmkext '+O;
+ Log(SLogCompilingFPMake+C+' '+O);
+ If ExecuteProcess(C,O)<>0 then
+ Error(SErrFailedToCompileFPCMake)
+end;
+
+procedure TMakeTool.CreateFPMake;
+begin
+ Log(SLogGeneratingFPMake);
+ With TMakeFileConverter.Create do
+ try
+ ConvertFile('Makefile.fpc','fpmake.pp');
+ finally
+ Free;
+ end;
+end;
+
+
+Function TMakeTool.RunFPMake : Integer;
+
+ Function MaybeQuote(Const S : String) : String;
+
+ begin
+ If Pos(' ',S)=0 then
+ Result:=S
+ else
+ Result:='"'+S+'"';
+ end;
+
+
+Var
+ I : integer;
+ D,O : String;
+
+begin
+ Log(SLogRunningFPMake);
+ D:=IncludeTrailingPathDelimiter(GetCurrentDir);
+ O:='';
+ For I:=1 to ParamCount do
+ begin
+ If (O<>'') then
+ O:=O+' ';
+ O:=O+MaybeQuote(ParamStr(I));
+ end;
+ Result:=ExecuteProcess(D+FFPMakeBin,O);
+end;
+
+procedure TMakeTool.Log(Msg: String);
+begin
+ If FLogging then
+ Writeln(stdErr,Msg);
+end;
+
+procedure TMakeTool.Error(Msg: String);
+begin
+ Raise EMakeToolError.Create(Msg);
+end;
+
+procedure TMakeTool.Error(Fmt: String; Args: array of const);
+begin
+ Raise EMakeToolError.CreateFmt(Fmt,Args);
+end;
+
+function TMakeTool.GetCompiler: String;
+begin
+ If (FCompiler='') then
+ begin
+ {$if defined(cpui386)}
+ FCompiler:='ppc386';
+ {$elseif defined(cpuAlpha)}
+ FCompiler:='ppcaxp';
+ {$elseif defined(cpusparc)}
+ FCompiler:='ppcsparc';
+ {$elseif defined(cpuarm)}
+ FCompiler:='ppcarm';
+ {$elseif defined(cpum68k)}
+ FCompiler:='ppcm68k';
+ {$elseif defined(cpux86_64)}
+ FCompiler:='ppcx64';
+ {$elseif defined(cpupowerpc)}
+ FCompiler:='ppcppc';
+ {$else}
+ {$Fatal Unknown architecture}
+ {$endif}
+ end;
+ If (ExtractFilePath(FCompiler)<>'') then
+ Result:=FCompiler
+ else
+ begin
+ Result:=FileSearch(FCompiler,GetEnvironmentVariable('PATH'));
+ If (Result='') then
+ Result:=FCompiler;
+ end;
+end;
+
+
+procedure TMakeTool.ProcessCommandLine;
+
+ Function CheckOption(Index : Integer;Short,Long : String): Boolean;
+
+ var
+ O : String;
+
+ begin
+ O:=Paramstr(Index);
+ Result:=(O='-'+short) or (O='--'+long) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
+ end;
+
+ Function OptionArg(Var Index : Integer) : String;
+
+ Var
+ P : Integer;
+
+ begin
+ if (Length(ParamStr(Index))>1) and (Paramstr(Index)[2]<>'-') then
+ begin
+ If Index<ParamCount then
+ begin
+ Inc(Index);
+ Result:=Paramstr(Index);
+ end
+ else
+ Error(SErrNeedArgument,[Index,ParamStr(Index)]);
+ end
+ else If length(ParamStr(Index))>2 then
+ begin
+ P:=Pos('=',Paramstr(Index));
+ If (P=0) then
+ Error(SErrNeedArgument,[Index,ParamStr(Index)])
+ else
+ begin
+ Result:=Paramstr(Index);
+ Delete(Result,1,P);
+ end;
+ end;
+ end;
+
+Var
+ I : Integer;
+
+begin
+ I:=0;
+ FLogging:=False;
+ FRunMode:=rmhelp;
+ FConvertOnly:=False;
+ While (I<ParamCount) do
+ begin
+ Inc(I);
+ if Checkoption(I,'n','convert') then
+ FConvertOnly:=True
+ else if Checkoption(I,'m','compile') then
+ FRunMode:=rmCompile
+ else if Checkoption(I,'b','build') then
+ FRunMode:=rmBuild
+ else if CheckOption(I,'i','install') then
+ FRunMode:=rmInstall
+ else if CheckOption(I,'c','clean') then
+ FRunMode:=rmClean
+ else if CheckOption(I,'a','archive') then
+ FRunMode:=rmarchive
+ else if CheckOption(I,'d','download') then
+ FRunMode:=rmDownload
+ else if CheckOption(I,'h','help') then
+ FRunMode:=rmhelp
+ // Check.
+ else if CheckOption(I,'r','compiler') then
+ FCompiler:=OptionArg(I)
+ else if CheckOption(I,'v','verbose') then
+ Flogging:=Pos('info',Lowercase(OptionArg(I)))<>0;
+ end;
+end;
+
+
+procedure TMakeTool.Run;
+
+
+begin
+ Try
+ ProcessCommandLine;
+ If FConvertOnly then
+ CreateFPMake
+ else
+ begin
+ FHaveMakefile:=FileExists('Makefile.fpc');
+ FFPMakeSrc:='fpmake.pp';
+ FHaveFpmake:=FileExists(FFPMakeSrc);
+ If Not FHaveFPMake then
+ begin
+ FHaveFPMake:=FileExists('fpmake.pas');
+ If FHaveFPMake then
+ FFPMakeSrc:='fpmake.pas';
+ end;
+ if Not (FHaveFPMake or FHaveMakeFile) then
+ Error(SErrMissingConfig);
+ If (Not FHaveFPMake) or (FileAge(FFPMakeSrc)<FileAge('Makefile.fpc')) then
+ CreateFPMake;
+ {$ifndef unix}
+ FFPMakeBin:='fpmake.exe';
+ {$else}
+ FFPMakeBin:='fpmake';
+ {$endif}
+ if FileAge(FFPMakeBin)<FileAge(FFPMakeSrc) then
+ CompileFPMake(FRunMode in [rmArchive,rmDownload]);
+ Halt(RunFPMake);
+ end;
+ except
+ On E : Exception do
+ begin
+ Writeln(StdErr,Format(SErrRunning,[E.Message]));
+ Halt(1);
+ end;
+ end;
+end;
+
+
+begin
+ With TMakeTool.Create do
+ try
+ run;
+ finally
+ Free;
+ end;
+end.
+
diff --git a/compiler/utils/gppc386.pp b/compiler/utils/gppc386.pp
new file mode 100644
index 0000000000..d2d1b45384
--- /dev/null
+++ b/compiler/utils/gppc386.pp
@@ -0,0 +1,138 @@
+{
+ Copyright (c) 2000-2002 by Pierre Muller
+
+ This program allows to run the Makefiles
+ with the compiler running inside GDB
+
+ GDB only stops if there is something special
+
+ 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.
+
+ ****************************************************************************}
+
+program fpc_with_gdb;
+
+{
+ This program uses several files :
+
+ -- 'gdb4fpc.ini' contains the standard breakpoints (see below)
+
+ -- 'gdb.fpc' is an optional file that can contain any other
+ instruction that GDB should do before starting.
+ Note that if gdb.fpc is present, no "run" command is
+ inserted if gdb4fpc.ini is found
+ but it can be inserted in gdb.fpc itself
+}
+
+uses
+ dos;
+
+const
+{$ifdef Unix}
+ GDBExeName = 'gdbpas';
+ GDBIniName = '.gdbinit';
+ DefaultCompilerName = 'ppc386';
+{$else}
+ GDBExeName = 'gdbpas.exe';
+ GDBIniName = 'gdb.ini';
+ DefaultCompilerName = 'ppc386.exe';
+{$endif not linux}
+
+ { If you add a gdb.fpc file in a given directory }
+ { GDB will read it; this allows you to add }
+ { special tests in specific directories PM }
+ FpcGDBIniName = 'gdb.fpc';
+ GDBIniTempName = 'gdb4fpc.ini';
+
+var
+ fpcgdbini : text;
+ CompilerName,Dir,Name,Ext : String;
+ GDBError,GDBExitCode,i : longint;
+
+begin
+
+ fsplit(paramstr(0),Dir,Name,Ext);
+ if (length(Name)>3) and (UpCase(Name[1])='G') then
+ CompilerName:=Copy(Name,2,255)+Ext
+ else
+ CompilerName:=DefaultCompilerName;
+
+ { support for info functions directly : used in makefiles }
+ if (paramcount=1) and (pos('-i',Paramstr(1))=1) then
+ begin
+ Exec(fsearch(CompilerName,GetEnv('PATH')),Paramstr(1));
+ exit;
+ end;
+
+ if fsearch(GDBIniTempName,'./')<>'' then
+ begin
+ Assign(fpcgdbini,GDBIniTempName);
+ erase(fpcgdbini);
+ end;
+ Assign(fpcgdbini,GdbIniTempName);
+ Rewrite(fpcgdbini);
+
+ Writeln(fpcgdbini,'set language pascal');
+ Writeln(fpcgdbini,'b SYSTEM_EXIT');
+ Writeln(fpcgdbini,'cond 1 EXITCODE <> 0');
+ Writeln(fpcgdbini,'b INTERNALERROR');
+ Writeln(fpcgdbini,'b HANDLEERRORADDRFRAME');
+ Writeln(fpcgdbini,'set $_exitcode := -1');
+ Write(fpcgdbini,'set args');
+
+ { this will not work correctly if there are " or '' inside the command line :( }
+ for i:=1 to Paramcount do
+ begin
+ if pos(' ',Paramstr(i))>0 then
+ Write(fpcgdbini,' "'+ParamStr(i)+'"')
+ else
+ Write(fpcgdbini,' '+ParamStr(i));
+ end;
+ Writeln(fpcgdbini);
+ if fsearch(FpcGDBIniName,'./')<>'' then
+ begin
+ Writeln(fpcgdbini,'source '+FpcGDBIniName);
+ end
+ else
+ Writeln(fpcgdbini,'run');
+ Writeln(fpcgdbini,'if ($_exitcode = -1)');
+ Writeln(fpcgdbini,' echo Program not completed');
+ Writeln(fpcgdbini,'else');
+ Writeln(fpcgdbini,' quit');
+ Writeln(fpcgdbini,'end');
+ Close(fpcgdbini);
+
+ Exec(fsearch(GDBExeName,GetEnv('PATH')),
+{$ifdef win32}
+ '--nw '+
+{$endif win32}
+ '--nx --quiet --command='+GDBIniTempName+' '+CompilerName);
+ GDBError:=DosError;
+ GDBExitCode:=DosExitCode;
+ if (GDBError<>0) or (GDBExitCode<>0) then
+ begin
+ Writeln('Error running GDB');
+ if (GDBError<>0) then
+ Writeln('DosError = ',GDBError);
+ if (GDBExitCode<>0) then
+ Writeln('DosExitCode = ',GDBExitCode);
+ if GDBExitCode<>0 then
+ RunError(GDBExitCode)
+ else
+ RunError(GDBError);
+ end
+ else
+ Erase(fpcgdbini);
+end.
diff --git a/compiler/utils/mk68kreg.pp b/compiler/utils/mk68kreg.pp
new file mode 100644
index 0000000000..fd7eb76aa8
--- /dev/null
+++ b/compiler/utils/mk68kreg.pp
@@ -0,0 +1,334 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert spreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program mkspreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ supregs,
+ numbers,
+ stdnames,
+ gasnames,
+ stabs : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index,gas_regname_index : array[0..max_regcount-1] of byte;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ var
+ result : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from m68kreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_gas_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ gas_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if gasnames[gas_regname_index[j]]>=gasnames[gas_regname_index[i]] then
+ break;
+ t:=gas_regname_index[i];
+ gas_regname_index[i]:=gas_regname_index[j];
+ gas_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure read_spreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'m68kreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ gasnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,gasfile,supfile,
+ numfile,stabfile,confile,
+ rnifile,srifile,grifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'r68kcon.inc');
+ openinc(supfile,'r68ksup.inc');
+ openinc(numfile,'r68knum.inc');
+ openinc(stdfile,'r68kstd.inc');
+ openinc(gasfile,'r68kgas.inc');
+ openinc(stabfile,'r68ksta.inc');
+ openinc(norfile,'r68knor.inc');
+ openinc(rnifile,'r68krni.inc');
+ openinc(srifile,'r68ksri.inc');
+ openinc(grifile,'r68kgri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(gasfile,',');
+ writeln(stabfile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ writeln(grifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(gasfile,'''',gasnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ write(grifile,gas_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(gasfile);
+ closeinc(stabfile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ closeinc(grifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_spreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ build_gas_regname_index;
+ write_inc_files;
+end.
diff --git a/compiler/utils/mkarmins.pp b/compiler/utils/mkarmins.pp
new file mode 100644
index 0000000000..bfce0f2e5e
--- /dev/null
+++ b/compiler/utils/mkarmins.pp
@@ -0,0 +1,432 @@
+{
+ Copyright (c) 1998-2005 by Peter Vreman and Florian Klaempfl
+
+ Convert i386ins.dat from Nasm to a .inc file for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program mkarmins;
+
+const
+ Version = '0.9';
+
+var
+ s : string;
+ i : longint;
+ x86_64 : boolean;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+ function lower(const s : string) : string;
+ {
+ return lowercased string of s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ if s[i] in ['A'..'Z'] then
+ lower[i]:=char(byte(s[i])+32)
+ else
+ lower[i]:=s[i];
+ lower[0]:=s[0];
+ end;
+
+ function Replace(var s:string;const s1,s2:string):boolean;
+ var
+ i : longint;
+ begin
+ i:=pos(s1,s);
+ if i>0 then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ Replace:=true;
+ end
+ else
+ Replace:=false;
+ end;
+
+
+function formatop(s:string):string;
+ const
+ replaces=19;
+ replacetab : array[1..replaces,1..2] of string[32]=(
+ (':',' or ot_colon'),
+ ('mem8','mem or ot_bits8'),
+ ('mem16','mem or ot_bits16'),
+ ('mem32','mem or ot_bits32'),
+ ('mem64','mem or ot_bits64'),
+ ('mem80','mem or ot_bits80'),
+ ('mem','memory'),
+ ('memory_offs','mem_offs'),
+ ('imm8','imm or ot_bits8'),
+ ('imm16','imm or ot_bits16'),
+ ('imm32','imm or ot_bits32'),
+ ('imm64','imm or ot_bits64'),
+ ('imm80','imm or ot_bits80'),
+ ('imm','immediate'),
+ ('rm8','regmem or ot_bits8'),
+ ('rm16','regmem or ot_bits16'),
+ ('rm32','regmem or ot_bits32'),
+ ('rm64','regmem or ot_bits64'),
+ ('rm80','regmem or ot_bits80')
+ );
+ var
+ i : longint;
+ begin
+ for i:=1to replaces do
+ replace(s,replacetab[i,1],replacetab[i,2]);
+ formatop:=s;
+ end;
+
+
+function readnumber : longint;
+
+ var
+ base : longint;
+ result : longint;
+
+ begin
+ result:=0;
+ if s[i]='\' then
+ begin
+ base:=8;
+ inc(i);
+ if s[i]='x' then
+ begin
+ base:=16;
+ inc(i);
+ end;
+ end
+ else
+ base:=10;
+ s[i]:=upcase(s[i]);
+ while s[i] in ['0'..'9','A'..'F'] do
+ begin
+ case s[i] of
+ '0'..'9':
+ result:=result*base+ord(s[i])-ord('0');
+
+ 'A'..'F':
+ result:=result*base+ord(s[i])-ord('A')+10;
+ end;
+ inc(i);
+ end;
+ readnumber:=result;
+ end;
+
+function tostr(l : longint) : string;
+
+ var
+ hs : string;
+
+ begin
+ str(l,hs);
+ tostr:=hs;
+ end;
+
+function readstr : string;
+
+ var
+ result : string;
+
+ begin
+ result:='';
+ while (s[i] in ['0'..'9','A'..'Z','a'..'z','_']) and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from armins.dat }');
+ writeln(f,'(');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ writeln(f,');');
+ close(f);
+end;
+
+
+var
+ attsuffix,
+ hs : string;
+ j : longint;
+ firstopcode,
+ first : boolean;
+ maxinfolen,
+ code : byte;
+ insns : longint;
+ attsuffile,propfile,opfile,
+ nopfile,attfile,
+ infile,insfile : text;
+ { instruction fields }
+ skip : boolean;
+ last,
+ ops : longint;
+ attopcode,
+ opcode,
+ codes,
+ flags : string;
+ optypes : array[1..4] of string;
+begin
+ writeln('Narm Instruction Table Converter Version ',Version);
+ insns:=0;
+ maxinfolen:=0;
+ { open dat file }
+ assign(infile,'../arm/armins.dat');
+ { create inc files }
+ openinc(insfile,'armtab.inc');
+ openinc(opfile,'armop.inc');
+ assign(nopfile,'armnop.inc');
+ openinc(attfile,'armatt.inc');
+ openinc(attsuffile,'armatts.inc');
+ {
+ openinc(intfile,'i386int.inc');
+ openinc(propfile,'i386prop.inc');
+ }
+ rewrite(nopfile);
+ writeln(nopfile,'{ don''t edit, this file is generated from armins.dat }');
+ reset(infile);
+ first:=true;
+ opcode:='';
+ firstopcode:=true;
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+ if (s[1]='[') then
+ begin
+ i:=pos(',',s);
+ j:=pos(']',s);
+ if i=0 then
+ begin
+ opcode:='A_'+Copy(s,2,j-2);
+ attopcode:=Copy(s,2,j-2);
+ { Conditional }
+ if (attopcode[length(attopcode)]='c') and
+ (attopcode[length(attopcode)-1]='c') then
+ begin
+ dec(byte(attopcode[0]),2);
+ dec(byte(opcode[0]),2);
+ end;
+ attsuffix:='attsufNONE';
+ end
+ else
+ begin
+ opcode:='A_'+Copy(s,2,i-2);
+ { intel conditional }
+ if (opcode[length(attopcode)]='c') and
+ (opcode[length(attopcode)-1]='c') then
+ dec(byte(opcode[0]),2);
+ attopcode:=Copy(s,i+1,j-i-1);
+ { att Suffix }
+ case attopcode[length(attopcode)] of
+ 'X' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufINT';
+ end;
+ 'F' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufFPU';
+ end;
+ 'R' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufFPUint';
+ end;
+ else
+ attsuffix:='attsufNONE';
+ end;
+ { att Conditional }
+ if (attopcode[length(attopcode)]='C') and
+ (attopcode[length(attopcode)-1]='C') then
+ dec(byte(attopcode[0]),2);
+ end;
+ attopcode:=Lower(attopcode);
+ if firstopcode then
+ firstopcode:=false
+ else
+ begin
+ writeln(opfile,',');
+ writeln(attfile,',');
+ writeln(attsuffile,',');
+{ writeln(propfile,','); }
+ end;
+ write(opfile,opcode);
+ write(attfile,'''',attopcode,'''');
+ write(attsuffile,attsuffix);
+ { read the next line which contains the Change options }
+ {
+ repeat
+ readln(infile,s);
+ until eof(infile) or ((s<>'') and (s[1]<>';'));
+ write(propfile,'(Ch: ',s,')');
+ }
+ continue;
+ end;
+ { we must have an opcode }
+ if opcode='' then
+ runerror(234);
+ { clear }
+ ops:=0;
+ optypes[1]:='';
+ optypes[2]:='';
+ optypes[3]:='';
+ optypes[4]:='';
+ codes:='';
+ flags:='';
+ skip:=false;
+ { ops and optypes }
+ i:=1;
+ repeat
+ hs:=readstr;
+ if (hs='void') or (hs='ignore') then
+ break;
+ inc(ops);
+ optypes[ops]:=optypes[ops]+'ot_'+formatop(hs);
+{ if s[i]=':' then
+ begin
+ inc(i);
+ optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr);
+ end;}
+ while s[i]='|' do
+ begin
+ inc(i);
+ optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr);
+ end;
+ if s[i] in [',',':'] then
+ inc(i)
+ else
+ break;
+ until false;
+ for j:=1 to 4-ops do
+ optypes[4-j+1]:='ot_none';
+ { codes }
+ skipspace;
+ j:=0;
+ last:=0;
+ if s[i] in ['\','0'..'9'] then
+ begin
+ while not(s[i] in [' ',#9]) do
+ begin
+ code:=readnumber;
+(*
+ { for some codes we want also to change the optypes, but not
+ if the last byte was a 1 then this byte belongs to a direct
+ copy }
+ if last<>1 then
+ begin
+ case code of
+ 12,13,14 :
+ optypes[code-11]:=optypes[code-11]+' or ot_signed';
+ end;
+ end;
+*)
+ codes:=codes+'#'+tostr(code);
+ last:=code;
+ inc(j);
+ end;
+ end
+ else
+ begin
+ readstr;
+ codes:='#0';
+ end;
+ if j>maxinfolen then
+ maxinfolen:=j;
+ { flags }
+ skipspace;
+ while not(s[i] in [' ',#9,#13,#10]) and (i<=length(s)) do
+ begin
+ hs:=readstr;
+ if hs<>'ND' then
+ begin
+ if flags<>'' then
+ flags:=flags+' or ';
+ flags:=flags+'if_'+lower(hs);
+ end;
+ if (s[i]=',') and (i<=length(s)) then
+ inc(i)
+ else
+ break;
+ end;
+ { write instruction }
+ if not skip then
+ begin
+ if not(first) then
+ writeln(insfile,',')
+ else
+ first:=false;
+ writeln(insfile,' (');
+ writeln(insfile,' opcode : ',opcode,';');
+ writeln(insfile,' ops : ',ops,';');
+ writeln(insfile,' optypes : (',optypes[1],',',optypes[2],',',optypes[3],',',optypes[4],');');
+ writeln(insfile,' code : ',codes,';');
+ writeln(insfile,' flags : ',flags);
+ write(insfile,' )');
+ inc(insns);
+ end;
+ end;
+ close(infile);
+ closeinc(insfile);
+ closeinc(attfile);
+ closeinc(attsuffile);
+ closeinc(opfile);
+ writeln(nopfile,insns,';');
+ close(nopfile);
+{ closeinc(propfile); }
+ writeln(insns,' nodes procesed (maxinfolen=',maxinfolen,')');
+end.
diff --git a/compiler/utils/mkarmreg.pp b/compiler/utils/mkarmreg.pp
new file mode 100644
index 0000000000..01b4053d6c
--- /dev/null
+++ b/compiler/utils/mkarmreg.pp
@@ -0,0 +1,298 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert spreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program mkspreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ supregs,
+ numbers,
+ stdnames,
+ stabs,dwarf : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index : array[0..max_regcount-1] of byte;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ var
+ result : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from armreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_spreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'armreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarf[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,supfile,
+ numfile,stabfile,dwarffile,confile,
+ rnifile,srifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'rarmcon.inc');
+ openinc(supfile,'rarmsup.inc');
+ openinc(numfile,'rarmnum.inc');
+ openinc(stdfile,'rarmstd.inc');
+ openinc(stabfile,'rarmsta.inc');
+ openinc(dwarffile,'rarmdwa.inc');
+ openinc(norfile,'rarmnor.inc');
+ openinc(rnifile,'rarmrni.inc');
+ openinc(srifile,'rarmsri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarf[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_spreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ write_inc_files;
+end.
diff --git a/compiler/utils/mkmpsreg.pp b/compiler/utils/mkmpsreg.pp
new file mode 100644
index 0000000000..b8130bb511
--- /dev/null
+++ b/compiler/utils/mkmpsreg.pp
@@ -0,0 +1,349 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert mipsreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program mkmipsreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ supregs,
+ numbers,
+ stdnames,
+ gasnames,
+ dwarfs,
+ stabs : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index,
+ gas_regname_index,
+ mot_regname_index : array[0..max_regcount-1] of byte;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ var
+ result : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from mipsreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure build_gas_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ gas_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if gasnames[gas_regname_index[j]]>=gasnames[gas_regname_index[i]] then
+ break;
+ t:=gas_regname_index[i];
+ gas_regname_index[i]:=gas_regname_index[j];
+ gas_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_mipsreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'mipsreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ gasnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarfs[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,supfile,
+ numfile,stabfile,confile,gasfile,dwarffile,
+ rnifile,srifile,mrifile,grifile : text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'rmipscon.inc');
+ openinc(supfile,'rmipssup.inc');
+ openinc(numfile,'rmipsnum.inc');
+ openinc(stdfile,'rmipsstd.inc');
+ openinc(gasfile,'rmipsgas.inc');
+ openinc(stabfile,'rmipssta.inc');
+ openinc(dwarffile,'rmipsdwf.inc');
+ openinc(norfile,'rmipsnor.inc');
+ openinc(rnifile,'rmipsrni.inc');
+ openinc(srifile,'rmipssri.inc');
+ openinc(grifile,'rmipsgri.inc');
+ openinc(mrifile,'rmipsmri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(gasfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ writeln(grifile,',');
+ writeln(mrifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(gasfile,'''',gasnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarfs[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ write(grifile,gas_regname_index[i]);
+ write(mrifile,mot_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(gasfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ closeinc(grifile);
+ closeinc(mrifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_mipsreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ build_gas_regname_index;
+ write_inc_files;
+end.
diff --git a/compiler/utils/mkppcreg.pp b/compiler/utils/mkppcreg.pp
new file mode 100644
index 0000000000..de4bca26d0
--- /dev/null
+++ b/compiler/utils/mkppcreg.pp
@@ -0,0 +1,396 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert ppcreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program mkppcreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ supregs,
+ numbers,
+ stdnames,
+ gasnames,
+ gssnames,
+ motnames,
+ dwarfs,
+ stabs : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index,
+ gas_regname_index,
+ mot_regname_index : array[0..max_regcount-1] of byte;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ var
+ result : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from ppcreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure build_gas_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ gas_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if gasnames[gas_regname_index[j]]>=gasnames[gas_regname_index[i]] then
+ break;
+ t:=gas_regname_index[i];
+ gas_regname_index[i]:=gas_regname_index[j];
+ gas_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure build_mot_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ mot_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if motnames[mot_regname_index[j]]>=motnames[mot_regname_index[i]] then
+ break;
+ t:=mot_regname_index[i];
+ mot_regname_index[i]:=mot_regname_index[j];
+ mot_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_ppcreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'ppcreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ gasnames[regcount]:=readstr;
+ readcomma;
+ gssnames[regcount]:=readstr;
+ readcomma;
+ motnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarfs[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,motfile,supfile,
+ numfile,stabfile,confile,gasfile,gssfile,dwarffile,
+ rnifile,srifile,mrifile,grifile : text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'rppccon.inc');
+ openinc(supfile,'rppcsup.inc');
+ openinc(numfile,'rppcnum.inc');
+ openinc(stdfile,'rppcstd.inc');
+ openinc(gasfile,'rppcgas.inc');
+ openinc(gssfile,'rppcgss.inc');
+ openinc(motfile,'rppcmot.inc');
+ openinc(stabfile,'rppcstab.inc');
+ openinc(dwarffile,'rppcdwrf.inc');
+ openinc(norfile,'rppcnor.inc');
+ openinc(rnifile,'rppcrni.inc');
+ openinc(srifile,'rppcsri.inc');
+ openinc(grifile,'rppcgri.inc');
+ openinc(mrifile,'rppcmri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(gasfile,',');
+ writeln(gssfile,',');
+ writeln(motfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ writeln(grifile,',');
+ writeln(mrifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(gasfile,'''',gasnames[i],'''');
+ write(gssfile,'''',gssnames[i],'''');
+ write(motfile,'''',motnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarfs[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ write(grifile,gas_regname_index[i]);
+ write(mrifile,mot_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(gasfile);
+ closeinc(gssfile);
+ closeinc(motfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ closeinc(grifile);
+ closeinc(mrifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_ppcreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ build_gas_regname_index;
+ build_mot_regname_index;
+ write_inc_files;
+end.
diff --git a/compiler/utils/mkspreg.pp b/compiler/utils/mkspreg.pp
new file mode 100644
index 0000000000..5208064750
--- /dev/null
+++ b/compiler/utils/mkspreg.pp
@@ -0,0 +1,301 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert spreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program mkspreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ supregs,
+ subregs,
+ names,
+ regtypes,
+ numbers,
+ stdnames,
+ stabs,
+ dwarfs : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index : array[0..max_regcount-1] of byte;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ var
+ result : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from spreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_spreg_file;
+var
+ infile:text;
+begin
+ { open dat file }
+ assign(infile,'spreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ subregs[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarfs[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+copy(subregs[regcount],2,255)+'00'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,supfile,
+ numfile,stabfile,dwarffile,confile,
+ rnifile,srifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'rspcon.inc');
+ openinc(supfile,'rspsup.inc');
+ openinc(numfile,'rspnum.inc');
+ openinc(stdfile,'rspstd.inc');
+ openinc(stabfile,'rspstab.inc');
+ openinc(dwarffile,'rspdwrf.inc');
+ openinc(norfile,'rspnor.inc');
+ openinc(rnifile,'rsprni.inc');
+ openinc(srifile,'rspsri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ end
+ else
+ first:=false;
+ writeln(confile,'NR_',names[i],' = tregister(',numbers[i],');');
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ write(numfile,'NR_',names[i]);
+ write(stdfile,'''',stdnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarfs[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_spreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ write_inc_files;
+end.
diff --git a/compiler/utils/mkx86ins.pp b/compiler/utils/mkx86ins.pp
new file mode 100644
index 0000000000..2601eae9d2
--- /dev/null
+++ b/compiler/utils/mkx86ins.pp
@@ -0,0 +1,454 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert i386ins.dat from Nasm to a .inc file for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program mkx86ins;
+
+const
+ Version = '1.5.0';
+
+var
+ s : string;
+ i : longint;
+ x86_64 : boolean;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+ function lower(const s : string) : string;
+ {
+ return lowercased string of s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ if s[i] in ['A'..'Z'] then
+ lower[i]:=char(byte(s[i])+32)
+ else
+ lower[i]:=s[i];
+ lower[0]:=s[0];
+ end;
+
+ function Replace(var s:string;const s1,s2:string):boolean;
+ var
+ i : longint;
+ begin
+ i:=pos(s1,s);
+ if i>0 then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ Replace:=true;
+ end
+ else
+ Replace:=false;
+ end;
+
+
+function formatop(s:string):string;
+ const
+ replaces=19;
+ replacetab : array[1..replaces,1..2] of string[32]=(
+ (':',' or ot_colon'),
+ ('mem8','mem or ot_bits8'),
+ ('mem16','mem or ot_bits16'),
+ ('mem32','mem or ot_bits32'),
+ ('mem64','mem or ot_bits64'),
+ ('mem80','mem or ot_bits80'),
+ ('mem','memory'),
+ ('memory_offs','mem_offs'),
+ ('imm8','imm or ot_bits8'),
+ ('imm16','imm or ot_bits16'),
+ ('imm32','imm or ot_bits32'),
+ ('imm64','imm or ot_bits64'),
+ ('imm80','imm or ot_bits80'),
+ ('imm','immediate'),
+ ('rm8','regmem or ot_bits8'),
+ ('rm16','regmem or ot_bits16'),
+ ('rm32','regmem or ot_bits32'),
+ ('rm64','regmem or ot_bits64'),
+ ('rm80','regmem or ot_bits80')
+ );
+ var
+ i : longint;
+ begin
+ for i:=1to replaces do
+ replace(s,replacetab[i,1],replacetab[i,2]);
+ formatop:=s;
+ end;
+
+
+function readnumber : longint;
+
+ var
+ base : longint;
+ result : longint;
+
+ begin
+ result:=0;
+ if s[i]='\' then
+ begin
+ base:=8;
+ inc(i);
+ if s[i]='x' then
+ begin
+ base:=16;
+ inc(i);
+ end;
+ end
+ else
+ base:=10;
+ s[i]:=upcase(s[i]);
+ while s[i] in ['0'..'9','A'..'F'] do
+ begin
+ case s[i] of
+ '0'..'9':
+ result:=result*base+ord(s[i])-ord('0');
+
+ 'A'..'F':
+ result:=result*base+ord(s[i])-ord('A')+10;
+ end;
+ inc(i);
+ end;
+ readnumber:=result;
+ end;
+
+function tostr(l : longint) : string;
+
+ var
+ hs : string;
+
+ begin
+ str(l,hs);
+ tostr:=hs;
+ end;
+
+function readstr : string;
+
+ var
+ result : string;
+
+ begin
+ result:='';
+ while (s[i] in ['0'..'9','A'..'Z','a'..'z','_']) and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from x86ins.dat }');
+ writeln(f,'(');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ writeln(f,');');
+ close(f);
+end;
+
+
+var
+ attsuffix,
+ hs : string;
+ j : longint;
+ firstopcode,
+ first : boolean;
+ maxinfolen,
+ code : byte;
+ insns : longint;
+ attsuffile,propfile,opfile,
+ nopfile,attfile,intfile,
+ infile,insfile : text;
+ { instruction fields }
+ skip : boolean;
+ last,
+ ops : longint;
+ intopcode,
+ attopcode,
+ opcode,
+ codes,
+ flags : string;
+ optypes : array[1..3] of string;
+begin
+ writeln('Nasm Instruction Table Converter Version ',Version);
+ x86_64:=paramstr(1)='x86_64';
+ insns:=0;
+ maxinfolen:=0;
+ { open dat file }
+ assign(infile,'../x86/x86ins.dat');
+ if x86_64 then
+ begin
+ { create inc files }
+ openinc(insfile,'x8664tab.inc');
+ openinc(opfile,'x8664op.inc');
+ assign(nopfile,'x8664nop.inc');
+ openinc(attfile,'x8664att.inc');
+ openinc(attsuffile,'x8664ats.inc');
+ openinc(intfile,'x8664int.inc');
+ openinc(propfile,'x8664pro.inc');
+ end
+ else
+ begin
+ { create inc files }
+ openinc(insfile,'i386tab.inc');
+ openinc(opfile,'i386op.inc');
+ assign(nopfile,'i386nop.inc');
+ openinc(attfile,'i386att.inc');
+ openinc(attsuffile,'i386atts.inc');
+ openinc(intfile,'i386int.inc');
+ openinc(propfile,'i386prop.inc');
+ end;
+ rewrite(nopfile);
+ writeln(nopfile,'{ don''t edit, this file is generated from x86ins.dat }');
+ reset(infile);
+ first:=true;
+ opcode:='';
+ firstopcode:=true;
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+ if (s[1]='[') then
+ begin
+ i:=pos(',',s);
+ j:=pos(']',s);
+ if i=0 then
+ begin
+ opcode:='A_'+Copy(s,2,j-2);
+ intopcode:=Copy(s,2,j-2);
+ { Conditional }
+ if (intopcode[length(intopcode)]='c') and
+ (intopcode[length(intopcode)-1]='c') then
+ dec(byte(intopcode[0]),2);
+ attopcode:=intopcode;
+ attsuffix:='attsufNONE';
+ end
+ else
+ begin
+ opcode:='A_'+Copy(s,2,i-2);
+ intopcode:=Copy(s,2,i-2);
+ { intel conditional }
+ if (intopcode[length(intopcode)]='c') and
+ (intopcode[length(intopcode)-1]='c') then
+ dec(byte(intopcode[0]),2);
+ attopcode:=Copy(s,i+1,j-i-1);
+ { att Suffix }
+ case attopcode[length(attopcode)] of
+ 'X' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufINT';
+ end;
+ 'F' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufFPU';
+ end;
+ 'R' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufFPUint';
+ end;
+ else
+ attsuffix:='attsufNONE';
+ end;
+ { att Conditional }
+ if (attopcode[length(attopcode)]='C') and
+ (attopcode[length(attopcode)-1]='C') then
+ dec(byte(attopcode[0]),2);
+ end;
+ intopcode:=Lower(intopcode);
+ attopcode:=Lower(attopcode);
+ if firstopcode then
+ firstopcode:=false
+ else
+ begin
+ writeln(opfile,',');
+ writeln(attfile,',');
+ writeln(attsuffile,',');
+ writeln(intfile,',');
+ writeln(propfile,',');
+ end;
+ write(opfile,opcode);
+ write(intfile,'''',intopcode,'''');
+ write(attfile,'''',attopcode,'''');
+ write(attsuffile,attsuffix);
+ { read the next line which contains the Change options }
+ repeat
+ readln(infile,s);
+ until eof(infile) or ((s<>'') and (s[1]<>';'));
+ write(propfile,'(Ch: ',s,')');
+ continue;
+ end;
+ { we must have an opcode }
+ if opcode='' then
+ runerror(234);
+ { clear }
+ ops:=0;
+ optypes[1]:='';
+ optypes[2]:='';
+ optypes[3]:='';
+ codes:='';
+ flags:='';
+ skip:=false;
+ { ops and optypes }
+ i:=1;
+ repeat
+ hs:=readstr;
+ if (hs='void') or (hs='ignore') then
+ break;
+ inc(ops);
+ optypes[ops]:=optypes[ops]+'ot_'+formatop(hs);
+{ if s[i]=':' then
+ begin
+ inc(i);
+ optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr);
+ end;}
+ while s[i]='|' do
+ begin
+ inc(i);
+ optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr);
+ end;
+ if s[i] in [',',':'] then
+ inc(i)
+ else
+ break;
+ until false;
+ for j:=1 to 3-ops do
+ optypes[3-j+1]:='ot_none';
+ { codes }
+ skipspace;
+ j:=0;
+ last:=0;
+ if s[i] in ['\','0'..'9'] then
+ begin
+ while not(s[i] in [' ',#9]) do
+ begin
+ code:=readnumber;
+ { for some codes we want also to change the optypes, but not
+ if the last byte was a 1 then this byte belongs to a direct
+ copy }
+ if last<>1 then
+ begin
+ case code of
+ 12,13,14 :
+ optypes[code-11]:=optypes[code-11]+' or ot_signed';
+ end;
+ end;
+ codes:=codes+'#'+tostr(code);
+ last:=code;
+ inc(j);
+ end;
+ end
+ else
+ begin
+ readstr;
+ codes:='#0';
+ end;
+ if j>maxinfolen then
+ maxinfolen:=j;
+ { flags }
+ skipspace;
+ while not(s[i] in [' ',#9,#13,#10]) and (i<=length(s)) do
+ begin
+ hs:=readstr;
+ if x86_64 then
+ begin
+ if (upcase(hs)='NOX86_64') then
+ skip:=true;
+ end
+ else
+ begin
+ if (upcase(hs)='X86_64') then
+ skip:=true;
+ end;
+ if hs<>'ND' then
+ begin
+ if flags<>'' then
+ flags:=flags+' or ';
+ flags:=flags+'if_'+lower(hs);
+ end;
+ if (s[i]=',') and (i<=length(s)) then
+ inc(i)
+ else
+ break;
+ end;
+ { write instruction }
+ if not skip then
+ begin
+ if not(first) then
+ writeln(insfile,',')
+ else
+ first:=false;
+ writeln(insfile,' (');
+ writeln(insfile,' opcode : ',opcode,';');
+ writeln(insfile,' ops : ',ops,';');
+ writeln(insfile,' optypes : (',optypes[1],',',optypes[2],',',optypes[3],');');
+ writeln(insfile,' code : ',codes,';');
+ writeln(insfile,' flags : ',flags);
+ write(insfile,' )');
+ inc(insns);
+ end;
+ end;
+ close(infile);
+ closeinc(insfile);
+ closeinc(intfile);
+ closeinc(attfile);
+ closeinc(attsuffile);
+ closeinc(opfile);
+ writeln(nopfile,insns,';');
+ close(nopfile);
+ closeinc(propfile);
+ writeln(insns,' nodes procesed (maxinfolen=',maxinfolen,')');
+end.
diff --git a/compiler/utils/mkx86reg.pp b/compiler/utils/mkx86reg.pp
new file mode 100644
index 0000000000..4b0cf7ef6d
--- /dev/null
+++ b/compiler/utils/mkx86reg.pp
@@ -0,0 +1,467 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert i386reg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+{$mode objfpc}
+{$i+}
+program mkx86reg;
+
+const Version = '1.00';
+ max_regcount = 128;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,numbers,stdnames,intnames,nasmnames,attnames,stabs,dwarf32,dwarf64,ots,ops:
+ array[0..max_regcount-1] of string[63];
+ regnumber_index,std_regname_index,int_regname_index,att_regname_index,
+ nasm_regname_index:array[0..max_regcount-1] of byte;
+ x86_64 : boolean;
+ fileprefix : string;
+
+{$ifndef FPC}
+ procedure readln(var t:text;var s:string);
+ var
+ c : char;
+ i : longint;
+ begin
+ c:=#0;
+ i:=0;
+ while (not eof(t)) and (c<>#10) do
+ begin
+ read(t,c);
+ if c<>#10 then
+ begin
+ inc(i);
+ s[i]:=c;
+ end;
+ end;
+ if (i>0) and (s[i]=#13) then
+ dec(i);
+ s[0]:=chr(i);
+ end;
+{$endif}
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from x86reg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_int_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ int_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if intnames[int_regname_index[j]]>=intnames[int_regname_index[i]] then
+ break;
+ t:=int_regname_index[i];
+ int_regname_index[i]:=int_regname_index[j];
+ int_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_att_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ att_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if attnames[att_regname_index[j]]>=attnames[att_regname_index[i]] then
+ break;
+ t:=att_regname_index[i];
+ att_regname_index[i]:=att_regname_index[j];
+ att_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_nasm_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ nasm_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if nasmnames[nasm_regname_index[j]]>=nasmnames[nasm_regname_index[i]] then
+ break;
+ t:=nasm_regname_index[i];
+ nasm_regname_index[i]:=nasm_regname_index[j];
+ nasm_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure read_x86reg_file;
+
+var infile:text;
+ cpustr:string;
+
+begin
+ { open dat file }
+ assign(infile,'x86reg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ numbers[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ attnames[regcount]:=readstr;
+ readcomma;
+ intnames[regcount]:=readstr;
+ readcomma;
+ nasmnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarf32[regcount]:=readstr;
+ readcomma;
+ dwarf64[regcount]:=readstr;
+ readcomma;
+ ots[regcount]:=readstr;
+ readcomma;
+ ops[regcount]:=readstr;
+ if s[i]=',' then
+ begin
+ readcomma;
+ cpustr:=readstr;
+ end
+ else
+ cpustr:='';
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ if (cpustr<>'64') or x86_64 then
+ begin
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var attfile,intfile,otfile,opfile,
+ norfile,nasmfile,stdfile,
+ numfile,stabfile,dwrffile,confile,
+ rnifile,irifile,srifile,
+ arifile,nrifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,fileprefix+'con.inc');
+ openinc(numfile,fileprefix+'num.inc');
+ openinc(stdfile,fileprefix+'std.inc');
+ openinc(attfile,fileprefix+'att.inc');
+ openinc(intfile,fileprefix+'int.inc');
+ if not(x86_64) then
+ begin
+ openinc(nasmfile,fileprefix+'nasm.inc');
+ end;
+ openinc(stabfile,fileprefix+'stab.inc');
+ openinc(dwrffile,fileprefix+'dwrf.inc');
+ openinc(otfile,fileprefix+'ot.inc');
+ openinc(opfile,fileprefix+'op.inc');
+ openinc(norfile,fileprefix+'nor.inc');
+ openinc(rnifile,fileprefix+'rni.inc');
+ openinc(srifile,fileprefix+'sri.inc');
+ openinc(arifile,fileprefix+'ari.inc');
+ openinc(irifile,fileprefix+'iri.inc');
+ if not(x86_64) then
+ begin
+ openinc(nrifile,fileprefix+'nri.inc');
+ end;
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(attfile,',');
+ writeln(intfile,',');
+ if not(x86_64) then
+ begin
+ writeln(nasmfile,',');
+ end;
+ writeln(stabfile,',');
+ writeln(dwrffile,',');
+ writeln(otfile,',');
+ writeln(opfile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ writeln(arifile,',');
+ writeln(irifile,',');
+ if not(x86_64) then
+ begin
+ writeln(nrifile,',');
+ end;
+ end
+ else
+ first:=false;
+ writeln(confile,names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(attfile,'''',attnames[i],'''');
+ write(intfile,'''',intnames[i],'''');
+ if not(x86_64) then
+ begin
+ write(nasmfile,'''',nasmnames[i],'''');
+ end;
+ write(stabfile,stabs[i]);
+ if x86_64 then
+ write(dwrffile,dwarf64[i])
+ else
+ write(dwrffile,dwarf32[i]);
+ write(otfile,ots[i]);
+ write(opfile,ops[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ write(arifile,att_regname_index[i]);
+ write(irifile,int_regname_index[i]);
+ if not(x86_64) then
+ begin
+ write(nrifile,nasm_regname_index[i]);
+ end;
+ end;
+ write(norfile,regcount);
+ close(confile);
+ closeinc(numfile);
+ closeinc(attfile);
+ closeinc(stdfile);
+ closeinc(intfile);
+ if not(x86_64) then
+ begin
+ closeinc(nasmfile);
+ end;
+ closeinc(stabfile);
+ closeinc(dwrffile);
+ closeinc(otfile);
+ closeinc(opfile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ closeinc(arifile);
+ closeinc(irifile);
+ if not(x86_64) then
+ begin
+ closeinc(nrifile);
+ end;
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ x86_64:=paramstr(1)='x86_64';
+ if x86_64 then
+ fileprefix:='r8664'
+ else
+ fileprefix:='r386';
+ line:=0;
+ regcount:=0;
+ read_x86reg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ if not(x86_64) then
+ begin
+ build_int_regname_index;
+ build_nasm_regname_index;
+ end;
+ build_std_regname_index;
+ build_att_regname_index;
+ write_inc_files;
+end.
diff --git a/compiler/utils/msg2inc.pp b/compiler/utils/msg2inc.pp
new file mode 100644
index 0000000000..905d530952
--- /dev/null
+++ b/compiler/utils/msg2inc.pp
@@ -0,0 +1,815 @@
+{
+ This program is part of the Free Pascal run time library.
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Convert a .msg file to an .inc file with a const array of char
+ And for the lazy docwriters it can also generate some TeX output
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+program msg2inc;
+uses
+ strings;
+
+{$ifdef unix}
+ {$define EOL_ONE_CHAR}
+{$endif unix}
+{$ifdef amiga}
+ {$define EOL_ONE_CHAR}
+{$endif amiga}
+{$ifdef morphos}
+ {$define EOL_ONE_CHAR}
+{$endif}
+{$ifdef macos}
+ {$define EOL_ONE_CHAR}
+{$endif}
+
+const
+ version='1.00';
+{$ifdef EOL_ONE_CHAR}
+ eollen=1;
+{$else}
+ eollen=2;
+{$endif}
+ msgparts = 20;
+
+type
+ TMode=(M_Char,M_Tex,M_Intel,M_String,M_Renumber);
+var
+ InFile,
+ OutFile,
+ OutName : string;
+ Mode : TMode;
+ TexHeader : boolean;
+
+ MsgTxt : pchar;
+ EnumTxt : pchar;
+ enumsize,
+ msgsize : longint;
+
+ msgidxmax : array[1..msgparts] of longint;
+ msgs : array[0..msgparts,0..999] of boolean;
+
+procedure LoadMsgFile(const fn:string);
+var
+ f : text;
+ error,
+ multiline : boolean;
+ code : word;
+ numpart,numidx,
+ line,i,j,num : longint;
+ ptxt,
+ penum : pchar;
+ number,
+ s,s1 : string;
+
+ procedure err(const msgstr:string);
+ begin
+ writeln('error in line ',line,': ',msgstr);
+ error:=true;
+ end;
+
+begin
+ Writeln('Loading messagefile ',fn);
+{Read the message file}
+ assign(f,fn);
+ {$I-}
+ reset(f);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ WriteLn('fatal error: '+fn+' not found');
+ halt(1);
+ end;
+{ First parse the file and count bytes needed }
+ fillchar(msgidxmax,sizeof(msgidxmax),0);
+ fillchar(msgs,sizeof(msgs),0);
+ error:=false;
+ line:=0;
+ multiline:=false;
+ msgsize:=0;
+ while not eof(f) do
+ begin
+ readln(f,s);
+ inc(line);
+ if multiline then
+ begin
+ if s=']' then
+ multiline:=false
+ else
+ inc(msgsize,length(s)+1); { +1 for linebreak }
+ end
+ else
+ begin
+ if (s<>'') and not(s[1] in ['#',';','%']) then
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ j:=i+1;
+ if not(s[j] in ['0'..'9']) then
+ err('no number found')
+ else
+ begin
+ while (s[j] in ['0'..'9']) do
+ inc(j);
+ end;
+ if j-i-1<>5 then
+ err('number length is not 5');
+ number:=Copy(s,i+1,j-i-1);
+ { update the max index }
+ val(number,num,code);
+ numpart:=num div 1000;
+ if numpart=0 then
+ err('number should be > 1000');
+ numidx:=num mod 1000;
+ { duplicate ? }
+ if msgs[numpart,numidx] then
+ err('duplicate number found');
+ msgs[numpart,numidx]:=true;
+ { check range }
+ if numpart > msgparts then
+ err('number is to large')
+ else
+ if numidx > msgidxmax[numpart] then
+ msgidxmax[numpart]:=numidx;
+ if s[j+1]='[' then
+ begin
+ inc(msgsize,j-i);
+ multiline:=true
+ end
+ else
+ inc(msgsize,length(s)-i+1);
+ inc(enumsize,j);
+ end
+ else
+ err('no = found');
+ end;
+ end;
+ end;
+ if multiline then
+ err('still in multiline mode');
+ if error then
+ begin
+ close(f);
+ writeln('aborting');
+ halt(1);
+ end;
+{ alloc memory }
+ getmem(msgtxt,msgsize);
+ ptxt:=msgtxt;
+ getmem(enumtxt,enumsize);
+ penum:=enumtxt;
+{ now read the buffer in mem }
+ reset(f);
+ while not eof(f) do
+ begin
+ readln(f,s);
+ if multiline then
+ begin
+ if s=']' then
+ begin
+ multiline:=false;
+ { overwrite last eol }
+ dec(ptxt);
+ ptxt^:=#0;
+ inc(ptxt);
+ end
+ else
+ begin
+ move(s[1],ptxt^,length(s));
+ inc(ptxt,length(s));
+ ptxt^:=#10;
+ inc(ptxt);
+ end;
+ end
+ else
+ begin
+ if (s<>'') and not(s[1] in ['#',';','%']) then
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ j:=i+1;
+ while (s[j] in ['0'..'9']) do
+ inc(j);
+ {enum}
+ move(s[1],penum^,i-1);
+ inc(penum,i-1);
+ penum^:='=';
+ inc(penum);
+ number:=Copy(s,i+1,j-i-1);
+ move(number[1],penum^,length(number));
+ inc(penum,length(number));
+ penum^:=#0;
+ inc(penum);
+ { multiline start then no txt }
+ if s[j+1]='[' then
+ begin
+ s1:=Copy(s,i+1,j-i);
+ move(s1[1],ptxt^,length(s1));
+ inc(ptxt,length(s1));
+ multiline:=true;
+ end
+ else
+ begin
+ { txt including number }
+ s1:=Copy(s,i+1,255);
+ move(s1[1],ptxt^,length(s1));
+ inc(ptxt,length(s1));
+ ptxt^:=#0;
+ inc(ptxt);
+ end;
+ end;
+ end;
+ end;
+ end;
+ close(f);
+end;
+
+
+{*****************************************************************************
+ WriteEnumFile
+*****************************************************************************}
+
+procedure WriteEnumFile(const fn,typename:string);
+var
+ t : text;
+ i : longint;
+ p : pchar;
+ start : boolean;
+begin
+ writeln('Writing enumfile '+fn);
+{Open textfile}
+ assign(t,fn);
+ rewrite(t);
+ writeln(t,'const');
+{Parse buffer in msgbuf and create indexs}
+ p:=enumtxt;
+ start:=true;
+ for i:=1 to enumsize do
+ begin
+ if start then
+ begin
+ write(t,' ');
+ start:=false;
+ end;
+ if p^=#0 then
+ begin
+ writeln(t,';');
+ start:=true;
+ end
+ else
+ begin
+ write(t,p^);
+ end;
+ inc(p);
+ end;
+ writeln(t,'');
+ { msgtxt size }
+ writeln(t,' MsgTxtSize = ',msgsize,';');
+ writeln(t,'');
+ { max msg idx table }
+ writeln(t,' MsgIdxMax : array[1..20] of longint=(');
+ write(t,' ');
+ for i:=1 to 20 do
+ begin
+ write(t,msgidxmax[i]+1);
+ if i<20 then
+ write(t,',');
+ if i=10 then
+ begin
+ writeln(t,'');
+ write(t,' ');
+ end;
+ end;
+ writeln(t,'');
+ writeln(t,' );');
+ close(t);
+end;
+
+
+{*****************************************************************************
+ WriteStringFile
+*****************************************************************************}
+
+procedure WriteStringFile(const fn,constname:string);
+const
+ maxslen=240; { to overcome aligning problems }
+
+ function l0(l:longint):string;
+ var
+ s : string[16];
+ begin
+ str(l,s);
+ while (length(s)<5) do
+ s:='0'+s;
+ l0:=s;
+ end;
+
+var
+ t : text;
+ f : file;
+ slen,
+ len,i : longint;
+ p : pchar;
+ s : string;
+ start,
+ quote : boolean;
+begin
+ writeln('Writing stringfile ',fn);
+{Open textfile}
+ assign(t,fn);
+ rewrite(t);
+ writeln(t,'{$ifdef Delphi}');
+ writeln(t,'const '+constname+' : array[0..000000] of string[',maxslen,']=(');
+ writeln(t,'{$else Delphi}');
+ writeln(t,'const '+constname+' : array[0..000000,1..',maxslen,'] of char=(');
+ write(t,'{$endif Delphi}');
+{Parse buffer in msgbuf and create indexs}
+ p:=msgtxt;
+ slen:=0;
+ len:=0;
+ quote:=false;
+ start:=true;
+ for i:=1 to msgsize do
+ begin
+ if slen>=maxslen then
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ quote:=false;
+ end;
+ write(t,',');
+ slen:=0;
+ inc(len);
+ end;
+ if (len>70) or (start) then
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ quote:=false;
+ end;
+ if slen>0 then
+ writeln(t,'+')
+ else
+ writeln(t);
+ len:=0;
+ start:=false;
+ end;
+ if (len=0) then
+ write(t,' ');
+ if (ord(p^)>=32) and (p^<>#39) then
+ begin
+ if not quote then
+ begin
+ write(t,'''');
+ quote:=true;
+ inc(len);
+ end;
+ write(t,p^);
+ inc(len);
+ end
+ else
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ inc(len);
+ quote:=false;
+ end;
+ write(t,'#'+chr(ord(p^) div 100+48)+chr((ord(p^) mod 100) div 10+48)+chr(ord(p^) mod 10+48));
+ inc(len,3);
+ end;
+ if p^ in [#0,#10] then
+ start:=true;
+ inc(slen);
+ inc(p);
+ end;
+ if quote then
+ write(t,'''');
+ writeln(t,'');
+ writeln(t,');');
+ close(t);
+{update arraysize}
+ s:=l0(msgsize div maxslen); { we start with 0 }
+ assign(f,fn);
+ reset(f,1);
+ seek(f,34+eollen+length(constname));
+ blockwrite(f,s[1],5);
+ seek(f,90+3*eollen+2*length(constname));
+ blockwrite(f,s[1],5);
+ close(f);
+end;
+
+
+{*****************************************************************************
+ WriteCharFile
+*****************************************************************************}
+
+procedure WriteCharFile(const fn,constname:string);
+
+ function l0(l:longint):string;
+ var
+ s : string[16];
+ begin
+ str(l,s);
+ while (length(s)<5) do
+ s:='0'+s;
+ l0:=s;
+ end;
+
+ function createconst(b:byte):string;
+ begin
+ if (b in [32..127]) and (b<>39) then
+ createconst:=''''+chr(b)+''''
+ else
+ createconst:='#'+chr(b div 100+48)+chr((b mod 100) div 10+48)+chr(b mod 10+48)
+ end;
+
+var
+ t : text;
+ f : file;
+ cidx,i : longint;
+ p : pchar;
+ s : string;
+begin
+ writeln('Writing charfile '+fn);
+{Open textfile}
+ assign(t,fn);
+ rewrite(t);
+ writeln(t,'const ',constname,' : array[1..00000] of char=(');
+{Parse buffer in msgbuf and create indexs}
+ p:=msgtxt;
+ cidx:=0;
+ for i:=1to msgsize do
+ begin
+ if cidx=15 then
+ begin
+ if cidx>0 then
+ writeln(t,',')
+ else
+ writeln(t,'');
+ write(t,' ');
+ cidx:=0;
+ end
+ else
+ if cidx>0 then
+ write(t,',')
+ else
+ write(t,' ');
+ write(t,createconst(ord(p^)));
+ inc(cidx);
+ inc(p);
+ end;
+ writeln(t,');');
+ close(t);
+{update arraysize}
+ s:=l0(msgsize);
+ assign(f,fn);
+ reset(f,1);
+ seek(f,18+length(constname));
+ blockwrite(f,s[1],5);
+ close(f);
+end;
+
+
+{*****************************************************************************
+ WriteIntelFile
+*****************************************************************************}
+
+procedure WriteIntelFile(const fn,constname:string);
+var
+ t : text;
+ len,i : longint;
+ p : pchar;
+ start,
+ quote : boolean;
+begin
+ writeln('Writing Intelfile ',fn);
+{Open textfile}
+ assign(t,fn);
+ rewrite(t);
+ writeln(t,'procedure '+constname+';assembler;');
+ writeln(t,'asm');
+{Parse buffer in msgbuf and create indexs}
+ p:=msgtxt;
+ len:=0;
+ start:=true;
+ quote:=false;
+ for i:=1to msgsize do
+ begin
+ if len>70 then
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ quote:=false;
+ end;
+ writeln(t,'');
+ start:=true;
+ end;
+ if start then
+ begin
+ write(t,' db ''');
+ len:=0;
+ quote:=true;
+ end;
+ if (ord(p^)>=32) and (p^<>#39) then
+ begin
+ if not quote then
+ begin
+ write(t,',''');
+ quote:=true;
+ inc(len);
+ end;
+ write(t,p^);
+ inc(len);
+ end
+ else
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ inc(len);
+ quote:=false;
+ end;
+ write(t,','+chr(ord(p^) div 100+48)+chr((ord(p^) mod 100) div 10+48)+chr(ord(p^) mod 10+48));
+ inc(len,4);
+ end;
+ inc(p);
+ end;
+ if quote then
+ write(t,'''');
+ writeln(t,'');
+ writeln(t,'end;');
+ close(t);
+end;
+
+
+{*****************************************************************************
+ RenumberFile
+*****************************************************************************}
+
+procedure RenumberFile(const fn,name:string);
+var
+ f,t : text;
+ i : longint;
+ s,s1 : string;
+begin
+ Writeln('Renumbering ',fn);
+{Read the message file}
+ assign(f,fn);
+ {$I-}
+ reset(f);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ WriteLn('*** message file '+fn+' not found ***');
+ exit;
+ end;
+ assign(t,'msg2inc.$$$');
+ rewrite(t);
+ i:=0;
+ while not eof(f) do
+ begin
+ readln(f,s);
+ if (copy(s,1,length(Name))=Name) and (s[3] in ['0'..'9']) then
+ begin
+ inc(i);
+ str(i,s1);
+ while length(s1)<3 do
+ s1:='0'+s1;
+ writeln(t,Name+s1+Copy(s,6,255));
+ end
+ else
+ writeln(t,s);
+ end;
+ close(t);
+ close(f);
+{ rename new file }
+ erase(f);
+ rename(t,fn);
+end;
+
+
+{*****************************************************************************
+ WriteTexFile
+*****************************************************************************}
+
+Function EscapeString (Const S : String) : String;
+Var
+ I : longint;
+ hs : string;
+begin
+ hs:='';
+ for i:=1 to length(s) do
+ if (S[i]='$') then
+ begin
+ if (s[i+1] in ['0'..'9']) then
+ hs:=hs+'arg'
+ else
+ hs:=hs+'\$';
+ end
+ else
+ hs:=hs+s[i];
+ EscapeString:=hs;
+end;
+
+procedure WriteTexFile(const infn,outfn:string);
+var
+ t,f : text;
+ line,
+ i,k : longint;
+ s,s1 : string;
+ texoutput : boolean;
+begin
+ Writeln('Loading messagefile ',infn);
+ writeln('Writing TeXfile ',outfn);
+{ Open infile }
+ assign(f,infn);
+ {$I-}
+ reset(f);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ WriteLn('*** message file '+infn+' not found ***');
+ exit;
+ end;
+{ Open outfile }
+ assign(t,outfn);
+ rewrite(t);
+ If texheader then
+ begin
+ writeln (t,'\documentclass{article}');
+ writeln (t,'\usepackage{html}');
+ writeln (t,'\usepackage{fpc}');
+ writeln (t,'\begin{document}');
+ end;
+{ Parse }
+ line:=0;
+ TexOutput:=False;
+ while not eof(f) do
+ begin
+ readln(f,s);
+ inc(line);
+ If Pos ('# BeginOfTeX',S)=1 then
+ TexOutPut:=True
+ else if pos ('# EndOfTeX',S)=1 then
+ TexOutPut:=False;
+ if (s<>'') and not(s[1] in ['#',';']) and TeXOutPut then
+ begin
+ if s[1]='%' then
+ begin
+ Delete(s,1,1);
+ writeln(t,s);
+ end
+ else
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ inc(i);
+ while s[i] in ['0'..'9'] do
+ inc(i);
+ inc(i);
+ s1:='';
+ k:=0;
+ while (k<5) and (s[i+k]<>'_') do
+ begin
+ case s[i+k] of
+ 'W' : s1:='Warning: ';
+ 'E' : s1:='Error: ';
+ 'F' : s1:='Fatal: ';
+ 'N' : s1:='Note: ';
+ 'I' : s1:='Info: ';
+ 'H' : s1:='Hint: ';
+ end;
+ inc(k);
+ end;
+ if s[i+k]='_' then
+ inc(i,k+1);
+ writeln(t,'\item ['+s1+escapestring(Copy(s,i,255))+']');
+ end
+ else
+ writeln('error in line: ',line,' skipping');
+ end;
+ end;
+ end;
+ If TexHeader then
+ writeln (t,'\end{document}');
+ close(t);
+ close(f);
+end;
+
+
+{*****************************************************************************
+ Main Program
+*****************************************************************************}
+
+procedure getpara;
+var
+ ch : char;
+ para : string;
+ files,i : word;
+
+ procedure helpscreen;
+ begin
+ writeln('usage : msg2inc [Options] <msgfile> <incfile> <constname>');
+ writeln('<Options> can be : -T Create .doc TeX file');
+ writeln(' -TS Create .doc TeX file (stand-alone)');
+ writeln(' -I Intel style asm output');
+ writeln(' -S array of string');
+ writeln(' -C array of char');
+ writeln(' -R renumber section <incfile>');
+ writeln(' -V Show version');
+ writeln(' -? or -H This HelpScreen');
+ halt(1);
+ end;
+
+begin
+ Mode:=M_String;
+ FIles:=0;
+ for i:=1to paramcount do
+ begin
+ para:=paramstr(i);
+ if (para[1]='-') then
+ begin
+ ch:=upcase(para[2]);
+ delete(para,1,2);
+ case ch of
+ 'T' : begin
+ case upcase(para[1]) of
+ 'S' : TexHeader:=True;
+ end;
+ Mode:=M_Tex;
+ end;
+ 'I' : Mode:=M_Intel;
+ 'S' : Mode:=M_String;
+ 'C' : Mode:=M_Char;
+ 'R' : Mode:=M_Renumber;
+ 'V' : begin
+ Writeln('Msg2Inc ',version,' for Free Pascal (C) 1998-2002 Peter Vreman');
+ Writeln;
+ Halt;
+ end;
+ '?','H' : helpscreen;
+ end;
+ end
+ else
+ begin
+ inc(Files);
+ if Files>3 then
+ HelpScreen;
+ case Files of
+ 1 : InFile:=Para;
+ 2 : OutFile:=Para;
+ 3 : OutName:=Para;
+ end;
+ end;
+ end;
+ case Mode of
+ M_Renumber,
+ M_Tex : if Files<2 then
+ Helpscreen;
+ else
+ if FIles<3 then
+ HelpScreen;
+ end;
+end;
+
+
+begin
+ GetPara;
+ case Mode of
+ M_Renumber : begin
+ Renumberfile(Infile,OutFile);
+ end;
+ M_Tex : begin
+ WriteTexFile(InFile,Outfile);
+ end;
+ M_Intel : begin
+ Loadmsgfile(InFile);
+ WriteEnumFile(OutFile+'idx.inc',OutName+'const');
+ WriteIntelFile(OutFile+'txt.inc',OutName+'txt');
+ end;
+ M_String : begin
+ Loadmsgfile(InFile);
+ WriteEnumFile(OutFile+'idx.inc',OutName+'const');
+ WriteStringFile(OutFile+'txt.inc',OutName+'txt');
+ end;
+ M_Char : begin
+ Loadmsgfile(InFile);
+ WriteEnumFile(OutFile+'idx.inc',OutName+'const');
+ WriteCharFile(OutFile+'txt.inc',OutName+'txt');
+ end;
+ end;
+end.
diff --git a/compiler/utils/msgdif.pp b/compiler/utils/msgdif.pp
new file mode 100644
index 0000000000..1052f30bc8
--- /dev/null
+++ b/compiler/utils/msgdif.pp
@@ -0,0 +1,529 @@
+{
+ This program is part of the Free Pascal run time library.
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Show the differences between two .msg files
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+{ May be we need to compare a prefixes of option_help_pages too?
+ Currently this is not performed }
+
+Program messagedif;
+
+{$h+} {Huge strings}
+
+Uses
+ Strings;
+
+Type
+ TEnum = String;
+ TText = String;
+
+ PMsg = ^TMsg;
+ TMsg = Record
+ Line, ctxt, cnb : Longint;
+ enum : TEnum;
+ text : TText;
+ comment : pchar;
+ Next,Prev : PMsg;
+ FileNext,
+ Equivalent : PMsg;
+ end;
+Var
+ OrgFileName,DiffFileName : String;
+ OrgRoot,DiffRoot : PMsg;
+ OrgFirst,DiffFirst : PMsg;
+ Last : PMsg;
+
+const
+ NewFileName = 'new.msg';
+ Is_interactive : boolean = false;
+ Auto_verbosity : boolean = false;
+
+
+Procedure GetTranslation( p : PMsg);
+var
+ s : string;
+ i,j,k : longint;
+begin
+ i:=pos('_',p^.text);
+ if i>0 then
+ for j:=i+1 to Length(p^.text) do
+ if p^.text[j]='_' then
+ begin
+ i:=j;
+ break;
+ end;
+ if (i>0) and (i<=15) then
+ Writeln(P^.Enum,' type "',copy(p^.text,1,i-1),'" "',copy(p^.text,i+1,255),'"')
+ else
+ Writeln(P^.enum,' "',p^.text,'"');
+ Writeln('Type translated error message in,');
+ Writeln('Press return to keep it unchanged, or "q" to finish interactive mode');
+ Readln(s);
+ if s='' then
+ exit;
+ if s='q' then
+ begin
+ Is_interactive:=false;
+ exit;
+ end;
+ j:=pos('_',s);
+ if j>0 then
+ for k:=j+1 to Length(s) do
+ if s[j]='_' then
+ begin
+ j:=k;
+ break;
+ end;
+ if (j>0) then
+ begin
+ if copy(p^.text,1,i)<>copy(s,1,j) then
+ Writeln('Warning : different verbosity !!');
+ p^.text:=s;
+ end
+ else
+ p^.text:=copy(p^.text,1,i)+s;
+end;
+
+Function NewMsg (Var RM : PMsg; L : Longint; Const E : TEnum;Const T : TText;C : pchar;NbLn,TxtLn : longint) : PMsg;
+
+Var
+ P,R : PMsg;
+
+begin
+ New(P);
+ with P^ do
+ begin
+ Line:=L;
+ Text:=T;
+ enum:=E;
+ comment:=c;
+ cnb:=NbLn;
+ ctxt:=TxtLn;
+ next:=Nil;
+ prev:=Nil;
+ filenext:=nil;
+ equivalent:=nil;
+ if assigned(last) then
+ last^.FileNext:=P;
+ last:=P;
+ end;
+ R:=RM;
+ While (R<>Nil) and (UpCase(R^.enum)>UpCase(P^.Enum)) do
+ begin
+ P^.Prev:=R;
+ R:=R^.next;
+ end;
+ if assigned(R) and (UpCase(R^.Enum)=UpCase(P^.Enum)) then
+ Writeln('Error ',R^.Enum,' duplicate');
+ P^.Next:=R;
+ If R<>Nil then
+ R^.Prev:=P;
+ If P^.Prev<>Nil then
+ P^.Prev^.Next:=P
+ else
+ RM:=P;
+ NewMsg:=P;
+end;
+
+Procedure PrintList(const name : string;R : PMsg);
+var
+ P : PMsg;
+ f : text;
+begin
+ P:=R;
+ Assign(f,name);
+ Rewrite(f);
+ while assigned(P) do
+ begin
+ Writeln(f,UpCase(P^.Enum));
+ P:=P^.Next;
+ end;
+ Close(f);
+end;
+
+Procedure Usage;
+
+begin
+ Writeln('Usage : msgdif [options] <org-file> <dif-file>');
+ Writeln('Options:');
+ Writeln(' -i allow to enter translated messages interactively');
+ Writeln(' -y1 use <org-file> verbosity (do not query acknowledge)');
+ Writeln('');
+ Writeln('Generates "',NewFileName,'" that contain the messages from <dif-file>');
+ Writeln('with a new messages from <org-file>');
+ Writeln('');
+ Writeln('Example:');
+ Writeln(' msgdif errore.msg errorr.msg');
+ halt(1)
+end;
+
+Procedure ProcessOptions;
+var
+ i,count : longint;
+begin
+ Is_interactive:=false;
+ Auto_verbosity:=false;
+
+ count:=paramcount; i:=1;
+ while (count>0) and (Paramstr(i)[1]='-') do
+ case UpCase(Paramstr(i)[2]) of
+ 'I': begin
+ Is_interactive:=true;
+ dec(count); Inc(i);
+ end;
+ 'Y': case Paramstr(i)[3] of
+ '1': begin
+ Auto_verbosity:=true;
+ dec(count); Inc(i);
+ end;
+ else
+ Writeln ('Error: unknown option ', Paramstr(i));
+ Usage;
+ end;
+ else
+ Writeln ('Error: unknown option ', Paramstr(i));
+ Usage;
+ end;
+ If Count<>2 then begin
+ Writeln ('Error: there must be exactly two message files');
+ Usage;
+ end;
+
+ OrgfileName:=Paramstr(i);
+ DiffFileName:=Paramstr(i+1);
+ if (OrgFileName=NewFileName) or (DiffFileName=NewFileName) then
+ begin
+ Writeln('The file names must be different from ',NewFileName);
+ Halt(1);
+ end;
+end;
+
+Procedure ProcessFile (FileName : String; Var Root,First : PMsg);
+
+Const
+ ArrayLength = 65500;
+Var F : Text;
+ S,prevS : String;
+ J,LineNo,Count,NbLn,TxtLn : Longint;
+ chararray : array[0..ArrayLength] of char;
+ currentindex : longint;
+ c : pchar;
+ multiline : boolean;
+begin
+ Assign(F,FileName);
+ Reset(F);
+ Write ('Processing: ',Filename,'...');
+ LineNo:=0;
+ NbLn:=0;
+ TxtLn:=0;
+ Count:=0;
+ currentindex:=0;
+ Root:=Nil;
+ First:=nil;
+ Last:=nil;
+ PrevS:='';
+ multiline:=false;
+ While not eof(f) do
+ begin
+ Readln(F,S);
+ Inc(LineNo);
+ If multiline then
+ begin
+ PrevS:=PrevS+#10+S; Inc(TxtLn);
+ if (Length(S)<>0) and (S[1]=']') then
+ multiline:=false;
+ end
+ else
+ if (length(S)>0) and Not (S[1] in ['%','#']) Then
+ begin
+ J:=Pos('=',S);
+ If j<1 then
+ writeln (Filename,'(',LineNo,') : Invalid entry')
+ else
+ begin
+ chararray[currentindex]:=#0;
+ c:=strnew(@chararray);
+ if PrevS<>'' then
+ NewMsg(Root,LineNo,Copy(PrevS,1,Pos('=',PrevS)-1),
+ Copy(PrevS,Pos('=',PrevS)+1,Length(PrevS)),c,NbLn,TxtLn)
+ else
+ StrDispose(c);
+ currentindex:=0;
+ NbLn:=0; TxtLn:=0;
+ PrevS:=S; Inc(TxtLn);
+ if S[j+7]='[' then multiline:=true;
+ if First=nil then
+ First:=Root;
+ Inc(Count);
+ end;
+ end
+ else
+ begin
+ if currentindex+length(s)+1>ArrayLength then
+ Writeln('Comment too long : over ',ArrayLength,' chars')
+ else
+ begin
+ strpcopy(@chararray[currentindex],s+#10);
+ inc(currentindex,length(s)+1);
+ inc(NbLn);
+ end;
+ end;
+ end;
+ chararray[currentindex]:=#0;
+ c:=strnew(@chararray);
+ if PrevS<>'' then
+ NewMsg(Root,LineNo,Copy(PrevS,1,Pos('=',PrevS)-1),
+ Copy(PrevS,Pos('=',PrevS)+1,Length(PrevS)),c,NbLn,TxtLn);
+ Writeln (' Done. Read ',LineNo,' lines, got ',Count,' constants.');
+ Close(f);
+end;
+
+Procedure ShowDiff (POrg,PDiff : PMsg);
+
+Var
+ count,orgcount,diffcount : longint;
+
+Procedure NotFound (Org : Boolean; P : PMsg);
+
+begin
+ With P^ do
+ If Org Then
+ Writeln ('Not found in ',DiffFileName,' : ',Enum,' ',OrgFileName,'(',Line,')')
+ else
+ Writeln ('Extra in ',DiffFileName,'(',line,') : ',enum);
+ if org then
+ inc(orgcount)
+ else
+ inc(diffcount);
+end;
+
+begin
+ orgcount:=0;
+ diffcount:=0;
+ count:=0;
+ While (Porg<>Nil) and (PDiff<>Nil) do
+ begin
+// Writeln (POrg^.enum,'<=>',PDiff^.Enum);
+ If UpCase(Porg^.Enum)>UpCase(PDiff^.Enum) then
+ begin
+ NotFound (True,Porg);
+ POrg:=POrg^.Next
+ end
+ else If UpCase(POrg^.enum)=UpCase(PDiff^.Enum) then
+ begin
+ inc(count);
+ POrg^.Equivalent:=PDiff;
+ PDiff^.Equivalent:=POrg;
+ POrg:=POrg^.Next;
+ PDiff:=PDiff^.Next;
+ end
+ else
+ begin
+ NotFound (False,PDiff);
+ PDiff:=PDiff^.Next
+ end;
+ end;
+ While POrg<>Nil do
+ begin
+ NotFound(True,Porg);
+ POrg:=pOrg^.Next;
+ end;
+ While PDiff<>Nil do
+ begin
+ NotFound(False,PDiff);
+ PDiff:=PDiff^.Next;
+ end;
+ Writeln(count,' messages found in common to both files');
+ Writeln(orgcount,' messages only in ',OrgFileName);
+ Writeln(diffcount,' messages only in ',DiffFileName);
+end;
+
+type TArgSet = set of 0..31;
+
+function MsgToSet(const Msg, FileName: string; var R: TArgSet): Boolean;
+ var
+ i, j, num : integer;
+ code : word;
+ begin
+ R:=[];
+ MsgToSet:=false;
+ for i:=1 to Length(Msg) do
+ if Msg[i]='$' then
+ begin
+ j:=i+1;
+ while Msg[j] in ['0'..'9'] do Inc(j);
+ if j > i+1 then
+ begin
+ val(copy(Msg,i+1,j-i-1),num,code);
+ if num > high(TArgSet) then begin
+ WriteLn('Error in ', FileName,': ', Msg);
+ WriteLn(' number at position ', i);
+ WriteLn(' must be LE ', high(TArgSet));
+ Exit;
+ end;
+ R:=R+[num];
+ end;
+ end;
+ MsgToSet:=true;
+ end;
+
+
+procedure CheckParm(const s1, s2: string);
+ var
+ R1, R2: TArgSet;
+ begin
+ if MsgToSet(s1,OrgFileName, R1) <> true then Exit;
+ if MsgToSet(s2,DiffFileName,R2) <> true then Exit;
+ if R1<>R2 then begin
+ WriteLn('Error: set of arguments is different');
+ WriteLn(' ',s1);
+ WriteLn(' ',s2);
+ end;
+ end;
+
+procedure WriteReorderedFile(FileName : string;orgnext,diffnext : PMsg);
+ var t,t2,t3 : text;
+ i,ntcount : longint;
+ j : integer;
+ s,s2,s3 : string;
+ is_msg : boolean;
+ nextdiffkept : pmsg;
+ begin
+ ntcount:=0;
+ Assign(t,FileName);
+ Rewrite(t);
+ Writeln(t,'%%% Reordering of ',DiffFileName,' respective to ',OrgFileName);
+ Writeln(t,'%%% Contains all comments from ',DiffFileName);
+ Assign(t2,DiffFileName);
+ Reset(t2);
+ Assign(t3,OrgFileName);
+ Reset(t3);
+ i:=2;
+ s:='';s3:='';
+ nextdiffkept:=diffnext;
+ while assigned(nextdiffkept) and (nextdiffkept^.equivalent=nil) do
+ nextdiffkept:=nextdiffkept^.filenext;
+ { First write the header of diff }
+ repeat
+ Readln(t2,s);
+ is_msg:=(pos('=',s)>1) and (s[1]<>'%') and (s[1]<>'#');
+ if not is_msg then
+ begin
+ Writeln(t,s);
+ inc(i);
+ end;
+ until is_msg;
+ { Write all messages in Org order }
+ while assigned(orgnext) do
+ begin
+ if not assigned(orgnext^.equivalent) then
+ begin
+ { Insert a new error msg with the english comments }
+ Writeln('New error ',orgnext^.enum,' added');
+ If Is_interactive then
+ GetTranslation(orgnext);
+ Writeln(t,orgnext^.enum,'=',orgnext^.text);
+ inc(i,orgnext^.ctxt);
+ Write(t,orgnext^.comment);
+ inc(i,orgnext^.cnb);
+ end
+ else
+ begin
+ inc(i);
+ if orgnext^.text=orgnext^.equivalent^.text then
+ begin
+ Writeln(FileName,'(',i,') ',orgnext^.enum,' not translated');
+ If Is_interactive then
+ GetTranslation(orgnext^.equivalent);
+ if orgnext^.text=orgnext^.equivalent^.text then
+ inc(ntcount);
+ end;
+ s2:=orgnext^.text;
+ j:=pos('_',copy(s2,7,20)) + 6;
+ s2:=upcase(copy(s2,1,j));
+ s3:=orgnext^.equivalent^.text;
+ j:=pos('_',copy(s3,7,20)) + 6;
+ s3:=upcase(copy(s3,1,j));
+ { that are the conditions in verbose unit }
+ if (length(s3)<12) and (s2<>s3) then
+ begin
+ Writeln('Warning: different options for ',orgnext^.enum);
+ Writeln(' ',orgnext^.text);
+ Writeln(' ',orgnext^.equivalent^.text);
+ s:='N';
+ if Auto_verbosity then
+ s:='Y'
+ else
+ If Is_interactive then
+ begin
+ Write('Use ',s2,' verbosity ? [y/n] ');
+ Readln(s);
+ end;
+ if UpCase(s[1])='Y' then
+ begin
+ orgnext^.equivalent^.text:=s2+copy(orgnext^.equivalent^.text,
+ length(s3)+1,Length(orgnext^.equivalent^.text));
+ WriteLn(' Using ', s2);
+ end;
+ end;
+
+ CheckParm(orgnext^.text, orgnext^.equivalent^.text);
+
+ Writeln(t,orgnext^.enum,'=',orgnext^.equivalent^.text);
+ Dec(i); Inc(i,orgnext^.equivalent^.ctxt);
+ if assigned(orgnext^.equivalent^.comment) and
+ (strlen(orgnext^.equivalent^.comment)>0) then
+ begin
+ Write(t,orgnext^.equivalent^.comment);
+ inc(i,orgnext^.equivalent^.cnb);
+ end
+ else if assigned(orgnext^.comment) and
+ (strlen(orgnext^.comment)>0) then
+ begin
+ Writeln('Comment from ',OrgFileName,' for enum ',orgnext^.enum,' added');
+ Write(t,orgnext^.comment);
+ inc(i,orgnext^.cnb);
+ end;
+ end;
+ orgnext:=orgnext^.filenext;
+ end;
+
+ while assigned(diffnext) do
+ begin
+ if not assigned(diffnext^.Equivalent) then
+ begin
+ { Skip removed enum in errore.msg}
+ { maybe a renaming of an enum !}
+ Writeln(diffnext^.enum,' commented out');
+ Writeln(t,'%%% ',diffnext^.enum,'=',diffnext^.text);
+ inc(i,diffnext^.ctxt);
+ Write(t,diffnext^.comment);
+ inc(i,diffnext^.cnb);
+ end;
+ diffnext:=diffnext^.filenext;
+ end;
+ Close(t);
+ Close(t2);
+ Close(t3);
+ Writeln(ntcount,' not translated items found');
+ end;
+
+begin
+ ProcessOptions;
+ ProcessFile(OrgFileName,orgroot,orgfirst);
+ ProcessFile(DiffFileName,diffRoot,difffirst);
+ PrintList('org.lst',OrgRoot);
+ PrintList('diff.lst',DiffRoot);
+ ShowDiff (OrgRoot,DiffRoot);
+ WriteReorderedFile(NewFileName,orgfirst,difffirst);
+end.
diff --git a/compiler/utils/msgused.pl b/compiler/utils/msgused.pl
new file mode 100644
index 0000000000..6ac46d655b
--- /dev/null
+++ b/compiler/utils/msgused.pl
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+#
+# find not used messages
+
+unlink("./msgidx.inc");
+unlink("./msgtxt.inc");
+@compiler_src = (glob("./*.inc"),
+ glob("./*.pas"));
+
+open(MESSAGE_FILE, "< ./msg/errore.msg") or
+ die "Couldn't open <./msg/errore.msg> for reading: $!\n";
+
+open(FOUND, "> MSG-OK.TXT") or
+ die "Couldn't open <MSG-OK.TXT> for writing: $!\n";
+
+select FOUND; $| = 1;
+
+open(NOT_FOUND, "> MSG_BAD.TXT") or
+ die "Couldn't open <MSG_BAD.TXT> for writing: $!\n";
+
+select NOT_FOUND; $| = 1;
+
+while (<MESSAGE_FILE>)
+{
+ if (/^(\w\w\w*?_\w\w*?_\w\w*?)=/)
+ {
+ $msg = $1;
+ $found = `grep -il $msg @compiler_src`;
+ if ($found) {
+ print stderr "$msg\n";
+ print FOUND $msg . "\n";
+ }
+ else {
+ print stderr "NOT FOUND \t $msg\n";
+ print NOT_FOUND $msg . "\n";
+ }
+ }
+}
+
+close(IN);
+close(FOUND);
+close(NOT_FOUND);
diff --git a/compiler/utils/ppudump.pp b/compiler/utils/ppudump.pp
new file mode 100644
index 0000000000..1d73b79276
--- /dev/null
+++ b/compiler/utils/ppudump.pp
@@ -0,0 +1,2191 @@
+{
+ Copyright (c) 1998-2002 by the FPC Development Team
+
+ Dumps the contents of a FPC unit file (PPU File)
+
+ 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.
+
+ ****************************************************************************}
+{$ifdef TP}
+ {$N+,E+}
+{$endif}
+program pppdump;
+uses
+ dos,
+ ppu;
+
+const
+ Version = 'Version 2.0.0';
+ Title = 'PPU-Analyser';
+ Copyright = 'Copyright (c) 1998-2005 by the Free Pascal Development Team';
+
+{ verbosity }
+ v_none = $0;
+ v_header = $1;
+ v_defs = $2;
+ v_syms = $4;
+ v_interface = $8;
+ v_implementation = $10;
+ v_browser = $20;
+ v_all = $ff;
+
+type
+ tprocinfoflag=(
+ {# procedure uses asm }
+ pi_uses_asm,
+ {# procedure does a call }
+ pi_do_call,
+ {# procedure has a try statement = no register optimization }
+ pi_uses_exceptions,
+ {# procedure is declared as @var(assembler), don't optimize}
+ pi_is_assembler,
+ {# procedure contains data which needs to be finalized }
+ pi_needs_implicit_finally
+ );
+ tprocinfoflags=set of tprocinfoflag;
+
+ { Copied from systems.pas }
+ tsystemcpu=
+ (
+ cpu_no, { 0 }
+ cpu_i386, { 1 }
+ cpu_m68k, { 2 }
+ cpu_alpha, { 3 }
+ cpu_powerpc, { 4 }
+ cpu_sparc, { 5 }
+ cpu_vm, { 6 }
+ cpu_iA64, { 7 }
+ cpu_x86_64, { 8 }
+ cpu_mips, { 9 }
+ cpu_arm { 10 }
+ );
+
+var
+ ppufile : tppufile;
+ space : string;
+ unitindex : longint;
+ verbose : longint;
+ derefdata : pbyte;
+ derefdatalen : longint;
+
+{****************************************************************************
+ Helper Routines
+****************************************************************************}
+
+const has_errors : boolean = false;
+Procedure Error(const S : string);
+Begin
+ Writeln(S);
+ has_errors:=true;
+End;
+
+
+function ToStr(w:longint):String;
+begin
+ Str(w,ToStr);
+end;
+
+Function Target2Str(w:longint):string;
+type
+ { taken from systems.pas }
+ ttarget =
+ (
+ target_none, { 0 }
+ target_i386_GO32V1, { 1 }
+ target_i386_GO32V2, { 2 }
+ target_i386_linux, { 3 }
+ target_i386_OS2, { 4 }
+ target_i386_Win32, { 5 }
+ target_i386_freebsd, { 6 }
+ target_m68k_Amiga, { 7 }
+ target_m68k_Atari, { 8 }
+ target_m68k_Mac, { 9 }
+ target_m68k_linux, { 10 }
+ target_m68k_PalmOS, { 11 }
+ target_alpha_linux, { 12 }
+ target_powerpc_linux, { 13 }
+ target_powerpc_macos, { 14 }
+ target_i386_sunos, { 15 }
+ target_i386_beos, { 16 }
+ target_i386_netbsd, { 17 }
+ target_m68k_netbsd, { 18 }
+ target_i386_Netware, { 19 }
+ target_i386_qnx, { 20 }
+ target_i386_wdosx, { 21 }
+ target_sparc_sunos, { 22 }
+ target_sparc_linux, { 23 }
+ target_i386_openbsd, { 24 }
+ target_m68k_openbsd, { 25 }
+ system_x86_64_linux, { 26 }
+ system_powerpc_macosx, { 27 }
+ target_i386_emx, { 28 }
+ target_powerpc_netbsd, { 29 }
+ target_powerpc_openbsd, { 30 }
+ target_arm_linux, { 31 }
+ target_i386_watcom, { 32 }
+ target_powerpc_MorphOS, { 33 }
+ target_x86_64_freebsd, { 34 }
+ target_i386_netwlibc, { 35 }
+ system_powerpc_Amiga, { 36 }
+ system_x86_64_win64, { 37 }
+ system_arm_wince, { 38 }
+ system_ia64_win64, { 39 }
+ system_i386_wince, { 40 }
+ system_x86_6432_linux, { 41 }
+ system_arm_gba { 42 }
+ );
+const
+ Targets : array[ttarget] of string[17]=(
+ { 0 } 'none',
+ { 1 } 'GO32V1',
+ { 2 } 'GO32V2',
+ { 3 } 'Linux-i386',
+ { 4 } 'OS/2',
+ { 5 } 'Win32',
+ { 6 } 'FreeBSD-i386',
+ { 7 } 'Amiga',
+ { 8 } 'Atari',
+ { 9 } 'MacOS-m68k',
+ { 10 } 'Linux-m68k',
+ { 11 } 'PalmOS-m68k',
+ { 12 } 'Linux-alpha',
+ { 13 } 'Linux-ppc',
+ { 14 } 'MacOS-ppc',
+ { 15 } 'Solaris-i386',
+ { 16 } 'BeOS-i386',
+ { 17 } 'NetBSD-i386',
+ { 18 } 'NetBSD-m68k',
+ { 19 } 'Netware-i386-clib',
+ { 20 } 'Qnx-i386',
+ { 21 } 'WDOSX-i386',
+ { 22 } 'Solaris-sparc',
+ { 23 } 'Linux-sparc',
+ { 24 } 'OpenBSD-i386',
+ { 25 } 'OpenBSD-m68k',
+ { 26 } 'Linux-x86-64',
+ { 27 } 'MacOSX-ppc',
+ { 28 } 'OS/2 via EMX',
+ { 29 } 'NetBSD-powerpc',
+ { 30 } 'OpenBSD-powerpc',
+ { 31 } 'Linux-arm',
+ { 32 } 'Watcom-i386',
+ { 33 } 'MorphOS-powerpc',
+ { 34 } 'FreeBSD-x86-64',
+ { 35 } 'Netware-i386-libc',
+ { 36 } 'Amiga-PowerPC',
+ { 37 } 'Win64-x64',
+ { 38 } 'WinCE-ARM',
+ { 39 } 'Win64-iA64',
+ { 40 } 'WinCE-i386',
+ { 41 } 'Linux-x64',
+ { 42 } 'GBA-ARM'
+ );
+begin
+ if w<=ord(high(ttarget)) then
+ Target2Str:=Targets[ttarget(w)]
+ else
+ Target2Str:='<!! Unknown target value '+tostr(w)+'>';
+end;
+
+
+Function Cpu2Str(w:longint):string;
+const
+ CpuTxt : array[tsystemcpu] of string[8]=
+ ('none','i386','m68k','alpha','powerpc','sparc','vis','ia64','x86_64','mips','arm');
+begin
+ if w<=ord(high(tsystemcpu)) then
+ Cpu2Str:=CpuTxt[tsystemcpu(w)]
+ else
+ Cpu2Str:='<!! Unknown cpu value '+tostr(w)+'>';
+end;
+
+
+Function Varspez2Str(w:longint):string;
+const
+ varspezstr : array[0..4] of string[6]=('Value','Const','Var','Out','Hidden');
+begin
+ if w<=ord(high(varspezstr)) then
+ Varspez2Str:=varspezstr[w]
+ else
+ Varspez2Str:='<!! Unknown varspez value '+tostr(w)+'>';
+end;
+
+Function VarRegable2Str(w:longint):string;
+const
+ varregableStr : array[0..3] of string[6]=('None','IntReg','FPUReg','MMReg');
+begin
+ if w<=ord(high(varregablestr)) then
+ Varregable2Str:=varregablestr[w]
+ else
+ Varregable2Str:='<!! Unknown regable value '+tostr(w)+'>';
+end;
+
+
+function PPUFlags2Str(flags:longint):string;
+type
+ tflagopt=record
+ mask : longint;
+ str : string[30];
+ end;
+const
+ flagopts=19;
+ flagopt : array[1..flagopts] of tflagopt=(
+ (mask: $1 ;str:'init'),
+ (mask: $2 ;str:'final'),
+ (mask: $4 ;str:'big_endian'),
+ (mask: $8 ;str:'dbx'),
+ (mask: $10 ;str:'browser'),
+ (mask: $20 ;str:'in_library'),
+ (mask: $40 ;str:'smart_linked'),
+ (mask: $80 ;str:'static_linked'),
+ (mask: $100 ;str:'shared_linked'),
+ (mask: $200 ;str:'local_browser'),
+ (mask: $400 ;str:'no_link'),
+ (mask: $800 ;str:'has_resources'),
+ (mask: $1000 ;str:'little_endian'),
+ (mask: $2000 ;str:'release'),
+ (mask: $4000 ;str:'local_threadvars'),
+ (mask: $8000 ;str:'fpu_emulation_on'),
+ (mask: $10000 ;str:'has_debug_info'),
+ (mask: $20000 ;str:'local_symtable'),
+ (mask: $40000 ;str:'uses_variants')
+ );
+var
+ i : longint;
+ first : boolean;
+ s : string;
+begin
+ s:='';
+ if flags<>0 then
+ begin
+ first:=true;
+ for i:=1to flagopts do
+ if (flags and flagopt[i].mask)<>0 then
+ begin
+ if first then
+ first:=false
+ else
+ s:=s+', ';
+ s:=s+flagopt[i].str;
+ end;
+ end
+ else
+ s:='none';
+ PPUFlags2Str:=s;
+end;
+
+
+const
+ HexTbl : array[0..15] of char='0123456789ABCDEF';
+function HexB(b:byte):string;
+begin
+ HexB[0]:=#2;
+ HexB[1]:=HexTbl[b shr 4];
+ HexB[2]:=HexTbl[b and $f];
+end;
+
+
+function hexstr(val : cardinal;cnt : byte) : string;
+const
+ HexTbl : array[0..15] of char='0123456789ABCDEF';
+var
+ i : longint;
+begin
+ hexstr[0]:=char(cnt);
+ for i:=cnt downto 1 do
+ begin
+ hexstr[i]:=hextbl[val and $f];
+ val:=val shr 4;
+ end;
+end;
+
+
+ Function L0(l:longint):string;
+ {
+ return the string of value l, if l<10 then insert a zero, so
+ the string is always at least 2 chars '01','02',etc
+ }
+ var
+ s : string;
+ begin
+ Str(l,s);
+ if l<10 then
+ s:='0'+s;
+ L0:=s;
+ end;
+
+
+ function filetimestring( t : longint) : string;
+ {
+ convert dos datetime t to a string YY/MM/DD HH:MM:SS
+ }
+ var
+ DT : DateTime;
+ begin
+ if t=-1 then
+ begin
+ FileTimeString:='Not Found';
+ exit;
+ end;
+ unpacktime(t,DT);
+ filetimestring:=L0(dt.Year)+'/'+L0(dt.Month)+'/'+L0(dt.Day)+' '+L0(dt.Hour)+':'+L0(dt.min)+':'+L0(dt.sec);
+ end;
+
+
+{****************************************************************************
+ Read Routines
+****************************************************************************}
+
+Procedure ReadLinkContainer(const prefix:string);
+{
+ Read a serie of strings and write to the screen starting every line
+ with prefix
+}
+ function maskstr(m:longint):string;
+ const
+ { link options }
+ link_none = $0;
+ link_allways = $1;
+ link_static = $2;
+ link_smart = $4;
+ link_shared = $8;
+ var
+ s : string;
+ begin
+ s:='';
+ if (m and link_allways)<>0 then
+ s:=s+'always ';
+ if (m and link_static)<>0 then
+ s:=s+'static ';
+ if (m and link_smart)<>0 then
+ s:=s+'smart ';
+ if (m and link_shared)<>0 then
+ s:=s+'shared ';
+ maskstr:=s;
+ end;
+
+var
+ s : string;
+ m : longint;
+begin
+ while not ppufile.endofentry do
+ begin
+ s:=ppufile.getstring;
+ m:=ppufile.getlongint;
+ WriteLn(prefix,s,' (',maskstr(m),')');
+ end;
+end;
+
+
+Procedure ReadContainer(const prefix:string);
+{
+ Read a serie of strings and write to the screen starting every line
+ with prefix
+}
+begin
+ while not ppufile.endofentry do
+ WriteLn(prefix,ppufile.getstring);
+end;
+
+
+procedure ReadLoadUnit;
+var
+ ucrc,uintfcrc : cardinal;
+begin
+ while not ppufile.EndOfEntry do
+ begin
+ write('Uses unit: ',ppufile.getstring);
+ ucrc:=cardinal(ppufile.getlongint);
+ uintfcrc:=cardinal(ppufile.getlongint);
+ writeln(' (Crc: ',hexstr(ucrc,8),', IntfcCrc: ',hexstr(uintfcrc,8),')');
+ end;
+end;
+
+
+Procedure ReadDerefmap;
+var
+ i,mapsize : longint;
+begin
+ mapsize:=ppufile.getword;
+ writeln('DerefMapsize: ',mapsize);
+ for i:=0 to mapsize-1 do
+ writeln('DerefMap[',i,'] = ',ppufile.getstring);
+end;
+
+
+Procedure ReadDerefdata;
+begin
+ derefdatalen:=ppufile.entrysize;
+ if derefdatalen=0 then
+ begin
+ writeln('!! Error: derefdatalen=0');
+ exit;
+ end;
+ Writeln('Derefdata length: ',derefdatalen);
+ derefdata:=allocmem(derefdatalen);
+ ppufile.getdata(derefdata^,derefdatalen);
+end;
+
+
+Procedure ReadRef;
+begin
+ if (verbose and v_browser)=0 then
+ exit;
+ while (not ppufile.endofentry) and (not ppufile.error) do
+ Writeln(space,' - Refered : ',ppufile.getword,', (',ppufile.getlongint,',',ppufile.getword,')');
+end;
+
+
+Procedure ReadAsmSymbols;
+type
+ { Copied from aasmbase.pas }
+ TAsmsymbind=(AB_NONE,AB_EXTERNAL,AB_COMMON,AB_LOCAL,AB_GLOBAL);
+ TAsmsymtype=(AT_NONE,AT_FUNCTION,AT_DATA,AT_SECTION,AT_LABEL);
+var
+ s,
+ bindstr,
+ typestr : string;
+ i : longint;
+begin
+ writeln(space,'Number of AsmSymbols: ',ppufile.getlongint);
+ i:=0;
+ while (not ppufile.endofentry) and (not ppufile.error) do
+ begin
+ s:=ppufile.getstring;
+ case tasmsymbind(ppufile.getbyte) of
+ AB_EXTERNAL :
+ bindstr:='External';
+ AB_COMMON :
+ bindstr:='Common';
+ AB_LOCAL :
+ bindstr:='Local';
+ AB_GLOBAL :
+ bindstr:='Global';
+ else
+ bindstr:='<Error !!>'
+ end;
+ case tasmsymtype(ppufile.getbyte) of
+ AT_FUNCTION :
+ typestr:='Function';
+ AT_DATA :
+ typestr:='Data';
+ AT_SECTION :
+ typestr:='Section';
+ AT_LABEL :
+ typestr:='Label';
+ else
+ typestr:='<Error !!>'
+ end;
+ Writeln(space,' ',i,' : ',s,' [',bindstr,',',typestr,']');
+ inc(i);
+ end;
+end;
+
+
+Procedure ReadPosInfo;
+var
+ info : byte;
+ fileindex,line,column : longint;
+begin
+ with ppufile do
+ begin
+ {
+ info byte layout in bits:
+ 0-1 - amount of bytes for fileindex
+ 2-3 - amount of bytes for line
+ 4-5 - amount of bytes for column
+ }
+ info:=getbyte;
+ case (info and $03) of
+ 0 : fileindex:=getbyte;
+ 1 : fileindex:=getword;
+ 2 : fileindex:=(getbyte shl 16) or getword;
+ 3 : fileindex:=getlongint;
+ end;
+ case ((info shr 2) and $03) of
+ 0 : line:=getbyte;
+ 1 : line:=getword;
+ 2 : line:=(getbyte shl 16) or getword;
+ 3 : line:=getlongint;
+ end;
+ case ((info shr 4) and $03) of
+ 0 : column:=getbyte;
+ 1 : column:=getword;
+ 2 : column:=(getbyte shl 16) or getword;
+ 3 : column:=getlongint;
+ end;
+ Writeln(fileindex,' (',line,',',column,')');
+ end;
+end;
+
+
+procedure readderef;
+type
+ tdereftype = (deref_nil,
+ deref_sym,
+ deref_def,
+ deref_aktrecord,
+ deref_aktstatic,
+ deref_aktglobal,
+ deref_aktlocal,
+ deref_aktpara,
+ deref_unit,
+ deref_record,
+ deref_local,
+ deref_para,
+ deref_parent_object
+ );
+var
+ b : tdereftype;
+ first : boolean;
+ idx : longint;
+ i,n : byte;
+ pdata : pbyte;
+begin
+ if not assigned(derefdata) then
+ exit;
+ first:=true;
+ idx:=ppufile.getlongint;
+ if (idx>derefdatalen) then
+ begin
+ writeln('!! Error: Deref idx ',idx,' > ',derefdatalen);
+ exit;
+ end;
+ write('(',idx,') ');
+ pdata:=@derefdata[idx];
+ i:=0;
+ n:=pdata[i];
+ inc(i);
+ if n<1 then
+ begin
+ writeln('!! Error: Deref len < 1');
+ exit;
+ end;
+ while (i<n) do
+ begin
+ if not first then
+ write(', ')
+ else
+ first:=false;
+ b:=tdereftype(pdata[i]);
+ inc(i);
+ case b of
+ deref_nil :
+ write('Nil');
+ deref_def :
+ begin
+ idx:=pdata[i] shl 8;
+ idx:=idx or pdata[i+1];
+ inc(i,2);
+ write('Definition ',idx);
+ end;
+ deref_sym :
+ begin
+ idx:=pdata[i] shl 8;
+ idx:=idx or pdata[i+1];
+ inc(i,2);
+ write('Symbol ',idx);
+ end;
+ deref_aktrecord :
+ write('AktRecord');
+ deref_aktstatic :
+ write('AktStatic');
+ deref_aktglobal :
+ write('AktGlobal');
+ deref_aktlocal :
+ write('AktLocal');
+ deref_aktpara :
+ write('AktPara');
+ deref_unit :
+ begin
+ idx:=pdata[i] shl 8;
+ idx:=idx or pdata[i+1];
+ inc(i,2);
+ write('Unit ',idx);
+ end;
+ deref_record :
+ write('RecordDef');
+ deref_para :
+ write('Parameter of procdef');
+ deref_local :
+ write('Local of procdef');
+ deref_parent_object :
+ write('Parent object');
+ else
+ begin
+ writeln('!! unsupported dereftyp: ',ord(b));
+ break;
+ end;
+ end;
+ end;
+ writeln;
+end;
+
+
+procedure readtype;
+begin
+ readderef;
+end;
+
+
+procedure readsymlist(const s:string);
+type
+ tsltype = (sl_none,
+ sl_load,
+ sl_call,
+ sl_subscript,
+ sl_vec
+ );
+const
+ slstr : array[tsltype] of string[9] = ('',
+ 'load',
+ 'call',
+ 'subscript',
+ 'vec'
+ );
+var
+ sl : tsltype;
+begin
+ readderef;
+ repeat
+ sl:=tsltype(ppufile.getbyte);
+ if sl=sl_none then
+ break;
+ write(s,'(',slstr[sl],') ');
+ case sl of
+ sl_call,
+ sl_load,
+ sl_subscript :
+ readderef;
+ sl_vec :
+ writeln(ppufile.getlongint);
+ end;
+ until false;
+end;
+
+
+procedure readsymoptions;
+type
+ tsymoption=(sp_none,
+ sp_public,
+ sp_private,
+ sp_published,
+ sp_protected,
+ sp_static,
+ sp_hint_deprecated,
+ sp_hint_platform,
+ sp_hint_library,
+ sp_hint_unimplemented,
+ sp_has_overloaded,
+ sp_internal { internal symbol, not reported as unused }
+ );
+ tsymoptions=set of tsymoption;
+ tsymopt=record
+ mask : tsymoption;
+ str : string[30];
+ end;
+const
+ symopts=11;
+ symopt : array[1..symopts] of tsymopt=(
+ (mask:sp_public; str:'Public'),
+ (mask:sp_private; str:'Private'),
+ (mask:sp_published; str:'Published'),
+ (mask:sp_protected; str:'Protected'),
+ (mask:sp_static; str:'Static'),
+ (mask:sp_hint_deprecated;str:'Hint Deprecated'),
+ (mask:sp_hint_deprecated;str:'Hint Platform'),
+ (mask:sp_hint_deprecated;str:'Hint Library'),
+ (mask:sp_hint_deprecated;str:'Hint Unimplemented'),
+ (mask:sp_has_overloaded; str:'Has overloaded'),
+ (mask:sp_internal; str:'Internal')
+ );
+var
+ symoptions : tsymoptions;
+ i : longint;
+ first : boolean;
+begin
+ ppufile.getsmallset(symoptions);
+ if symoptions<>[] then
+ begin
+ first:=true;
+ for i:=1to symopts do
+ if (symopt[i].mask in symoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(symopt[i].str);
+ end;
+ end;
+ writeln;
+end;
+
+
+procedure readcommonsym(const s:string);
+begin
+ writeln(space,'** Symbol Nr. ',ppufile.getword,' **');
+ writeln(space,s,ppufile.getstring);
+ write(space,' File Pos : ');
+ readposinfo;
+ write(space,' SymOptions : ');
+ readsymoptions;
+end;
+
+
+procedure readcommondef(const s:string);
+type
+ tdefoption=(df_none,
+ df_has_inittable, { init data has been generated }
+ df_has_rttitable, { rtti data has been generated }
+ df_unique
+ );
+ tdefoptions=set of tdefoption;
+var
+ defopts : tdefoptions;
+begin
+ writeln(space,'** Definition Nr. ',ppufile.getword,' **');
+ writeln(space,s);
+ write (space,' Type symbol : ');
+ readderef;
+ ppufile.getsmallset(defopts);
+
+ if df_unique in defopts then
+ writeln (space,' Unique type symbol');
+
+ if df_has_rttitable in defopts then
+ begin
+ write (space,' RTTI symbol : ');
+ readderef;
+ end;
+ if df_has_inittable in defopts then
+ begin
+ write (space,' Init symbol : ');
+ readderef;
+ end;
+end;
+
+
+{ Read abstract procdef and return if inline procdef }
+type
+ tproccalloption=(pocall_none,
+ { procedure uses C styled calling }
+ pocall_cdecl,
+ { C++ calling conventions }
+ pocall_cppdecl,
+ { Far16 for OS/2 }
+ pocall_far16,
+ { Old style FPC default calling }
+ pocall_oldfpccall,
+ { Procedure has compiler magic}
+ pocall_internproc,
+ { procedure is a system call, applies e.g. to MorphOS and PalmOS }
+ pocall_syscall,
+ { pascal standard left to right }
+ pocall_pascal,
+ { procedure uses register (fastcall) calling }
+ pocall_register,
+ { safe call calling conventions }
+ pocall_safecall,
+ { procedure uses stdcall call }
+ pocall_stdcall,
+ { Special calling convention for cpus without a floating point
+ unit. Floating point numbers are passed in integer registers
+ instead of floating point registers. Depending on the other
+ available calling conventions available for the cpu
+ this replaces either pocall_fastcall or pocall_stdcall.
+ }
+ pocall_softfloat,
+ { Metrowerks Pascal. Special case on Mac OS (X): passes all }
+ { constant records by reference. }
+ pocall_mwpascal
+ );
+ tproccalloptions=set of tproccalloption;
+ tproctypeoption=(potype_none,
+ potype_proginit, { Program initialization }
+ potype_unitinit, { unit initialization }
+ potype_unitfinalize, { unit finalization }
+ potype_constructor, { Procedure is a constructor }
+ potype_destructor, { Procedure is a destructor }
+ potype_operator, { Procedure defines an operator }
+ potype_procedure,
+ potype_function
+ );
+ tproctypeoptions=set of tproctypeoption;
+ tprocoption=(po_none,
+ po_classmethod, { class method }
+ po_virtualmethod, { Procedure is a virtual method }
+ po_abstractmethod, { Procedure is an abstract method }
+ po_staticmethod, { static method }
+ po_overridingmethod, { method with override directive }
+ po_methodpointer, { method pointer, only in procvardef, also used for 'with object do' }
+ po_interrupt, { Procedure is an interrupt handler }
+ po_iocheck, { IO checking should be done after a call to the procedure }
+ po_assembler, { Procedure is written in assembler }
+ po_msgstr, { method for string message handling }
+ po_msgint, { method for int message handling }
+ po_exports, { Procedure has export directive (needed for OS/2) }
+ po_external, { Procedure is external (in other object or lib)}
+ po_overload, { procedure is declared with overload directive }
+ po_varargs, { printf like arguments }
+ po_internconst, { procedure has constant evaluator intern }
+ { flag that only the address of a method is returned and not a full methodpointer }
+ po_addressonly,
+ { procedure is exported }
+ po_public,
+ { calling convention is specified explicitly }
+ po_hascallingconvention,
+ { reintroduce flag }
+ po_reintroduce,
+ { location of parameters is given explicitly as it is necessary for some syscall
+ conventions like that one of MorphOS }
+ po_explicitparaloc,
+ { no stackframe will be generated, used by lowlevel assembler like get_frame }
+ po_nostackframe,
+ po_has_mangledname,
+ po_has_public_name,
+ po_forward,
+ po_global,
+ po_has_inlininginfo,
+ { The different kind of syscalls on MorphOS }
+ po_syscall_legacy,
+ po_syscall_sysv,
+ po_syscall_basesysv,
+ po_syscall_sysvbase,
+ po_syscall_r12base,
+ po_local,
+ { Procedure can be inlined }
+ po_inline,
+ { Procedure is used for internal compiler calls }
+ po_compilerproc
+ );
+ tprocoptions=set of tprocoption;
+procedure read_abstract_proc_def(var proccalloption:tproccalloption;var procoptions:tprocoptions);
+type
+ tproccallopt=record
+ mask : tproccalloption;
+ str : string[30];
+ end;
+ tproctypeopt=record
+ mask : tproctypeoption;
+ str : string[30];
+ end;
+ tprocopt=record
+ mask : tprocoption;
+ str : string[30];
+ end;
+const
+ proccalloptionStr : array[tproccalloption] of string[14]=('',
+ 'CDecl',
+ 'CPPDecl',
+ 'Far16',
+ 'OldFPCCall',
+ 'InternProc',
+ 'SysCall',
+ 'Pascal',
+ 'Register',
+ 'SafeCall',
+ 'StdCall',
+ 'SoftFloat',
+ 'MWPascal'
+ );
+ proctypeopts=8;
+ proctypeopt : array[1..proctypeopts] of tproctypeopt=(
+ (mask:potype_proginit; str:'ProgInit'),
+ (mask:potype_unitinit; str:'UnitInit'),
+ (mask:potype_unitfinalize;str:'UnitFinalize'),
+ (mask:potype_constructor; str:'Constructor'),
+ (mask:potype_destructor; str:'Destructor'),
+ (mask:potype_operator; str:'Operator'),
+ (mask:potype_function; str:'Function'),
+ (mask:potype_procedure; str:'Procedure')
+ );
+ procopts=35;
+ procopt : array[1..procopts] of tprocopt=(
+ (mask:po_classmethod; str:'ClassMethod'),
+ (mask:po_virtualmethod; str:'VirtualMethod'),
+ (mask:po_abstractmethod; str:'AbstractMethod'),
+ (mask:po_staticmethod; str:'StaticMethod'),
+ (mask:po_overridingmethod;str:'OverridingMethod'),
+ (mask:po_methodpointer; str:'MethodPointer'),
+ (mask:po_interrupt; str:'Interrupt'),
+ (mask:po_iocheck; str:'IOCheck'),
+ (mask:po_assembler; str:'Assembler'),
+ (mask:po_msgstr; str:'MsgStr'),
+ (mask:po_msgint; str:'MsgInt'),
+ (mask:po_exports; str:'Exports'),
+ (mask:po_external; str:'External'),
+ (mask:po_overload; str:'Overload'),
+ (mask:po_varargs; str:'VarArgs'),
+ (mask:po_internconst; str:'InternConst'),
+ (mask:po_addressonly; str:'AddressOnly'),
+ (mask:po_public; str:'Public'),
+ (mask:po_hascallingconvention;str:'HasCallingConvention'),
+ (mask:po_reintroduce; str:'ReIntroduce'),
+ (mask:po_explicitparaloc; str:'ExplicitParaloc'),
+ (mask:po_nostackframe; str:'NoStackFrame'),
+ (mask:po_has_mangledname; str:'HasMangledName'),
+ (mask:po_has_public_name; str:'HasPublicName'),
+ (mask:po_forward; str:'Forward'),
+ (mask:po_global; str:'Global'),
+ (mask:po_has_inlininginfo;str:'HasInliningInfo'),
+ (mask:po_syscall_legacy; str:'SyscallLegacy'),
+ (mask:po_syscall_sysv; str:'SyscallSysV'),
+ (mask:po_syscall_basesysv;str:'SyscallBaseSysV'),
+ (mask:po_syscall_sysvbase;str:'SyscallSysVBase'),
+ (mask:po_syscall_r12base; str:'SyscallR12Base'),
+ (mask:po_local; str:'Local'),
+ (mask:po_inline; str:'Inline'),
+ (mask:po_compilerproc; str:'CompilerProc')
+ );
+var
+ proctypeoption : tproctypeoption;
+ i : longint;
+ first : boolean;
+ tempbuf : array[0..255] of byte;
+begin
+ write(space,' Return type : ');
+ readtype;
+ writeln(space,' Fpu used : ',ppufile.getbyte);
+ proctypeoption:=tproctypeoption(ppufile.getbyte);
+ write(space,' TypeOption : ');
+ first:=true;
+ for i:=1 to proctypeopts do
+ if (proctypeopt[i].mask=proctypeoption) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(proctypeopt[i].str);
+ end;
+ writeln;
+ proccalloption:=tproccalloption(ppufile.getbyte);
+ writeln(space,' CallOption : ',proccalloptionStr[proccalloption]);
+ ppufile.getnormalset(procoptions);
+ if procoptions<>[] then
+ begin
+ write(space,' Options : ');
+ first:=true;
+ for i:=1to procopts do
+ if (procopt[i].mask in procoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(procopt[i].str);
+ end;
+ writeln;
+ end;
+ if (po_explicitparaloc in procoptions) then
+ begin
+ i:=ppufile.getbyte;
+ ppufile.getdata(tempbuf,i);
+ end;
+end;
+
+
+type
+ { options for variables }
+ tvaroption=(vo_none,
+ vo_is_C_var,
+ vo_is_external,
+ vo_is_dll_var,
+ vo_is_thread_var,
+ vo_has_local_copy,
+ vo_is_const, { variable is declared as const (parameter) and can't be written to }
+ vo_is_exported,
+ vo_is_high_para,
+ vo_is_funcret,
+ vo_is_self,
+ vo_is_vmt,
+ vo_is_result, { special result variable }
+ vo_is_parentfp,
+ vo_is_loop_counter, { used to detect assignments to loop counter }
+ vo_is_hidden_para,
+ vo_has_explicit_paraloc,
+ vo_is_syscall_lib,
+ vo_has_mangledname
+ );
+ tvaroptions=set of tvaroption;
+ { register variable }
+ tvarregable=(vr_none,
+ vr_intreg,
+ vr_fpureg,
+ vr_mmreg
+ );
+procedure readabstractvarsym(const s:string;var varoptions:tvaroptions);
+type
+ tvaropt=record
+ mask : tvaroption;
+ str : string[30];
+ end;
+const
+ varopts=18;
+ varopt : array[1..varopts] of tvaropt=(
+ (mask:vo_is_C_var; str:'CVar'),
+ (mask:vo_is_external; str:'External'),
+ (mask:vo_is_dll_var; str:'DLLVar'),
+ (mask:vo_is_thread_var; str:'ThreadVar'),
+ (mask:vo_has_local_copy; str:'HasLocalCopy'),
+ (mask:vo_is_const; str:'Constant'),
+ (mask:vo_is_exported; str:'Exported'),
+ (mask:vo_is_high_para; str:'HighValue'),
+ (mask:vo_is_funcret; str:'Funcret'),
+ (mask:vo_is_self; str:'Self'),
+ (mask:vo_is_vmt; str:'VMT'),
+ (mask:vo_is_result; str:'Result'),
+ (mask:vo_is_parentfp; str:'ParentFP'),
+ (mask:vo_is_loop_counter; str:'LoopCounter'),
+ (mask:vo_is_hidden_para; str:'Hidden'),
+ (mask:vo_has_explicit_paraloc;str:'ExplicitParaloc'),
+ (mask:vo_is_syscall_lib; str:'SysCallLib'),
+ (mask:vo_has_mangledname; str:'HasMangledName')
+ );
+var
+ i : longint;
+ first : boolean;
+begin
+ readcommonsym(s);
+ writeln(space,' Spez : ',Varspez2Str(ppufile.getbyte));
+ writeln(space,' Regable : ',Varregable2Str(ppufile.getbyte));
+ write (space,' Var Type : ');
+ readtype;
+ ppufile.getsmallset(varoptions);
+ if varoptions<>[] then
+ begin
+ write(space,' Options : ');
+ first:=true;
+ for i:=1to varopts do
+ if (varopt[i].mask in varoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(varopt[i].str);
+ end;
+ writeln;
+ end;
+end;
+
+
+procedure readnodetree;
+var
+ l : longint;
+ p : pointer;
+begin
+ with ppufile do
+ begin
+ if space<>'' then
+ Writeln(space,'------ nodetree ------');
+ if readentry=ibnodetree then
+ begin
+ l:=entrysize;
+ Writeln(space,'Tree size : ',l);
+ { Read data to prevent error that entry is not completly read }
+ getmem(p,l);
+ getdata(p^,l);
+ freemem(p);
+ end
+ else
+ begin
+ Writeln('!! ibnodetree not found');
+ end;
+ end;
+end;
+
+
+{****************************************************************************
+ Read Symbols Part
+****************************************************************************}
+
+procedure readsymbols(const s:string);
+type
+ pguid = ^tguid;
+ tguid = packed record
+ D1: LongWord;
+ D2: Word;
+ D3: Word;
+ D4: array[0..7] of Byte;
+ end;
+
+ absolutetyp = (tovar,toasm,toaddr);
+ tconsttyp = (constnone,
+ constord,conststring,constreal,
+ constset,constpointer,constnil,
+ constresourcestring,constwstring,constguid
+ );
+var
+ b : byte;
+ pc : pchar;
+ totalsyms,
+ symcnt,
+ i,j,len : longint;
+ guid : tguid;
+ tempbuf : array[0..127] of char;
+ varoptions : tvaroptions;
+begin
+ symcnt:=1;
+ with ppufile do
+ begin
+ if space<>'' then
+ Writeln(space,'------ ',s,' ------');
+ if readentry=ibstartsyms then
+ begin
+ totalsyms:=getlongint;
+ Writeln(space,'Number of symbols : ',totalsyms);
+ Writeln(space,'Symtable datasize : ',getlongint);
+ Writeln(space,'Symtable alignment: ',getlongint);
+ end
+ else
+ begin
+ totalsyms:=-1;
+ Writeln('!! ibstartsym not found');
+ end;
+ repeat
+ b:=readentry;
+ if not (b in [iberror,ibendsyms]) then
+ inc(symcnt);
+ case b of
+
+ ibunitsym :
+ readcommonsym('Unit symbol ');
+
+ iblabelsym :
+ readcommonsym('Label symbol ');
+
+ ibtypesym :
+ begin
+ readcommonsym('Type symbol ');
+ write(space,' Result Type : ');
+ readtype;
+ end;
+
+ ibprocsym :
+ begin
+ readcommonsym('Procedure symbol ');
+ len:=ppufile.getword;
+ for i:=1 to len do
+ begin
+ write(space,' Definition : ');
+ readderef;
+ end;
+ end;
+
+ ibconstsym :
+ begin
+ readcommonsym('Constant symbol ');
+ b:=getbyte;
+ case tconsttyp(b) of
+ constord :
+ begin
+ write (space,' OrdinalType : ');
+ readtype;
+ writeln(space,' Value : ',getint64);
+ end;
+ constpointer :
+ begin
+ write (space,' PointerType : ');
+ readtype;
+ writeln(space,' Value : ',getlongint)
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ len:=getlongint;
+ getmem(pc,len+1);
+ getdata(pc^,len);
+ (pc+len)^:= #0;
+ writeln(space,' Length : ',len);
+ writeln(space,' Value : "',pc,'"');
+ freemem(pc,len+1);
+ if tconsttyp(b)=constresourcestring then
+ writeln(space,' Index : ',getlongint);
+ end;
+ constreal :
+ writeln(space,' Value : ',getreal);
+ constset :
+ begin
+ write (space,' Set Type : ');
+ readtype;
+ for i:=1to 4 do
+ begin
+ write (space,' Value : ');
+ for j:=1to 8 do
+ begin
+ if j>1 then
+ write(',');
+ write(hexb(getbyte));
+ end;
+ writeln;
+ end;
+ end;
+ constwstring:
+ begin
+ end;
+ constguid:
+ begin
+ getdata(guid,sizeof(guid));
+ write (space,' IID String: {',hexstr(guid.d1,8),'-',hexstr(guid.d2,4),'-',hexstr(guid.d3,4),'-');
+ for i:=0 to 7 do
+ begin
+ write(hexstr(guid.d4[i],2));
+ if i=1 then write('-');
+ end;
+ writeln('}');
+ end
+ else
+ Writeln ('!! Invalid unit format : Invalid const type encountered: ',b);
+ end;
+ end;
+
+ ibabsolutevarsym :
+ begin
+ readabstractvarsym('Absolute variable symbol ',varoptions);
+ Write (space,' Relocated to ');
+ b:=getbyte;
+ case absolutetyp(b) of
+ tovar :
+ readsymlist(space+' Sym : ');
+ toasm :
+ Writeln('Assembler name : ',getstring);
+ toaddr :
+ begin
+ Write('Address : ',getlongint);
+ if tsystemcpu(ppufile.header.cpu)=cpu_i386 then
+ WriteLn(' (Far: ',getbyte<>0,')');
+ end;
+ else
+ Writeln ('!! Invalid unit format : Invalid absolute type encountered: ',b);
+ end;
+ end;
+
+ ibfieldvarsym :
+ begin
+ readabstractvarsym('Field Variable symbol ',varoptions);
+ writeln(space,' Address : ',getlongint);
+ end;
+
+ ibglobalvarsym :
+ begin
+ readabstractvarsym('Global Variable symbol ',varoptions);
+ write (space,' DefaultConst : ');
+ readderef;
+ if (vo_has_mangledname in varoptions) then
+ writeln(space,' Mangledname : ',getstring);
+ end;
+
+ iblocalvarsym :
+ begin
+ readabstractvarsym('Local Variable symbol ',varoptions);
+ write (space,' DefaultConst : ');
+ readderef;
+ end;
+
+ ibparavarsym :
+ begin
+ readabstractvarsym('Parameter Variable symbol ',varoptions);
+ write (space,' DefaultConst : ');
+ readderef;
+ writeln(space,' ParaNr : ',getword);
+ if (vo_has_explicit_paraloc in varoptions) then
+ begin
+ i:=getbyte;
+ getdata(tempbuf,i);
+ end;
+ end;
+
+ ibenumsym :
+ begin
+ readcommonsym('Enumeration symbol ');
+ write (space,' Definition : ');
+ readderef;
+ writeln(space,' Value : ',getlongint);
+ end;
+
+ ibsyssym :
+ begin
+ readcommonsym('Internal system symbol ');
+ writeln(space,' Internal Nr : ',getlongint);
+ end;
+
+ ibrttisym :
+ begin
+ readcommonsym('RTTI symbol ');
+ writeln(space,' RTTI Type : ',getbyte);
+ end;
+
+ ibmacrosym :
+ begin
+ readcommonsym('Macro symbol ');
+ writeln(space,' Name: ',getstring);
+ writeln(space,' Defined: ',getbyte);
+ writeln(space,' Compiler var: ',getbyte);
+ len:=getlongint;
+ writeln(space,' Value length: ',len);
+ if len > 0 then
+ begin
+ getmem(pc,len+1);
+ getdata(pc^,len);
+ (pc+len)^:= #0;
+ writeln(space,' Value: "',pc,'"');
+ freemem(pc,len+1);
+ end;
+ end;
+
+ ibtypedconstsym :
+ begin
+ readcommonsym('Typed constant ');
+ write (space,' Constant Type : ');
+ readtype;
+ writeln(space,' ReallyConst : ',(getbyte<>0));
+ end;
+
+ ibpropertysym :
+ begin
+ readcommonsym('Property ');
+ i:=getlongint;
+ writeln(space,' PropOptions : ',i);
+ if (i and 32)>0 then
+ begin
+ write (space,' OverrideProp : ');
+ readderef;
+ end
+ else
+ begin
+ write (space,' Prop Type : ');
+ readtype;
+ writeln(space,' Index : ',getlongint);
+ writeln(space,' Default : ',getlongint);
+ write (space,' Index Type : ');
+ readtype;
+ write (space,' Readaccess : ');
+ readsymlist(space+' Sym: ');
+ write (space,' Writeaccess : ');
+ readsymlist(space+' Sym: ');
+ write (space,' Storedaccess : ');
+ readsymlist(space+' Sym: ');
+ end;
+ end;
+
+ iberror :
+ begin
+ Writeln('!! Error in PPU');
+ exit;
+ end;
+
+ ibendsyms :
+ break;
+
+ else
+ WriteLn('!! Skipping unsupported PPU Entry in Symbols: ',b);
+ end;
+ if not EndOfEntry then
+ Writeln('!! Entry has more information stored');
+ until false;
+ if (totalsyms<>-1) and (symcnt-1<>totalsyms) then
+ Writeln('!! Only read ',symcnt-1,' of ',totalsyms,' symbols');
+ end;
+end;
+
+
+{****************************************************************************
+ Read defintions Part
+****************************************************************************}
+
+procedure readdefinitions(const s:string;start_read : boolean);
+type
+ tsettype = (normset,smallset,varset);
+ tbasetype = (
+ uvoid,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit,
+ bool8bit,bool16bit,bool32bit,
+ uchar,uwidechar,scurrency
+ );
+ tobjectdeftype = (odt_none,
+ odt_class,
+ odt_object,
+ odt_interfacecom,
+ odt_interfacecorba,
+ odt_cppclass
+ );
+ tvarianttype = (
+ vt_normalvariant,vt_olevariant
+ );
+var
+ b : byte;
+ totaldefs,l,j,
+ defcnt : longint;
+ calloption : tproccalloption;
+ procoptions : tprocoptions;
+ procinfooptions : tprocinfoflag;
+
+begin
+ defcnt:=0;
+ with ppufile do
+ begin
+ if space<>'' then
+ Writeln(space,'------ ',s,' ------');
+ if not start_read then
+ if readentry=ibstartdefs then
+ begin
+ totaldefs:=getlongint;
+ Writeln(space,'Number of definitions: ',totaldefs);
+ end
+ else
+ begin
+ totaldefs:=-1;
+ Writeln('!! ibstartdef not found');
+ end;
+ repeat
+ b:=readentry;
+ if not (b in [iberror,ibenddefs]) then
+ inc(defcnt);
+ case b of
+
+ ibpointerdef :
+ begin
+ readcommondef('Pointer definition');
+ write (space,' Pointed Type : ');
+ readtype;
+ writeln(space,' Is Far : ',(getbyte<>0));
+ end;
+
+ iborddef :
+ begin
+ readcommondef('Ordinal definition');
+ write (space,' Base type : ');
+ b:=getbyte;
+ case tbasetype(b) of
+ uvoid : writeln('uvoid');
+ u8bit : writeln('u8bit');
+ u16bit : writeln('u16bit');
+ u32bit : writeln('s32bit');
+ u64bit : writeln('u64bit');
+ s8bit : writeln('s8bit');
+ s16bit : writeln('s16bit');
+ s32bit : writeln('s32bit');
+ s64bit : writeln('s64bit');
+ bool8bit : writeln('bool8bit');
+ bool16bit : writeln('bool16bit');
+ bool32bit : writeln('bool32bit');
+ uchar : writeln('uchar');
+ uwidechar : writeln('uwidechar');
+ scurrency : writeln('ucurrency');
+ else writeln('!! Warning: Invalid base type ',b);
+ end;
+ writeln(space,' Range : ',getint64,' to ',getint64);
+ end;
+
+ ibfloatdef :
+ begin
+ readcommondef('Float definition');
+ writeln(space,' Float type : ',getbyte);
+ end;
+
+ ibarraydef :
+ begin
+ readcommondef('Array definition');
+ write (space,' Element type : ');
+ readtype;
+ write (space,' Range Type : ');
+ readtype;
+ writeln(space,' Range : ',getlongint,' to ',getlongint);
+ writeln(space,' Is Constructor : ',(getbyte<>0));
+ writeln(space,' Is Dynamic : ',(getbyte<>0));
+ end;
+
+ ibprocdef :
+ begin
+ readcommondef('Procedure definition');
+ read_abstract_proc_def(calloption,procoptions);
+ if (po_has_mangledname in procoptions) then
+ writeln(space,' Mangled name : ',getstring);
+ writeln(space,' Number : ',getword);
+ writeln(space,' Level : ',getbyte);
+ write (space,' Class : ');
+ readderef;
+ write (space,' Procsym : ');
+ readderef;
+ write (space,' File Pos : ');
+ readposinfo;
+ write (space,' SymOptions : ');
+ readsymoptions;
+ if tsystemcpu(ppufile.header.cpu)=cpu_powerpc then
+ begin
+ { library symbol for AmigaOS/MorphOS }
+ write (space,' Library symbol : ');
+ readderef;
+ end;
+ if (po_inline in procoptions) then
+ begin
+ write (space,' FuncretSym : ');
+ readderef;
+ ppufile.getsmallset(procinfooptions);
+ writeln(space,' ProcInfoOptions : ',dword(procinfooptions));
+ b := ppufile.getbyte;
+ writeln(space,' Inline node tree : ',b);
+ end;
+ if not EndOfEntry then
+ Writeln('!! Entry has more information stored');
+ space:=' '+space;
+ { parast }
+ readdefinitions('parast',false);
+ readsymbols('parast');
+ { localst }
+ if (po_has_inlininginfo in procoptions) or
+ ((ppufile.header.flags and uf_local_browser)<>0) then
+ begin
+ readdefinitions('localst',false);
+ readsymbols('localst');
+ end;
+ if (po_has_inlininginfo in procoptions) then
+ readnodetree;
+ delete(space,1,4);
+ end;
+
+ ibprocvardef :
+ begin
+ readcommondef('Procedural type (ProcVar) definition');
+ read_abstract_proc_def(calloption,procoptions);
+ if not EndOfEntry then
+ Writeln('!! Entry has more information stored');
+ space:=' '+space;
+ { parast }
+ readdefinitions('parast',false);
+ readsymbols('parast');
+ delete(space,1,4);
+ end;
+
+ ibshortstringdef :
+ begin
+ readcommondef('ShortString definition');
+ writeln(space,' Length : ',getbyte);
+ end;
+
+ ibwidestringdef :
+ begin
+ readcommondef('WideString definition');
+ writeln(space,' Length : ',getlongint);
+ end;
+
+ ibansistringdef :
+ begin
+ readcommondef('AnsiString definition');
+ writeln(space,' Length : ',getlongint);
+ end;
+
+ iblongstringdef :
+ begin
+ readcommondef('Longstring definition');
+ writeln(space,' Length : ',getlongint);
+ end;
+
+ ibrecorddef :
+ begin
+ readcommondef('Record definition');
+ writeln(space,' DataSize : ',getlongint);
+ writeln(space,' FieldAlign : ',getbyte);
+ writeln(space,' RecordAlign : ',getbyte);
+ writeln(space,' PadAlign : ',getbyte);
+ if not EndOfEntry then
+ Writeln('!! Entry has more information stored');
+ {read the record definitions and symbols}
+ space:=' '+space;
+ readdefinitions('fields',false);
+ readsymbols('fields');
+ Delete(space,1,4);
+ end;
+
+ ibobjectdef :
+ begin
+ readcommondef('Object/Class definition');
+ b:=getbyte;
+ write (space,' Type : ');
+ case tobjectdeftype(b) of
+ odt_class : writeln('class');
+ odt_object : writeln('object');
+ odt_interfacecom : writeln('interfacecom');
+ odt_interfacecorba : writeln('interfacecorba');
+ odt_cppclass : writeln('cppclass');
+ else writeln('!! Warning: Invalid object type ',b);
+ end;
+ writeln(space,' Name of Class : ',getstring);
+ writeln(space,' DataSize : ',getlongint);
+ writeln(space,' FieldAlign : ',getbyte);
+ writeln(space,' RecordAlign : ',getbyte);
+ writeln(space,' Vmt offset : ',getlongint);
+ write(space, ' Ancestor Class : ');
+ readderef;
+ writeln(space,' Options : ',getlongint);
+
+ if tobjectdeftype(b) in [odt_interfacecom,odt_interfacecorba] then
+ begin
+ { IIDGUID }
+ for j:=1to 16 do
+ getbyte;
+ writeln(space,' IID String : ',getstring);
+ writeln(space,' Last VTable idx : ',getlongint);
+ end;
+
+ if tobjectdeftype(b) in [odt_class,odt_interfacecorba] then
+ begin
+ l:=getlongint;
+ writeln(space,' Impl Intf Count : ',l);
+ for j:=1 to l do
+ begin
+ write (space,' - Definition : ');
+ readderef;
+ writeln(space,' IOffset : ',getlongint);
+ end;
+ end;
+
+ if not EndOfEntry then
+ Writeln('!! Entry has more information stored');
+ {read the record definitions and symbols}
+ space:=' '+space;
+ readdefinitions('fields',false);
+ readsymbols('fields');
+ Delete(space,1,4);
+ end;
+
+ ibfiledef :
+ begin
+ ReadCommonDef('File definition');
+ write (space,' Type : ');
+ case getbyte of
+ 0 : writeln('Text');
+ 1 : begin
+ writeln('Typed');
+ write (space,' File of Type : ');
+ Readtype;
+ end;
+ 2 : writeln('Untyped');
+ end;
+ end;
+
+ ibformaldef :
+ readcommondef('Generic Definition (void-typ)');
+
+ ibenumdef :
+ begin
+ readcommondef('Enumeration type definition');
+ write(space,'Base enumeration type : ');
+ readderef;
+ writeln(space,' Smallest element : ',getlongint);
+ writeln(space,' Largest element : ',getlongint);
+ writeln(space,' Size : ',getlongint);
+ end;
+
+ ibclassrefdef :
+ begin
+ readcommondef('Class reference definition');
+ write (space,' Pointed Type : ');
+ readtype;
+ end;
+
+ ibsetdef :
+ begin
+ readcommondef('Set definition');
+ write (space,' Element type : ');
+ readtype;
+ b:=getbyte;
+ case tsettype(b) of
+ smallset : writeln(space,' Set with 32 Elements');
+ normset : writeln(space,' Set with 256 Elements');
+ varset : writeln(space,' Set with ',getlongint,' Elements');
+ else writeln('!! Warning: Invalid set type ',b);
+ end;
+ end;
+
+ ibvariantdef :
+ begin
+ readcommondef('Variant definition');
+ write (space,' Varianttype : ');
+ b:=getbyte;
+ case tvarianttype(b) of
+ vt_normalvariant :
+ writeln('Normal');
+ vt_olevariant :
+ writeln('OLE');
+ else
+ writeln('!! Warning: Invalid varianttype ',b);
+ end;
+
+ end;
+
+ iberror :
+ begin
+ Writeln('!! Error in PPU');
+ exit;
+ end;
+
+ ibenddefs :
+ break;
+
+ else
+ WriteLn('!! Skipping unsupported PPU Entry in definitions: ',b);
+ end;
+ if not EndOfEntry then
+ Writeln('!! Entry has more information stored');
+ until false;
+ if (totaldefs<>-1) and (defcnt<>totaldefs) then
+ Writeln('!! Only read ',defcnt,' of ',totaldefs,' definitions');
+ end;
+end;
+
+
+{****************************************************************************
+ Read General Part
+****************************************************************************}
+
+procedure readinterface;
+var
+ b : byte;
+ sourcenumber : longint;
+begin
+ with ppufile do
+ begin
+ repeat
+ b:=readentry;
+ case b of
+
+ ibmodulename :
+ Writeln('Module Name: ',getstring);
+
+ ibsourcefiles :
+ begin
+ sourcenumber:=1;
+ while not EndOfEntry do
+ begin
+ Writeln('Source file ',sourcenumber,' : ',getstring,' ',filetimestring(getlongint));
+ inc(sourcenumber);
+ end;
+ end;
+{$IFDEF MACRO_DIFF_HINT}
+ ibusedmacros :
+ begin
+ while not EndOfEntry do
+ begin
+ Write('Conditional ',getstring);
+ b:=getbyte;
+ if boolean(b)=true then
+ write(' defined at startup')
+ else
+ write(' not defined at startup');
+ b:=getbyte;
+ if boolean(b)=true then
+ writeln(' was used')
+ else
+ writeln;
+ end;
+ end;
+{$ENDIF}
+ ibloadunit :
+ ReadLoadUnit;
+
+ iblinkunitofiles :
+ ReadLinkContainer('Link unit object file: ');
+
+ iblinkunitstaticlibs :
+ ReadLinkContainer('Link unit static lib: ');
+
+ iblinkunitsharedlibs :
+ ReadLinkContainer('Link unit shared lib: ');
+
+ iblinkotherofiles :
+ ReadLinkContainer('Link other object file: ');
+
+ iblinkotherstaticlibs :
+ ReadLinkContainer('Link other static lib: ');
+
+ iblinkothersharedlibs :
+ ReadLinkContainer('Link other shared lib: ');
+
+ ibderefdata :
+ ReadDerefData;
+
+ ibderefmap :
+ ReadDerefMap;
+
+ iberror :
+ begin
+ Writeln('Error in PPU');
+ exit;
+ end;
+
+ ibendinterface :
+ break;
+
+ else
+ WriteLn('!! Skipping unsupported PPU Entry in General Part: ',b);
+ end;
+ until false;
+ end;
+end;
+
+
+
+{****************************************************************************
+ Read Implementation Part
+****************************************************************************}
+
+procedure readimplementation;
+var
+ b : byte;
+begin
+ with ppufile do
+ begin
+ repeat
+ b:=readentry;
+ case b of
+ ibasmsymbols :
+ ReadAsmSymbols;
+
+ ibloadunit :
+ ReadLoadUnit;
+
+ iberror :
+ begin
+ Writeln('Error in PPU');
+ exit;
+ end;
+ ibendimplementation :
+ break;
+ else
+ WriteLn('!! Skipping unsupported PPU Entry in Implementation: ',b);
+ end;
+ until false;
+ end;
+end;
+
+
+{****************************************************************************
+ Read Browser Part
+****************************************************************************}
+
+procedure readbrowser;
+var
+ b : byte;
+const indent : string = '';
+begin
+ Writeln(indent,'Start of symtable browser');
+ indent:=indent+'**';
+ with ppufile do
+ begin
+ repeat
+ b:=readentry;
+ case b of
+ ibbeginsymtablebrowser :
+ begin
+ { here we must read object and record symtables !! }
+ indent:=indent+' ';
+ Writeln(indent,'Record/Object symtable');
+ readbrowser;
+ Indent:=Copy(Indent,1,Length(Indent)-2);
+ end;
+ ibsymref :
+ begin
+ readderef;
+ readref;
+ end;
+ ibdefref :
+ begin
+ readderef;
+ readref;
+ if ((ppufile.header.flags and uf_local_browser)<>0) and
+ (UnitIndex=0) then
+ begin
+ { parast and localst }
+ indent:=indent+' ';
+ b:=ppufile.readentry;
+ if b=ibbeginsymtablebrowser then
+ readbrowser;
+ b:=ppufile.readentry;
+ if b=ibbeginsymtablebrowser then
+ readbrowser;
+ Indent:=Copy(Indent,1,Length(Indent)-2);
+ end;
+ end;
+ iberror :
+ begin
+ Writeln('Error in PPU');
+ exit;
+ end;
+ ibendsymtablebrowser :
+ break;
+ else
+ begin
+ WriteLn('!! Skipping unsupported PPU Entry in Browser: ',b);
+ Halt;
+ end;
+ end;
+ until false;
+ end;
+ Indent:=Copy(Indent,1,Length(Indent)-2);
+ Writeln(Indent,'End of symtable browser');
+end;
+
+
+
+
+procedure dofile (filename : string);
+var
+ b : byte;
+begin
+{ reset }
+ space:='';
+{ fix filename }
+ if pos('.',filename)=0 then
+ filename:=filename+'.ppu';
+ ppufile:=tppufile.create(filename);
+ if not ppufile.openfile then
+ begin
+ writeln ('IO-Error when opening : ',filename,', Skipping');
+ exit;
+ end;
+{ PPU File is open, check for PPU Id }
+ if not ppufile.CheckPPUID then
+ begin
+ writeln(Filename,' : Not a valid PPU file, Skipping');
+ exit;
+ end;
+{ Check PPU Version }
+ Writeln('Analyzing ',filename,' (v',ppufile.GetPPUVersion,')');
+ if ppufile.GetPPUVersion<16 then
+ begin
+ writeln(Filename,' : Old PPU Formats (<v16) are not supported, Skipping');
+ exit;
+ end;
+{ Write PPU Header Information }
+ if (verbose and v_header)<>0 then
+ begin
+ Writeln;
+ Writeln('Header');
+ Writeln('-------');
+ with ppufile.header do
+ begin
+ Writeln('Compiler version : ',ppufile.header.compiler shr 14,'.',
+ (ppufile.header.compiler shr 7) and $7f,'.',
+ ppufile.header.compiler and $7f);
+ WriteLn('Target processor : ',Cpu2Str(cpu));
+ WriteLn('Target operating system : ',Target2Str(target));
+ Writeln('Unit flags : ',PPUFlags2Str(flags));
+ Writeln('FileSize (w/o header) : ',size);
+ Writeln('Checksum : ',hexstr(checksum,8));
+ Writeln('Interface Checksum : ',hexstr(interface_checksum,8));
+ end;
+ end;
+{read the general stuff}
+ if (verbose and v_interface)<>0 then
+ begin
+ Writeln;
+ Writeln('Interface section');
+ Writeln('------------------');
+ readinterface;
+ end
+ else
+ ppufile.skipuntilentry(ibendinterface);
+{read the definitions}
+ if (verbose and v_defs)<>0 then
+ begin
+ Writeln;
+ Writeln('Interface definitions');
+ Writeln('----------------------');
+ readdefinitions('interface',false);
+ end
+ else
+ ppufile.skipuntilentry(ibenddefs);
+{read the symbols}
+ if (verbose and v_syms)<>0 then
+ begin
+ Writeln;
+ Writeln('Interface Symbols');
+ Writeln('------------------');
+ readsymbols('interface');
+ end
+ else
+ ppufile.skipuntilentry(ibendsyms);
+
+{read the macro symbols}
+ if (verbose and v_syms)<>0 then
+ begin
+ Writeln;
+ Writeln('Interface Macro Symbols');
+ Writeln('-----------------------');
+ end;
+ if ppufile.readentry<>ibexportedmacros then
+ begin
+ Writeln('!! Error in PPU');
+ exit;
+ end;
+ if boolean(ppufile.getbyte) then
+ begin
+ {skip the definition section for macros (since they are never used) }
+ ppufile.skipuntilentry(ibenddefs);
+ {read the macro symbols}
+ if (verbose and v_syms)<>0 then
+ readsymbols('interface macro')
+ else
+ ppufile.skipuntilentry(ibendsyms);
+ end
+ else
+ Writeln('(no exported macros)');
+
+{read the implementation stuff}
+ if (verbose and v_implementation)<>0 then
+ begin
+ Writeln;
+ Writeln('Implementation section');
+ Writeln('-----------------------');
+ readimplementation;
+ end
+ else
+ ppufile.skipuntilentry(ibendimplementation);
+{read the static browser units stuff}
+ if (ppufile.header.flags and uf_local_symtable)<>0 then
+ begin
+ if (verbose and v_defs)<>0 then
+ begin
+ Writeln;
+ Writeln('Static definitions');
+ Writeln('----------------------');
+ readdefinitions('implementation',false);
+ end
+ else
+ ppufile.skipuntilentry(ibenddefs);
+ {read the symbols}
+ if (verbose and v_syms)<>0 then
+ begin
+ Writeln;
+ Writeln('Static Symbols');
+ Writeln('------------------');
+ readsymbols('implementation');
+ end
+ else
+ ppufile.skipuntilentry(ibendsyms);
+ end;
+{read the browser units stuff}
+ if (ppufile.header.flags and uf_has_browser)<>0 then
+ begin
+ if (verbose and v_browser)<>0 then
+ begin
+ Writeln;
+ Writeln('Browser section');
+ Writeln('---------------');
+ UnitIndex:=0;
+ repeat
+ b:=ppufile.readentry;
+ if b = ibendbrowser then break;
+ if b=ibbeginsymtablebrowser then
+ begin
+ Writeln('Unit ',UnitIndex);
+ readbrowser;
+ Inc(UnitIndex);
+ end
+ else
+ Writeln('Wrong end browser entry ',b,' should be ',ibendbrowser);
+ until false;
+ end;
+ end;
+{read the static browser units stuff}
+ if (ppufile.header.flags and uf_local_browser)<>0 then
+ begin
+ if (verbose and v_browser)<>0 then
+ begin
+ Writeln;
+ Writeln('Static browser section');
+ Writeln('---------------');
+ UnitIndex:=0;
+ b:=ppufile.readentry;
+ if b=ibbeginsymtablebrowser then
+ readbrowser
+ else
+ Writeln('Wrong end browser entry ',b,' should be ',ibendbrowser);
+ end;
+ end;
+{shutdown ppufile}
+ ppufile.closefile;
+ ppufile.free;
+ Writeln;
+end;
+
+
+
+procedure help;
+begin
+ writeln('usage: ppudump [options] <filename1> <filename2>...');
+ writeln;
+ writeln('[options] can be:');
+ writeln(' -V<verbose> Set verbosity to <verbose>');
+ writeln(' H - Show header info');
+ writeln(' I - Show interface');
+ writeln(' M - Show implementation');
+ writeln(' S - Show interface symbols');
+ writeln(' D - Show interface definitions');
+ writeln(' B - Show browser info');
+ writeln(' A - Show all');
+ writeln(' -h, -? This helpscreen');
+ halt;
+end;
+
+var
+ startpara,
+ nrfile,i : longint;
+ para : string;
+begin
+ writeln(Title+' '+Version);
+ writeln(Copyright);
+ writeln;
+ if paramcount<1 then
+ begin
+ writeln('usage: dumpppu [options] <filename1> <filename2>...');
+ halt(1);
+ end;
+{ turn verbose on by default }
+ verbose:=v_all;
+{ read options }
+ startpara:=1;
+ while copy(paramstr(startpara),1,1)='-' do
+ begin
+ para:=paramstr(startpara);
+ case upcase(para[2]) of
+ 'V' : begin
+ verbose:=0;
+ for i:=3 to length(para) do
+ case upcase(para[i]) of
+ 'H' : verbose:=verbose or v_header;
+ 'I' : verbose:=verbose or v_interface;
+ 'M' : verbose:=verbose or v_implementation;
+ 'D' : verbose:=verbose or v_defs;
+ 'S' : verbose:=verbose or v_syms;
+ 'B' : verbose:=verbose or v_browser;
+ 'A' : verbose:=verbose or v_all;
+ end;
+ end;
+ 'H' : help;
+ '?' : help;
+ end;
+ inc(startpara);
+ end;
+{ process files }
+ for nrfile:=startpara to paramcount do
+ dofile (paramstr(nrfile));
+ if has_errors then
+ Halt(1);
+end.
diff --git a/compiler/utils/ppufiles.pp b/compiler/utils/ppufiles.pp
new file mode 100644
index 0000000000..66ff08736f
--- /dev/null
+++ b/compiler/utils/ppufiles.pp
@@ -0,0 +1,252 @@
+{
+ Copyright (c) 1999-2002 by Peter Vreman
+
+ List files needed by PPU
+
+ 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.
+
+ ****************************************************************************}
+Program ppufiles;
+
+uses
+ dos,
+ ppu;
+
+const
+ Version = 'Version 1.00';
+ Title = 'PPU-Files';
+ Copyright = 'Copyright (c) 1999-2002 by the Free Pascal Development Team';
+
+ PPUExt = 'ppu';
+
+type
+ poutfile = ^toutfile;
+ toutfile = record
+ name : string;
+ next : poutfile;
+ end;
+
+var
+ skipdup,
+ showstatic,
+ showshared,
+ showobjects : boolean;
+
+ OutFiles : poutfile;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+Procedure Error(const s:string;stop:boolean);
+{
+ Write an error message to stderr
+}
+begin
+{$ifdef FPC}
+ writeln(stderr,s);
+{$else}
+ writeln(s);
+{$endif}
+ if stop then
+ halt(1);
+end;
+
+
+Function AddExtension(Const HStr,ext:String):String;
+{
+ Return a filename which will have extension ext added if no
+ extension is found
+}
+var
+ j : longint;
+begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ AddExtension:=Hstr+'.'+Ext
+ else
+ AddExtension:=HStr;
+end;
+
+
+Function SplitPath(Const HStr:String):String;
+var
+ i : longint;
+begin
+ i:=Length(Hstr);
+ while (i>0) and not(Hstr[i] in ['\','/']) do
+ dec(i);
+ SplitPath:=Copy(Hstr,1,i);
+end;
+
+
+Procedure AddFile(const s:string);
+var
+ p : poutfile;
+begin
+ p:=nil;
+ if skipdup then
+ begin
+ p:=outfiles;
+ while assigned(p) do
+ begin
+ if s=p^.name then
+ break;
+ p:=p^.next;
+ end;
+ end;
+ if not assigned(p) then
+ begin
+ new(p);
+ p^.name:=s;
+ p^.next:=outfiles;
+ outfiles:=p;
+ end;
+end;
+
+
+Function DoPPU(const PPUFn:String):Boolean;
+{
+ Convert one file (in Filename) to library format.
+ Return true if successful, false otherwise.
+}
+Var
+ inppu : tppufile;
+ b : byte;
+
+ procedure showfiles;
+ begin
+ while not inppu.endofentry do
+ begin
+ AddFile(inppu.getstring);
+ inppu.getlongint;
+ end;
+ end;
+
+begin
+ DoPPU:=false;
+ inppu:=tppufile.create(PPUFn);
+ if not inppu.openfile then
+ begin
+ inppu.free;
+ Error('Error: Could not open : '+PPUFn,false);
+ Exit;
+ end;
+{ Check the ppufile }
+ if not inppu.CheckPPUId then
+ begin
+ inppu.free;
+ Error('Error: Not a PPU File : '+PPUFn,false);
+ Exit;
+ end;
+ if inppu.GetPPUVersion<CurrentPPUVersion then
+ begin
+ inppu.free;
+ Error('Error: Wrong PPU Version : '+PPUFn,false);
+ Exit;
+ end;
+{ read until the object files are found }
+ repeat
+ b:=inppu.readentry;
+ case b of
+ ibendinterface,
+ ibend :
+ break;
+ iblinkunitstaticlibs :
+ if showstatic then
+ showfiles;
+ iblinkunitsharedlibs :
+ if showshared then
+ showfiles;
+ iblinkunitofiles :
+ if showobjects then
+ showfiles;
+ end;
+ until false;
+ inppu.free;
+ DoPPU:=True;
+end;
+
+
+
+var
+ i,parafile : longint;
+ dir : SearchRec;
+ s,InFile : String;
+ p : poutfile;
+begin
+{ defaults }
+ skipdup:=true;
+{ options }
+ i:=1;
+ while (i<=paramcount) do
+ begin
+ s:=paramstr(i);
+ if s[1]<>'-' then
+ break;
+ case upcase(s[2]) of
+ 'L' : showshared:=true;
+ 'S' : showstatic:=true;
+ 'O' : showobjects:=true;
+ 'A' : skipdup:=false;
+ '?','H' :
+ begin
+ writeln('usage: ppufiles [options] <files>');
+ writeln('options:');
+ writeln(' -A Show all files (don''t remove duplicates)');
+ writeln(' -L Show only shared libraries');
+ writeln(' -S Show only static libraries');
+ writeln(' -O Show only object files');
+ writeln(' -H This helpscreen');
+ end;
+ end;
+ inc(i);
+ end;
+ { default shows everything }
+ if i=1 then
+ begin
+ showshared:=true;
+ showstatic:=true;
+ showobjects:=true;
+ end;
+{ files }
+ parafile:=i;
+ for i:=parafile to ParamCount do
+ begin
+ InFile:=AddExtension(ParamStr(i),PPUExt);
+ FindFirst(InFile,$20,Dir);
+ while (DosError=0) do
+ begin
+ DoPPU(SplitPath(InFile)+Dir.Name);
+ FindNext(Dir);
+ end;
+{$ifdef fpc}
+ FindClose(Dir);
+{$endif}
+ end;
+{ Display the files }
+ while assigned(outfiles) do
+ begin
+ p:=outfiles;
+ write(outfiles^.name);
+ outfiles:=outfiles^.next;
+ dispose(p);
+ if assigned(outfiles) then
+ write(' ');
+ end;
+end.
diff --git a/compiler/utils/ppumove.pp b/compiler/utils/ppumove.pp
new file mode 100644
index 0000000000..8250004622
--- /dev/null
+++ b/compiler/utils/ppumove.pp
@@ -0,0 +1,613 @@
+{
+ Copyright (c) 1999-2002 by the FPC Development Team
+
+ Add multiple FPC units into a static/shared library
+
+ 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.
+
+ ****************************************************************************}
+{$ifndef TP}
+ {$H+}
+{$endif}
+Program ppumove;
+uses
+{$ifdef unix}
+ {$ifdef ver1_0}
+ linux,
+ {$else}
+ Baseunix,Unix, UnixUtil,
+ {$endif}
+{$else unix}
+ dos,
+{$endif unix}
+ ppu,
+ getopts;
+
+const
+ Version = 'Version 1.00';
+ Title = 'PPU-Mover';
+ Copyright = 'Copyright (c) 1998-2002 by the Free Pascal Development Team';
+
+ ShortOpts = 'o:e:d:qhsvbw';
+ BufSize = 4096;
+ PPUExt = 'ppu';
+ ObjExt = 'o';
+ StaticLibExt ='a';
+{$ifdef unix}
+ SharedLibExt ='so';
+ BatchExt ='.sh';
+{$else}
+ SharedLibExt ='dll';
+ BatchExt ='.bat';
+{$endif unix}
+
+ { link options }
+ link_none = $0;
+ link_allways = $1;
+ link_static = $2;
+ link_smart = $4;
+ link_shared = $8;
+
+Type
+ PLinkOEnt = ^TLinkOEnt;
+ TLinkOEnt = record
+ Name : string;
+ Next : PLinkOEnt;
+ end;
+
+Var
+ ArBin,LDBin,StripBin,
+ OutputFile,
+ OutputFileForLink, { the name of the output file needed when linking }
+ DestPath,
+ PPLExt,
+ LibExt : string;
+ Batch,
+ Quiet,
+ MakeStatic : boolean;
+ Buffer : Pointer;
+ ObjFiles : PLinkOEnt;
+ BatchFile : Text;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+Procedure Error(const s:string;stop:boolean);
+{
+ Write an error message to stderr
+}
+begin
+{$ifdef FPC}
+ writeln(stderr,s);
+{$else}
+ writeln(s);
+{$endif}
+ if stop then
+ halt(1);
+end;
+
+
+function Shell(const s:string):longint;
+{
+ Run a shell commnad and return the exitcode
+}
+begin
+ if Batch then
+ begin
+ Writeln(BatchFile,s);
+ Shell:=0;
+ exit;
+ end;
+{$ifdef unix}
+ Shell:={$ifdef ver1_0}linux{$else}unix{$endif}.shell(s);
+{$else}
+ exec(getenv('COMSPEC'),'/C '+s);
+ Shell:=DosExitCode;
+{$endif}
+end;
+
+
+Function FileExists (Const F : String) : Boolean;
+{
+ Returns True if the file exists, False if not.
+}
+Var
+{$ifdef unix}
+ info : Stat;
+{$else}
+ info : searchrec;
+{$endif}
+begin
+{$ifdef unix}
+ FileExists:={$ifdef VER1_0}FStat{$ELSE}FpStat{$endif} (F,Info){$ifndef VER1_0}=0{$endif};
+{$else}
+ FindFirst (F,anyfile,Info);
+ FileExists:=DosError=0;
+{$endif}
+end;
+
+
+Function AddExtension(Const HStr,ext:String):String;
+{
+ Return a filename which will have extension ext added if no
+ extension is found
+}
+var
+ j : longint;
+begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ AddExtension:=Hstr+'.'+Ext
+ else
+ AddExtension:=HStr;
+end;
+
+
+Function ForceExtension(Const HStr,ext:String):String;
+{
+ Return a filename which certainly has the extension ext
+}
+var
+ j : longint;
+begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ j:=255;
+ ForceExtension:=Copy(Hstr,1,j-1)+'.'+Ext;
+end;
+
+
+Procedure AddToLinkFiles(const S : String);
+{
+ Adds a filename to a list of object files to link to.
+ No duplicates allowed.
+}
+Var
+ P : PLinKOEnt;
+begin
+ P:=ObjFiles;
+ { Don't add files twice }
+ While (P<>nil) and (p^.name<>s) do
+ p:=p^.next;
+ if p=nil then
+ begin
+ new(p);
+ p^.next:=ObjFiles;
+ p^.name:=s;
+ ObjFiles:=P;
+ end;
+end;
+
+
+Function ExtractLib(const libfn:string):string;
+{
+ Extract a static library libfn and return the files with a
+ wildcard
+}
+var
+ n : namestr;
+ d : dirstr;
+ e : extstr;
+begin
+{ create the temp dir first }
+ fsplit(libfn,d,n,e);
+ {$I-}
+ mkdir(n+'.sl');
+ {$I+}
+ if ioresult<>0 then;
+{ Extract }
+ if Shell(arbin+' x '+libfn)<>0 then
+ Error('Fatal: Error running '+arbin,true);
+{ Remove the lib file, it's extracted so it can be created with ease }
+ if PPLExt=PPUExt then
+ Shell('rm '+libfn);
+{$ifdef unix}
+ ExtractLib:=n+'.sl/*';
+{$else}
+ ExtractLib:=n+'.sl\*';
+{$endif}
+end;
+
+
+Function DoPPU(const PPUFn,PPLFn:String):Boolean;
+{
+ Convert one file (in Filename) to library format.
+ Return true if successful, false otherwise.
+}
+Var
+ inppu,
+ outppu : tppufile;
+ b,
+ untilb : byte;
+ l,m : longint;
+ f : file;
+ s : string;
+begin
+ DoPPU:=false;
+ If Not Quiet then
+ Write ('Processing ',PPUFn,'...');
+ inppu:=tppufile.create(PPUFn);
+ if not inppu.openfile then
+ begin
+ inppu.free;
+ Error('Error: Could not open : '+PPUFn,false);
+ Exit;
+ end;
+{ Check the ppufile }
+ if not inppu.CheckPPUId then
+ begin
+ inppu.free;
+ Error('Error: Not a PPU File : '+PPUFn,false);
+ Exit;
+ end;
+ if inppu.GetPPUVersion<CurrentPPUVersion then
+ begin
+ inppu.free;
+ Error('Error: Wrong PPU Version : '+PPUFn,false);
+ Exit;
+ end;
+{ No .o file generated for this ppu, just skip }
+ if (inppu.header.flags and uf_no_link)<>0 then
+ begin
+ inppu.free;
+ If Not Quiet then
+ Writeln (' No files.');
+ DoPPU:=true;
+ Exit;
+ end;
+{ Already a lib? }
+ if (inppu.header.flags and uf_in_library)<>0 then
+ begin
+ inppu.free;
+ Error('Error: PPU is already in a library : '+PPUFn,false);
+ Exit;
+ end;
+{ We need a static linked unit }
+ if (inppu.header.flags and uf_static_linked)=0 then
+ begin
+ inppu.free;
+ Error('Error: PPU is not static linked : '+PPUFn,false);
+ Exit;
+ end;
+{ Create the new ppu }
+ if PPUFn=PPLFn then
+ outppu:=tppufile.create('ppumove.$$$')
+ else
+ outppu:=tppufile.create(PPLFn);
+ outppu.createfile;
+{ Create new header, with the new flags }
+ outppu.header:=inppu.header;
+ outppu.header.flags:=outppu.header.flags or uf_in_library;
+ if MakeStatic then
+ outppu.header.flags:=outppu.header.flags or uf_static_linked
+ else
+ outppu.header.flags:=outppu.header.flags or uf_shared_linked;
+{ read until the object files are found }
+ untilb:=iblinkunitofiles;
+ repeat
+ b:=inppu.readentry;
+ if b in [ibendinterface,ibend] then
+ begin
+ inppu.free;
+ outppu.free;
+ Error('Error: No files to be linked found : '+PPUFn,false);
+ Exit;
+ end;
+ if b<>untilb then
+ begin
+ repeat
+ inppu.getdatabuf(buffer^,bufsize,l);
+ outppu.putdata(buffer^,l);
+ until l<bufsize;
+ outppu.writeentry(b);
+ end;
+ until (b=untilb);
+{ we have now reached the section for the files which need to be added,
+ now add them to the list }
+ case b of
+ iblinkunitofiles :
+ begin
+ { add all o files, and save the entry when not creating a static
+ library to keep staticlinking possible }
+ while not inppu.endofentry do
+ begin
+ s:=inppu.getstring;
+ m:=inppu.getlongint;
+ if not MakeStatic then
+ begin
+ outppu.putstring(s);
+ outppu.putlongint(m);
+ end;
+ AddToLinkFiles(s);
+ end;
+ if not MakeStatic then
+ outppu.writeentry(b);
+ end;
+{ iblinkunitstaticlibs :
+ begin
+ AddToLinkFiles(ExtractLib(inppu.getstring));
+ if not inppu.endofentry then
+ begin
+ repeat
+ inppu.getdatabuf(buffer^,bufsize,l);
+ outppu.putdata(buffer^,l);
+ until l<bufsize;
+ outppu.writeentry(b);
+ end;
+ end; }
+ end;
+{ just add a new entry with the new lib }
+ if MakeStatic then
+ begin
+ outppu.putstring(outputfileforlink);
+ outppu.putlongint(link_static);
+ outppu.writeentry(iblinkunitstaticlibs)
+ end
+ else
+ begin
+ outppu.putstring(outputfileforlink);
+ outppu.putlongint(link_shared);
+ outppu.writeentry(iblinkunitsharedlibs);
+ end;
+{ read all entries until the end and write them also to the new ppu }
+ repeat
+ b:=inppu.readentry;
+ { don't write ibend, that's written automaticly }
+ if b<>ibend then
+ begin
+ repeat
+ inppu.getdatabuf(buffer^,bufsize,l);
+ outppu.putdata(buffer^,l);
+ until l<bufsize;
+ outppu.writeentry(b);
+ end;
+ until b=ibend;
+{ write the last stuff and close }
+ outppu.flush;
+ outppu.writeheader;
+ outppu.free;
+ inppu.free;
+{ rename }
+ if PPUFn=PPLFn then
+ begin
+ {$I-}
+ assign(f,PPUFn);
+ erase(f);
+ assign(f,'ppumove.$$$');
+ rename(f,PPUFn);
+ {$I+}
+ if ioresult<>0 then;
+ end;
+{ the end }
+ If Not Quiet then
+ Writeln (' Done.');
+ DoPPU:=True;
+end;
+
+
+Function DoFile(const FileName:String):Boolean;
+{
+ Process a file, mainly here for wildcard support under Dos
+}
+{$ifndef unix}
+var
+ dir : searchrec;
+{$endif}
+begin
+{$ifdef unix}
+ DoFile:=DoPPU(FileName,ForceExtension(FileName,PPLExt));
+{$else}
+ DoFile:=false;
+ findfirst(filename,$20,dir);
+ while doserror=0 do
+ begin
+ if not DoPPU(Dir.Name,ForceExtension(Dir.Name,PPLExt)) then
+ exit;
+ findnext(dir);
+ end;
+ findclose(dir);
+ DoFile:=true;
+{$endif}
+end;
+
+
+Procedure DoLink;
+{
+ Link the object files together to form a (shared) library, the only
+ problem here is the 255 char limit of Names
+}
+Var
+ Names : String;
+ f : file;
+ Err : boolean;
+ P : PLinkOEnt;
+begin
+ if not Quiet then
+ Write ('Linking ');
+ P:=ObjFiles;
+ names:='';
+ While p<>nil do
+ begin
+ if Names<>'' then
+ Names:=Names+' '+P^.name
+ else
+ Names:=p^.Name;
+ p:=p^.next;
+ end;
+ if Names='' then
+ begin
+ If not Quiet then
+ Writeln('Error: no files found to be linked');
+ exit;
+ end;
+ If not Quiet then
+ WriteLn(names);
+{ Run ar or ld to create the lib }
+ If MakeStatic then
+ Err:=Shell(arbin+' rs '+outputfile+' '+names)<>0
+ else
+ begin
+ Err:=Shell(ldbin+' -shared -o '+OutputFile+' '+names)<>0;
+ if not Err then
+ Shell(stripbin+' --strip-unneeded '+OutputFile);
+ end;
+ If Err then
+ Error('Fatal: Library building stage failed.',true);
+{ fix permission to 644, so it's not 755 }
+{$ifdef unix}
+ {$ifdef VER1_0}ChMod{$ELSE}FPChmod{$endif}(OutputFile,420);
+{$endif}
+{ Rename to the destpath }
+ if DestPath<>'' then
+ begin
+ Assign(F, OutputFile);
+ Rename(F,DestPath+'/'+OutputFile);
+ end;
+end;
+
+
+Procedure usage;
+{
+ Print usage and exit.
+}
+begin
+ Writeln(paramstr(0),': [-qhwvbs] [-e ext] [-o name] [-d path] file [file ...]');
+ Halt(0);
+end;
+
+
+
+Procedure processopts;
+{
+ Process command line opions, and checks if command line options OK.
+}
+var
+ C : char;
+begin
+ if paramcount=0 then
+ usage;
+{ Reset }
+ ObjFiles:=Nil;
+ Quiet:=False;
+ Batch:=False;
+ OutputFile:='';
+ PPLExt:='ppu';
+ ArBin:='ar';
+ LdBin:='ld';
+ StripBin:='strip';
+ repeat
+ c:=Getopt (ShortOpts);
+ Case C of
+ EndOfOptions : break;
+ 's' : MakeStatic:=True;
+ 'o' : OutputFile:=OptArg;
+ 'd' : DestPath:=OptArg;
+ 'e' : PPLext:=OptArg;
+ 'q' : Quiet:=True;
+ 'w' : begin
+ ArBin:='arw';
+ LdBin:='ldw';
+ end;
+ 'b' : Batch:=true;
+ '?' : Usage;
+ 'h' : Usage;
+ end;
+ until false;
+{ Test filenames on the commandline }
+ if (OptInd>Paramcount) then
+ Error('Error: no input files',true);
+ if (OptInd<ParamCount) and (OutputFile='') then
+ Error('Error: when moving multiple units, specify an output name.',true);
+{ alloc a buffer }
+ GetMem (Buffer,Bufsize);
+ If Buffer=Nil then
+ Error('Error: could not allocate memory for buffer.',true);
+end;
+
+
+var
+ i : longint;
+begin
+ ProcessOpts;
+{ Write Header }
+ if not Quiet then
+ begin
+ Writeln(Title+' '+Version);
+ Writeln(Copyright);
+ Writeln;
+ end;
+{ Check if shared is allowed }
+{$ifndef unix}
+ if arbin<>'arw' then
+ begin
+ Writeln('Warning: shared library not supported for Go32, switching to static library');
+ MakeStatic:=true;
+ end;
+{$endif}
+{ fix the libext and outputfilename }
+ if Makestatic then
+ LibExt:=StaticLibExt
+ else
+ LibExt:=SharedLibExt;
+ if OutputFile='' then
+ OutPutFile:=Paramstr(OptInd);
+{ fix filename }
+{$ifdef unix}
+ if Copy(OutputFile,1,3)<>'lib' then
+ OutputFile:='lib'+OutputFile;
+ { For unix skip replacing the extension if a full .so.X.X if specified }
+ i:=pos('.so.',Outputfile);
+ if i<>0 then
+ OutputFileForLink:=Copy(Outputfile,4,i-4)
+ else
+ begin
+ OutputFile:=ForceExtension(OutputFile,LibExt);
+ OutputFileForLink:=Copy(Outputfile,4,length(Outputfile)-length(LibExt)-4);
+ end;
+{$else}
+ OutputFile:=ForceExtension(OutputFile,LibExt);
+ OutputFileForLink:=OutputFile;
+{$endif}
+{ Open BatchFile }
+ if Batch then
+ begin
+ Assign(BatchFile,'pmove'+BatchExt);
+ Rewrite(BatchFile);
+ end;
+{ Process Files }
+ i:=OptInd;
+ While (i<=ParamCount) and Dofile(AddExtension(Paramstr(i),PPUExt)) do
+ Inc(i);
+{ Do Linking stage }
+ DoLink;
+{ Close BatchFile }
+ if Batch then
+ begin
+ if Not Quiet then
+ Writeln('Writing pmove'+BatchExt);
+ Close(BatchFile);
+{$ifdef unix}
+ {$ifdef VER1_0}ChMod{$ELSE}FPChmod{$endif}('pmove'+BatchExt,493);
+{$endif}
+ end;
+{ The End }
+ if Not Quiet then
+ Writeln('Done.');
+end.
diff --git a/compiler/utils/samplecfg b/compiler/utils/samplecfg
new file mode 100644
index 0000000000..bad2d8f569
--- /dev/null
+++ b/compiler/utils/samplecfg
@@ -0,0 +1,267 @@
+#!/bin/sh
+#
+# $Id: samplecfg,v 1.13 2005/02/19 18:50:20 florian Exp $
+#
+# Generate Sample Free Pascal configuration file
+#
+
+HOSTOS=`uname -s | tr A-Z a-z`
+echo Running on $HOSTOS
+
+if [ $# = 0 ]; then
+ echo 'Usage :'
+ echo 'samplecfg fpcdir confdir'
+ echo 'fpcdir = Path where FPC is installed'
+ echo 'confdir = Path to /etc'
+ exit 1
+fi
+if [ $2 ]; then
+ sysdir=$2
+ [ -d $sysdir ] || mkdir $sysdir
+else
+ sysdir=/etc
+fi
+
+# Detect if we have write permission in root.
+if [ -w $sysdir ] ; then
+ echo Write permission in $sysdir.
+ thefile=$sysdir/fpc.cfg
+else
+ echo No write premission in $sysdir.
+ thefile=$HOME/.fpc.cfg
+fi
+#
+if [ -f $thefile ] ; then
+ mv $thefile $thefile.orig >/dev/null 2>&1
+ if [ $? = 0 ]; then
+ echo Saved old config to $thefile.orig
+ else
+ echo Could not save old config. Bailing out...
+ exit
+ fi
+fi
+
+# Find path to libgcc.a
+GCCSPEC=`(gcc -v 2>&1)| head -n 1| awk '{ print $4 } '`
+if [ -z "$GCCSPEC" ] ; then
+ GCCSPEC=`gcc -print-libgcc-file-name`
+fi
+GCCDIR=`dirname $GCCSPEC`
+echo $GCCDIR
+if [ -f $GCCDIR ]; then
+# include ports tree dir for FreeBSDers.
+case $HOSTOS in
+ freebsd)
+ GCCDIR=-Fl/usr/local/lib
+ ;;
+ openbsd)
+ GCCDIR=-Fl/usr/local/lib
+ ;;
+ netbsd)
+ GCCDIR=-Fl/usr/pkg/lib
+ ;;
+esac
+else
+ echo Found libgcc.a in $GCCDIR
+ GCCDIR=-Fl$GCCDIR
+fi
+# Write the file
+echo Writing sample configuration file to $thefile
+cat <<EOFCFG > $thefile
+#
+# Example fpc.cfg for Free Pascal Compiler
+#
+
+# ----------------------
+# Defines (preprocessor)
+# ----------------------
+
+#
+# nested #IFNDEF, #IFDEF, #ENDIF, #ELSE, #DEFINE, #UNDEF are allowed
+#
+# -d is the same as #DEFINE
+# -u is the same as #UNDEF
+#
+
+#
+# Some examples (for switches see below, and the -? helppages)
+#
+# Try compiling with the -dRELEASE or -dDEBUG on the commandline
+#
+
+# For a release compile with optimizes and strip debuginfo
+#IFDEF RELEASE
+ -OG2p3
+ -Xs
+ #WRITE Compiling Release Version
+#ENDIF
+
+# For a debug version compile with debuginfo and all codegeneration checks on
+#IFDEF DEBUG
+ -g
+ -Crtoi
+ #WRITE Compiling Debug Version
+#ENDIF
+
+# set binutils prefix
+#IFDEF FPC_CROSSCOMPILING
+ -XP$fpctarget-
+#ENDIF
+
+# ----------------
+# Parsing switches
+# ----------------
+
+# Pascal language mode
+# -Mfpc free pascal dialect (default)
+# -Mobjfpc switch some Delphi 2 extensions on
+# -Mdelphi tries to be Delphi compatible
+# -Mtp tries to be TP/BP 7.0 compatible
+# -Mgpc tries to be gpc compatible
+# -Mmacpas tries to be compatible to the macintosh pascal dialects
+#
+# Turn on Object Pascal extensions by default
+#-Mobjfpc
+
+# Assembler reader mode
+# -Rdefault use default assembler
+# -Ratt read AT&T style assembler
+# -Rintel read Intel style assembler
+#
+# All assembler blocks are AT&T styled by default
+#-Ratt
+
+# Semantic checking
+# -S2 same as -Mobjfpc
+# -Sc supports operators like C (*=,+=,/= and -=)
+# -Sa include assertion code.
+# -Sd same as -Mdelphi
+# -Se<x> compiler stops after the <x> errors (default is 1)
+# -Sg allow LABEL and GOTO
+# -Sh Use ansistrings
+# -Si support C++ styled INLINE
+# -SI<x> set interface style to <x>
+# -SIcomCOM compatible interface (default)
+# -SIcorbaCORBA compatible interface
+# -Sm support macros like C (global)
+# -So same as -Mtp
+# -Sp same as -Mgpc
+# -Ss constructor name must be init (destructor must be done)
+# -St allow static keyword in objects
+#
+# Allow goto, inline, C-operators, C-vars
+-Sgic
+
+# ---------------
+# Code generation
+# ---------------
+
+# Uncomment the next line if you always want static/dynamic units by default
+# (can be overruled with -CD, -CS at the commandline)
+#-CS
+#-CD
+
+# Set the default heapsize to 8Mb
+#-Ch8000000
+
+# Set default codegeneration checks (iocheck, overflow, range, stack)
+#-Ci
+#-Co
+#-Cr
+#-Ct
+
+# Optimizer switches for i386 compiler
+# -Og generate smaller code
+# -OG generate faster code (default)
+# -Or keep certain variables in registers (still BUGGY!!!)
+# -Ou enable uncertain optimizations (see docs)
+# -O1 level 1 optimizations (quick optimizations)
+# -O2 level 2 optimizations (-O1 + slower optimizations)
+# -O3 level 3 optimizations (same as -O2u)
+# -Op target processor
+# -Op1 set target processor to 386/486
+# -Op2 set target processor to Pentium/PentiumMMX (tm)
+# -Op3 set target processor to PPro/PII/c6x86/K6 (tm)
+
+# Optimize always for Size and PII
+#-OG2p3
+
+
+# -----------------------
+# Set Filenames and Paths
+# -----------------------
+
+# Slashes are also allowed under dos
+
+# path to the messagefile, not necessary anymore but can be used to override
+# the default language
+#-Fr$1/msg/errore.msg
+#-Fr$1/msg/errorn.msg
+
+# searchpath for includefiles
+#-Fi/pp/inc;/pp/rtl/inc
+
+# searchpath for units and other system dependent things
+-Fu$1/units/\$fpctarget
+-Fu$1/units/\$fpctarget/*
+-Fu$1/units/\$fpctarget/rtl
+#-Fu~/fpc/packages/base/*/units/$fpctarget;~/fpc/fcl/units/$fpctarget;~/fpc/rtl/units/$fpctarget
+
+# searchpath for libraries
+$GCCDIR
+#-Fl/pp/lib
+#-Fl/lib;/usr/lib
+
+
+# -------------
+# Linking
+# -------------
+
+# generate always debugging information for GDB (slows down the compiling
+# process)
+# -gc generate checks for pointers
+# -gd use dbx
+# -gg use gsym
+# -gh use heap trace unit (for memory leak debugging)
+# -gl use line info unit to show more info for backtraces
+# -gv generates programs tracable with valgrind
+# -gw generate dwarf debugging info
+#
+# Enable debuginfo and use the line info unit by default
+#-gl
+
+# always pass an option to the linker
+#-k-s
+
+# Always strip debuginfo from the executable
+-Xs
+
+
+# -------------
+# Miscellaneous
+# -------------
+
+# Write always a nice FPC logo ;)
+-l
+
+# Verbosity
+# e : Show errors (default) d : Show debug info
+# w : Show warnings u : Show unit info
+# n : Show notes t : Show tried/used files
+# h : Show hints m : Show defined macros
+# i : Show general info p : Show compiled procedures
+# l : Show linenumbers c : Show conditionals
+# a : Show everything 0 : Show nothing (except errors)
+# b : Show all procedure r : Rhide/GCC compatibility mode
+# declarations if an error x : Executable info (Win32 only)
+# occurs
+#
+# Display Info, Warnings, Notes and Hints
+-viwn
+# If you don't want so much verbosity use
+#-vw
+
+#
+# That's all folks
+#
+EOFCFG
diff --git a/compiler/utils/usubst.pp b/compiler/utils/usubst.pp
new file mode 100644
index 0000000000..56c0ed38f7
--- /dev/null
+++ b/compiler/utils/usubst.pp
@@ -0,0 +1,109 @@
+{$mode objfpc}
+{$H+}
+{
+ This file is part of Free Pascal build tools
+ Copyright (c) 2005 by Michael Van Canneyt
+
+ Implements string substitutions
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+unit usubst;
+
+interface
+
+uses SysUtils,Classes;
+
+// Add N=V pair to list.
+Procedure AddToList(List : TStrings; Const N,V : String);
+// Split NV to N/V and call AddToList
+Function AddPair(List : TStrings; Const NV : String) : Boolean;
+// Perform substitutions in S, from List.
+Function DoSubStitutions(List : TStrings; Var S : String) : Integer;
+
+implementation
+
+Procedure AddToList(List : TStrings; Const N,V : String);
+
+var
+ I : Integer;
+
+begin
+ I:=List.IndexOfName(N);
+ If (V='') then
+ begin
+ If (I<>-1) then
+ List.Delete(I)
+ end
+ else
+ begin
+ If (I=-1) then
+ List.Add(N+'='+V)
+ else
+ List[I]:=N+'='+V;
+ end;
+end;
+
+Function AddPair(List : TStrings; Const NV : String) : Boolean;
+
+Var
+ P,I : Integer;
+ N,V : string;
+
+begin
+ P:=Pos('=',NV);
+ Result:=(P<>0);
+ If Result then
+ begin
+ V:=NV;
+ N:=Copy(V,1,P-1);
+ Delete(V,1,P);
+ AddToList(List,N,V);
+ end;
+end;
+
+Function DoSubstitutions(List : TStrings; Var S : String) : Integer;
+
+Var
+ N,T : String;
+ P : Integer;
+
+begin
+ Result:=0;
+ T:=S;
+ S:='';
+ P:=Pos('%',T);
+ While (P>0) do
+ begin
+ S:=S+Copy(T,1,P-1);
+ Delete(T,1,P);
+ If (Length(T)>0) then
+ if (T[1]='%') then
+ begin
+ S:=S+'%';
+ Delete(T,1,1);
+ end
+ else
+ begin
+ P:=Pos('%',T);
+ If (P=0) then
+ S:=S+'%'
+ else
+ begin
+ N:=Copy(T,1,P-1);
+ Delete(T,1,P);
+ S:=S+List.Values[N];
+ end;
+ end;
+ P:=Pos('%',T);
+ end;
+ S:=S+T;
+end;
+
+end.
diff --git a/compiler/verbose.pas b/compiler/verbose.pas
new file mode 100644
index 0000000000..6d1463f76c
--- /dev/null
+++ b/compiler/verbose.pas
@@ -0,0 +1,830 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit handles the verbose management
+
+ 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 verbose;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+{$IFNDEF MACOS_USE_FAKE_SYSUTILS}
+ sysutils,
+{$ENDIF}
+ cutils,
+ globals,finput,
+ cmsgs;
+
+{$ifndef EXTERN_MSG}
+ {$i msgtxt.inc}
+{$endif}
+
+{$i msgidx.inc}
+
+ Const
+ { Levels }
+ V_None = $0;
+ V_Fatal = $1;
+ V_Error = $2;
+ V_Normal = $4; { doesn't show a text like Error: }
+ V_Warning = $8;
+ V_Note = $10;
+ V_Hint = $20;
+ V_LineInfoMask = $fff;
+ { From here by default no line info }
+ V_Info = $1000;
+ V_Status = $2000;
+ V_Used = $4000;
+ V_Tried = $8000;
+ V_Conditional = $10000;
+ V_Debug = $20000;
+ V_Executable = $40000;
+ V_LevelMask = $fffffff;
+ V_All = V_LevelMask;
+ V_Default = V_Fatal + V_Error + V_Normal;
+ { Flags }
+ V_LineInfo = $10000000;
+
+ var
+ msg : pmessage;
+
+ const
+ msgfilename : string = '';
+
+ procedure SetRedirectFile(const fn:string);
+ function SetVerbosity(const s:string):boolean;
+ procedure PrepareReport;
+
+ function CheckVerbosity(v:longint):boolean;
+ procedure SetCompileModule(p:tmodulebase);
+ procedure ShowStatus;
+ function ErrorCount:longint;
+ procedure SetErrorFlags(const s:string);
+ procedure GenerateError;
+ procedure Internalerror(i:longint);
+ procedure Comment(l:longint;s:string);
+ function MessagePchar(w:longint):pchar;
+ procedure Message(w:longint);
+ procedure Message1(w:longint;const s1:string);
+ procedure Message2(w:longint;const s1,s2:string);
+ procedure Message3(w:longint;const s1,s2,s3:string);
+ procedure Message4(w:longint;const s1,s2,s3,s4:string);
+ procedure MessagePos(const pos:tfileposinfo;w:longint);
+ procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
+ procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
+ procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
+ procedure MessagePos4(const pos:tfileposinfo;w:longint;const s1,s2,s3,s4:string);
+
+ { message calls with codegenerror support }
+ procedure cgmessage(t : longint);
+ procedure cgmessage1(t : longint;const s : string);
+ procedure cgmessage2(t : longint;const s1,s2 : string);
+ procedure cgmessage3(t : longint;const s1,s2,s3 : string);
+ procedure CGMessagePos(const pos:tfileposinfo;t:longint);
+ procedure CGMessagePos1(const pos:tfileposinfo;t:longint;const s1:string);
+ procedure CGMessagePos2(const pos:tfileposinfo;t:longint;const s1,s2:string);
+ procedure CGMessagePos3(const pos:tfileposinfo;t:longint;const s1,s2,s3:string);
+
+ procedure InitVerbose;
+ procedure DoneVerbose;
+
+
+
+implementation
+
+ uses
+ comphook;
+
+var
+ compiling_module : tmodulebase;
+
+
+{****************************************************************************
+ Extra Handlers for default compiler
+****************************************************************************}
+
+ procedure DoneRedirectFile;
+ begin
+ if status.use_redir then
+ begin
+ close(status.redirfile);
+ status.use_redir:=false;
+ end;
+ if status.use_bugreport then
+ begin
+ close(status.reportbugfile);
+ status.use_bugreport:=false;
+ end;
+ end;
+
+
+ procedure SetRedirectFile(const fn:string);
+ begin
+ assign(status.redirfile,fn);
+ {$I-}
+ append(status.redirfile);
+ if ioresult <> 0 then
+ rewrite(status.redirfile);
+ {$I+}
+ status.use_redir:=(ioresult=0);
+ end;
+
+
+ procedure PrepareReport;
+ var
+ fn : string;
+ begin
+ if status.use_bugreport then
+ exit;
+ fn:='fpcdebug.txt';
+ assign(status.reportbugfile,fn);
+ {$I-}
+ append(status.reportbugfile);
+ if ioresult <> 0 then
+ rewrite(status.reportbugfile);
+ {$I+}
+ status.use_bugreport:=(ioresult=0);
+ if status.use_bugreport then
+ writeln(status.reportbugfile,'FPC bug report file');
+ end;
+
+
+ function CheckVerbosity(v:longint):boolean;
+ begin
+ CheckVerbosity:=status.use_bugreport or
+ ((status.verbosity and (v and V_LevelMask))=(v and V_LevelMask));
+ end;
+
+
+ function SetVerbosity(const s:string):boolean;
+ var
+ m : Longint;
+ i : Integer;
+ inverse : boolean;
+ c : char;
+ begin
+ Setverbosity:=false;
+ val(s,m,i);
+ if (i=0) and (s<>'') then
+ status.verbosity:=m
+ else
+ begin
+ i:=1;
+ while i<=length(s) do
+ begin
+ c:=upcase(s[i]);
+ inverse:=false;
+ { on/off ? }
+ if (i<length(s)) then
+ case s[i+1] of
+ '-' : begin
+ inc(i);
+ inverse:=true;
+ end;
+ '+' : inc(i);
+ end;
+ { handle switch }
+ case c of
+ { Special cases }
+ 'A' : status.verbosity:=V_All;
+ 'B' : begin
+ if inverse then
+ status.print_source_path:=false
+ else
+ status.print_source_path:=true;
+ end;
+ '0' : status.verbosity:=V_Default;
+ 'P' : begin
+ if inverse then
+ paraprintnodetree:=0
+ else
+ paraprintnodetree:=1;
+ end;
+ 'R' : begin
+ if inverse then
+ begin
+ status.use_gccoutput:=false;
+ status.use_stderr:=false;
+ end
+ else
+ begin
+ status.use_gccoutput:=true;
+ status.use_stderr:=true;
+ end;
+ end;
+ 'Z' : begin
+ if inverse then
+ status.use_stderr:=false
+ else
+ status.use_stderr:=true;
+ end;
+ { Normal cases - do an or }
+ 'E' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Error)
+ else
+ status.verbosity:=status.verbosity or V_Error;
+ 'I' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Info)
+ else
+ status.verbosity:=status.verbosity or V_Info;
+ 'W' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Warning)
+ else
+ status.verbosity:=status.verbosity or V_Warning;
+ 'N' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Note)
+ else
+ status.verbosity:=status.verbosity or V_Note;
+ 'H' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Hint)
+ else
+ status.verbosity:=status.verbosity or V_Hint;
+ 'L' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Status)
+ else
+ status.verbosity:=status.verbosity or V_Status;
+ 'U' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Used)
+ else
+ status.verbosity:=status.verbosity or V_Used;
+ 'T' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Tried)
+ else
+ status.verbosity:=status.verbosity or V_Tried;
+ 'C' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Conditional)
+ else
+ status.verbosity:=status.verbosity or V_Conditional;
+ 'D' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Debug)
+ else
+ status.verbosity:=status.verbosity or V_Debug;
+ 'X' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Executable)
+ else
+ status.verbosity:=status.verbosity or V_Executable;
+ 'V' : PrepareReport;
+ end;
+ inc(i);
+ end;
+ end;
+ if status.verbosity=0 then
+ status.verbosity:=V_Default;
+ setverbosity:=true;
+ end;
+
+
+ procedure Loadprefixes;
+
+ function loadprefix(w:longint):string;
+ var
+ s : string;
+ idx : longint;
+ begin
+ s:=msg^.get(w,[]);
+ idx:=pos('_',s);
+ if idx>0 then
+ Loadprefix:=Copy(s,idx+1,255)
+ else
+ Loadprefix:=s;
+ end;
+
+ begin
+ { Load the prefixes }
+ fatalstr:=Loadprefix(general_i_fatal);
+ errorstr:=Loadprefix(general_i_error);
+ warningstr:=Loadprefix(general_i_warning);
+ notestr:=Loadprefix(general_i_note);
+ hintstr:=Loadprefix(general_i_hint);
+ end;
+
+
+ procedure LoadMsgFile(const fn:string);
+ begin
+ { reload the internal messages if not already loaded }
+{$ifndef EXTERN_MSG}
+ if not msg^.msgintern then
+ msg^.LoadIntern(@msgtxt,msgtxtsize);
+{$endif}
+ if not msg^.LoadExtern(fn) then
+ begin
+{$ifdef EXTERN_MSG}
+ writeln('Fatal: Cannot find error message file.');
+ halt(3);
+{$else}
+ msg^.LoadIntern(@msgtxt,msgtxtsize);
+{$endif}
+ end;
+ { reload the prefixes using the new messages }
+ Loadprefixes;
+ end;
+
+
+ procedure MaybeLoadMessageFile;
+ begin
+ { Load new message file }
+ if (msgfilename<>'') then
+ begin
+ LoadMsgFile(msgfilename);
+ msgfilename:='';
+ end;
+ end;
+
+
+ procedure SetCompileModule(p:tmodulebase);
+ begin
+ compiling_module:=p;
+ end;
+
+
+ var
+ lastfileidx,
+ lastmoduleidx : longint;
+ Procedure UpdateStatus;
+ begin
+ { fix status }
+ status.currentline:=aktfilepos.line;
+ status.currentcolumn:=aktfilepos.column;
+ if assigned(compiling_module) and
+ assigned(compiling_module.sourcefiles) and
+ ((compiling_module.unit_index<>lastmoduleidx) or
+ (aktfilepos.fileindex<>lastfileidx)) then
+ begin
+ { update status record }
+ status.currentmodule:=compiling_module.modulename^;
+ status.currentsource:=compiling_module.sourcefiles.get_file_name(aktfilepos.fileindex);
+ status.currentsourcepath:=compiling_module.sourcefiles.get_file_path(aktfilepos.fileindex);
+ { update lastfileidx only if name known PM }
+ if status.currentsource<>'' then
+ lastfileidx:=aktfilepos.fileindex
+ else
+ lastfileidx:=0;
+ lastmoduleidx:=compiling_module.unit_index;
+ end;
+ if assigned(compiling_module) then
+ status.compiling_current:=(compiling_module.state in [ms_compile,ms_second_compile]);
+ end;
+
+
+ procedure ShowStatus;
+ begin
+ UpdateStatus;
+ if do_status() then
+ raise ECompilerAbort.Create;
+ end;
+
+
+ function ErrorCount:longint;
+ begin
+ ErrorCount:=status.errorcount;
+ end;
+
+
+ procedure SetErrorFlags(const s:string);
+ var
+ code : integer;
+ i,j,l : longint;
+ begin
+ { empty string means error count = 1 for backward compatibility (PFV) }
+ if s='' then
+ begin
+ status.maxerrorcount:=1;
+ exit;
+ end;
+ i:=0;
+ while (i<length(s)) do
+ begin
+ inc(i);
+ case s[i] of
+ '0'..'9' :
+ begin
+ j:=i;
+ while (j<=length(s)) and (s[j] in ['0'..'9']) do
+ inc(j);
+ val(copy(s,i,j-i),l,code);
+ if code<>0 then
+ l:=1;
+ status.maxerrorcount:=l;
+ i:=j;
+ end;
+ 'w','W' :
+ status.errorwarning:=true;
+ 'n','N' :
+ status.errornote:=true;
+ 'h','H' :
+ status.errorhint:=true;
+ end;
+ end;
+ end;
+
+
+ procedure GenerateError;
+ begin
+ inc(status.errorcount);
+ end;
+
+
+ procedure internalerror(i : longint);
+ begin
+ UpdateStatus;
+ do_internalerror(i);
+ inc(status.errorcount);
+ raise ECompilerAbort.Create;
+ end;
+
+
+ procedure Comment(l:longint;s:string);
+ var
+ dostop : boolean;
+ begin
+ dostop:=((l and V_Fatal)<>0);
+ if ((l and V_Error)<>0) or
+ (status.errorwarning and ((l and V_Warning)<>0)) or
+ (status.errornote and ((l and V_Note)<>0)) or
+ (status.errorhint and ((l and V_Hint)<>0)) then
+ inc(status.errorcount);
+ { check verbosity level }
+ if not CheckVerbosity(l) then
+ exit;
+ if (l and V_LineInfoMask)<>0 then
+ l:=l or V_LineInfo;
+ { Create status info }
+ UpdateStatus;
+ { Fix replacements }
+ DefaultReplacements(s);
+ { show comment }
+ if do_comment(l,s) or dostop then
+ raise ECompilerAbort.Create;
+ if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(status.errorcount));
+ status.skip_error:=true;
+ raise ECompilerAbort.Create;
+ end;
+ end;
+
+
+ Procedure Msg2Comment(s:string);
+ var
+ idx,i,v : longint;
+ dostop : boolean;
+ begin
+ {Reset}
+ dostop:=false;
+ v:=0;
+ {Parse options}
+ idx:=pos('_',s);
+ if idx=0 then
+ v:=V_Normal
+ else
+ if (idx >= 1) And (idx <= 5) then
+ begin
+ for i:=1 to idx do
+ begin
+ case upcase(s[i]) of
+ 'F' :
+ begin
+ v:=v or V_Fatal;
+ inc(status.errorcount);
+ dostop:=true;
+ end;
+ 'E' :
+ begin
+ v:=v or V_Error;
+ inc(status.errorcount);
+ end;
+ 'O' :
+ v:=v or V_Normal;
+ 'W':
+ begin
+ v:=v or V_Warning;
+ if status.errorwarning then
+ inc(status.errorcount);
+ end;
+ 'N' :
+ begin
+ v:=v or V_Note;
+ if status.errornote then
+ inc(status.errorcount);
+ end;
+ 'H' :
+ begin
+ v:=v or V_Hint;
+ if status.errorhint then
+ inc(status.errorcount);
+ end;
+ 'I' :
+ v:=v or V_Info;
+ 'L' :
+ v:=v or V_LineInfo;
+ 'U' :
+ v:=v or V_Used;
+ 'T' :
+ v:=v or V_Tried;
+ 'C' :
+ v:=v or V_Conditional;
+ 'D' :
+ v:=v or V_Debug;
+ 'X' :
+ v:=v or V_Executable;
+ 'S' :
+ dostop:=true;
+ '_' : ;
+ end;
+ end;
+ end;
+ Delete(s,1,idx);
+ { check verbosity level }
+ if not CheckVerbosity(v) then
+ exit;
+ if (v and V_LineInfoMask)<>0 then
+ v:=v or V_LineInfo;
+ { fix status }
+ UpdateStatus;
+ { Fix replacements }
+ DefaultReplacements(s);
+ { show comment }
+ if do_comment(v,s) or dostop then
+ raise ECompilerAbort.Create;
+ if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(status.errorcount));
+ status.skip_error:=true;
+ raise ECompilerAbort.Create;
+ end;
+ end;
+
+
+ function MessagePchar(w:longint):pchar;
+ begin
+ MaybeLoadMessageFile;
+ MessagePchar:=msg^.GetPchar(w)
+ end;
+
+
+ procedure Message(w:longint);
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[]));
+ end;
+
+
+ procedure Message1(w:longint;const s1:string);
+
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1]));
+ end;
+
+
+ procedure Message2(w:longint;const s1,s2:string);
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2]));
+ end;
+
+
+ procedure Message3(w:longint;const s1,s2,s3:string);
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2,s3]));
+ end;
+
+
+ procedure Message4(w:longint;const s1,s2,s3,s4:string);
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2,s3,s4]));
+ end;
+
+
+ procedure MessagePos(const pos:tfileposinfo;w:longint);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=aktfilepos;
+ aktfilepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[]));
+ aktfilepos:=oldpos;
+ end;
+
+
+ procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=aktfilepos;
+ aktfilepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1]));
+ aktfilepos:=oldpos;
+ end;
+
+
+ procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=aktfilepos;
+ aktfilepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2]));
+ aktfilepos:=oldpos;
+ end;
+
+
+ procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=aktfilepos;
+ aktfilepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2,s3]));
+ aktfilepos:=oldpos;
+ end;
+
+
+ procedure MessagePos4(const pos:tfileposinfo;w:longint;const s1,s2,s3,s4:string);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=aktfilepos;
+ aktfilepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2,s3,s4]));
+ aktfilepos:=oldpos;
+ end;
+
+
+{*****************************************************************************
+ override the message calls to set codegenerror
+*****************************************************************************}
+
+ procedure cgmessage(t : longint);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.Message(t);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessage1(t : longint;const s : string);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.Message1(t,s);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessage2(t : longint;const s1,s2 : string);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.Message2(t,s1,s2);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessage3(t : longint;const s1,s2,s3 : string);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.Message3(t,s1,s2,s3);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+
+ procedure cgmessagepos(const pos:tfileposinfo;t : longint);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.MessagePos(pos,t);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessagepos1(const pos:tfileposinfo;t : longint;const s1 : string);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.MessagePos1(pos,t,s1);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessagepos2(const pos:tfileposinfo;t : longint;const s1,s2 : string);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.MessagePos2(pos,t,s1,s2);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessagepos3(const pos:tfileposinfo;t : longint;const s1,s2,s3 : string);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.MessagePos3(pos,t,s1,s2,s3);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+
+{*****************************************************************************
+ Initialization
+*****************************************************************************}
+
+ procedure InitVerbose;
+ begin
+ { Init }
+ msg:=new(pmessage,Init(20,msgidxmax));
+ if msg=nil then
+ begin
+ writeln('Fatal: MsgIdx Wrong');
+ halt(3);
+ end;
+{$ifndef EXTERN_MSG}
+ msg^.LoadIntern(@msgtxt,msgtxtsize);
+{$else EXTERN_MSG}
+ LoadMsgFile(exepath+'errore.msg');
+{$endif EXTERN_MSG}
+ FillChar(Status,sizeof(TCompilerStatus),0);
+ status.verbosity:=V_Default;
+ Status.MaxErrorCount:=50;
+ Loadprefixes;
+ lastfileidx:=-1;
+ lastmoduleidx:=-1;
+ status.currentmodule:='';
+ status.currentsource:='';
+ status.currentsourcepath:='';
+ status.compiling_current:=false;
+ compiling_module:=nil;
+ { Register internalerrorproc for cutils/cclasses }
+ internalerrorproc:=@internalerror;
+ end;
+
+
+ procedure DoneVerbose;
+ begin
+ if assigned(msg) then
+ begin
+ dispose(msg,Done);
+ msg:=nil;
+ end;
+ DoneRedirectFile;
+ end;
+
+
+initialization
+finalization
+ { Be sure to close the redirect files to flush all data }
+ DoneRedirectFile;
+end.
diff --git a/compiler/version.pas b/compiler/version.pas
new file mode 100644
index 0000000000..ca5b6f4ab5
--- /dev/null
+++ b/compiler/version.pas
@@ -0,0 +1,92 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Version/target constants
+
+ 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 version;
+
+{$i fpcdefs.inc}
+
+interface
+
+ const
+ { version string }
+ version_nr = '2';
+ release_nr = '1';
+ patch_nr = '1';
+ minorpatch = '';
+
+ { word version for ppu file }
+ wordversion = ((ord(version_nr)-ord('0')) shl 14)+
+ ((ord(release_nr)-ord('0')) shl 7)+
+ (ord(patch_nr)-ord('0'));
+
+ { date string }
+ date_string = {$I %DATE%};
+
+ { source cpu string }
+{$ifdef cpu86}
+ source_cpu_string = 'i386';
+{$endif cpu86}
+{$ifdef cpupowerpc32}
+ source_cpu_string = 'powerpc';
+{$endif cpupowerpc32}
+{$ifdef cpupowerpc64}
+ source_cpu_string = 'powerpc64';
+{$endif cpupowerpc64}
+{$ifdef cpum68k}
+ source_cpu_string = 'm68k';
+{$endif cpum68k}
+{$ifdef cpuia64}
+ source_cpu_string = 'ia64';
+{$endif cpuia64}
+{$ifdef cpux86_64}
+ source_cpu_string = 'x86_64';
+{$endif cpux86_64}
+{$ifdef cpusparc}
+ source_cpu_string = 'sparc';
+{$endif cpusparc}
+{$ifdef cpusalpha}
+ source_cpu_string = 'alpha';
+{$endif cpualpha}
+{$ifdef cpuvis}
+ source_cpu_string = 'vis';
+{$endif cpuvis}
+{$ifdef cpuarm}
+ source_cpu_string = 'arm';
+{$endif cpuarm}
+
+function version_string:string;
+function full_version_string:string;
+
+
+implementation
+
+function version_string:string;
+begin
+ version_string := version_nr+'.'+release_nr+'.'+patch_nr;
+end;
+
+
+function full_version_string:string;
+begin
+ full_version_string := version_nr+'.'+release_nr+'.'+patch_nr+minorpatch;
+end;
+
+end.
diff --git a/compiler/vis/aasmcpu.pas b/compiler/vis/aasmcpu.pas
new file mode 100644
index 0000000000..5f51d232a0
--- /dev/null
+++ b/compiler/vis/aasmcpu.pas
@@ -0,0 +1,248 @@
+{
+ Copyright (c) 1998-2001 by Florian Klaempfl and Pierre Muller
+
+ virtual instruction set family assembler instructions
+
+ 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;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,aasmtai,
+ aasmbase,globals,verbose,
+ cpubase,cpuinfo;
+
+
+type
+
+ taicpu = class(taicpu_abstract)
+ opsize : topsize;
+ constructor op_none(op : tasmop;_size : topsize);
+
+ constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
+ constructor op_ref(op : tasmop;_size : topsize;_op1 : treference);
+
+ constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
+ constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
+
+ constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+ constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : 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);
+ { for DBxx opcodes }
+ constructor op_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
+ constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+
+ constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
+ constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+
+ private
+ procedure init(_size : topsize); { this need to be called by all constructor }
+ end;
+
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+
+implementation
+
+
+{*****************************************************************************
+ Taicpu Constructors
+*****************************************************************************}
+
+
+
+
+ procedure taicpu.init(_size : topsize);
+ begin
+ typ:=ait_instruction;
+ is_jmp:=false;
+ opsize:=_size;
+ ops:=0;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop;_size : topsize);
+ begin
+ inherited create(op);;
+ init(_size);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=1;
+ loadconst(0,aword(_op1));
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : treference);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadreg(1,_op2);
+ end;
+
+
+
+ constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(1,_op2);
+ 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_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadsymbol(1,_op2,0);
+ 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;
+
+
+ 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;
+ loadreg(0,_op2);
+ loadsymbol(1,_op1,_op1ofs);
+ 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;
+
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+end.
diff --git a/compiler/vis/cpubase.pas b/compiler/vis/cpubase.pas
new file mode 100644
index 0000000000..74f5ae18e8
--- /dev/null
+++ b/compiler/vis/cpubase.pas
@@ -0,0 +1,643 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal dev. team
+
+ Contains the base types for the virtual instruction set
+
+ 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 contains the base types for the Virtual Instruction machine
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ strings,cutils,cclasses,aasmbase,cpuinfo,cginfo;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp=(a_none,a_beqs,a_bges,a_bgts,a_bles,a_blts,a_bnes,
+ a_bras,a_rets,a_bccs,a_bcss,a_bvcs,a_bvss,a_bbss,
+ a_bass,a_bats,a_bbts,a_beql,a_bgel,a_bgtl,a_blel,
+ a_bltl,a_bnel,a_bral,a_bsrl,a_bbsl,a_basl,a_batl,
+ a_bbtl,a_add,a_addc,a_and,a_asr,a_lsl,a_lsr,a_cmp,
+ a_sub,a_subb,a_divs,a_divu,a_mod,a_move,a_muls,a_mulu,
+ a_neg,a_not,a_or,a_xor,a_fadd,a_fcmp,a_fdiv,a_fmove,
+ a_fmul,a_fneg,a_fsub,a_fldd,a_flds,a_lbzx,a_lbsx,a_llsx,
+ a_llzx,a_lwsx,a_lwzx,a_fstd,a_fsts,a_stb,a_stl,a_stw,
+ a_syscall,a_nop,a_lims,a_orhi,a_lilo,a_call,a_popl,
+ a_pushl,
+ { these are simplified mnemonics }
+ a_lea,a_limm,a_bxx
+ );
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[8];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ toldregister = (R_NO,R_R0,R_R1,R_R2,R_R3,
+ R_R4,R_R5,R_R6,R_R7,
+ R_R8,R_R9,R_R10,R_R11,
+ R_CCR,R_SP,R_FP,R_PC,
+ R_FP0,R_FP1,R_FP2,R_FP3,
+ R_FP4,R_FP5,R_FP6,R_FP7,
+ R_FP8,R_FP9,R_FP10,R_FP11,
+ R_FP12,R_FP13,R_FP14,R_FP15,
+ R_INTREGISTER,R_FPUREGISTER
+ );
+
+ {# Set type definition for registers }
+ tregisterset = set of Toldregister;
+ Tnewregister=word;
+
+ tregister=record
+ enum:toldregister;
+ number:Tnewregister;
+ end;
+
+ { A type to store register locations for 64 Bit values. }
+ tregister64 = packed record
+ reglo,reghi : tregister;
+ end;
+
+ Tsuperregister=byte;
+ Tsubregister=byte;
+
+ Tsupregset=set of Tsuperregister;
+
+ { alias for compact code }
+ treg64 = tregister64;
+
+ {# Type definition for the array of string of register nnames }
+ treg2strtable = array[toldregister] of string[5];
+
+ Const
+
+ {Special registers:}
+ NR_NO = $0000; {Invalid register}
+
+ {Normal registers:}
+
+ {General purpose registers:}
+ NR_R0 = $0100; NR_R1 = $0200; NR_R2 = $0300;
+ NR_R3 = $0400; NR_R4 = $0500; NR_R5 = $0600;
+ NR_R6 = $0700; NR_R7 = $0800; NR_R8 = $0900;
+ NR_R9 = $0A00; NR_R10 = $0B00; NR_R11 = $0C00;
+ NR_SP = $0D00; NR_FP = $0E00;
+
+ {Super registers:}
+ RS_R0 = $01; RS_R1 = $02; RS_R2 = $03;
+ RS_R3 = $04; RS_R4 = $05; RS_R5 = $06;
+ RS_R6 = $07; RS_R7 = $08; RS_R8 = $09;
+ RS_R9 = $0A; RS_R10 = $0B; RS_R11 = $0C;
+ RS_SP = $0D; RS_FP = $0E;
+
+ {Subregisters:}
+ R_SUBL = $00;
+ R_SUBW = $01;
+ R_SUBD = $02;
+
+ {# First register in the tregister enumeration }
+ firstreg = low(toldregister);
+ {# Last register in the tregister enumeration }
+ lastreg = high(toldregister);
+
+ first_supreg = $01;
+ last_supreg = $0c;
+
+
+ std_reg2str : treg2strtable = ('',
+ 'r0','r1','r2','r3','r4','r5','r6','r7','r8','r9','r10','r11','ccr',
+ 'sp','fp','pc','fp0','fp1','fp2','fp3','fp4','fp5','fp6','fp7',
+ 'fp8','fp9','fp10','fp11','fp12','fp13','fp14','fp15','',''
+ );
+
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_EQ, { equal }
+ C_NE, { not equal }
+ C_GE, { greater or equal (signed) }
+ C_GT, { greater than (signed) }
+ C_LE, { less or equal (signed) }
+ C_LT, { less than (signed) }
+ C_LS, { lower or same (unordered) }
+ C_AS, { above or same (unordered) }
+ C_AT, { above than (unordered) }
+ C_BT, { below than (unordered) }
+ C_CC, { carry clear }
+ C_CS { carry set }
+ );
+
+
+ const
+ cond2str:array[TAsmCond] of string[3]=('',
+ 'eq','ne','ge','gt','le','lt','ls','as',
+ 'at','bt','cc','cs');
+
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (
+ F_E, { zero flag = equal }
+ F_NE, { !zero_flag = not equal }
+ F_G, { greater (signed) }
+ F_L, { less (signed) }
+ F_GE,
+ F_LE,
+ F_C, { carry flag }
+ F_NC, { !carry flag }
+ F_A, { greater (unsigned) }
+ F_AE,
+ F_B, { less (unsigned) }
+ F_BE
+ );
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+ type
+ trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
+
+ { reference record }
+ preference = ^treference;
+ treference = packed record
+ base,
+ index : tregister;
+ offset : longint;
+ symbol : tasmsymbol;
+ offsetfixup : longint;
+ options : trefoptions;
+ alignment : byte;
+ end;
+
+ { reference record }
+ pparareference = ^tparareference;
+ tparareference = packed record
+ index : tregister;
+ offset : aword;
+ end;
+
+
+{*****************************************************************************
+ Operand
+*****************************************************************************}
+
+ type
+ toptype=(top_none,top_reg,top_ref,top_const,top_symbol,top_bool);
+
+ toper=record
+ ot : longint;
+ case typ : toptype of
+ top_none : ();
+ top_reg : (reg:tregister);
+ top_ref : (ref:^treference);
+ top_const : (val:aword);
+ top_symbol : (sym:tasmsymbol;symofs:longint);
+ top_bool : (b: boolean);
+ end;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+ { S_NO = No Size of operand }
+ { S_B = 8-bit size operand }
+ { S_W = 16-bit size operand }
+ { S_L = 32-bit size operand }
+ { Floating point types }
+ { S_FS = single type (32 bit) }
+ { S_FD = double/64bit integer }
+ { S_FX = Extended type }
+ topsize = (S_NO,S_B,S_W,S_L,S_FS,S_FD,S_FX,S_IQ);
+
+
+{*****************************************************************************
+ Generic Location
+*****************************************************************************}
+
+ type
+ TLoc=(
+ { added for tracking problems}
+ LOC_INVALID,
+ { ordinal constant }
+ LOC_CONSTANT,
+ { in a processor register }
+ LOC_REGISTER,
+ { Constant register which shouldn't be modified }
+ LOC_CREGISTER,
+ { FPU register}
+ LOC_FPUREGISTER,
+ { Constant FPU register which shouldn't be modified }
+ LOC_CFPUREGISTER,
+ { multimedia register }
+ LOC_MMREGISTER,
+ { Constant multimedia reg which shouldn't be modified }
+ LOC_CMMREGISTER,
+ { in memory }
+ LOC_REFERENCE,
+ { in memory (constant) }
+ LOC_CREFERENCE,
+ { boolean results only, jump to false or true label }
+ LOC_JUMP,
+ { boolean results only, flags are set }
+ LOC_FLAGS
+ );
+
+ { tparamlocation describes where a parameter for a procedure is stored.
+ References are given from the caller's point of view. The usual
+ TLocation isn't used, because contains a lot of unnessary fields.
+ }
+ tparalocation = packed record
+ size : TCGSize;
+ { The location type where the parameter is passed, usually
+ LOC_REFERENCE,LOC_REGISTER or LOC_FPUREGISTER
+ }
+ loc : TLoc;
+ { The stack pointer must be decreased by this value before
+ the parameter is copied to the given destination.
+ This allows to "encode" pushes with tparalocation.
+ On the PowerPC, this field is unsed but it is there
+ because several generic code accesses it.
+ }
+ sp_fixup : longint;
+ case TLoc of
+ LOC_REFERENCE : (reference : tparareference);
+ LOC_FPUREGISTER, LOC_CFPUREGISTER, LOC_MMREGISTER, LOC_CMMREGISTER,
+ LOC_REGISTER,LOC_CREGISTER : (
+ case longint of
+ 1 : (register,register64.reghi : tregister);
+ { overlay a register64.reglo }
+ 2 : (register64.reglo : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ );
+ end;
+
+ treglocation = packed record
+ case longint of
+ 1 : (register,register64.reghi : tregister);
+ { overlay a register64.reglo }
+ 2 : (register64.reglo : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ end;
+
+
+ tlocation = packed record
+ size : TCGSize;
+ loc : tloc;
+ case tloc of
+ LOC_CREFERENCE,LOC_REFERENCE : (reference : treference);
+ LOC_CONSTANT : (
+ case longint of
+ 1 : (value : AWord);
+ { can't do this, this layout depends on the host cpu. Use }
+ { lo(valueqword)/hi(valueqword) instead (JM) }
+ { 2 : (valuelow, valuehigh:AWord); }
+ { overlay a complete 64 Bit value }
+ 3 : (valueqword : qword);
+ );
+ LOC_FPUREGISTER, LOC_CFPUREGISTER, LOC_MMREGISTER, LOC_CMMREGISTER,
+ LOC_REGISTER,LOC_CREGISTER : (
+ case longint of
+ 1 : (register64.reglo,register64.reghi : tregister);
+ 2 : (register : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ );
+ LOC_FLAGS : (resflags : tresflags);
+ end;
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 2;
+
+ lvaluelocations = [LOC_REFERENCE, LOC_CREGISTER, LOC_CFPUREGISTER,
+ LOC_CMMREGISTER];
+
+ {# Constant defining possibly all registers which might require saving }
+ ALL_REGISTERS = [R_FP0..R_FP15];
+
+ general_registers = [R_R0..R_R11];
+
+ {# low and high of the available maximum width integer general purpose }
+ { registers }
+ LoGPReg = R_R0;
+ HiGPReg = R_R11;
+
+ {# low and high of every possible width general purpose register (same as }
+ { above on most architctures apart from the 80x86) }
+ LoReg = R_R0;
+ HiReg = R_R11;
+
+ {# Table of registers which can be allocated by the code generator
+ internally, when generating the code.
+ }
+ { legend: }
+ { xxxregs = set of all possibly used registers of that type in the code }
+ { generator }
+ { usableregsxxx = set of all 32bit components of registers that can be }
+ { possible allocated to a regvar or using getregisterxxx (this }
+ { excludes registers which can be only used for parameter }
+ { passing on ABI's that define this) }
+ { c_countusableregsxxx = amount of registers in the usableregsxxx set }
+
+ maxintregs = 12;
+ intregs = [R_R0..R_R11];
+ usableregsint = [R_R2..R_R11];
+ c_countusableregsint = 18;
+
+ maxfpuregs = 16;
+ fpuregs = [R_FP0..R_FP15];
+ usableregsfpu = [R_FP1..R_FP15];
+ c_countusableregsfpu = 15;
+
+ mmregs = [];
+ usableregsmm = [];
+ c_countusableregsmm = 0;
+
+ { no distinction on this platform }
+ maxaddrregs = 0;
+ addrregs = [];
+ usableregsaddr = [];
+ c_countusableregsaddr = 0;
+
+ firstsaveintreg = R_R2;
+ lastsaveintreg = R_R11;
+ firstsavefpureg = R_FP1;
+ lastsavefpureg = R_FP15;
+ firstsavemmreg = R_NO;
+ lastsavemmreg = R_NO;
+
+ maxvarregs = 10;
+ varregs : Array [1..maxvarregs] of toldregister =
+ (R_R2,R_R3,R_R4,R_R5,R_R6,R_R7,R_R8,R_R9,R_R10,R_R11);
+
+ maxfpuvarregs = 15;
+ fpuvarregs : Array [1..maxfpuvarregs] of toldregister =
+ (R_FP1,R_FP2,R_FP3,
+ R_FP4,R_FP5,R_FP6,
+ R_FP7,R_FP8,R_FP9,
+ R_FP10,R_FP11,R_FP12,
+ R_FP13,R_FP14,R_FP15);
+
+
+ max_param_regs_int = 0;
+
+ max_param_regs_fpu = 0;
+
+ max_param_regs_mm = 0;
+
+ {# Registers which are defined as scratch and no need to save across
+ routine calls or in assembler blocks.
+ }
+ max_scratch_regs = 2;
+ scratch_regs: Array[1..max_scratch_regs] of Tsuperregister = (RS_R0,RS_R1);
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_NO;
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Currently unsupported by abstract machine
+ }
+
+ stab_regindex : array[toldregister] of shortint =
+ (-1,
+ { r0..r11 }
+ -1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,
+ { sp,fp,ccr,pc }
+ -1,-1,-1,-1,
+ { FP0..FP7 }
+ -1,-1,-1,-1,-1,-1,-1,-1,
+ { FP8..FP15 }
+ -1,-1,-1,-1,-1,-1,-1,-1,
+ { invalid }
+ -1,-1
+ );
+
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ stack_pointer_reg = R_SP;
+ NR_STACK_POINTER_REG = NR_SP;
+ RS_STACK_POINTER_REG = RS_SP;
+ {# Frame pointer register }
+ frame_pointer_reg = R_FP;
+ NR_FRAME_POINTER_REG = NR_FP;
+ RS_FRAME_POINTER_REG = RS_FP;
+ {# Self pointer register : contains the instance address of an
+ object or class. }
+ self_pointer_reg = R_R11;
+ NR_SELF_POINTER_REG = NR_R11;
+ RS_SELF_POINTER_REG = RS_R11;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific.
+ }
+ pic_offset_reg = R_R10;
+ {# Results are returned in this register (32-bit values) }
+ accumulator = R_R0;
+ NR_ACCUMULATOR = NR_R0;
+ RS_ACCUMULATOR = RS_R0;
+ {the return_result_reg, is used inside the called function to store its return
+ value when that is a scalar value otherwise a pointer to the address of the
+ result is placed inside it}
+ return_result_reg = accumulator;
+
+ {the function_result_reg contains the function result after a call to a scalar
+ function othewise it contains a pointer to the returned result}
+ function_result_reg = accumulator;
+ {# Hi-Results are returned in this register (64-bit value high register) }
+ accumulatorhigh = R_R1;
+ NR_ACCUMULATORHIGH = NR_R1;
+ RS_ACCUMULATORHIGH = RS_R1;
+ fpu_result_reg = R_FP0;
+ mmresultreg = R_NO;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ std_saved_registers = [RS_R0,RS_R1,RS_R10,RS_R11];
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+
+ procedure inverse_flags(var r : TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ procedure convert_register_to_enum(var r:Tregister);
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+
+
+implementation
+
+ uses
+ verbose;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ is_calljmp := false;
+ if o in [a_bxx,a_call,a_beqs..a_bbtl] then
+ is_calljmp := true;
+ end;
+
+ procedure inverse_flags(var r: TResFlags);
+ const flagsinvers : array[F_E..F_BE] of tresflags =
+ (F_NE,F_E,
+ F_LE,F_GE,
+ F_L,F_G,
+ F_NC,F_C,
+ F_BE,F_B,
+ F_AE,F_A);
+ begin
+ r:=flagsinvers[r];
+ end;
+
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const flags2cond : array[tresflags] of tasmcond =
+ (
+ {F_E} C_EQ,
+ {F_NE} C_NE,
+ {F_G } C_GT,
+ {F_L } C_LT,
+ {F_GE} C_GE,
+ {F_LE} C_LE,
+ {F_C} C_CS,
+ {F_NC} C_CC,
+ {F_A} C_AT,
+ {F_AE} C_AS,
+ {F_B} C_BT,
+ {F_BE} C_LS);
+ begin
+ flags_to_cond := flags2cond[f];
+ end;
+
+
+ procedure convert_register_to_enum(var r:Tregister);
+
+ begin
+ if r.enum = R_INTREGISTER then
+ case r.number of
+ NR_NO: r.enum:= R_NO;
+ NR_R0: r.enum:= R_R0;
+ NR_R1: r.enum:= R_R1;
+ NR_R2: r.enum:= R_R2;
+ NR_R3: r.enum:= R_R3;
+ NR_R4: r.enum:= R_R4;
+ NR_R5: r.enum:= R_R5;
+ NR_R6: r.enum:= R_R6;
+ NR_R7: r.enum:= R_R7;
+ NR_R8: r.enum:= R_R8;
+ NR_R9: r.enum:= R_R9;
+ NR_R10: r.enum:= R_R10;
+ NR_R11: r.enum:= R_R11;
+ else
+ internalerror(200301082);
+ end;
+ end;
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+
+ begin
+ case s of
+ OS_8,OS_S8:
+ cgsize2subreg:=R_SUBL;
+ OS_16,OS_S16:
+ cgsize2subreg:=R_SUBW;
+ OS_32,OS_S32:
+ cgsize2subreg:=R_SUBD;
+ else
+ internalerror(200301231);
+ end;
+ end;
+
+
+end.
diff --git a/compiler/vis/cpuinfo.pas b/compiler/vis/cpuinfo.pas
new file mode 100644
index 0000000000..e72cb981a9
--- /dev/null
+++ b/compiler/vis/cpuinfo.pas
@@ -0,0 +1,56 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the virtual instruction set
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+Type
+ { Architecture word - Native unsigned type }
+ AWord = Longword;
+ PAWord = ^AWord;
+
+ { this must be an ordinal type with the same size as a pointer }
+ { to allow some dirty type casts for example when using }
+ { tconstsym.value }
+ { Note: must be unsigned!! Otherwise, ugly code like }
+ { pointer(-1) will result in a pointer with the value }
+ { $fffffffffffffff on a 32bit machine if the compiler uses }
+ { int64 constants internally (JM) }
+ TConstPtrUInt = Longword;
+
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tprocessors = (no_processor);
+
+Const
+ {# Size of native extended floating point type }
+ extended_size = 8;
+ {# Size of a pointer }
+ sizeof(aint) = 4;
+ {# Size of a multimedia register }
+ mmreg_size = 8;
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'vis';
+
+Implementation
+
+end.
diff --git a/compiler/vis/cpunode.pas b/compiler/vis/cpunode.pas
new file mode 100644
index 0000000000..010879c0e5
--- /dev/null
+++ b/compiler/vis/cpunode.pas
@@ -0,0 +1,47 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the Virtual instrution set 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
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+// nvisadd,
+// nviscal,
+// nviscon,
+// nvisflw,
+// nvismem,
+// nvisinl,
+// nvismat,
+// nviscnv
+ ;
+
+end.
diff --git a/compiler/vis/cpupara.pas b/compiler/vis/cpupara.pas
new file mode 100644
index 0000000000..6aa41f049d
--- /dev/null
+++ b/compiler/vis/cpupara.pas
@@ -0,0 +1,74 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generates the argument location information for the
+ virtual instruction set machine
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published bymethodpointer
+ 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.
+
+ ****************************************************************************
+}
+{ Generates the argument location information for 680x0.
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ symdef,paramgr;
+
+ type
+ { Returns the location for the nr-st 32 Bit int parameter
+ if every parameter before is an 32 Bit int parameter as well
+ and if the calling conventions for the helper routines of the
+ rtl are used.
+ }
+ tcpuparamanager = class(tparamanager)
+ function getintparaloc(nr : longint) : tparalocation;override;
+ procedure create_param_loc_info(p : tabstractprocdef);override;
+ function getselflocation(p : tabstractprocdef) : tparalocation;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,
+ globals,
+ globtype,
+ systems,
+ cpuinfo,cginfo,cgbase,
+ defutil;
+
+ function tcpuparamanager.getintparaloc(nr : longint) : tparalocation;
+ begin
+ end;
+
+ procedure tcpuparamanager.create_param_loc_info(p : tabstractprocdef);
+ var
+ param_offset : integer;
+ hp : tparaitem;
+ begin
+ end;
+
+ function tcpuparamanager.getselflocation(p : tabstractprocdef) : tparalocation;
+ begin
+ end;
+
+begin
+ paramanager:=tcpuparamanager.create;
+end.
diff --git a/compiler/widestr.pas b/compiler/widestr.pas
new file mode 100644
index 0000000000..da57074510
--- /dev/null
+++ b/compiler/widestr.pas
@@ -0,0 +1,227 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ This unit contains basic functions for unicode support in the
+ compiler, this unit is mainly necessary to bootstrap widestring
+ support ...
+
+ 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 widestr;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ charset,globtype
+ ;
+
+
+ type
+ tcompilerwidechar = word;
+ tcompilerwidecharptr = ^tcompilerwidechar;
+ pcompilerwidechar = ^tcompilerwidechar;
+
+ pcompilerwidestring = ^_tcompilerwidestring;
+ _tcompilerwidestring = record
+ data : pcompilerwidechar;
+ maxlen,len : SizeInt;
+ end;
+
+ procedure initwidestring(out r : pcompilerwidestring);
+ procedure donewidestring(out r : pcompilerwidestring);
+ procedure setlengthwidestring(r : pcompilerwidestring;l : SizeInt);
+ function getlengthwidestring(r : pcompilerwidestring) : SizeInt;
+ procedure concatwidestringchar(r : pcompilerwidestring;c : tcompilerwidechar);
+ procedure concatwidestrings(s1,s2 : pcompilerwidestring);
+ function comparewidestrings(s1,s2 : pcompilerwidestring) : SizeInt;
+ procedure copywidestring(s,d : pcompilerwidestring);
+ function asciichar2unicode(c : char) : tcompilerwidechar;
+ function unicode2asciichar(c : tcompilerwidechar) : char;
+ procedure ascii2unicode(p : pchar;l : SizeInt;r : pcompilerwidestring);
+ procedure unicode2ascii(r : pcompilerwidestring;p : pchar);
+ function getcharwidestring(r : pcompilerwidestring;l : SizeInt) : tcompilerwidechar;
+ function cpavailable(const s : string) : boolean;
+
+ implementation
+
+ uses
+ cp8859_1,cp850,cp437,
+ globals;
+
+
+ procedure initwidestring(out r : pcompilerwidestring);
+
+ begin
+ new(r);
+ r^.data:=nil;
+ r^.len:=0;
+ r^.maxlen:=0;
+ end;
+
+ procedure donewidestring(out r : pcompilerwidestring);
+
+ begin
+ if assigned(r^.data) then
+ freemem(r^.data);
+ dispose(r);
+ r:=nil;
+ end;
+
+ function getcharwidestring(r : pcompilerwidestring;l : SizeInt) : tcompilerwidechar;
+
+ begin
+ getcharwidestring:=r^.data[l];
+ end;
+
+ function getlengthwidestring(r : pcompilerwidestring) : SizeInt;
+
+ begin
+ getlengthwidestring:=r^.len;
+ end;
+
+ procedure setlengthwidestring(r : pcompilerwidestring;l : SizeInt);
+
+ begin
+ if r^.maxlen>=l then
+ exit;
+ if assigned(r^.data) then
+ reallocmem(r^.data,sizeof(tcompilerwidechar)*l)
+ else
+ getmem(r^.data,sizeof(tcompilerwidechar)*l);
+ end;
+
+ procedure concatwidestringchar(r : pcompilerwidestring;c : tcompilerwidechar);
+
+ begin
+ if r^.len>=r^.maxlen then
+ setlengthwidestring(r,r^.len+16);
+ r^.data[r^.len]:=c;
+ inc(r^.len);
+ end;
+
+ procedure concatwidestrings(s1,s2 : pcompilerwidestring);
+ begin
+ setlengthwidestring(s1,s1^.len+s2^.len);
+ inc(s1^.len,s2^.len);
+ move(s2^.data^,s1^.data[s1^.len],s2^.len*sizeof(tcompilerwidechar));
+ end;
+
+ procedure copywidestring(s,d : pcompilerwidestring);
+
+ begin
+ setlengthwidestring(d,s^.len);
+ d^.len:=s^.len;
+ move(s^.data^,d^.data^,s^.len*sizeof(tcompilerwidechar));
+ end;
+
+ function comparewidestrings(s1,s2 : pcompilerwidestring) : SizeInt;
+ var
+ maxi,temp : SizeInt;
+ begin
+ if pointer(s1)=pointer(s2) then
+ begin
+ comparewidestrings:=0;
+ exit;
+ end;
+ maxi:=s1^.len;
+ temp:=s2^.len;
+ if maxi>temp then
+ maxi:=Temp;
+ temp:=compareword(s1^.data^,s2^.data^,maxi);
+ if temp=0 then
+ temp:=s1^.len-s2^.len;
+ comparewidestrings:=temp;
+ end;
+
+ function asciichar2unicode(c : char) : tcompilerwidechar;
+ var
+ m : punicodemap;
+ begin
+ m:=getmap(aktsourcecodepage);
+ asciichar2unicode:=getunicode(c,m);
+ end;
+
+ function unicode2asciichar(c : tcompilerwidechar) : char;
+
+ begin
+ {$ifdef fpc}{$warning todo}{$endif}
+ unicode2asciichar:=#0;
+ end;
+
+ procedure ascii2unicode(p : pchar;l : SizeInt;r : pcompilerwidestring);
+ var
+ source : pchar;
+ dest : tcompilerwidecharptr;
+ i : SizeInt;
+ m : punicodemap;
+ begin
+ m:=getmap(aktsourcecodepage);
+ setlengthwidestring(r,l);
+ source:=p;
+ r^.len:=l;
+ dest:=tcompilerwidecharptr(r^.data);
+ for i:=1 to l do
+ begin
+ dest^:=getunicode(source^,m);
+ inc(dest);
+ inc(source);
+ end;
+ end;
+
+ procedure unicode2ascii(r : pcompilerwidestring;p:pchar);
+(*
+ var
+ m : punicodemap;
+ i : longint;
+
+ begin
+ m:=getmap(aktsourcecodepage);
+ { should be a very good estimation :) }
+ setlengthwidestring(r,length(s));
+ // !!!! MBCS
+ for i:=1 to length(s) do
+ begin
+ end;
+ end;
+*)
+ var
+ source : tcompilerwidecharptr;
+ dest : pchar;
+ i : longint;
+ begin
+ source:=tcompilerwidecharptr(r^.data);
+ dest:=p;
+ for i:=1 to r^.len do
+ begin
+ if word(source^)<128 then
+ dest^:=char(word(source^))
+ else
+ dest^:=' ';
+ inc(dest);
+ inc(source);
+ end;
+ end;
+
+
+ function cpavailable(const s : string) : boolean;
+ begin
+ cpavailable:=mappingavailable(s);
+ end;
+
+end.
diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas
new file mode 100644
index 0000000000..68ebd7238a
--- /dev/null
+++ b/compiler/x86/aasmcpu.pas
@@ -0,0 +1,2155 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Contains the abstract assembler implementation for the i386
+
+ * Portions of 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;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,globals,verbose,
+ cpubase,
+ cgbase,cgutils,
+ symtype,
+ aasmbase,aasmtai;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 0;
+ { "mov reg,reg" destination operand number }
+ O_MOV_DEST = 1;
+
+ { Operand types }
+ OT_NONE = $00000000;
+
+ OT_BITS8 = $00000001; { size, and other attributes, of the operand }
+ OT_BITS16 = $00000002;
+ OT_BITS32 = $00000004;
+ OT_BITS64 = $00000008; { FPU only }
+ OT_BITS80 = $00000010;
+ OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
+ OT_NEAR = $00000040;
+ OT_SHORT = $00000080;
+
+ OT_SIZE_MASK = $000000FF; { all the size attributes }
+ OT_NON_SIZE = longint(not OT_SIZE_MASK);
+
+ OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
+
+ OT_TO = $00000200; { operand is followed by a colon }
+ { reverse effect in FADD, FSUB &c }
+ OT_COLON = $00000400;
+
+ OT_REGISTER = $00001000;
+ OT_IMMEDIATE = $00002000;
+ OT_IMM8 = $00002001;
+ OT_IMM16 = $00002002;
+ OT_IMM32 = $00002004;
+ OT_IMM64 = $00002008;
+ OT_IMM80 = $00002010;
+ OT_REGMEM = $00200000; { for r/m, ie EA, operands }
+ OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
+ OT_REG8 = $00201001;
+ OT_REG16 = $00201002;
+ OT_REG32 = $00201004;
+ OT_REG64 = $00201008;
+ OT_MMXREG = $00201008; { MMX registers }
+ OT_XMMREG = $00201010; { Katmai registers }
+ OT_MEMORY = $00204000; { register number in 'basereg' }
+ OT_MEM8 = $00204001;
+ OT_MEM16 = $00204002;
+ OT_MEM32 = $00204004;
+ OT_MEM64 = $00204008;
+ OT_MEM80 = $00204010;
+ OT_FPUREG = $01000000; { floating point stack registers }
+ OT_FPU0 = $01000800; { FPU stack register zero }
+ OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
+ { a mask for the following }
+ OT_REG_ACCUM = $00211000; { FUNCTION_RETURN_REG: AL, AX or EAX }
+ OT_REG_AL = $00211001; { REG_ACCUM | BITSxx }
+ OT_REG_AX = $00211002; { ditto }
+ OT_REG_EAX = $00211004; { and again }
+{$ifdef x86_64}
+ OT_REG_RAX = $00211008;
+{$endif x86_64}
+ OT_REG_COUNT = $00221000; { counter: CL, CX or ECX }
+ OT_REG_CL = $00221001; { REG_COUNT | BITSxx }
+ OT_REG_CX = $00221002; { ditto }
+ OT_REG_ECX = $00221004; { another one }
+{$ifdef x86_64}
+ OT_REG_RCX = $00221008;
+{$endif x86_64}
+ OT_REG_DX = $00241002;
+ OT_REG_EDX = $00241004;
+
+ OT_REG_SREG = $00081002; { any segment register }
+ OT_REG_CS = $01081002; { CS }
+ OT_REG_DESS = $02081002; { DS, ES, SS (non-CS 86 registers) }
+ OT_REG_FSGS = $04081002; { FS, GS (386 extended registers) }
+
+ OT_REG_CDT = $00101004; { CRn, DRn and TRn }
+ OT_REG_CREG = $08101004; { CRn }
+ OT_REG_CR4 = $08101404; { CR4 (Pentium only) }
+ OT_REG_DREG = $10101004; { DRn }
+ OT_REG_TREG = $20101004; { TRn }
+
+ OT_MEM_OFFS = $00604000; { special type of EA }
+ { simple [address] offset }
+ OT_ONENESS = $00800000; { special type of immediate operand }
+ { so UNITY == IMMEDIATE | ONENESS }
+ OT_UNITY = $00802000; { for shift/rotate instructions }
+
+ { Size of the instruction table converted by nasmconv.pas }
+{$ifdef x86_64}
+ instabentries = {$i x8664nop.inc}
+{$else x86_64}
+ instabentries = {$i i386nop.inc}
+{$endif x86_64}
+ maxinfolen = 8;
+ MaxInsChanges = 3; { Max things a instruction can change }
+
+ type
+ { What an instruction can change. Needed for optimizer and spilling code.
+
+ Note: The order of this enumeration is should not be changed! }
+ TInsChange = (Ch_None,
+ {Read from a register}
+ Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
+ {write from a register}
+ Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
+ {read and write from/to a register}
+ Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
+ {modify the contents of a register with the purpose of using
+ this changed content afterwards (add/sub/..., but e.g. not rep
+ or movsd)}
+ Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
+ Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
+ Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
+ Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
+ Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
+ Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
+ Ch_WMemEDI,
+ Ch_All,
+ { x86_64 registers }
+ Ch_RRAX, Ch_RRCX, Ch_RRDX, Ch_RRBX, Ch_RRSP, Ch_RRBP, Ch_RRSI, Ch_RRDI,
+ Ch_WRAX, Ch_WRCX, Ch_WRDX, Ch_WRBX, Ch_WRSP, Ch_WRBP, Ch_WRSI, Ch_WRDI,
+ Ch_RWRAX, Ch_RWRCX, Ch_RWRDX, Ch_RWRBX, Ch_RWRSP, Ch_RWRBP, Ch_RWRSI, Ch_RWRDI,
+ Ch_MRAX, Ch_MRCX, Ch_MRDX, Ch_MRBX, Ch_MRSP, Ch_MRBP, Ch_MRSI, Ch_MRDI
+ );
+
+ TInsProp = packed record
+ Ch : Array[1..MaxInsChanges] of TInsChange;
+ end;
+
+ const
+ InsProp : array[tasmop] of TInsProp =
+{$ifdef x86_64}
+ {$i x8664pro.inc}
+{$else x86_64}
+ {$i i386prop.inc}
+{$endif x86_64}
+
+ type
+ TOperandOrder = (op_intel,op_att);
+
+ tinsentry=packed record
+ opcode : tasmop;
+ ops : byte;
+ optypes : array[0..2] of longint;
+ code : array[0..maxinfolen] of char;
+ flags : longint;
+ end;
+ pinsentry=^tinsentry;
+
+ { alignment for operator }
+ tai_align = class(tai_align_abstract)
+ reg : tregister;
+ constructor create(b:byte);override;
+ constructor create_op(b: byte; _op: byte);override;
+ function calculatefillbuf(var buf : tfillbuffer):pchar;override;
+ end;
+
+ taicpu = class(tai_cpu_abstract)
+ opsize : topsize;
+ constructor op_none(op : tasmop);
+ constructor op_none(op : tasmop;_size : topsize);
+
+ constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ constructor op_const(op : tasmop;_size : topsize;_op1 : aint);
+ constructor op_ref(op : tasmop;_size : topsize;const _op1 : treference);
+
+ constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
+ constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
+
+ constructor op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
+ constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
+ constructor op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
+
+ constructor op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
+
+ constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
+ constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
+ constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
+ constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; const _op3 : treference);
+ constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_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);
+
+ function GetString:string;
+ procedure CheckNonCommutativeOpcodes;
+ private
+ FOperandOrder : TOperandOrder;
+ procedure init(_size : topsize); { this need to be called by all constructor }
+ {$ifndef NOAG386BIN}
+ public
+ { the next will reset all instructions that can change in pass 2 }
+ procedure ResetPass1;
+ procedure ResetPass2;
+ function CheckIfValid:boolean;
+ function Pass1(offset:longint):longint;override;
+ procedure Pass2(objdata:TAsmObjectdata);override;
+ procedure SetOperandOrder(order:TOperandOrder);
+ function is_same_reg_move(regtype: Tregistertype):boolean;override;
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+ protected
+ procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
+ procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
+ procedure ppubuildderefimploper(var o:toper);override;
+ procedure ppuderefoper(var o:toper);override;
+ private
+ { next fields are filled in pass1, so pass2 is faster }
+ inssize : shortint;
+ insoffset : longint;
+ LastInsOffset : longint; { need to be public to be reset }
+ insentry : PInsEntry;
+ function InsEnd:longint;
+ procedure create_ot;
+ function Matches(p:PInsEntry):longint;
+ function calcsize(p:PInsEntry):shortint;
+ procedure gencode(objdata:TAsmObjectData);
+ function NeedAddrPrefix(opidx:byte):boolean;
+ procedure Swapoperands;
+ function FindInsentry:boolean;
+ {$endif NOAG386BIN}
+ 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;
+
+
+implementation
+
+ uses
+ cutils,
+ itcpugas,
+ symsym;
+
+{*****************************************************************************
+ Instruction table
+*****************************************************************************}
+
+ const
+ {Instruction flags }
+ IF_NONE = $00000000;
+ IF_SM = $00000001; { size match first two operands }
+ IF_SM2 = $00000002;
+ IF_SB = $00000004; { unsized operands can't be non-byte }
+ IF_SW = $00000008; { unsized operands can't be non-word }
+ IF_SD = $00000010; { unsized operands can't be nondword }
+ IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
+ IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
+ IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
+ IF_ARMASK = $00000060; { mask for unsized argument spec }
+ IF_PRIV = $00000100; { it's a privileged instruction }
+ IF_SMM = $00000200; { it's only valid in SMM }
+ IF_PROT = $00000400; { it's protected mode only }
+ IF_NOX86_64 = $00000800; { removed instruction in x86_64 }
+ IF_UNDOC = $00001000; { it's an undocumented instruction }
+ IF_FPU = $00002000; { it's an FPU instruction }
+ IF_MMX = $00004000; { it's an MMX instruction }
+ { it's a 3DNow! instruction }
+ IF_3DNOW = $00008000;
+ { it's a SSE (KNI, MMX2) instruction }
+ IF_SSE = $00010000;
+ { SSE2 instructions }
+ IF_SSE2 = $00020000;
+ { SSE3 instructions }
+ IF_SSE3 = $00040000;
+ { SSE64 instructions }
+ IF_SSE64 = $00080000;
+ { the mask for processor types }
+ {IF_PMASK = longint($FF000000);}
+ { the mask for disassembly "prefer" }
+ {IF_PFMASK = longint($F001FF00);}
+ IF_8086 = $00000000; { 8086 instruction }
+ IF_186 = $01000000; { 186+ instruction }
+ IF_286 = $02000000; { 286+ instruction }
+ IF_386 = $03000000; { 386+ instruction }
+ IF_486 = $04000000; { 486+ instruction }
+ IF_PENT = $05000000; { Pentium instruction }
+ IF_P6 = $06000000; { P6 instruction }
+ IF_KATMAI = $07000000; { Katmai instructions }
+ { Willamette instructions }
+ IF_WILLAMETTE = $08000000;
+ { Prescott instructions }
+ IF_PRESCOTT = $09000000;
+ IF_X86_64 = $0a000000;
+ IF_CYRIX = $10000000; { Cyrix-specific instruction }
+ IF_AMD = $20000000; { AMD-specific instruction }
+ { added flags }
+ IF_PRE = $40000000; { it's a prefix instruction }
+ IF_PASS2 = longint($80000000); { if the instruction can change in a second pass }
+
+ type
+ TInsTabCache=array[TasmOp] of longint;
+ PInsTabCache=^TInsTabCache;
+
+ const
+{$ifdef x86_64}
+ InsTab:array[0..instabentries-1] of TInsEntry={$i x8664tab.inc}
+{$else x86_64}
+ InsTab:array[0..instabentries-1] of TInsEntry={$i i386tab.inc}
+{$endif x86_64}
+ var
+ InsTabCache : PInsTabCache;
+
+ const
+{$ifdef x86_64}
+ { Intel style operands ! }
+ opsize_2_type:array[0..2,topsize] of longint=(
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,OT_BITS64,OT_BITS64,OT_BITS64,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ ),
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,OT_BITS8,OT_BITS16,OT_BITS32,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ ),
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ )
+ );
+
+ reg_ot_table : array[tregisterindex] of longint = (
+ {$i r8664ot.inc}
+ );
+{$else x86_64}
+ { Intel style operands ! }
+ opsize_2_type:array[0..2,topsize] of longint=(
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ ),
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ ),
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ )
+ );
+
+ reg_ot_table : array[tregisterindex] of longint = (
+ {$i r386ot.inc}
+ );
+{$endif x86_64}
+
+ { Operation type for spilling code }
+ type
+ toperation_type_table=array[tasmop,0..Max_Operands] of topertype;
+ var
+ operation_type_table : ^toperation_type_table;
+
+
+{****************************************************************************
+ TAI_ALIGN
+ ****************************************************************************}
+
+ constructor tai_align.create(b: byte);
+ begin
+ inherited create(b);
+ reg:=NR_ECX;
+ end;
+
+
+ constructor tai_align.create_op(b: byte; _op: byte);
+ begin
+ inherited create_op(b,_op);
+ reg:=NR_NO;
+ end;
+
+
+ function tai_align.calculatefillbuf(var buf : tfillbuffer):pchar;
+ const
+ alignarray:array[0..5] of string[8]=(
+ #$8D#$B4#$26#$00#$00#$00#$00,
+ #$8D#$B6#$00#$00#$00#$00,
+ #$8D#$74#$26#$00,
+ #$8D#$76#$00,
+ #$89#$F6,
+ #$90
+ );
+ var
+ bufptr : pchar;
+ j : longint;
+ begin
+ inherited calculatefillbuf(buf);
+ if not use_op then
+ begin
+ bufptr:=pchar(@buf);
+ while (fillsize>0) do
+ begin
+ for j:=0 to 5 do
+ if (fillsize>=length(alignarray[j])) then
+ break;
+ move(alignarray[j][1],bufptr^,length(alignarray[j]));
+ inc(bufptr,length(alignarray[j]));
+ dec(fillsize,length(alignarray[j]));
+ end;
+ end;
+ calculatefillbuf:=pchar(@buf);
+ end;
+
+
+{*****************************************************************************
+ Taicpu Constructors
+*****************************************************************************}
+
+ procedure taicpu.changeopsize(siz:topsize);
+ begin
+ opsize:=siz;
+ end;
+
+
+ procedure taicpu.init(_size : topsize);
+ begin
+ { default order is att }
+ FOperandOrder:=op_att;
+ segprefix:=NR_NO;
+ opsize:=_size;
+{$ifndef NOAG386BIN}
+ insentry:=nil;
+ LastInsOffset:=-1;
+ InsOffset:=0;
+ InsSize:=0;
+{$endif}
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ init(S_NO);
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop;_size : topsize);
+ begin
+ inherited create(op);
+ init(_size);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadconst(0,_op1);
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_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; _size: topsize; _op1: tregister; _op2: aint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_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_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,_op1);
+ loadref(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,_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;
+
+
+ function taicpu.GetString:string;
+ var
+ i : longint;
+ s : string;
+ addsize : boolean;
+ begin
+ s:='['+std_op2str[opcode];
+ for i:=0 to ops-1 do
+ begin
+ with oper[i]^ do
+ begin
+ if i=0 then
+ s:=s+' '
+ else
+ s:=s+',';
+ { type }
+ addsize:=false;
+ if (ot and OT_XMMREG)=OT_XMMREG then
+ s:=s+'xmmreg'
+ else
+ if (ot and OT_MMXREG)=OT_MMXREG then
+ s:=s+'mmxreg'
+ else
+ if (ot and OT_FPUREG)=OT_FPUREG then
+ s:=s+'fpureg'
+ else
+ if (ot and OT_REGISTER)=OT_REGISTER then
+ begin
+ s:=s+'reg';
+ addsize:=true;
+ end
+ else
+ if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
+ begin
+ s:=s+'imm';
+ addsize:=true;
+ end
+ else
+ if (ot and OT_MEMORY)=OT_MEMORY then
+ begin
+ s:=s+'mem';
+ addsize:=true;
+ end
+ else
+ s:=s+'???';
+ { size }
+ if addsize then
+ begin
+ if (ot and OT_BITS8)<>0 then
+ s:=s+'8'
+ else
+ if (ot and OT_BITS16)<>0 then
+ s:=s+'16'
+ else
+ if (ot and OT_BITS32)<>0 then
+ s:=s+'32'
+ else
+ s:=s+'??';
+ { signed }
+ if (ot and OT_SIGNED)<>0 then
+ s:=s+'s';
+ end;
+ end;
+ end;
+ GetString:=s+']';
+ end;
+
+
+ procedure taicpu.Swapoperands;
+ var
+ p : POper;
+ 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;
+
+
+ procedure taicpu.SetOperandOrder(order:TOperandOrder);
+ begin
+ if FOperandOrder<>order then
+ begin
+ Swapoperands;
+ FOperandOrder:=order;
+ end;
+ end;
+
+
+ procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
+ begin
+ o.typ:=toptype(ppufile.getbyte);
+ o.ot:=ppufile.getlongint;
+ case o.typ of
+ top_reg :
+ ppufile.getdata(o.reg,sizeof(Tregister));
+ top_ref :
+ begin
+ new(o.ref);
+ ppufile.getdata(o.ref^.segment,sizeof(Tregister));
+ ppufile.getdata(o.ref^.base,sizeof(Tregister));
+ ppufile.getdata(o.ref^.index,sizeof(Tregister));
+ o.ref^.scalefactor:=ppufile.getbyte;
+ o.ref^.offset:=ppufile.getaint;
+ o.ref^.symbol:=ppufile.getasmsymbol;
+ o.ref^.relsymbol:=ppufile.getasmsymbol;
+ end;
+ top_const :
+ o.val:=ppufile.getaint;
+ top_local :
+ begin
+ new(o.localoper);
+ with o.localoper^ do
+ begin
+ ppufile.getderef(localsymderef);
+ localsymofs:=ppufile.getaint;
+ localindexreg:=tregister(ppufile.getlongint);
+ localscale:=ppufile.getbyte;
+ localgetoffset:=(ppufile.getbyte<>0);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
+ begin
+ ppufile.putbyte(byte(o.typ));
+ ppufile.putlongint(o.ot);
+ case o.typ of
+ top_reg :
+ ppufile.putdata(o.reg,sizeof(Tregister));
+ top_ref :
+ begin
+ ppufile.putdata(o.ref^.segment,sizeof(Tregister));
+ ppufile.putdata(o.ref^.base,sizeof(Tregister));
+ ppufile.putdata(o.ref^.index,sizeof(Tregister));
+ ppufile.putbyte(o.ref^.scalefactor);
+ ppufile.putaint(o.ref^.offset);
+ ppufile.putasmsymbol(o.ref^.symbol);
+ ppufile.putasmsymbol(o.ref^.relsymbol);
+ end;
+ top_const :
+ ppufile.putaint(o.val);
+ top_local :
+ begin
+ with o.localoper^ do
+ begin
+ ppufile.putderef(localsymderef);
+ ppufile.putaint(localsymofs);
+ ppufile.putlongint(longint(localindexreg));
+ ppufile.putbyte(localscale);
+ ppufile.putbyte(byte(localgetoffset));
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure taicpu.ppubuildderefimploper(var o:toper);
+ begin
+ case o.typ of
+ top_local :
+ o.localoper^.localsymderef.build(tlocalvarsym(o.localoper^.localsym));
+ end;
+ end;
+
+
+ procedure taicpu.ppuderefoper(var o:toper);
+ begin
+ case o.typ of
+ top_ref :
+ begin
+ if assigned(o.ref^.symbol) then
+ objectlibrary.derefasmsymbol(o.ref^.symbol);
+ if assigned(o.ref^.relsymbol) then
+ objectlibrary.derefasmsymbol(o.ref^.relsymbol);
+ end;
+ top_local :
+ o.localoper^.localsym:=tlocalvarsym(o.localoper^.localsymderef.resolve);
+ end;
+ end;
+
+
+ procedure taicpu.CheckNonCommutativeOpcodes;
+ begin
+ { we need ATT order }
+ SetOperandOrder(op_att);
+
+ if (
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ { if the first is ST and the second is also a register
+ it is necessarily ST1 .. ST7 }
+ ((oper[0]^.reg=NR_ST) or
+ (oper[0]^.reg=NR_ST0))
+ ) or
+ { ((ops=1) and
+ (oper[0]^.typ=top_reg) and
+ (oper[0]^.reg in [R_ST1..R_ST7])) or}
+ (ops=0) then
+ begin
+ if opcode=A_FSUBR then
+ opcode:=A_FSUB
+ else if opcode=A_FSUB then
+ opcode:=A_FSUBR
+ else if opcode=A_FDIVR then
+ opcode:=A_FDIV
+ else if opcode=A_FDIV then
+ opcode:=A_FDIVR
+ else if opcode=A_FSUBRP then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBP then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIVRP then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVP then
+ opcode:=A_FDIVRP;
+ end;
+ if (
+ (ops=1) and
+ (oper[0]^.typ=top_reg) and
+ (getregtype(oper[0]^.reg)=R_FPUREGISTER) and
+ (oper[0]^.reg<>NR_ST)
+ ) then
+ begin
+ if opcode=A_FSUBRP then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBP then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIVRP then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVP then
+ opcode:=A_FDIVRP;
+ end;
+ end;
+
+
+{*****************************************************************************
+ Assembler
+*****************************************************************************}
+
+{$ifndef NOAG386BIN}
+
+ type
+ ea=packed record
+ sib_present : boolean;
+ bytes : byte;
+ size : byte;
+ modrm : byte;
+ sib : byte;
+ end;
+
+ procedure taicpu.create_ot;
+ {
+ this function will also fix some other fields which only needs to be once
+ }
+ var
+ i,l,relsize : longint;
+ begin
+ if ops=0 then
+ exit;
+ { update oper[].ot field }
+ for i:=0 to ops-1 do
+ with oper[i]^ do
+ begin
+ case typ of
+ top_reg :
+ begin
+ ot:=reg_ot_table[findreg_by_number(reg)];
+ end;
+ top_ref :
+ begin
+ if ref^.refaddr=addr_no then
+ begin
+ { create ot field }
+ if (ot and OT_SIZE_MASK)=0 then
+ ot:=OT_MEMORY or opsize_2_type[i,opsize]
+ else
+ ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+ if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
+ ot:=ot or OT_MEM_OFFS;
+ { fix scalefactor }
+ if (ref^.index=NR_NO) then
+ ref^.scalefactor:=0
+ else
+ if (ref^.scalefactor=0) then
+ ref^.scalefactor:=1;
+ end
+ else
+ begin
+ l:=ref^.offset;
+ if assigned(ref^.symbol) then
+ inc(l,ref^.symbol.address);
+ { when it is a forward jump we need to compensate the
+ offset of the instruction since the previous time,
+ because the symbol address is then still using the
+ 'old-style' addressing.
+ For backwards jumps this is not required because the
+ address of the symbol is already adjusted to the
+ new offset }
+ if (l>InsOffset) and (LastInsOffset<>-1) then
+ inc(l,InsOffset-LastInsOffset);
+ { instruction size will then always become 2 (PFV) }
+ relsize:=(InsOffset+2)-l;
+ if (not assigned(ref^.symbol) or
+ ((ref^.symbol.currbind<>AB_EXTERNAL) and (ref^.symbol.address<>0))) and
+ (relsize>=-128) and (relsize<=127) then
+ ot:=OT_IMM32 or OT_SHORT
+ else
+ ot:=OT_IMM32 or OT_NEAR;
+ end;
+ end;
+ top_local :
+ begin
+ if (ot and OT_SIZE_MASK)=0 then
+ ot:=OT_MEMORY or opsize_2_type[i,opsize]
+ else
+ ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+ end;
+ top_const :
+ begin
+ if opsize=S_NO then
+ message(asmr_e_invalid_opcode_and_operand);
+ if (opsize<>S_W) and (longint(val)>=-128) and (val<=127) then
+ ot:=OT_IMM8 or OT_SIGNED
+ else
+ ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
+ end;
+ top_none :
+ begin
+ { generated when there was an error in the
+ assembler reader. It never happends when generating
+ assembler }
+ end;
+ else
+ internalerror(200402261);
+ end;
+ end;
+ end;
+
+
+ function taicpu.InsEnd:longint;
+ begin
+ InsEnd:=InsOffset+InsSize;
+ end;
+
+
+ function taicpu.Matches(p:PInsEntry):longint;
+ { * IF_SM stands for Size Match: any operand whose size is not
+ * explicitly specified by the template is `really' intended to be
+ * the same size as the first size-specified operand.
+ * Non-specification is tolerated in the input instruction, but
+ * _wrong_ specification is not.
+ *
+ * IF_SM2 invokes Size Match on only the first _two_ operands, for
+ * three-operand instructions such as SHLD: it implies that the
+ * first two operands must match in size, but that the third is
+ * required to be _unspecified_.
+ *
+ * IF_SB invokes Size Byte: operands with unspecified size in the
+ * template are really bytes, and so no non-byte specification in
+ * the input instruction will be tolerated. IF_SW similarly invokes
+ * Size Word, and IF_SD invokes Size Doubleword.
+ *
+ * (The default state if neither IF_SM nor IF_SM2 is specified is
+ * that any operand with unspecified size in the template is
+ * required to have unspecified size in the instruction too...)
+ }
+ var
+ i,j,asize,oprs : longint;
+ siz : array[0..2] of longint;
+ begin
+ Matches:=100;
+
+ { Check the opcode and operands }
+ if (p^.opcode<>opcode) or (p^.ops<>ops) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { Check that no spurious colons or TOs are present }
+ for i:=0 to p^.ops-1 do
+ if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { Check that the operand flags all match up }
+ for i:=0 to p^.ops-1 do
+ begin
+ if ((p^.optypes[i] and (not oper[i]^.ot)) or
+ ((p^.optypes[i] and OT_SIZE_MASK) and
+ ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
+ begin
+ if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
+ (oper[i]^.ot and OT_SIZE_MASK))<>0 then
+ begin
+ Matches:=0;
+ exit;
+ end
+ else
+ Matches:=1;
+ end;
+ end;
+
+ { Check operand sizes }
+ { as default an untyped size can get all the sizes, this is different
+ from nasm, but else we need to do a lot checking which opcodes want
+ size or not with the automatic size generation }
+ asize:=longint($ffffffff);
+ if (p^.flags and IF_SB)<>0 then
+ asize:=OT_BITS8
+ else if (p^.flags and IF_SW)<>0 then
+ asize:=OT_BITS16
+ else if (p^.flags and IF_SD)<>0 then
+ asize:=OT_BITS32;
+ if (p^.flags and IF_ARMASK)<>0 then
+ begin
+ siz[0]:=0;
+ siz[1]:=0;
+ siz[2]:=0;
+ if (p^.flags and IF_AR0)<>0 then
+ siz[0]:=asize
+ else if (p^.flags and IF_AR1)<>0 then
+ siz[1]:=asize
+ else if (p^.flags and IF_AR2)<>0 then
+ siz[2]:=asize;
+ end
+ else
+ begin
+ { we can leave because the size for all operands is forced to be
+ the same
+ but not if IF_SB IF_SW or IF_SD is set PM }
+ if asize=-1 then
+ exit;
+ siz[0]:=asize;
+ siz[1]:=asize;
+ siz[2]:=asize;
+ end;
+
+ if (p^.flags and (IF_SM or IF_SM2))<>0 then
+ begin
+ if (p^.flags and IF_SM2)<>0 then
+ oprs:=2
+ else
+ oprs:=p^.ops;
+ for i:=0 to oprs-1 do
+ if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
+ begin
+ for j:=0 to oprs-1 do
+ siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
+ break;
+ end;
+ end
+ else
+ oprs:=2;
+
+ { Check operand sizes }
+ for i:=0 to p^.ops-1 do
+ begin
+ if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
+ ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
+ { Immediates can always include smaller size }
+ ((oper[i]^.ot and OT_IMMEDIATE)=0) and
+ (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
+ Matches:=2;
+ end;
+ end;
+
+
+ procedure taicpu.ResetPass1;
+ begin
+ { we need to reset everything here, because the choosen insentry
+ can be invalid for a new situation where the previously optimized
+ insentry is not correct }
+ InsEntry:=nil;
+ InsSize:=0;
+ LastInsOffset:=-1;
+ end;
+
+
+ procedure taicpu.ResetPass2;
+ begin
+ { we are here in a second pass, check if the instruction can be optimized }
+ if assigned(InsEntry) and
+ ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ InsEntry:=nil;
+ InsSize:=0;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+
+ function taicpu.CheckIfValid:boolean;
+ begin
+ result:=FindInsEntry;
+ end;
+
+
+ function taicpu.FindInsentry:boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ { Things which may only be done once, not when a second pass is done to
+ optimize }
+ if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ { We need intel style operands }
+ SetOperandOrder(op_intel);
+ { create the .ot fields }
+ create_ot;
+ { set the file postion }
+ aktfilepos:=fileinfo;
+ end
+ else
+ begin
+ { we've already an insentry so it's valid }
+ result:=true;
+ exit;
+ end;
+ { Lookup opcode in the table }
+ InsSize:=-1;
+ i:=instabcache^[opcode];
+ if i=-1 then
+ begin
+ Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
+ exit;
+ end;
+ insentry:=@instab[i];
+ while (insentry^.opcode=opcode) do
+ begin
+ if matches(insentry)=100 then
+ begin
+ result:=true;
+ exit;
+ end;
+ inc(i);
+ insentry:=@instab[i];
+ end;
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+ { No instruction found, set insentry to nil and inssize to -1 }
+ insentry:=nil;
+ inssize:=-1;
+ end;
+
+
+ function taicpu.Pass1(offset:longint):longint;
+ begin
+ Pass1:=0;
+ { Save the old offset and set the new offset }
+ InsOffset:=Offset;
+ { Error? }
+ if (Insentry=nil) and (InsSize=-1) then
+ exit;
+ { set the file postion }
+ aktfilepos:=fileinfo;
+ { Get InsEntry }
+ if FindInsEntry then
+ begin
+ { Calculate instruction size }
+ InsSize:=calcsize(insentry);
+ if segprefix<>NR_NO then
+ inc(InsSize);
+ { Fix opsize if size if forced }
+ if (insentry^.flags and (IF_SB or IF_SW or IF_SD))<>0 then
+ begin
+ if (insentry^.flags and IF_ARMASK)=0 then
+ begin
+ if (insentry^.flags and IF_SB)<>0 then
+ begin
+ if opsize=S_NO then
+ opsize:=S_B;
+ end
+ else if (insentry^.flags and IF_SW)<>0 then
+ begin
+ if opsize=S_NO then
+ opsize:=S_W;
+ end
+ else if (insentry^.flags and IF_SD)<>0 then
+ begin
+ if opsize=S_NO then
+ opsize:=S_L;
+ end;
+ end;
+ end;
+ LastInsOffset:=InsOffset;
+ Pass1:=InsSize;
+ exit;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+
+ procedure taicpu.Pass2(objdata:TAsmObjectData);
+ var
+ c : longint;
+ begin
+ { error in pass1 ? }
+ if insentry=nil then
+ exit;
+ aktfilepos:=fileinfo;
+ { Segment override }
+ if (segprefix<>NR_NO) then
+ begin
+ case segprefix of
+ NR_CS : c:=$2e;
+ NR_DS : c:=$3e;
+ NR_ES : c:=$26;
+ NR_FS : c:=$64;
+ NR_GS : c:=$65;
+ NR_SS : c:=$36;
+ end;
+ objdata.writebytes(c,1);
+ { fix the offset for GenNode }
+ inc(InsOffset);
+ end;
+ { Generate the instruction }
+ GenCode(objdata);
+ end;
+
+
+ function taicpu.needaddrprefix(opidx:byte):boolean;
+ begin
+ result:=(oper[opidx]^.typ=top_ref) and
+ (oper[opidx]^.ref^.refaddr=addr_no) and
+ (
+ (
+ (oper[opidx]^.ref^.index<>NR_NO) and
+ (getsubreg(oper[opidx]^.ref^.index)<>R_SUBD)
+ ) or
+ (
+ (oper[opidx]^.ref^.base<>NR_NO) and
+ (getsubreg(oper[opidx]^.ref^.base)<>R_SUBD)
+ )
+ );
+ end;
+
+
+ function regval(r:Tregister):byte;
+ const
+ {$ifdef x86_64}
+ opcode_table:array[tregisterindex] of tregisterindex = (
+ {$i r8664op.inc}
+ );
+ {$else x86_64}
+ opcode_table:array[tregisterindex] of tregisterindex = (
+ {$i r386op.inc}
+ );
+ {$endif x86_64}
+ var
+ regidx : tregisterindex;
+ begin
+ regidx:=findreg_by_number(r);
+ if regidx<>0 then
+ result:=opcode_table[regidx]
+ else
+ begin
+ Message1(asmw_e_invalid_register,generic_regname(r));
+ result:=0;
+ end;
+ end;
+
+
+ function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
+ var
+ sym : tasmsymbol;
+ md,s,rv : byte;
+ base,index,scalefactor,
+ o : longint;
+ ir,br : Tregister;
+ isub,bsub : tsubregister;
+ begin
+ process_ea:=false;
+ {Register ?}
+ if (input.typ=top_reg) then
+ begin
+ rv:=regval(input.reg);
+ output.sib_present:=false;
+ output.bytes:=0;
+ output.modrm:=$c0 or (rfield shl 3) or rv;
+ output.size:=1;
+ process_ea:=true;
+ exit;
+ end;
+ {No register, so memory reference.}
+ if (input.typ<>top_ref) then
+ internalerror(200409262);
+ if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER)) or
+ ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
+ internalerror(200301081);
+ ir:=input.ref^.index;
+ br:=input.ref^.base;
+ isub:=getsubreg(ir);
+ bsub:=getsubreg(br);
+ s:=input.ref^.scalefactor;
+ o:=input.ref^.offset;
+ sym:=input.ref^.symbol;
+ { it's direct address }
+ if (br=NR_NO) and (ir=NR_NO) then
+ begin
+ { it's a pure offset }
+ output.sib_present:=false;
+ output.bytes:=4;
+ output.modrm:=5 or (rfield shl 3);
+ end
+ else
+ { it's an indirection }
+ begin
+ { 16 bit address? }
+ if ((ir<>NR_NO) and (isub<>R_SUBD)) or
+ ((br<>NR_NO) and (bsub<>R_SUBD)) then
+ message(asmw_e_16bit_not_supported);
+{$ifdef OPTEA}
+ { make single reg base }
+ if (br=NR_NO) and (s=1) then
+ begin
+ br:=ir;
+ ir:=NR_NO;
+ end;
+ { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
+ if (br=NR_NO) and
+ (((s=2) and (ir<>NR_ESP)) or
+ (s=3) or (s=5) or (s=9)) then
+ begin
+ br:=ir;
+ dec(s);
+ end;
+ { swap ESP into base if scalefactor is 1 }
+ if (s=1) and (ir=NR_ESP) then
+ begin
+ ir:=br;
+ br:=NR_ESP;
+ end;
+{$endif OPTEA}
+ { wrong, for various reasons }
+ if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
+ exit;
+ { base }
+ case br of
+ NR_EAX : base:=0;
+ NR_ECX : base:=1;
+ NR_EDX : base:=2;
+ NR_EBX : base:=3;
+ NR_ESP : base:=4;
+ NR_NO,
+ NR_EBP : base:=5;
+ NR_ESI : base:=6;
+ NR_EDI : base:=7;
+ else
+ exit;
+ end;
+ { index }
+ case ir of
+ NR_EAX : index:=0;
+ NR_ECX : index:=1;
+ NR_EDX : index:=2;
+ NR_EBX : index:=3;
+ NR_NO : index:=4;
+ NR_EBP : index:=5;
+ NR_ESI : index:=6;
+ NR_EDI : index:=7;
+ else
+ exit;
+ end;
+ case s of
+ 0,
+ 1 : scalefactor:=0;
+ 2 : scalefactor:=1;
+ 4 : scalefactor:=2;
+ 8 : scalefactor:=3;
+ else
+ exit;
+ end;
+ if (br=NR_NO) or
+ ((br<>NR_EBP) and (o=0) and (sym=nil)) then
+ md:=0
+ else
+ if ((o>=-128) and (o<=127) and (sym=nil)) then
+ md:=1
+ else
+ md:=2;
+ if (br=NR_NO) or (md=2) then
+ output.bytes:=4
+ else
+ output.bytes:=md;
+ { SIB needed ? }
+ if (ir=NR_NO) and (br<>NR_ESP) then
+ begin
+ output.sib_present:=false;
+ output.modrm:=(md shl 6) or (rfield shl 3) or base;
+ end
+ else
+ begin
+ output.sib_present:=true;
+ output.modrm:=(md shl 6) or (rfield shl 3) or 4;
+ output.sib:=(scalefactor shl 6) or (index shl 3) or base;
+ end;
+ end;
+ if output.sib_present then
+ output.size:=2+output.bytes
+ else
+ output.size:=1+output.bytes;
+ process_ea:=true;
+ end;
+
+
+ function taicpu.calcsize(p:PInsEntry):shortint;
+ var
+ codes : pchar;
+ c : byte;
+ len : shortint;
+ ea_data : ea;
+ begin
+ len:=0;
+ codes:=@p^.code;
+ repeat
+ c:=ord(codes^);
+ inc(codes);
+ case c of
+ 0 :
+ break;
+ 1,2,3 :
+ begin
+ inc(codes,c);
+ inc(len,c);
+ end;
+ 8,9,10 :
+ begin
+ inc(codes);
+ inc(len);
+ end;
+ 4,5,6,7 :
+ begin
+ if opsize=S_W then
+ inc(len,2)
+ else
+ inc(len);
+ end;
+ 15,
+ 12,13,14,
+ 16,17,18,
+ 20,21,22,
+ 40,41,42 :
+ inc(len);
+ 24,25,26,
+ 31,
+ 48,49,50 :
+ inc(len,2);
+ 28,29,30, { we don't have 16 bit immediates code }
+ 32,33,34,
+ 52,53,54,
+ 56,57,58 :
+ inc(len,4);
+ 192,193,194 :
+ if NeedAddrPrefix(c-192) then
+ inc(len);
+ 208,
+ 210 :
+ inc(len);
+ 200,
+ 201,
+ 202,
+ 209,
+ 211,
+ 217,218: ;
+ 219,220 :
+ inc(len);
+ 216 :
+ begin
+ inc(codes);
+ inc(len);
+ end;
+ 224,225,226 :
+ begin
+ InternalError(777002);
+ end;
+ else
+ begin
+ if (c>=64) and (c<=191) then
+ begin
+ if not process_ea(oper[(c shr 3) and 7]^, ea_data, 0) then
+ Message(asmw_e_invalid_effective_address)
+ else
+ inc(len,ea_data.size);
+ end
+ else
+ InternalError(777003);
+ end;
+ end;
+ until false;
+ calcsize:=len;
+ end;
+
+
+ procedure taicpu.GenCode(objdata:TAsmObjectData);
+ {
+ * the actual codes (C syntax, i.e. octal):
+ * \0 - terminates the code. (Unless it's a literal of course.)
+ * \1, \2, \3 - that many literal bytes follow in the code stream
+ * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
+ * (POP is never used for CS) depending on operand 0
+ * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
+ * on operand 0
+ * \10, \11, \12 - a literal byte follows in the code stream, to be added
+ * to the register value of operand 0, 1 or 2
+ * \17 - encodes the literal byte 0. (Some compilers don't take
+ * kindly to a zero byte in the _middle_ of a compile time
+ * string constant, so I had to put this hack in.)
+ * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
+ * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
+ * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
+ * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
+ * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
+ * assembly mode or the address-size override on the operand
+ * \37 - a word constant, from the _segment_ part of operand 0
+ * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
+ * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
+ * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
+ * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
+ * assembly mode or the address-size override on the operand
+ * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
+ * \1ab - a ModRM, calculated on EA in operand a, with the spare
+ * field the register value of operand b.
+ * \2ab - a ModRM, calculated on EA in operand a, with the spare
+ * field equal to digit b.
+ * \30x - might be an 0x67 byte, depending on the address size of
+ * the memory reference in operand x.
+ * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
+ * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
+ * \312 - indicates fixed 64-bit address size, i.e. optional 0x48.
+ * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
+ * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
+ * \322 - indicates fixed 64-bit operand size, i.e. optional 0x48.
+ * \323 - indicates that this instruction is only valid when the
+ * operand size is the default (instruction to disassembler,
+ * generates no code in the assembler)
+ * \330 - a literal byte follows in the code stream, to be added
+ * to the condition code value of the instruction.
+ * \340 - reserve <operand 0> bytes of uninitialised storage.
+ * Operand 0 had better be a segmentless constant.
+ }
+
+ var
+ currval : longint;
+ currsym : tasmsymbol;
+
+ procedure getvalsym(opidx:longint);
+ begin
+ case oper[opidx]^.typ of
+ top_ref :
+ begin
+ currval:=oper[opidx]^.ref^.offset;
+ currsym:=oper[opidx]^.ref^.symbol;
+ end;
+ top_const :
+ begin
+ currval:=longint(oper[opidx]^.val);
+ currsym:=nil;
+ end;
+ else
+ Message(asmw_e_immediate_or_reference_expected);
+ end;
+ end;
+
+ const
+ CondVal:array[TAsmCond] of byte=($0,
+ $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
+ $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
+ $0, $A, $A, $B, $8, $4);
+ var
+ c : byte;
+ pb,
+ codes : pchar;
+ bytes : array[0..3] of byte;
+ rfield,
+ data,s,opidx : longint;
+ ea_data : ea;
+ begin
+{$ifdef EXTDEBUG}
+ { safety check }
+ if objdata.currsec.datasize<>insoffset then
+ internalerror(200130121);
+{$endif EXTDEBUG}
+ { load data to write }
+ codes:=insentry^.code;
+ { Force word push/pop for registers }
+ if (opsize=S_W) and ((codes[0]=#4) or (codes[0]=#6) or
+ ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
+ begin
+ bytes[0]:=$66;
+ objdata.writebytes(bytes,1);
+ end;
+ repeat
+ c:=ord(codes^);
+ inc(codes);
+ case c of
+ 0 :
+ break;
+ 1,2,3 :
+ begin
+ objdata.writebytes(codes^,c);
+ inc(codes,c);
+ end;
+ 4,6 :
+ begin
+ case oper[0]^.reg of
+ NR_CS:
+ bytes[0]:=$e;
+ NR_NO,
+ NR_DS:
+ bytes[0]:=$1e;
+ NR_ES:
+ bytes[0]:=$6;
+ NR_SS:
+ bytes[0]:=$16;
+ else
+ internalerror(777004);
+ end;
+ if c=4 then
+ inc(bytes[0]);
+ objdata.writebytes(bytes,1);
+ end;
+ 5,7 :
+ begin
+ case oper[0]^.reg of
+ NR_FS:
+ bytes[0]:=$a0;
+ NR_GS:
+ bytes[0]:=$a8;
+ else
+ internalerror(777005);
+ end;
+ if c=5 then
+ inc(bytes[0]);
+ objdata.writebytes(bytes,1);
+ end;
+ 8,9,10 :
+ begin
+ bytes[0]:=ord(codes^)+regval(oper[c-8]^.reg);
+ inc(codes);
+ objdata.writebytes(bytes,1);
+ end;
+ 15 :
+ begin
+ bytes[0]:=0;
+ objdata.writebytes(bytes,1);
+ end;
+ 12,13,14 :
+ begin
+ getvalsym(c-12);
+ if (currval<-128) or (currval>127) then
+ Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
+ if assigned(currsym) then
+ objdata.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
+ else
+ objdata.writebytes(currval,1);
+ end;
+ 16,17,18 :
+ begin
+ getvalsym(c-16);
+ if (currval<-256) or (currval>255) then
+ Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
+ if assigned(currsym) then
+ objdata.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
+ else
+ objdata.writebytes(currval,1);
+ end;
+ 20,21,22 :
+ begin
+ getvalsym(c-20);
+ if (currval<0) or (currval>255) then
+ Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
+ if assigned(currsym) then
+ objdata.writereloc(currval,1,currsym,RELOC_ABSOLUTE)
+ else
+ objdata.writebytes(currval,1);
+ end;
+ 24,25,26 :
+ begin
+ getvalsym(c-24);
+ if (currval<-65536) or (currval>65535) then
+ Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
+ if assigned(currsym) then
+ objdata.writereloc(currval,2,currsym,RELOC_ABSOLUTE)
+ else
+ objdata.writebytes(currval,2);
+ end;
+ 28,29,30 :
+ begin
+ getvalsym(c-28);
+ if assigned(currsym) then
+ objdata.writereloc(currval,4,currsym,RELOC_ABSOLUTE)
+ else
+ objdata.writebytes(currval,4);
+ end;
+ 32,33,34 :
+ begin
+ getvalsym(c-32);
+ if assigned(currsym) then
+ objdata.writereloc(currval,4,currsym,RELOC_ABSOLUTE)
+ else
+ objdata.writebytes(currval,4);
+ end;
+ 40,41,42 :
+ begin
+ getvalsym(c-40);
+ data:=currval-insend;
+ if assigned(currsym) then
+ inc(data,currsym.address);
+ if (data>127) or (data<-128) then
+ Message1(asmw_e_short_jmp_out_of_range,tostr(data));
+ objdata.writebytes(data,1);
+ end;
+ 52,53,54 :
+ begin
+ getvalsym(c-52);
+ if assigned(currsym) then
+ objdata.writereloc(currval,4,currsym,RELOC_RELATIVE)
+ else
+ objdata.writereloc(currval-insend,4,nil,RELOC_ABSOLUTE)
+ end;
+ 56,57,58 :
+ begin
+ getvalsym(c-56);
+ if assigned(currsym) then
+ objdata.writereloc(currval,4,currsym,RELOC_RELATIVE)
+ else
+ objdata.writereloc(currval-insend,4,nil,RELOC_ABSOLUTE)
+ end;
+ 192,193,194 :
+ begin
+ if NeedAddrPrefix(c-192) then
+ begin
+ bytes[0]:=$67;
+ objdata.writebytes(bytes,1);
+ end;
+ end;
+ 200 :
+ begin
+ bytes[0]:=$67;
+ objdata.writebytes(bytes,1);
+ end;
+ 208 :
+ begin
+ bytes[0]:=$66;
+ objdata.writebytes(bytes,1);
+ end;
+ 210 :
+ begin
+ bytes[0]:=$48;
+ objdata.writebytes(bytes,1);
+ end;
+ 216 :
+ begin
+ bytes[0]:=ord(codes^)+condval[condition];
+ inc(codes);
+ objdata.writebytes(bytes,1);
+ end;
+ 201,
+ 202,
+ 209,
+ 211,
+ 217,218 :
+ begin
+ { these are dissambler hints or 32 bit prefixes which
+ are not needed }
+ end;
+ 219 :
+ begin
+ bytes[0]:=$f3;
+ objdata.writebytes(bytes,1);
+ end;
+ 220 :
+ begin
+ bytes[0]:=$f2;
+ objdata.writebytes(bytes,1);
+ end;
+ 31,
+ 48,49,50,
+ 224,225,226 :
+ begin
+ InternalError(777006);
+ end
+ else
+ begin
+ if (c>=64) and (c<=191) then
+ begin
+ if (c<127) then
+ begin
+ if (oper[c and 7]^.typ=top_reg) then
+ rfield:=regval(oper[c and 7]^.reg)
+ else
+ rfield:=regval(oper[c and 7]^.ref^.base);
+ end
+ else
+ rfield:=c and 7;
+ opidx:=(c shr 3) and 7;
+ if not process_ea(oper[opidx]^,ea_data,rfield) then
+ Message(asmw_e_invalid_effective_address);
+
+ pb:=@bytes;
+ pb^:=chr(ea_data.modrm);
+ inc(pb);
+ if ea_data.sib_present then
+ begin
+ pb^:=chr(ea_data.sib);
+ inc(pb);
+ end;
+
+ s:=pb-pchar(@bytes);
+ objdata.writebytes(bytes,s);
+
+ case ea_data.bytes of
+ 0 : ;
+ 1 :
+ begin
+ if (oper[opidx]^.ot and OT_MEMORY)=OT_MEMORY then
+ objdata.writereloc(oper[opidx]^.ref^.offset,1,oper[opidx]^.ref^.symbol,RELOC_ABSOLUTE)
+ else
+ begin
+ bytes[0]:=oper[opidx]^.ref^.offset;
+ objdata.writebytes(bytes,1);
+ end;
+ inc(s);
+ end;
+ 2,4 :
+ begin
+ objdata.writereloc(oper[opidx]^.ref^.offset,ea_data.bytes,
+ oper[opidx]^.ref^.symbol,RELOC_ABSOLUTE);
+ inc(s,ea_data.bytes);
+ end;
+ end;
+ end
+ else
+ InternalError(777007);
+ end;
+ end;
+ until false;
+ end;
+{$endif NOAG386BIN}
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ result:=(((opcode=A_MOV) or (opcode=A_XCHG)) and
+ (regtype = R_INTREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ ) or
+ (((opcode=A_MOVSS) or (opcode=A_MOVSD)) and
+ (regtype = R_MMREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ );
+ end;
+
+
+ procedure build_spilling_operation_type_table;
+ var
+ opcode : tasmop;
+ i : integer;
+ begin
+ new(operation_type_table);
+ fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read));
+ for opcode:=low(tasmop) to high(tasmop) do
+ begin
+ for i:=1 to MaxInsChanges do
+ begin
+ case InsProp[opcode].Ch[i] of
+ Ch_Rop1 :
+ operation_type_table^[opcode,0]:=operand_read;
+ Ch_Wop1 :
+ operation_type_table^[opcode,0]:=operand_write;
+ Ch_RWop1,
+ Ch_Mop1 :
+ operation_type_table^[opcode,0]:=operand_readwrite;
+ Ch_Rop2 :
+ operation_type_table^[opcode,1]:=operand_read;
+ Ch_Wop2 :
+ operation_type_table^[opcode,1]:=operand_write;
+ Ch_RWop2,
+ Ch_Mop2 :
+ operation_type_table^[opcode,1]:=operand_readwrite;
+ Ch_Rop3 :
+ operation_type_table^[opcode,2]:=operand_read;
+ Ch_Wop3 :
+ operation_type_table^[opcode,2]:=operand_write;
+ Ch_RWop3,
+ Ch_Mop3 :
+ operation_type_table^[opcode,2]:=operand_readwrite;
+ end;
+ end;
+ end;
+ { Special cases that can't be decoded from the InsChanges flags }
+ operation_type_table^[A_IMUL,1]:=operand_readwrite;
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ { the information in the instruction table is made for the string copy
+ operation MOVSD so hack here (FK)
+ }
+ if (opcode=A_MOVSD) and (ops=2) then
+ begin
+ case opnr of
+ 0:
+ result:=operand_read;
+ 1:
+ result:=operand_write;
+ else
+ internalerror(200506055);
+ end
+ end
+ else
+ result:=operation_type_table^[opcode,opnr];
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister): tai;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),ref,r);
+ R_MMREGISTER :
+ case getsubreg(r) of
+ R_SUBMMD:
+ result:=taicpu.op_ref_reg(A_MOVSD,reg2opsize(r),ref,r);
+ R_SUBMMS:
+ result:=taicpu.op_ref_reg(A_MOVSS,reg2opsize(r),ref,r);
+ else
+ internalerror(200506043);
+ end;
+ 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_MOV,reg2opsize(r),r,ref);
+ R_MMREGISTER :
+ case getsubreg(r) of
+ R_SUBMMD:
+ result:=taicpu.op_reg_ref(A_MOVSD,reg2opsize(r),r,ref);
+ R_SUBMMS:
+ result:=taicpu.op_reg_ref(A_MOVSS,reg2opsize(r),r,ref);
+ else
+ internalerror(200506042);
+ end;
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Instruction table
+*****************************************************************************}
+
+ procedure BuildInsTabCache;
+{$ifndef NOAG386BIN}
+ var
+ i : longint;
+{$endif}
+ begin
+{$ifndef NOAG386BIN}
+ new(instabcache);
+ FillChar(instabcache^,sizeof(tinstabcache),$ff);
+ i:=0;
+ while (i<InsTabEntries) do
+ begin
+ if InsTabCache^[InsTab[i].OPcode]=-1 then
+ InsTabCache^[InsTab[i].OPcode]:=i;
+ inc(i);
+ end;
+{$endif NOAG386BIN}
+ end;
+
+
+ procedure InitAsm;
+ begin
+ build_spilling_operation_type_table;
+{$ifndef NOAG386BIN}
+ if not assigned(instabcache) then
+ BuildInsTabCache;
+{$endif NOAG386BIN}
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ if assigned(operation_type_table) then
+ begin
+ dispose(operation_type_table);
+ operation_type_table:=nil;
+ end;
+{$ifndef NOAG386BIN}
+ if assigned(instabcache) then
+ begin
+ dispose(instabcache);
+ instabcache:=nil;
+ end;
+{$endif NOAG386BIN}
+ end;
+
+
+begin
+ cai_align:=tai_align;
+ cai_cpu:=taicpu;
+end.
diff --git a/compiler/x86/agx86att.pas b/compiler/x86/agx86att.pas
new file mode 100644
index 0000000000..c5410ab940
--- /dev/null
+++ b/compiler/x86/agx86att.pas
@@ -0,0 +1,284 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for i386 AT&T 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.
+
+ ****************************************************************************
+}
+{ This unit implements an asmoutput class for i386 AT&T syntax
+}
+unit agx86att;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,cpubase,
+ globals,cgutils,
+ aasmbase,aasmtai,assemble,aggas;
+
+ type
+ Tx86ATTAssembler=class(TGNUassembler)
+ private
+ procedure WriteReference(var ref : treference);
+ procedure WriteOper(const o:toper);
+ procedure WriteOper_jmp(const o:toper);
+ public
+ procedure WriteInstruction(hp: tai);override;
+ end;
+
+
+ implementation
+
+ uses
+ cutils,systems,
+ verbose,
+ itcpugas,
+ cgbase,
+ aasmcpu;
+
+
+{****************************************************************************
+ TX86ATTASMOUTPUT
+ ****************************************************************************}
+
+ procedure Tx86AttAssembler.WriteReference(var ref : treference);
+ begin
+ with ref do
+ begin
+ { have we a segment prefix ? }
+ { These are probably not correctly handled under GAS }
+ { should be replaced by coding the segment override }
+ { directly! - DJGPP FAQ }
+ if segment<>NR_NO then
+ AsmWrite(gas_regname(segment)+':');
+ if assigned(symbol) then
+ AsmWrite(symbol.name);
+ if ref.refaddr=addr_pic then
+{$ifdef x86_64}
+ AsmWrite('@GOTPCREL');
+{$else x86_64}
+ AsmWrite('@GOT');
+{$endif x86_64}
+ if offset<0 then
+ AsmWrite(tostr(offset))
+ else
+ if (offset>0) then
+ begin
+ if assigned(symbol) then
+ AsmWrite('+'+tostr(offset))
+ else
+ AsmWrite(tostr(offset));
+ end
+ else if (index=NR_NO) and (base=NR_NO) and (not assigned(symbol)) then
+ AsmWrite('0');
+ if (index<>NR_NO) and (base=NR_NO) then
+ begin
+ AsmWrite('(,'+gas_regname(index));
+ if scalefactor<>0 then
+ AsmWrite(','+tostr(scalefactor)+')')
+ else
+ AsmWrite(')');
+ end
+ else
+ if (index=NR_NO) and (base<>NR_NO) then
+ AsmWrite('('+gas_regname(base)+')')
+ else
+ if (index<>NR_NO) and (base<>NR_NO) then
+ begin
+ AsmWrite('('+gas_regname(base)+','+gas_regname(index));
+ if scalefactor<>0 then
+ AsmWrite(','+tostr(scalefactor));
+ AsmWrite(')');
+ end;
+ end;
+ end;
+
+
+ procedure Tx86AttAssembler.WriteOper(const o:toper);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(gas_regname(o.reg));
+ top_ref :
+ if o.ref^.refaddr in [addr_no,addr_pic] then
+ WriteReference(o.ref^)
+ else
+ begin
+ AsmWrite('$');
+ if assigned(o.ref^.symbol) then
+ AsmWrite(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ AsmWrite(tostr(o.ref^.offset))
+ else
+ if not(assigned(o.ref^.symbol)) then
+ AsmWrite('0');
+ end;
+ top_const :
+ AsmWrite('$'+tostr(o.val));
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ procedure Tx86AttAssembler.WriteOper_jmp(const o:toper);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite('*'+gas_regname(o.reg));
+ top_ref :
+ begin
+ if o.ref^.refaddr=addr_no then
+ begin
+ AsmWrite('*');
+ WriteReference(o.ref^);
+ end
+ else
+ begin
+ AsmWrite(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ AsmWrite(tostr(o.ref^.offset));
+ end;
+ end;
+ top_const :
+ AsmWrite(tostr(o.val));
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ procedure Tx86AttAssembler.WriteInstruction(hp: tai);
+ var
+ op : tasmop;
+ calljmp : boolean;
+ i : integer;
+ begin
+ if hp.typ <> ait_instruction then
+ exit;
+ taicpu(hp).SetOperandOrder(op_att);
+ op:=taicpu(hp).opcode;
+ calljmp:=is_calljmp(op);
+ AsmWrite(#9);
+ { movsd should not be translated to movsl when there
+ are (xmm) arguments }
+ if (op=A_MOVSD) and (taicpu(hp).ops>0) then
+ AsmWrite('movsd')
+ else
+ AsmWrite(gas_op2str[op]);
+ AsmWrite(cond2str[taicpu(hp).condition]);
+ { suffix needed ? fnstsw,fldcw don't support suffixes
+ with binutils 2.9.5 under linux }
+{ if (Taicpu(hp).oper[0]^.typ=top_reg) and
+ (Taicpu(hp).oper[0]^.reg.enum>lastreg) then
+ internalerror(200301081);}
+
+ if (not calljmp) and
+ (gas_needsuffix[op]<>AttSufNONE) and
+ (op<>A_FNSTSW) and
+ (op<>A_FSTSW) and
+ (op<>A_FNSTCW) and
+ (op<>A_FSTCW) and
+ (op<>A_FLDCW) and
+ not(
+ (taicpu(hp).ops<>0) and
+ (taicpu(hp).oper[0]^.typ=top_reg) and
+ (getregtype(taicpu(hp).oper[0]^.reg)=R_FPUREGISTER)
+ ) then
+ AsmWrite(gas_opsize2str[taicpu(hp).opsize]);
+ { process operands }
+ if taicpu(hp).ops<>0 then
+ begin
+ if calljmp then
+ begin
+ AsmWrite(#9);
+ WriteOper_jmp(taicpu(hp).oper[0]^);
+ end
+ else
+ begin
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ if i=0 then
+ AsmWrite(#9)
+ else
+ AsmWrite(',');
+ WriteOper(taicpu(hp).oper[i]^);
+ end;
+ end;
+ end;
+ AsmLn;
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+{$ifdef x86_64}
+ as_x86_64_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+{$else x86_64}
+ as_i386_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+ as_i386_as_aout_info : tasminfo =
+ (
+ id : as_i386_as_aout;
+ idtxt : 'AS_AOUT';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar];
+ labelprefix : 'L';
+ comment : '# ';
+ );
+{$endif x86_64}
+
+initialization
+{$ifdef x86_64}
+ RegisterAssembler(as_x86_64_as_info,Tx86ATTAssembler);
+{$else x86_64}
+ RegisterAssembler(as_i386_as_info,Tx86ATTAssembler);
+ RegisterAssembler(as_i386_as_aout_info,Tx86ATTAssembler);
+{$endif x86_64}
+end.
diff --git a/compiler/x86/agx86int.pas b/compiler/x86/agx86int.pas
new file mode 100644
index 0000000000..d46211c8a6
--- /dev/null
+++ b/compiler/x86/agx86int.pas
@@ -0,0 +1,965 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for Intel syntax with Intel 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 an asmoutput class for Intel syntax with Intel i386+
+}
+unit agx86int;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ aasmbase,aasmtai,aasmcpu,assemble,cgutils;
+
+ type
+ Tx86IntelAssembler = class(TExternalAssembler)
+ private
+ procedure WriteReference(var ref : treference);
+ procedure WriteOper(const o:toper;s : topsize; opcode: tasmop;dest : boolean);
+ procedure WriteOper_jmp(const o:toper;s : topsize);
+ public
+ procedure WriteTree(p:TAAsmoutput);override;
+ procedure WriteAsmList;override;
+ Function DoAssemble:boolean;override;
+ procedure WriteExternals;
+ end;
+
+
+implementation
+
+ uses
+ cutils,globtype,globals,systems,cclasses,
+ verbose,finput,fmodule,script,cpuinfo,
+ itx86int,
+ cgbase
+ ;
+
+ const
+ line_length = 70;
+
+ secnames : array[TAsmSectionType] of string[4] = ('',
+ 'CODE','DATA','DATA','BSS','',
+ '','','','','','','',
+ '','','','','','',''
+ );
+
+ secnamesml64 : array[TAsmSectionType] of string[7] = ('',
+ '_TEXT','_DATE','_DATA','_BSS','',
+ '','','','','',
+ 'idata$2','idata$4','idata$5','idata$6','idata$7','edata',
+ '','',''
+ );
+
+ function single2str(d : single) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ single2str:=lower(hs);
+ end;
+
+ function double2str(d : double) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ double2str:=lower(hs);
+ end;
+
+ function extended2str(e : extended) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(e,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ extended2str:=lower(hs);
+ end;
+
+
+ function comp2str(d : bestreal) : string;
+ type
+ pdouble = ^double;
+ var
+ c : comp;
+ dd : pdouble;
+ begin
+{$ifdef FPC}
+ c:=comp(d);
+{$else}
+ c:=d;
+{$endif}
+ dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
+ comp2str:=double2str(dd^);
+ end;
+
+
+ function fixline(s:string):string;
+ {
+ return s with all leading and ending spaces and tabs removed
+ }
+ var
+ i,j,k : longint;
+ begin
+ i:=length(s);
+ while (i>0) and (s[i] in [#9,' ']) do
+ dec(i);
+ j:=1;
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ for k:=j to i do
+ if s[k] in [#0..#31,#127..#255] then
+ s[k]:='.';
+ fixline:=Copy(s,j,i-j+1);
+ end;
+
+
+{****************************************************************************
+ tx86IntelAssembler
+ ****************************************************************************}
+
+ procedure tx86IntelAssembler.WriteReference(var ref : treference);
+ var
+ first : boolean;
+ begin
+ with ref do
+ begin
+ first:=true;
+ if segment<>NR_NO then
+ AsmWrite(masm_regname(segment)+':[')
+ else
+ AsmWrite('[');
+ if assigned(symbol) then
+ begin
+ if (target_asm.id = as_i386_tasm) then
+ AsmWrite('dword ptr ');
+ AsmWrite(symbol.name);
+ first:=false;
+ end;
+ if (base<>NR_NO) then
+ begin
+ if not(first) then
+ AsmWrite('+')
+ else
+ first:=false;
+ AsmWrite(masm_regname(base));
+ end;
+ if (index<>NR_NO) then
+ begin
+ if not(first) then
+ AsmWrite('+')
+ else
+ first:=false;
+ AsmWrite(masm_regname(index));
+ if scalefactor<>0 then
+ AsmWrite('*'+tostr(scalefactor));
+ end;
+ if offset<0 then
+ begin
+ AsmWrite(tostr(offset));
+ first:=false;
+ end
+ else if (offset>0) then
+ begin
+ AsmWrite('+'+tostr(offset));
+ first:=false;
+ end;
+ if first then
+ AsmWrite('0');
+ AsmWrite(']');
+ end;
+ end;
+
+
+ procedure tx86IntelAssembler.WriteOper(const o:toper;s : topsize; opcode: tasmop;dest : boolean);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(masm_regname(o.reg));
+ top_const :
+ AsmWrite(tostr(longint(o.val)));
+ top_ref :
+ begin
+ if o.ref^.refaddr=addr_no then
+ begin
+ if ((opcode <> A_LGS) and (opcode <> A_LSS) and
+ (opcode <> A_LFS) and (opcode <> A_LDS) and
+ (opcode <> A_LES)) then
+ Begin
+ case s of
+ S_B : AsmWrite('byte ptr ');
+ S_W : AsmWrite('word ptr ');
+ S_L : AsmWrite('dword ptr ');
+ S_Q : AsmWrite('qword ptr ');
+ S_IS : AsmWrite('word ptr ');
+ S_IL : AsmWrite('dword ptr ');
+ S_IQ : AsmWrite('qword ptr ');
+ S_FS : AsmWrite('dword ptr ');
+ S_FL : AsmWrite('qword ptr ');
+ S_T,
+ S_FX : AsmWrite('tbyte ptr ');
+ S_BW : if dest then
+ AsmWrite('word ptr ')
+ else
+ AsmWrite('byte ptr ');
+ S_BL : if dest then
+ AsmWrite('dword ptr ')
+ else
+ AsmWrite('byte ptr ');
+ S_WL : if dest then
+ AsmWrite('dword ptr ')
+ else
+ AsmWrite('word ptr ');
+{$ifdef x86_64}
+ S_BQ : if dest then
+ AsmWrite('qword ptr ')
+ else
+ AsmWrite('byte ptr ');
+ S_WQ : if dest then
+ AsmWrite('qword ptr ')
+ else
+ AsmWrite('word ptr ');
+ S_LQ : if dest then
+ AsmWrite('qword ptr ')
+ else
+ AsmWrite('dword ptr ');
+ S_XMM: AsmWrite('xmmword ptr ');
+
+{$endif x86_64}
+ end;
+ end;
+ WriteReference(o.ref^);
+ end
+ else
+ begin
+ AsmWrite('offset ');
+ if assigned(o.ref^.symbol) then
+ AsmWrite(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ AsmWrite(tostr(o.ref^.offset))
+ else
+ if not(assigned(o.ref^.symbol)) then
+ AsmWrite('0');
+ end;
+ end;
+ else
+ internalerror(2005060510);
+ end;
+ end;
+
+
+ procedure tx86IntelAssembler.WriteOper_jmp(const o:toper;s : topsize);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(masm_regname(o.reg));
+ top_const :
+ AsmWrite(tostr(longint(o.val)));
+ top_ref :
+ { what about lcall or ljmp ??? }
+ begin
+ if o.ref^.refaddr=addr_no then
+ begin
+ if (target_asm.id <> as_i386_tasm) then
+ begin
+ if s=S_FAR then
+ AsmWrite('far ptr ')
+ else
+{$ifdef x86_64}
+ AsmWrite('qword ptr ');
+{$else x86_64}
+ AsmWrite('dword ptr ');
+{$endif x86_64}
+ end;
+ WriteReference(o.ref^);
+ end
+ else
+ begin
+ AsmWrite(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ AsmWrite(tostr(o.ref^.offset));
+ end;
+ end;
+ else
+ internalerror(2005060511);
+ end;
+ end;
+
+
+ var
+ LasTSectype : TAsmSectionType;
+ lastfileinfo : tfileposinfo;
+ infile,
+ lastinfile : tinputfile;
+
+ const
+ ait_const2str : array[ait_const_128bit..ait_const_indirect_symbol] of string[20]=(
+ #9''#9,#9'DQ'#9,#9'DD'#9,#9'DW'#9,#9'DB'#9,
+ #9'FIXMESLEB',#9'FIXEMEULEB',
+ #9'DD RVA'#9,#9'FIXMEINDIRECT'#9
+ );
+
+ Function PadTabs(const p:string;addch:char):string;
+ var
+ s : string;
+ i : longint;
+ begin
+ i:=length(p);
+ if addch<>#0 then
+ begin
+ inc(i);
+ s:=p+addch;
+ end
+ else
+ s:=p;
+ if i<8 then
+ PadTabs:=s+#9#9
+ else
+ PadTabs:=s+#9;
+ end;
+
+ procedure tx86IntelAssembler.WriteTree(p:TAAsmoutput);
+ const
+ regallocstr : array[tregalloctype] of string[10]=(' allocated',' released',' sync',' resized');
+ tempallocstr : array[boolean] of string[10]=(' released',' allocated');
+ var
+ s,
+ prefix,
+ suffix : string;
+ hp : tai;
+ hp1 : tailineinfo;
+ counter,
+ lines,
+ InlineLevel : longint;
+ i,j,l : longint;
+ consttyp : taitype;
+ do_line,DoNotSplitLine,
+ quoted : boolean;
+ begin
+ if not assigned(p) then
+ exit;
+ { lineinfo is only needed for al_procedures (PFV) }
+ do_line:=((cs_asm_source in aktglobalswitches) or
+ (cs_lineinfo in aktmoduleswitches))
+ and (p=asmlist[al_procedures]);
+ InlineLevel:=0;
+ DoNotSplitLine:=false;
+ hp:=tai(p.first);
+ while assigned(hp) do
+ begin
+ if do_line and not(hp.typ in SkipLineInfo) and
+ not DoNotSplitLine then
+ begin
+ hp1:=hp as tailineinfo;
+ { load infile }
+ if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
+ begin
+ infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
+ if assigned(infile) then
+ begin
+ { open only if needed !! }
+ if (cs_asm_source in aktglobalswitches) then
+ infile.open;
+ end;
+ { avoid unnecessary reopens of the same file !! }
+ lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
+ { be sure to change line !! }
+ lastfileinfo.line:=-1;
+ end;
+ { write source }
+ if (cs_asm_source in aktglobalswitches) and
+ assigned(infile) then
+ begin
+ if (infile<>lastinfile) then
+ begin
+ AsmWriteLn(target_asm.comment+'['+infile.name^+']');
+ if assigned(lastinfile) then
+ lastinfile.close;
+ end;
+ if (hp1.fileinfo.line<>lastfileinfo.line) and
+ ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
+ begin
+ if (hp1.fileinfo.line<>0) and
+ ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
+ AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
+ fixline(infile.GetLineStr(hp1.fileinfo.line)));
+ { set it to a negative value !
+ to make that is has been read already !! PM }
+ if (infile.linebuf^[hp1.fileinfo.line]>=0) then
+ infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
+ end;
+ end;
+ lastfileinfo:=hp1.fileinfo;
+ lastinfile:=infile;
+ end;
+ DoNotSplitLine:=false;
+ case hp.typ of
+ ait_comment :
+ Begin
+ AsmWrite(target_asm.comment);
+ AsmWritePChar(tai_comment(hp).str);
+ AsmLn;
+ End;
+
+ ait_regalloc :
+ begin
+ if (cs_asm_regalloc in aktglobalswitches) then
+ AsmWriteLn(target_asm.comment+'Register '+masm_regname(tai_regalloc(hp).reg)+
+ regallocstr[tai_regalloc(hp).ratype]);
+ end;
+
+ ait_tempalloc :
+ begin
+ if (cs_asm_tempalloc in aktglobalswitches) then
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(tai_tempalloc(hp).problem) then
+ AsmWriteLn(target_asm.comment+tai_tempalloc(hp).problem^+' ('+tostr(tai_tempalloc(hp).temppos)+','+
+ tostr(tai_tempalloc(hp).tempsize)+')')
+ else
+{$endif EXTDEBUG}
+ AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
+ tostr(tai_tempalloc(hp).tempsize)+tempallocstr[tai_tempalloc(hp).allocation]);
+ end;
+ end;
+
+ ait_section :
+ begin
+ if tai_section(hp).sectype<>sec_none then
+ begin
+ if target_asm.id=as_x86_64_masm then
+ begin
+ if LasTSecType<>sec_none then
+ AsmWriteLn(secnamesml64[LasTSecType]+#9#9'ENDS');
+ AsmLn;
+ AsmWriteLn(secnamesml64[tai_section(hp).sectype]+#9+'SEGMENT')
+ end
+ else
+ begin
+ if LasTSecType<>sec_none then
+ AsmWriteLn('_'+secnames[LasTSecType]+#9#9'ENDS');
+ AsmLn;
+ AsmWriteLn('_'+secnames[tai_section(hp).sectype]+#9#9+
+ 'SEGMENT'#9'PARA PUBLIC USE32 '''+
+ secnames[tai_section(hp).sectype]+'''');
+ end;
+ end;
+ LasTSecType:=tai_section(hp).sectype;
+ end;
+ ait_align :
+ begin
+ { CAUSES PROBLEMS WITH THE SEGMENT DEFINITION }
+ { SEGMENT DEFINITION SHOULD MATCH TYPE OF ALIGN }
+ { HERE UNDER TASM! }
+ if tai_align(hp).aligntype>1 then
+ AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype));
+ end;
+ ait_datablock :
+ begin
+ if tai_datablock(hp).is_global then
+ AsmWriteLn(#9'PUBLIC'#9+tai_datablock(hp).sym.name);
+ AsmWriteLn(PadTabs(tai_datablock(hp).sym.name,#0)+'DB'#9+tostr(tai_datablock(hp).size)+' DUP(?)');
+ end;
+ ait_const_uleb128bit,
+ ait_const_sleb128bit,
+ ait_const_128bit,
+ ait_const_64bit,
+ ait_const_32bit,
+ ait_const_16bit,
+ ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_const_indirect_symbol :
+ begin
+ AsmWrite(ait_const2str[hp.typ]);
+ consttyp:=hp.typ;
+ l:=0;
+ repeat
+ if assigned(tai_const(hp).sym) then
+ begin
+ if assigned(tai_const(hp).endsym) then
+ s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
+ else
+ s:=tai_const(hp).sym.name;
+ if tai_const(hp).value<>0 then
+ s:=s+tostr_with_plus(tai_const(hp).value);
+ end
+ else
+ s:=tostr(tai_const(hp).value);
+ AsmWrite(s);
+ if (l>line_length) or
+ (hp.next=nil) or
+ (tai(hp.next).typ<>consttyp) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmLn;
+ end;
+
+ ait_real_32bit :
+ AsmWriteLn(#9#9'DD'#9+single2str(tai_real_32bit(hp).value));
+ ait_real_64bit :
+ AsmWriteLn(#9#9'DQ'#9+double2str(tai_real_64bit(hp).value));
+ ait_real_80bit :
+ AsmWriteLn(#9#9'DT'#9+extended2str(tai_real_80bit(hp).value));
+ ait_comp_64bit :
+ AsmWriteLn(#9#9'DQ'#9+comp2str(tai_real_80bit(hp).value));
+ ait_string :
+ begin
+ counter := 0;
+ lines := tai_string(hp).len div line_length;
+ { separate lines in different parts }
+ if tai_string(hp).len > 0 then
+ Begin
+ for j := 0 to lines-1 do
+ begin
+ AsmWrite(#9#9'DB'#9);
+ quoted:=false;
+ for i:=counter to counter+line_length-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'"') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('"');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and ord('"') }
+ else
+ begin
+ if quoted then
+ AsmWrite('"');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then AsmWrite('"');
+ AsmWrite(target_info.newline);
+ counter := counter+line_length;
+ end; { end for j:=0 ... }
+ { do last line of lines }
+ if counter<tai_string(hp).len then
+ AsmWrite(#9#9'DB'#9);
+ quoted:=false;
+ for i:=counter to tai_string(hp).len-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'"') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('"');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and " }
+ else
+ begin
+ if quoted then
+ AsmWrite('"');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then
+ AsmWrite('"');
+ end;
+ AsmLn;
+ end;
+ ait_label :
+ begin
+ if tai_label(hp).l.is_used then
+ begin
+ AsmWrite(tai_label(hp).l.name);
+ if assigned(hp.next) and not(tai(hp.next).typ in
+ [ait_const_32bit,ait_const_16bit,ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
+ AsmWriteLn(':')
+ else
+ DoNotSplitLine:=true;
+ end;
+ end;
+ ait_symbol :
+ begin
+ if tai_symbol(hp).is_global then
+ AsmWriteLn(#9'PUBLIC'#9+tai_symbol(hp).sym.name);
+ AsmWrite(tai_symbol(hp).sym.name);
+ if assigned(hp.next) and not(tai(hp.next).typ in
+ [ait_const_32bit,ait_const_16bit,ait_const_8bit,
+ ait_const_rva_symbol,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
+ AsmWriteLn(':')
+ end;
+ ait_symbol_end :
+ begin
+ end;
+ ait_instruction :
+ begin
+ taicpu(hp).CheckNonCommutativeOpcodes;
+ taicpu(hp).SetOperandOrder(op_intel);
+ { Reset }
+ suffix:='';
+ prefix:= '';
+ { We need to explicitely set
+ word prefix to get selectors
+ to be pushed in 2 bytes PM }
+ if (taicpu(hp).opsize=S_W) and
+ (
+ (
+ (taicpu(hp).opcode=A_PUSH) or
+ (taicpu(hp).opcode=A_POP)
+ ) and
+ (taicpu(hp).oper[0]^.typ=top_reg) and
+ is_segment_reg(taicpu(hp).oper[0]^.reg)
+ ) then
+ AsmWriteln(#9#9'DB'#9'066h');
+
+ { added prefix instructions, must be on same line as opcode }
+ if (taicpu(hp).ops = 0) and
+ ((taicpu(hp).opcode = A_REP) or
+ (taicpu(hp).opcode = A_LOCK) or
+ (taicpu(hp).opcode = A_REPE) or
+ (taicpu(hp).opcode = A_REPNZ) or
+ (taicpu(hp).opcode = A_REPZ) or
+ (taicpu(hp).opcode = A_REPNE)) then
+ Begin
+ prefix:=std_op2str[taicpu(hp).opcode]+#9;
+ hp:=tai(hp.next);
+ { this is theorically impossible... }
+ if hp=nil then
+ begin
+ AsmWriteLn(#9#9+prefix);
+ break;
+ end;
+ { nasm prefers prefix on a line alone
+ AsmWriteln(#9#9+prefix); but not masm PM
+ prefix:=''; }
+ if target_asm.id in [as_i386_nasmcoff,as_i386_nasmwin32,as_i386_nasmwdosx,
+ as_i386_nasmelf,as_i386_nasmobj,as_i386_nasmbeos] then
+ begin
+ AsmWriteln(prefix);
+ prefix:='';
+ end;
+ end
+ else
+ prefix:= '';
+ if (target_asm.id = as_i386_wasm) and
+ (taicpu(hp).opsize=S_W) and
+ (taicpu(hp).opcode=A_PUSH) and
+ (taicpu(hp).oper[0]^.typ=top_const) then
+ begin
+ AsmWriteln(#9#9'DB 66h,68h ; pushw imm16');
+ AsmWrite(#9#9'DW');
+ end
+ else if (target_asm.id=as_x86_64_masm) and
+ (taicpu(hp).opcode=A_MOVQ) then
+ AsmWrite(#9#9'mov')
+ else
+ AsmWrite(#9#9+prefix+std_op2str[taicpu(hp).opcode]+cond2str[taicpu(hp).condition]+suffix);
+ if taicpu(hp).ops<>0 then
+ begin
+ if is_calljmp(taicpu(hp).opcode) then
+ begin
+ AsmWrite(#9);
+ WriteOper_jmp(taicpu(hp).oper[0]^,taicpu(hp).opsize);
+ end
+ else
+ begin
+ for i:=0to taicpu(hp).ops-1 do
+ begin
+ if i=0 then
+ AsmWrite(#9)
+ else
+ AsmWrite(',');
+ WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,taicpu(hp).opcode,(i=2));
+ end;
+ end;
+ end;
+ AsmLn;
+ end;
+
+ ait_stab,
+ ait_force_line,
+ ait_function_name : ;
+
+ ait_cutobject :
+ begin
+ { only reset buffer if nothing has changed }
+ if AsmSize=AsmStartSize then
+ AsmClear
+ else
+ begin
+ if LasTSecType<>sec_none then
+ AsmWriteLn('_'+secnames[LasTSecType]+#9#9'ENDS');
+ AsmLn;
+ AsmWriteLn(#9'END');
+ AsmClose;
+ DoAssemble;
+ AsmCreate(tai_cutobject(hp).place);
+ end;
+ { avoid empty files }
+ while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
+ begin
+ if tai(hp.next).typ=ait_section then
+ lasTSecType:=tai_section(hp.next).sectype;
+ hp:=tai(hp.next);
+ end;
+ AsmWriteLn(#9'.386p');
+ AsmWriteLn('DGROUP'#9'GROUP'#9'_BSS,_DATA');
+ AsmWriteLn(#9'ASSUME'#9'CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP');
+ { I was told that this isn't necesarry because }
+ { the labels generated by FPC are unique (FK) }
+ { AsmWriteLn(#9'LOCALS '+target_asm.labelprefix); }
+ if lasTSectype<>sec_none then
+ AsmWriteLn('_'+secnames[lasTSectype]+#9#9+
+ 'SEGMENT'#9'PARA PUBLIC USE32 '''+
+ secnames[lasTSectype]+'''');
+ AsmStartSize:=AsmSize;
+ end;
+ ait_marker :
+ begin
+ if tai_marker(hp).kind=InlineStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=InlineEnd then
+ dec(InlineLevel);
+ end;
+
+ ait_directive :
+ begin
+ case tai_directive(hp).directive of
+ asd_nasm_import :
+ AsmWrite('import ');
+ asd_extern :
+ AsmWrite('EXTRN ');
+ else
+ internalerror(200509192);
+ end;
+ if assigned(tai_directive(hp).name) then
+ AsmWrite(tai_directive(hp).name^);
+ AsmLn;
+ end;
+
+ else
+ internalerror(10000);
+ end;
+ hp:=tai(hp.next);
+ end;
+ end;
+
+ var
+ currentasmlist : TExternalAssembler;
+
+ procedure writeexternal(p:tnamedindexitem;arg:pointer);
+ begin
+ if tasmsymbol(p).defbind=AB_EXTERNAL then
+ begin
+ case target_asm.id of
+ as_i386_masm,as_i386_wasm:
+ currentasmlist.AsmWriteln(#9'EXTRN'#9+p.name
+ +': NEAR');
+ as_x86_64_masm:
+ currentasmlist.AsmWriteln(#9'EXTRN'#9+p.name
+ +': PROC');
+ else
+ currentasmlist.AsmWriteln(#9'EXTRN'#9+p.name);
+ end;
+ end;
+ end;
+
+ procedure tx86IntelAssembler.WriteExternals;
+ begin
+ currentasmlist:=self;
+ objectlibrary.symbolsearch.foreach_static(@writeexternal,nil);
+ end;
+
+
+ function tx86intelassembler.DoAssemble : boolean;
+ var f : file;
+ begin
+ DoAssemble:=Inherited DoAssemble;
+ { masm does not seem to recognize specific extensions and uses .obj allways PM }
+ if (target_asm.id in [as_i386_masm,as_i386_wasm]) then
+ begin
+ if not(cs_asm_extern in aktglobalswitches) then
+ begin
+ if Not FileExists(objfile) and
+ FileExists(ForceExtension(objfile,'.obj')) then
+ begin
+ Assign(F,ForceExtension(objfile,'.obj'));
+ Rename(F,objfile);
+ end;
+ end
+ else
+ AsmRes.AddAsmCommand('mv',ForceExtension(objfile,'.obj')+' '+objfile,objfile);
+ end;
+ end;
+
+
+ procedure tx86IntelAssembler.WriteAsmList;
+ var
+ hal : tasmlist;
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Start writing intel-styled assembler output for '+current_module.mainsource^);
+{$endif}
+ LasTSecType:=sec_none;
+ if target_asm.id<>as_x86_64_masm then
+ begin
+ AsmWriteLn(#9'.386p');
+ { masm 6.11 does not seem to like LOCALS PM }
+ if (target_asm.id = as_i386_tasm) then
+ begin
+ AsmWriteLn(#9'LOCALS '+target_asm.labelprefix);
+ end;
+ AsmWriteLn('DGROUP'#9'GROUP'#9'_BSS,_DATA');
+ AsmWriteLn(#9'ASSUME'#9'CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP');
+ AsmLn;
+ end;
+
+ WriteExternals;
+
+ for hal:=low(Tasmlist) to high(Tasmlist) do
+ begin
+ AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
+ writetree(asmlist[hal]);
+ AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
+ end;
+
+ AsmWriteLn(#9'END');
+ AsmLn;
+
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Done writing intel-styled assembler output for '+current_module.mainsource^);
+{$endif EXTDEBUG}
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_i386_tasm_info : tasminfo =
+ (
+ id : as_i386_tasm;
+ idtxt : 'TASM';
+ asmbin : 'tasm';
+ asmcmd : '/m2 /ml $ASM $OBJ';
+ supported_target : system_any; { what should I write here ?? }
+ flags : [af_allowdirect,af_needar,af_labelprefix_only_inside_procedure];
+ labelprefix : '@@';
+ comment : '; ';
+ );
+
+ as_i386_masm_info : tasminfo =
+ (
+ id : as_i386_masm;
+ idtxt : 'MASM';
+ asmbin : 'masm';
+ asmcmd : '/c /Cp $ASM /Fo$OBJ';
+ supported_target : system_any; { what should I write here ?? }
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '@@';
+ comment : '; ';
+ );
+
+ as_i386_wasm_info : tasminfo =
+ (
+ id : as_i386_wasm;
+ idtxt : 'WASM';
+ asmbin : 'wasm';
+ asmcmd : '$ASM -6s -fp6 -ms -zq -Fo=$OBJ';
+ supported_target : system_any; { what should I write here ?? }
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '@@';
+ comment : '; ';
+ );
+
+ as_x86_64_masm_info : tasminfo =
+ (
+ id : as_x86_64_masm;
+ idtxt : 'MASM';
+ asmbin : 'ml64';
+ asmcmd : '/c /Cp $ASM /Fo$OBJ';
+ supported_target : system_any; { what should I write here ?? }
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '@@';
+ comment : '; ';
+ );
+
+initialization
+{$ifdef x86_64}
+ RegisterAssembler(as_x86_64_masm_info,tx86IntelAssembler);
+{$endif x86_64}
+{$ifdef i386}
+ RegisterAssembler(as_i386_tasm_info,tx86IntelAssembler);
+ RegisterAssembler(as_i386_masm_info,tx86IntelAssembler);
+ RegisterAssembler(as_i386_wasm_info,tx86IntelAssembler);
+{$endif i386}
+end.
diff --git a/compiler/x86/cga.pas b/compiler/x86/cga.pas
new file mode 100644
index 0000000000..3be659cebf
--- /dev/null
+++ b/compiler/x86/cga.pas
@@ -0,0 +1,128 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Helper routines for the i386 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 cga;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cpuinfo,cpubase,cgbase,cgutils,
+ symconst,symtype,symdef,aasmbase,aasmtai,aasmcpu;
+
+ procedure emit_none(i : tasmop;s : topsize);
+
+ procedure emit_reg(i : tasmop;s : topsize;reg : tregister);
+ procedure emit_ref(i : tasmop;s : topsize;const ref : treference);
+
+ procedure emit_const_reg(i : tasmop;s : topsize;c : aint;reg : tregister);
+ procedure emit_const_ref(i : tasmop;s : topsize;c : aint;const ref : treference);
+ procedure emit_ref_reg(i : tasmop;s : topsize;const ref : treference;reg : tregister);
+ procedure emit_reg_ref(i : tasmop;s : topsize;reg : tregister;const ref : treference);
+ procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
+
+ procedure emit_const_reg_reg(i : tasmop;s : topsize;c : longint;reg1,reg2 : tregister);
+ procedure emit_reg_reg_reg(i : tasmop;s : topsize;reg1,reg2,reg3 : tregister);
+
+
+ procedure emit_sym(i : tasmop;s : topsize;op : tasmsymbol);
+
+
+implementation
+
+ uses
+ cutils,
+ systems,verbose,
+ cgobj;
+
+
+{*****************************************************************************
+ Emit Assembler
+*****************************************************************************}
+
+ procedure emit_none(i : tasmop;s : topsize);
+ begin
+ exprasmList.concat(Taicpu.Op_none(i,s));
+ end;
+
+ procedure emit_reg(i : tasmop;s : topsize;reg : tregister);
+ begin
+ exprasmList.concat(Taicpu.Op_reg(i,s,reg));
+ end;
+
+ procedure emit_ref(i : tasmop;s : topsize;const ref : treference);
+ begin
+ exprasmList.concat(Taicpu.Op_ref(i,s,ref));
+ end;
+
+ procedure emit_const_reg(i : tasmop;s : topsize;c : aint;reg : tregister);
+ begin
+ exprasmList.concat(Taicpu.Op_const_reg(i,s,c,reg));
+ end;
+
+ procedure emit_const_ref(i : tasmop;s : topsize;c : aint;const ref : treference);
+ begin
+ exprasmList.concat(Taicpu.Op_const_ref(i,s,c,ref));
+ end;
+
+ procedure emit_ref_reg(i : tasmop;s : topsize;const ref : treference;reg : tregister);
+ begin
+ exprasmList.concat(Taicpu.Op_ref_reg(i,s,ref,reg));
+ end;
+
+ procedure emit_reg_ref(i : tasmop;s : topsize;reg : tregister;const ref : treference);
+ begin
+ exprasmList.concat(Taicpu.Op_reg_ref(i,s,reg,ref));
+ end;
+
+ procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
+
+ var instr:Taicpu;
+
+ begin
+ if not ((reg1=reg2) and (i=A_MOV)) then
+ begin
+ instr:=Taicpu.op_reg_reg(i,s,reg1,reg2);
+ exprasmlist.concat(instr);
+ if i=A_MOV then
+ cg.add_move_instruction(instr);
+ end;
+ end;
+
+ procedure emit_const_reg_reg(i : tasmop;s : topsize;c : longint;reg1,reg2 : tregister);
+ begin
+ exprasmList.concat(Taicpu.Op_const_reg_reg(i,s,c,reg1,reg2));
+ end;
+
+ procedure emit_reg_reg_reg(i : tasmop;s : topsize;reg1,reg2,reg3 : tregister);
+ begin
+ exprasmList.concat(Taicpu.Op_reg_reg_reg(i,s,reg1,reg2,reg3));
+ end;
+
+ procedure emit_sym(i : tasmop;s : topsize;op : tasmsymbol);
+ begin
+ exprasmList.concat(Taicpu.Op_sym(i,s,op));
+ end;
+
+end.
diff --git a/compiler/x86/cgx86.pas b/compiler/x86/cgx86.pas
new file mode 100644
index 0000000000..1fc58e11e4
--- /dev/null
+++ b/compiler/x86/cgx86.pas
@@ -0,0 +1,1835 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the common parts of the code generator for the i386 and the x86-64.
+
+ 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 common parts of the code generator for the i386 and the x86-64.
+}
+unit cgx86;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cgbase,cgutils,cgobj,
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,cpuinfo,rgobj,rgx86,rgcpu,
+ symconst,symtype;
+
+ type
+ tcgx86 = class(tcg)
+ rgfpu : Trgx86fpu;
+ procedure done_register_allocators;override;
+
+ function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
+ function getmmxregister(list:Taasmoutput):Tregister;
+ function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
+
+ procedure getcpuregister(list:Taasmoutput;r:Tregister);override;
+ procedure ungetcpuregister(list:Taasmoutput;r:Tregister);override;
+ procedure alloccpuregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
+ procedure dealloccpuregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
+ function uses_registers(rt:Tregistertype):boolean;override;
+ procedure add_reg_instruction(instr:Tai;r:tregister);override;
+ procedure dec_fpu_stack;
+ procedure inc_fpu_stack;
+
+ procedure a_call_name(list : taasmoutput;const s : string);override;
+ procedure a_call_reg(list : taasmoutput;reg : tregister);override;
+
+ procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
+ procedure a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; const ref: TReference); override;
+ procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+ procedure a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
+ procedure a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
+
+ procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister); override;
+
+ { move instructions }
+ procedure a_load_const_reg(list : taasmoutput; tosize: tcgsize; a : aint;reg : tregister);override;
+ procedure a_load_const_ref(list : taasmoutput; tosize: tcgsize; a : aint;const ref : treference);override;
+ procedure a_load_reg_ref(list : taasmoutput;fromsize,tosize: tcgsize; reg : tregister;const ref : treference);override;
+ procedure a_load_ref_reg(list : taasmoutput;fromsize,tosize: tcgsize;const ref : treference;reg : tregister);override;
+ procedure a_load_reg_reg(list : taasmoutput;fromsize,tosize: tcgsize;reg1,reg2 : tregister);override;
+ procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
+
+ { vector register move instructions }
+ procedure a_loadmm_reg_reg(list: taasmoutput; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_ref_reg(list: taasmoutput; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_reg_ref(list: taasmoutput; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle); override;
+ procedure a_opmm_ref_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
+ procedure a_opmm_reg_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle);override;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;const ref : treference;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+ procedure a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister; l : tasmlabel); override;
+ procedure a_cmp_reg_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg : tregister; const ref: treference; l : tasmlabel); override;
+
+ procedure a_jmp_name(list : taasmoutput;const s : string);override;
+ procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
+ procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
+
+ procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister); override;
+ procedure g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref: TReference); override;
+
+ procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);override;
+
+ { entry/exit code helpers }
+ procedure g_releasevaluepara_openarray(list : taasmoutput;const l:tlocation);override;
+ procedure g_profilecode(list : taasmoutput);override;
+ procedure g_stackpointer_alloc(list : taasmoutput;localsize : longint);override;
+ procedure g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);override;
+
+ procedure g_overflowcheck(list: taasmoutput; const l:tlocation;def:tdef);override;
+
+ procedure make_simple_ref(list:taasmoutput;var ref: treference);
+ protected
+ procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
+ procedure check_register_size(size:tcgsize;reg:tregister);
+
+ procedure opmm_loc_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;loc : tlocation;dst: tregister; shuffle : pmmshuffle);
+ private
+ procedure sizes2load(s1,s2 : tcgsize;var op: tasmop; var s3: topsize);
+
+ procedure floatload(list: taasmoutput; t : tcgsize;const ref : treference);
+ procedure floatstore(list: taasmoutput; t : tcgsize;const ref : treference);
+ procedure floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
+ procedure floatstoreops(t : tcgsize;var op : tasmop;var s : topsize);
+ end;
+
+ const
+{$ifdef x86_64}
+ TCGSize2OpSize: Array[tcgsize] of topsize =
+ (S_NO,S_B,S_W,S_L,S_Q,S_T,S_B,S_W,S_L,S_Q,S_Q,
+ S_FS,S_FL,S_FX,S_IQ,S_FXX,
+ S_NO,S_NO,S_NO,S_MD,S_T,
+ S_NO,S_NO,S_NO,S_NO,S_T);
+{$else x86_64}
+ TCGSize2OpSize: Array[tcgsize] of topsize =
+ (S_NO,S_B,S_W,S_L,S_L,S_T,S_B,S_W,S_L,S_L,S_L,
+ S_FS,S_FL,S_FX,S_IQ,S_FXX,
+ S_NO,S_NO,S_NO,S_MD,S_T,
+ S_NO,S_NO,S_NO,S_NO,S_T);
+{$endif x86_64}
+
+{$ifndef NOTARGETWIN}
+ winstackpagesize = 4096;
+{$endif NOTARGETWIN}
+
+
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ dwarf,
+ symdef,defutil,paramgr,procinfo;
+
+ const
+ TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_ADD,A_AND,A_DIV,
+ A_IDIV,A_MUL, A_IMUL, A_NEG,A_NOT,A_OR,
+ A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
+
+ TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
+ C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A);
+
+ procedure Tcgx86.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_MMREGISTER].free;
+ rg[R_MMXREGISTER].free;
+ rgfpu.free;
+ inherited done_register_allocators;
+ end;
+
+
+ function Tcgx86.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
+ begin
+ result:=rgfpu.getregisterfpu(list);
+ end;
+
+
+ function Tcgx86.getmmxregister(list:Taasmoutput):Tregister;
+ begin
+ if not assigned(rg[R_MMXREGISTER]) then
+ internalerror(2003121214);
+ result:=rg[R_MMXREGISTER].getregister(list,R_SUBNONE);
+ end;
+
+
+ function Tcgx86.getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;
+ begin
+ if not assigned(rg[R_MMREGISTER]) then
+ internalerror(2003121234);
+ case size of
+ OS_F64:
+ result:=rg[R_MMREGISTER].getregister(list,R_SUBMMD);
+ OS_F32:
+ result:=rg[R_MMREGISTER].getregister(list,R_SUBMMS);
+ else
+ internalerror(200506041);
+ end;
+ end;
+
+
+ procedure Tcgx86.getcpuregister(list:Taasmoutput;r:Tregister);
+ begin
+ if getregtype(r)=R_FPUREGISTER then
+ internalerror(2003121210)
+ else
+ inherited getcpuregister(list,r);
+ end;
+
+
+ procedure tcgx86.ungetcpuregister(list:Taasmoutput;r:Tregister);
+ begin
+ if getregtype(r)=R_FPUREGISTER then
+ rgfpu.ungetregisterfpu(list,r)
+ else
+ inherited ungetcpuregister(list,r);
+ end;
+
+
+ procedure Tcgx86.alloccpuregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
+ begin
+ if rt<>R_FPUREGISTER then
+ inherited alloccpuregisters(list,rt,r);
+ end;
+
+
+ procedure Tcgx86.dealloccpuregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
+ begin
+ if rt<>R_FPUREGISTER then
+ inherited dealloccpuregisters(list,rt,r);
+ end;
+
+
+ function Tcgx86.uses_registers(rt:Tregistertype):boolean;
+ begin
+ if rt=R_FPUREGISTER then
+ result:=false
+ else
+ result:=inherited uses_registers(rt);
+ end;
+
+
+ procedure tcgx86.add_reg_instruction(instr:Tai;r:tregister);
+ begin
+ if getregtype(r)<>R_FPUREGISTER then
+ inherited add_reg_instruction(instr,r);
+ end;
+
+
+ procedure tcgx86.dec_fpu_stack;
+ begin
+ dec(rgfpu.fpuvaroffset);
+ end;
+
+
+ procedure tcgx86.inc_fpu_stack;
+ begin
+ inc(rgfpu.fpuvaroffset);
+ end;
+
+
+{****************************************************************************
+ This is private property, keep out! :)
+****************************************************************************}
+
+ procedure tcgx86.sizes2load(s1,s2 : tcgsize; var op: tasmop; var s3: topsize);
+
+ begin
+ case s2 of
+ OS_8,OS_S8 :
+ if S1 in [OS_8,OS_S8] then
+ s3 := S_B
+ else
+ internalerror(200109221);
+ OS_16,OS_S16:
+ case s1 of
+ OS_8,OS_S8:
+ s3 := S_BW;
+ OS_16,OS_S16:
+ s3 := S_W;
+ else
+ internalerror(200109222);
+ end;
+ OS_32,OS_S32:
+ case s1 of
+ OS_8,OS_S8:
+ s3 := S_BL;
+ OS_16,OS_S16:
+ s3 := S_WL;
+ OS_32,OS_S32:
+ s3 := S_L;
+ else
+ internalerror(200109223);
+ end;
+{$ifdef x86_64}
+ OS_64,OS_S64:
+ case s1 of
+ OS_8:
+ s3 := S_BL;
+ OS_S8:
+ s3 := S_BQ;
+ OS_16:
+ s3 := S_WL;
+ OS_S16:
+ s3 := S_WQ;
+ OS_32:
+ s3 := S_L;
+ OS_S32:
+ s3 := S_LQ;
+ OS_64,OS_S64:
+ s3 := S_Q;
+ else
+ internalerror(200304302);
+ end;
+{$endif x86_64}
+ else
+ internalerror(200109227);
+ end;
+ if s3 in [S_B,S_W,S_L,S_Q] then
+ op := A_MOV
+ else if s1 in [OS_8,OS_16,OS_32,OS_64] then
+ op := A_MOVZX
+ else
+{$ifdef x86_64}
+ if s3 in [S_LQ] then
+ op := A_MOVSXD
+ else
+{$endif x86_64}
+ op := A_MOVSX;
+ end;
+
+
+ procedure tcgx86.make_simple_ref(list:taasmoutput;var ref: treference);
+ var
+ hreg : tregister;
+ href : treference;
+ begin
+{$ifdef x86_64}
+ { Only 32bit is allowed }
+ if ((ref.offset<low(longint)) or (ref.offset>high(longint))) then
+ begin
+ { Load constant value to register }
+ hreg:=GetAddressRegister(list);
+ list.concat(taicpu.op_const_reg(A_MOV,S_Q,ref.offset,hreg));
+ ref.offset:=0;
+ {if assigned(ref.symbol) then
+ begin
+ list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_Q,ref.symbol,0,hreg));
+ ref.symbol:=nil;
+ end;}
+ { Add register to reference }
+ if ref.index=NR_NO then
+ ref.index:=hreg
+ else
+ begin
+ if ref.scalefactor<>0 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,S_Q,ref.base,hreg));
+ ref.base:=hreg;
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,S_Q,ref.index,hreg));
+ ref.index:=hreg;
+ end;
+ end;
+ end;
+ if (cs_create_pic in aktmoduleswitches) and
+ assigned(ref.symbol) then
+ begin
+ reference_reset_symbol(href,ref.symbol,0);
+ hreg:=getaddressregister(list);
+ href.refaddr:=addr_pic;
+ href.base:=NR_RIP;
+ list.concat(taicpu.op_ref_reg(A_MOV,S_Q,href,hreg));
+
+ ref.symbol:=nil;
+
+ if ref.index=NR_NO then
+ begin
+ ref.index:=hreg;
+ ref.scalefactor:=1;
+ end
+ else if ref.base=NR_NO then
+ ref.base:=hreg
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,S_Q,ref.base,hreg));
+ ref.base:=hreg;
+ end;
+ end;
+{$else x86_64}
+ if (cs_create_pic in aktmoduleswitches) and
+ assigned(ref.symbol) then
+ begin
+ reference_reset_symbol(href,ref.symbol,0);
+ hreg:=getaddressregister(list);
+ href.refaddr:=addr_pic;
+ href.base:=current_procinfo.got;
+ list.concat(taicpu.op_ref_reg(A_MOV,S_L,href,hreg));
+
+ ref.symbol:=nil;
+
+ if ref.base=NR_NO then
+ ref.base:=hreg
+ else if ref.index=NR_NO then
+ begin
+ ref.index:=hreg;
+ ref.scalefactor:=1;
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,S_Q,ref.base,hreg));
+ ref.base:=hreg;
+ end;
+ end;
+{$endif x86_64}
+ end;
+
+
+ procedure tcgx86.floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
+ begin
+ case t of
+ OS_F32 :
+ begin
+ op:=A_FLD;
+ s:=S_FS;
+ end;
+ OS_F64 :
+ begin
+ op:=A_FLD;
+ s:=S_FL;
+ end;
+ OS_F80 :
+ begin
+ op:=A_FLD;
+ s:=S_FX;
+ end;
+ OS_C64 :
+ begin
+ op:=A_FILD;
+ s:=S_IQ;
+ end;
+ else
+ internalerror(200204041);
+ end;
+ end;
+
+
+ procedure tcgx86.floatload(list: taasmoutput; t : tcgsize;const ref : treference);
+
+ var
+ op : tasmop;
+ s : topsize;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ floatloadops(t,op,s);
+ list.concat(Taicpu.Op_ref(op,s,tmpref));
+ inc_fpu_stack;
+ end;
+
+
+ procedure tcgx86.floatstoreops(t : tcgsize;var op : tasmop;var s : topsize);
+
+ begin
+ case t of
+ OS_F32 :
+ begin
+ op:=A_FSTP;
+ s:=S_FS;
+ end;
+ OS_F64 :
+ begin
+ op:=A_FSTP;
+ s:=S_FL;
+ end;
+ OS_F80 :
+ begin
+ op:=A_FSTP;
+ s:=S_FX;
+ end;
+ OS_C64 :
+ begin
+ op:=A_FISTP;
+ s:=S_IQ;
+ end;
+ else
+ internalerror(200204042);
+ end;
+ end;
+
+
+ procedure tcgx86.floatstore(list: taasmoutput; t : tcgsize;const ref : treference);
+
+ var
+ op : tasmop;
+ s : topsize;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ floatstoreops(t,op,s);
+ list.concat(Taicpu.Op_ref(op,s,tmpref));
+ { storing non extended floats can cause a floating point overflow }
+ if t<>OS_F80 then
+ list.concat(Taicpu.Op_none(A_FWAIT,S_NO));
+ dec_fpu_stack;
+ end;
+
+
+ procedure tcgx86.check_register_size(size:tcgsize;reg:tregister);
+ begin
+ if TCGSize2OpSize[size]<>TCGSize2OpSize[reg_cgsize(reg)] then
+ internalerror(200306031);
+ end;
+
+
+{****************************************************************************
+ Assembler code
+****************************************************************************}
+
+ procedure tcgx86.a_jmp_name(list : taasmoutput;const s : string);
+ begin
+ list.concat(taicpu.op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
+ end;
+
+
+ procedure tcgx86.a_jmp_always(list : taasmoutput;l: tasmlabel);
+ begin
+ a_jmp_cond(list, OC_NONE, l);
+ end;
+
+
+ procedure tcgx86.a_call_name(list : taasmoutput;const s : string);
+ begin
+ list.concat(taicpu.op_sym(A_CALL,S_NO,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
+ end;
+
+
+ procedure tcgx86.a_call_reg(list : taasmoutput;reg : tregister);
+ begin
+ list.concat(taicpu.op_reg(A_CALL,S_NO,reg));
+ end;
+
+
+{********************** load instructions ********************}
+
+ procedure tcgx86.a_load_const_reg(list : taasmoutput; tosize: TCGSize; a : aint; reg : TRegister);
+
+ begin
+ check_register_size(tosize,reg);
+ { the optimizer will change it to "xor reg,reg" when loading zero, }
+ { no need to do it here too (JM) }
+ list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[tosize],a,reg))
+ end;
+
+
+ procedure tcgx86.a_load_const_ref(list : taasmoutput; tosize: tcgsize; a : aint;const ref : treference);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (tosize in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ a_load_const_ref(list,OS_32,longint(a and $ffffffff),tmpref);
+ inc(tmpref.offset,4);
+ a_load_const_ref(list,OS_32,longint(a shr 32),tmpref);
+ end
+ else
+{$endif x86_64}
+ list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[tosize],a,tmpref));
+ end;
+
+
+ procedure tcgx86.a_load_reg_ref(list : taasmoutput; fromsize,tosize: TCGSize; reg : tregister;const ref : treference);
+ var
+ op: tasmop;
+ s: topsize;
+ tmpsize : tcgsize;
+ tmpreg : tregister;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(fromsize,reg);
+ sizes2load(fromsize,tosize,op,s);
+ case s of
+{$ifdef x86_64}
+ S_BQ,S_WQ,S_LQ,
+{$endif x86_64}
+ S_BW,S_BL,S_WL :
+ begin
+ tmpreg:=getintregister(list,tosize);
+{$ifdef x86_64}
+ { zero extensions to 64 bit on the x86_64 are simply done by writting to the lower 32 bit
+ which clears the upper 64 bit too, so it could be that s is S_L while the reg is
+ 64 bit (FK) }
+ if s in [S_BL,S_WL,S_L] then
+ begin
+ tmpreg:=makeregsize(list,tmpreg,OS_32);
+ tmpsize:=OS_32;
+ end
+ else
+{$endif x86_64}
+ tmpsize:=tosize;
+ list.concat(taicpu.op_reg_reg(op,s,reg,tmpreg));
+ a_load_reg_ref(list,tmpsize,tosize,tmpreg,tmpref);
+ end;
+ else
+ list.concat(taicpu.op_reg_ref(op,s,reg,tmpref));
+ end;
+ end;
+
+
+ procedure tcgx86.a_load_ref_reg(list : taasmoutput;fromsize,tosize : tcgsize;const ref: treference;reg : tregister);
+ var
+ op: tasmop;
+ s: topsize;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(tosize,reg);
+ sizes2load(fromsize,tosize,op,s);
+ {$ifdef x86_64}
+ { zero extensions to 64 bit on the x86_64 are simply done by writting to the lower 32 bit
+ which clears the upper 64 bit too, so it could be that s is S_L while the reg is
+ 64 bit (FK) }
+ if s in [S_BL,S_WL,S_L] then
+ reg:=makeregsize(list,reg,OS_32);
+{$endif x86_64}
+ list.concat(taicpu.op_ref_reg(op,s,tmpref,reg));
+ end;
+
+
+ procedure tcgx86.a_load_reg_reg(list : taasmoutput;fromsize,tosize : tcgsize;reg1,reg2 : tregister);
+ var
+ op: tasmop;
+ s: topsize;
+ instr:Taicpu;
+ begin
+ check_register_size(fromsize,reg1);
+ check_register_size(tosize,reg2);
+ if tcgsize2size[fromsize]>tcgsize2size[tosize] then
+ begin
+ reg1:=makeregsize(list,reg1,tosize);
+ s:=tcgsize2opsize[tosize];
+ op:=A_MOV;
+ end
+ else
+ sizes2load(fromsize,tosize,op,s);
+{$ifdef x86_64}
+ { zero extensions to 64 bit on the x86_64 are simply done by writting to the lower 32 bit
+ which clears the upper 64 bit too, so it could be that s is S_L while the reg is
+ 64 bit (FK)
+ }
+ if s in [S_BL,S_WL,S_L] then
+ reg2:=makeregsize(list,reg2,OS_32);
+{$endif x86_64}
+ if (reg1<>reg2) then
+ begin
+ instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ list.concat(instr);
+ end;
+{$ifdef x86_64}
+ { avoid merging of registers and killing the zero extensions (FK) }
+ if (tosize in [OS_64,OS_S64]) and (s=S_L) then
+ list.concat(taicpu.op_const_reg(A_AND,S_L,$ffffffff,reg2));
+{$endif x86_64}
+ end;
+
+
+ procedure tcgx86.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
+ var
+ tmpref : treference;
+ begin
+ with ref do
+ begin
+ if (base=NR_NO) and (index=NR_NO) then
+ if assigned(ref.symbol) then
+ if cs_create_pic in aktmoduleswitches then
+ begin
+{$ifdef x86_64}
+ reference_reset_symbol(tmpref,ref.symbol,0);
+ tmpref.refaddr:=addr_pic;
+ tmpref.base:=NR_RIP;
+ list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r));
+{$else x86_64}
+ reference_reset_symbol(tmpref,ref.symbol,0);
+ tmpref.refaddr:=addr_pic;
+ tmpref.base:=current_procinfo.got;
+ list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r));
+{$endif x86_64}
+ end
+ else
+ begin
+ tmpref:=ref;
+ tmpref.refaddr:=ADDR_FULL;
+ list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r));
+ end
+ else
+ a_load_const_reg(list,OS_ADDR,offset,r)
+ else if (base=NR_NO) and (index<>NR_NO) and
+ (offset=0) and (scalefactor=0) and (symbol=nil) then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,index,r)
+ else if (base<>NR_NO) and (index=NR_NO) and
+ (offset=0) and (symbol=nil) then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r)
+ else
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
+ end;
+ if (segment<>NR_NO) then
+ if segment=NR_GS then
+ begin
+{$ifdef segment_threadvars}
+ {Convert thread local address to a process global addres
+ as we cannot handle far pointers.}
+ reference_reset_symbol(tmpref,objectlibrary.newasmsymbol(
+ '___fpc_threadvar_offset',AB_EXTERNAL,AT_DATA),0);
+ tmpref.segment:=NR_GS;
+ list.concat(Taicpu.op_ref_reg(A_ADD,tcgsize2opsize[OS_ADDR],tmpref,r));
+{$endif}
+ end
+ else
+ cgmessage(cg_e_cant_use_far_pointer_there);
+ end;
+ end;
+
+
+ { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
+ { R_ST means "the current value at the top of the fpu stack" (JM) }
+ procedure tcgx86.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
+
+ begin
+ if (reg1<>NR_ST) then
+ begin
+ list.concat(taicpu.op_reg(A_FLD,S_NO,rgfpu.correct_fpuregister(reg1,rgfpu.fpuvaroffset)));
+ inc_fpu_stack;
+ end;
+ if (reg2<>NR_ST) then
+ begin
+ list.concat(taicpu.op_reg(A_FSTP,S_NO,rgfpu.correct_fpuregister(reg2,rgfpu.fpuvaroffset)));
+ dec_fpu_stack;
+ end;
+ end;
+
+
+ procedure tcgx86.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
+ begin
+ floatload(list,size,ref);
+ if (reg<>NR_ST) then
+ a_loadfpu_reg_reg(list,size,NR_ST,reg);
+ end;
+
+
+ procedure tcgx86.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
+ begin
+ if reg<>NR_ST then
+ a_loadfpu_reg_reg(list,size,reg,NR_ST);
+ floatstore(list,size,ref);
+ end;
+
+
+ function get_scalar_mm_op(fromsize,tosize : tcgsize) : tasmop;
+ const
+ convertop : array[OS_F32..OS_F128,OS_F32..OS_F128] of tasmop = (
+ (A_MOVSS,A_CVTSS2SD,A_NONE,A_NONE,A_NONE),
+ (A_CVTSD2SS,A_MOVSD,A_NONE,A_NONE,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_MOVQ,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE));
+ begin
+ result:=convertop[fromsize,tosize];
+ if result=A_NONE then
+ internalerror(200312205);
+ end;
+
+
+ procedure tcgx86.a_loadmm_reg_reg(list: taasmoutput; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle);
+ var
+ instr : taicpu;
+ begin
+ if shuffle=nil then
+ begin
+ if fromsize=tosize then
+ instr:=taicpu.op_reg_reg(A_MOVAPS,S_NO,reg1,reg2)
+ else
+ internalerror(200312202);
+ end
+ else if shufflescalar(shuffle) then
+ instr:=taicpu.op_reg_reg(get_scalar_mm_op(fromsize,tosize),S_NO,reg1,reg2)
+ else
+ internalerror(200312201);
+ case get_scalar_mm_op(fromsize,tosize) of
+ A_MOVSS,
+ A_MOVSD,
+ A_MOVQ:
+ add_move_instruction(instr);
+ end;
+ list.concat(instr);
+ end;
+
+
+ procedure tcgx86.a_loadmm_ref_reg(list: taasmoutput; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ if shuffle=nil then
+ list.concat(taicpu.op_ref_reg(A_MOVQ,S_NO,tmpref,reg))
+ else if shufflescalar(shuffle) then
+ list.concat(taicpu.op_ref_reg(get_scalar_mm_op(fromsize,tosize),S_NO,tmpref,reg))
+ else
+ internalerror(200312252);
+ end;
+
+
+ procedure tcgx86.a_loadmm_reg_ref(list: taasmoutput; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle);
+ var
+ hreg : tregister;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ if shuffle=nil then
+ list.concat(taicpu.op_reg_ref(A_MOVQ,S_NO,reg,tmpref))
+ else if shufflescalar(shuffle) then
+ begin
+ if tosize<>fromsize then
+ begin
+ hreg:=getmmregister(list,tosize);
+ list.concat(taicpu.op_reg_reg(get_scalar_mm_op(fromsize,tosize),S_NO,reg,hreg));
+ list.concat(taicpu.op_reg_ref(get_scalar_mm_op(tosize,tosize),S_NO,hreg,tmpref));
+ end
+ else
+ list.concat(taicpu.op_reg_ref(get_scalar_mm_op(fromsize,tosize),S_NO,reg,tmpref));
+ end
+ else
+ internalerror(200312252);
+ end;
+
+
+ procedure tcgx86.a_opmm_ref_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle);
+ var
+ l : tlocation;
+ begin
+ l.loc:=LOC_REFERENCE;
+ l.reference:=ref;
+ l.size:=size;
+ opmm_loc_reg(list,op,size,l,reg,shuffle);
+ end;
+
+
+ procedure tcgx86.a_opmm_reg_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle);
+ var
+ l : tlocation;
+ begin
+ l.loc:=LOC_MMREGISTER;
+ l.register:=src;
+ l.size:=size;
+ opmm_loc_reg(list,op,size,l,dst,shuffle);
+ end;
+
+
+ procedure tcgx86.opmm_loc_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;loc : tlocation;dst: tregister; shuffle : pmmshuffle);
+ const
+ opmm2asmop : array[0..1,OS_F32..OS_F64,topcg] of tasmop = (
+ ( { scalar }
+ ( { OS_F32 }
+ A_NOP,A_ADDSS,A_NOP,A_DIVSS,A_NOP,A_NOP,A_MULSS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSS,A_NOP
+ ),
+ ( { OS_F64 }
+ A_NOP,A_ADDSD,A_NOP,A_DIVSD,A_NOP,A_NOP,A_MULSD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSD,A_NOP
+ )
+ ),
+ ( { vectorized/packed }
+ { because the logical packed single instructions have shorter op codes, we use always
+ these
+ }
+ ( { OS_F32 }
+ A_NOP,A_ADDPS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPS
+ ),
+ ( { OS_F64 }
+ A_NOP,A_ADDPD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPD
+ )
+ )
+ );
+
+ var
+ resultreg : tregister;
+ asmop : tasmop;
+ begin
+ { this is an internally used procedure so the parameters have
+ some constrains
+ }
+ if loc.size<>size then
+ internalerror(200312213);
+ resultreg:=dst;
+ { deshuffle }
+ //!!!
+ if (shuffle<>nil) and not(shufflescalar(shuffle)) then
+ begin
+ end
+ else if (shuffle=nil) then
+ asmop:=opmm2asmop[1,size,op]
+ else if shufflescalar(shuffle) then
+ begin
+ asmop:=opmm2asmop[0,size,op];
+ { no scalar operation available? }
+ if asmop=A_NOP then
+ begin
+ { do vectorized and shuffle finally }
+ //!!!
+ end;
+ end
+ else
+ internalerror(200312211);
+ if asmop=A_NOP then
+ internalerror(200312215);
+ case loc.loc of
+ LOC_CREFERENCE,LOC_REFERENCE:
+ list.concat(taicpu.op_ref_reg(asmop,S_NO,loc.reference,resultreg));
+ LOC_CMMREGISTER,LOC_MMREGISTER:
+ list.concat(taicpu.op_reg_reg(asmop,S_NO,loc.register,resultreg));
+ else
+ internalerror(200312214);
+ end;
+ { shuffle }
+ if resultreg<>dst then
+ begin
+ internalerror(200312212);
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
+
+ var
+ opcode : tasmop;
+ power : longint;
+{$ifdef x86_64}
+ tmpreg : tregister;
+{$endif x86_64}
+ begin
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_reg(list,op,size,tmpreg,reg);
+ exit;
+ end;
+{$endif x86_64}
+ check_register_size(size,reg);
+ case op of
+ OP_DIV, OP_IDIV:
+ begin
+ if ispowerof2(int64(a),power) then
+ begin
+ case op of
+ OP_DIV:
+ opcode := A_SHR;
+ OP_IDIV:
+ opcode := A_SAR;
+ end;
+ list.concat(taicpu.op_const_reg(opcode,TCgSize2OpSize[size],power,reg));
+ exit;
+ end;
+ { the rest should be handled specifically in the code }
+ { generator because of the silly register usage restraints }
+ internalerror(200109224);
+ end;
+ OP_MUL,OP_IMUL:
+ begin
+ if not(cs_check_overflow in aktlocalswitches) and
+ ispowerof2(int64(a),power) then
+ begin
+ list.concat(taicpu.op_const_reg(A_SHL,TCgSize2OpSize[size],power,reg));
+ exit;
+ end;
+ if op = OP_IMUL then
+ list.concat(taicpu.op_const_reg(A_IMUL,TCgSize2OpSize[size],a,reg))
+ else
+ { OP_MUL should be handled specifically in the code }
+ { generator because of the silly register usage restraints }
+ internalerror(200109225);
+ end;
+ OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
+ if not(cs_check_overflow in aktlocalswitches) and
+ (a = 1) and
+ (op in [OP_ADD,OP_SUB]) then
+ if op = OP_ADD then
+ list.concat(taicpu.op_reg(A_INC,TCgSize2OpSize[size],reg))
+ else
+ list.concat(taicpu.op_reg(A_DEC,TCgSize2OpSize[size],reg))
+ else if (a = 0) then
+ if (op <> OP_AND) then
+ exit
+ else
+ list.concat(taicpu.op_const_reg(A_MOV,TCgSize2OpSize[size],0,reg))
+ else if (aword(a) = high(aword)) and
+ (op in [OP_AND,OP_OR,OP_XOR]) then
+ begin
+ case op of
+ OP_AND:
+ exit;
+ OP_OR:
+ list.concat(taicpu.op_const_reg(A_MOV,TCgSize2OpSize[size],aint(high(aword)),reg));
+ OP_XOR:
+ list.concat(taicpu.op_reg(A_NOT,TCgSize2OpSize[size],reg));
+ end
+ end
+ else
+ list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],TCgSize2OpSize[size],a,reg));
+ OP_SHL,OP_SHR,OP_SAR:
+ begin
+ if (a and 31) <> 0 Then
+ list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,reg));
+ if (a shr 5) <> 0 Then
+ internalerror(68991);
+ end
+ else internalerror(68992);
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; const ref: TReference);
+ var
+ opcode: tasmop;
+ power: longint;
+{$ifdef x86_64}
+ tmpreg : tregister;
+{$endif x86_64}
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_ref(list,op,size,tmpreg,tmpref);
+ exit;
+ end;
+{$endif x86_64}
+ Case Op of
+ OP_DIV, OP_IDIV:
+ Begin
+ if ispowerof2(int64(a),power) then
+ begin
+ case op of
+ OP_DIV:
+ opcode := A_SHR;
+ OP_IDIV:
+ opcode := A_SAR;
+ end;
+ list.concat(taicpu.op_const_ref(opcode,
+ TCgSize2OpSize[size],power,tmpref));
+ exit;
+ end;
+ { the rest should be handled specifically in the code }
+ { generator because of the silly register usage restraints }
+ internalerror(200109231);
+ End;
+ OP_MUL,OP_IMUL:
+ begin
+ if not(cs_check_overflow in aktlocalswitches) and
+ ispowerof2(int64(a),power) then
+ begin
+ list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
+ power,tmpref));
+ exit;
+ end;
+ { can't multiply a memory location directly with a constant }
+ if op = OP_IMUL then
+ inherited a_op_const_ref(list,op,size,a,tmpref)
+ else
+ { OP_MUL should be handled specifically in the code }
+ { generator because of the silly register usage restraints }
+ internalerror(200109232);
+ end;
+ OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
+ if not(cs_check_overflow in aktlocalswitches) and
+ (a = 1) and
+ (op in [OP_ADD,OP_SUB]) then
+ if op = OP_ADD then
+ list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],tmpref))
+ else
+ list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],tmpref))
+ else if (a = 0) then
+ if (op <> OP_AND) then
+ exit
+ else
+ a_load_const_ref(list,size,0,tmpref)
+ else if (aword(a) = high(aword)) and
+ (op in [OP_AND,OP_OR,OP_XOR]) then
+ begin
+ case op of
+ OP_AND:
+ exit;
+ OP_OR:
+ list.concat(taicpu.op_const_ref(A_MOV,TCgSize2OpSize[size],aint(high(aword)),tmpref));
+ OP_XOR:
+ list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],tmpref));
+ end
+ end
+ else
+ list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
+ TCgSize2OpSize[size],a,tmpref));
+ OP_SHL,OP_SHR,OP_SAR:
+ begin
+ if (a and 31) <> 0 then
+ list.concat(taicpu.op_const_ref(
+ TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,tmpref));
+ if (a shr 5) <> 0 Then
+ internalerror(68991);
+ end
+ else internalerror(68992);
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+ var
+ dstsize: topsize;
+ instr:Taicpu;
+ begin
+ check_register_size(size,src);
+ check_register_size(size,dst);
+ dstsize := tcgsize2opsize[size];
+ case op of
+ OP_NEG,OP_NOT:
+ begin
+ if src<>dst then
+ a_load_reg_reg(list,size,size,src,dst);
+ list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst));
+ end;
+ OP_MUL,OP_DIV,OP_IDIV:
+ { special stuff, needs separate handling inside code }
+ { generator }
+ internalerror(200109233);
+ OP_SHR,OP_SHL,OP_SAR:
+ begin
+ getcpuregister(list,NR_CL);
+ a_load_reg_reg(list,OS_8,OS_8,makeregsize(list,src,OS_8),NR_CL);
+ list.concat(taicpu.op_reg_reg(Topcg2asmop[op],tcgsize2opsize[size],NR_CL,src));
+ ungetcpuregister(list,NR_CL);
+ end;
+ else
+ begin
+ if reg2opsize(src) <> dstsize then
+ internalerror(200109226);
+ instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
+ list.concat(instr);
+ end;
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(size,reg);
+ case op of
+ OP_NEG,OP_NOT,OP_IMUL:
+ begin
+ inherited a_op_ref_reg(list,op,size,tmpref,reg);
+ end;
+ OP_MUL,OP_DIV,OP_IDIV:
+ { special stuff, needs separate handling inside code }
+ { generator }
+ internalerror(200109239);
+ else
+ begin
+ reg := makeregsize(list,reg,size);
+ list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],tcgsize2opsize[size],tmpref,reg));
+ end;
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(size,reg);
+ case op of
+ OP_NEG,OP_NOT:
+ begin
+ if reg<>NR_NO then
+ internalerror(200109237);
+ list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],tmpref));
+ end;
+ OP_IMUL:
+ begin
+ { this one needs a load/imul/store, which is the default }
+ inherited a_op_ref_reg(list,op,size,tmpref,reg);
+ end;
+ OP_MUL,OP_DIV,OP_IDIV:
+ { special stuff, needs separate handling inside code }
+ { generator }
+ internalerror(200109238);
+ else
+ begin
+ list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],reg,tmpref));
+ end;
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_const_reg_reg(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister);
+ var
+ tmpref: treference;
+ power: longint;
+{$ifdef x86_64}
+ tmpreg : tregister;
+{$endif x86_64}
+ begin
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
+ exit;
+ end;
+{$endif x86_64}
+ check_register_size(size,src);
+ check_register_size(size,dst);
+ if tcgsize2size[size]<>tcgsize2size[OS_INT] then
+ begin
+ inherited a_op_const_reg_reg(list,op,size,a,src,dst);
+ exit;
+ end;
+ { if we get here, we have to do a 32 bit calculation, guaranteed }
+ case op of
+ OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
+ OP_SAR:
+ { can't do anything special for these }
+ inherited a_op_const_reg_reg(list,op,size,a,src,dst);
+ OP_IMUL:
+ begin
+ if not(cs_check_overflow in aktlocalswitches) and
+ ispowerof2(int64(a),power) then
+ { can be done with a shift }
+ begin
+ inherited a_op_const_reg_reg(list,op,size,a,src,dst);
+ exit;
+ end;
+ list.concat(taicpu.op_const_reg_reg(A_IMUL,tcgsize2opsize[size],a,src,dst));
+ end;
+ OP_ADD, OP_SUB:
+ if (a = 0) then
+ a_load_reg_reg(list,size,size,src,dst)
+ else
+ begin
+ reference_reset(tmpref);
+ tmpref.base := src;
+ tmpref.offset := longint(a);
+ if op = OP_SUB then
+ tmpref.offset := -tmpref.offset;
+ list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[size],tmpref,dst));
+ end
+ else internalerror(200112302);
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;size: tcgsize; src1, src2, dst: tregister);
+ var
+ tmpref: treference;
+ begin
+ check_register_size(size,src1);
+ check_register_size(size,src2);
+ check_register_size(size,dst);
+ if tcgsize2size[size]<>tcgsize2size[OS_INT] then
+ begin
+ inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+ exit;
+ end;
+ { if we get here, we have to do a 32 bit calculation, guaranteed }
+ Case Op of
+ OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
+ OP_SAR,OP_SUB,OP_NOT,OP_NEG:
+ { can't do anything special for these }
+ inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+ OP_IMUL:
+ list.concat(taicpu.op_reg_reg_reg(A_IMUL,tcgsize2opsize[size],src1,src2,dst));
+ OP_ADD:
+ begin
+ reference_reset(tmpref);
+ tmpref.base := src1;
+ tmpref.index := src2;
+ tmpref.scalefactor := 1;
+ list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[size],tmpref,dst));
+ end
+ else internalerror(200112303);
+ end;
+ end;
+
+{*************** compare instructructions ****************}
+
+ procedure tcgx86.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+ l : tasmlabel);
+
+{$ifdef x86_64}
+ var
+ tmpreg : tregister;
+{$endif x86_64}
+ begin
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
+ exit;
+ end;
+{$endif x86_64}
+ if (a = 0) then
+ list.concat(taicpu.op_reg_reg(A_TEST,tcgsize2opsize[size],reg,reg))
+ else
+ list.concat(taicpu.op_const_reg(A_CMP,tcgsize2opsize[size],a,reg));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;const ref : treference;
+ l : tasmlabel);
+
+ var
+{$ifdef x86_64}
+ tmpreg : tregister;
+{$endif x86_64}
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_cmp_reg_ref_label(list,size,cmp_op,tmpreg,tmpref,l);
+ exit;
+ end;
+{$endif x86_64}
+ list.concat(taicpu.op_const_ref(A_CMP,TCgSize2OpSize[size],a,tmpref));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;
+ reg1,reg2 : tregister;l : tasmlabel);
+
+ begin
+ check_register_size(size,reg1);
+ check_register_size(size,reg2);
+ list.concat(taicpu.op_reg_reg(A_CMP,TCgSize2OpSize[size],reg1,reg2));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister;l : tasmlabel);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(size,reg);
+ list.concat(taicpu.op_ref_reg(A_CMP,TCgSize2OpSize[size],tmpref,reg));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_cmp_reg_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg : tregister;const ref: treference; l : tasmlabel);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(size,reg);
+ list.concat(taicpu.op_reg_ref(A_CMP,TCgSize2OpSize[size],reg,tmpref));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ if cond=OC_None then
+ ai := Taicpu.Op_sym(A_JMP,S_NO,l)
+ else
+ begin
+ ai:=Taicpu.Op_sym(A_Jcc,S_NO,l);
+ ai.SetCondition(TOpCmp2AsmCond[cond]);
+ end;
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgx86.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai := Taicpu.op_sym(A_Jcc,S_NO,l);
+ ai.SetCondition(flags_to_cond(f));
+ ai.is_jmp := true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgx86.g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister);
+ var
+ ai : taicpu;
+ hreg : tregister;
+ begin
+ hreg:=makeregsize(list,reg,OS_8);
+ ai:=Taicpu.op_reg(A_SETcc,S_B,hreg);
+ ai.setcondition(flags_to_cond(f));
+ list.concat(ai);
+ if (reg<>hreg) then
+ a_load_reg_reg(list,OS_8,size,hreg,reg);
+ end;
+
+
+ procedure tcgx86.g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref: TReference);
+ var
+ ai : taicpu;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ if not(size in [OS_8,OS_S8]) then
+ a_load_const_ref(list,size,0,tmpref);
+ ai:=Taicpu.op_ref(A_SETcc,S_B,tmpref);
+ ai.setcondition(flags_to_cond(f));
+ list.concat(ai);
+ end;
+
+
+{ ************* concatcopy ************ }
+
+ procedure Tcgx86.g_concatcopy(list:Taasmoutput;const source,dest:Treference;len:aint);
+
+ const
+{$ifdef cpu64bit}
+ REGCX=NR_RCX;
+ REGSI=NR_RSI;
+ REGDI=NR_RDI;
+{$else cpu64bit}
+ REGCX=NR_ECX;
+ REGSI=NR_ESI;
+ REGDI=NR_EDI;
+{$endif cpu64bit}
+
+ type copymode=(copy_move,copy_mmx,copy_string);
+
+ var srcref,dstref:Treference;
+ r,r0,r1,r2,r3:Tregister;
+ helpsize:aint;
+ copysize:byte;
+ cgsize:Tcgsize;
+ cm:copymode;
+
+ begin
+ cm:=copy_move;
+ helpsize:=12;
+ if cs_littlesize in aktglobalswitches then
+ helpsize:=8;
+ if (cs_mmx in aktlocalswitches) and
+ not(pi_uses_fpu in current_procinfo.flags) and
+ ((len=8) or (len=16) or (len=24) or (len=32)) then
+ cm:=copy_mmx;
+ if (len>helpsize) then
+ cm:=copy_string;
+ if (cs_littlesize in aktglobalswitches) and
+ not((len<=16) and (cm=copy_mmx)) then
+ cm:=copy_string;
+ case cm of
+ copy_move:
+ begin
+ dstref:=dest;
+ srcref:=source;
+ copysize:=sizeof(aint);
+ cgsize:=int_cgsize(copysize);
+ while len<>0 do
+ begin
+ if len<2 then
+ begin
+ copysize:=1;
+ cgsize:=OS_8;
+ end
+ else if len<4 then
+ begin
+ copysize:=2;
+ cgsize:=OS_16;
+ end
+ else if len<8 then
+ begin
+ copysize:=4;
+ cgsize:=OS_32;
+ end;
+ dec(len,copysize);
+ r:=getintregister(list,cgsize);
+ a_load_ref_reg(list,cgsize,cgsize,srcref,r);
+ a_load_reg_ref(list,cgsize,cgsize,r,dstref);
+ inc(srcref.offset,copysize);
+ inc(dstref.offset,copysize);
+ end;
+ end;
+ copy_mmx:
+ begin
+ dstref:=dest;
+ srcref:=source;
+ r0:=getmmxregister(list);
+ a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r0,nil);
+ if len>=16 then
+ begin
+ inc(srcref.offset,8);
+ r1:=getmmxregister(list);
+ a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r1,nil);
+ end;
+ if len>=24 then
+ begin
+ inc(srcref.offset,8);
+ r2:=getmmxregister(list);
+ a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r2,nil);
+ end;
+ if len>=32 then
+ begin
+ inc(srcref.offset,8);
+ r3:=getmmxregister(list);
+ a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r3,nil);
+ end;
+ a_loadmm_reg_ref(list,OS_M64,OS_M64,r0,dstref,nil);
+ if len>=16 then
+ begin
+ inc(dstref.offset,8);
+ a_loadmm_reg_ref(list,OS_M64,OS_M64,r1,dstref,nil);
+ end;
+ if len>=24 then
+ begin
+ inc(dstref.offset,8);
+ a_loadmm_reg_ref(list,OS_M64,OS_M64,r2,dstref,nil);
+ end;
+ if len>=32 then
+ begin
+ inc(dstref.offset,8);
+ a_loadmm_reg_ref(list,OS_M64,OS_M64,r3,dstref,nil);
+ end;
+ end
+ else {copy_string, should be a good fallback in case of unhandled}
+ begin
+ getcpuregister(list,REGDI);
+ a_loadaddr_ref_reg(list,dest,REGDI);
+ getcpuregister(list,REGSI);
+ a_loadaddr_ref_reg(list,source,REGSI);
+
+ getcpuregister(list,REGCX);
+
+ list.concat(Taicpu.op_none(A_CLD,S_NO));
+ if cs_littlesize in aktglobalswitches then
+ begin
+ a_load_const_reg(list,OS_INT,len,REGCX);
+ list.concat(Taicpu.op_none(A_REP,S_NO));
+ list.concat(Taicpu.op_none(A_MOVSB,S_NO));
+ end
+ else
+ begin
+ helpsize:=len div sizeof(aint);
+ len:=len mod sizeof(aint);
+ if helpsize>1 then
+ begin
+ a_load_const_reg(list,OS_INT,helpsize,REGCX);
+ list.concat(Taicpu.op_none(A_REP,S_NO));
+ end;
+ if helpsize>0 then
+ begin
+{$ifdef cpu64bit}
+ if sizeof(aint)=8 then
+ list.concat(Taicpu.op_none(A_MOVSQ,S_NO))
+ else
+{$endif cpu64bit}
+ list.concat(Taicpu.op_none(A_MOVSD,S_NO));
+ end;
+ if len>=4 then
+ begin
+ dec(len,4);
+ list.concat(Taicpu.op_none(A_MOVSD,S_NO));
+ end;
+ if len>=2 then
+ begin
+ dec(len,2);
+ list.concat(Taicpu.op_none(A_MOVSW,S_NO));
+ end;
+ if len=1 then
+ list.concat(Taicpu.op_none(A_MOVSB,S_NO));
+ end;
+ ungetcpuregister(list,REGCX);
+ ungetcpuregister(list,REGSI);
+ ungetcpuregister(list,REGDI);
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ Entry/Exit Code Helpers
+****************************************************************************}
+
+ procedure tcgx86.g_releasevaluepara_openarray(list : taasmoutput;const l:tlocation);
+ begin
+ { Nothing to release }
+ end;
+
+
+ procedure tcgx86.g_profilecode(list : taasmoutput);
+
+ var
+ pl : tasmlabel;
+ mcountprefix : String[4];
+
+ begin
+ case target_info.system of
+ {$ifndef NOTARGETWIN}
+ system_i386_win32,
+ {$endif}
+ system_i386_freebsd,
+ system_i386_netbsd,
+// system_i386_openbsd,
+ system_i386_wdosx :
+ begin
+ Case target_info.system Of
+ system_i386_freebsd : mcountprefix:='.';
+ system_i386_netbsd : mcountprefix:='__';
+// system_i386_openbsd : mcountprefix:='.';
+ else
+ mcountPrefix:='';
+ end;
+ objectlibrary.getaddrlabel(pl);
+ new_section(list,sec_data,lower(current_procinfo.procdef.mangledname),sizeof(aint));
+ list.concat(Tai_label.Create(pl));
+ list.concat(Tai_const.Create_32bit(0));
+ new_section(list,sec_code,lower(current_procinfo.procdef.mangledname),0);
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EDX));
+ list.concat(Taicpu.Op_sym_ofs_reg(A_MOV,S_L,pl,0,NR_EDX));
+ a_call_name(list,target_info.Cprefix+mcountprefix+'mcount');
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDX));
+ end;
+
+ system_i386_linux:
+ a_call_name(list,target_info.Cprefix+'mcount');
+
+ system_i386_go32v2,system_i386_watcom:
+ begin
+ a_call_name(list,'MCOUNT');
+ end;
+ system_x86_64_linux:
+ begin
+ a_call_name(list,'mcount');
+ end;
+ end;
+ end;
+
+
+ procedure tcgx86.g_stackpointer_alloc(list : taasmoutput;localsize : longint);
+{$ifdef i386}
+{$ifndef NOTARGETWIN}
+ var
+ href : treference;
+ i : integer;
+ again : tasmlabel;
+{$endif NOTARGETWIN}
+{$endif i386}
+ begin
+ if localsize>0 then
+ begin
+{$ifdef i386}
+{$ifndef NOTARGETWIN}
+ { windows guards only a few pages for stack growing, }
+ { so we have to access every page first }
+ if (target_info.system=system_i386_win32) and
+ (localsize>=winstackpagesize) then
+ begin
+ if localsize div winstackpagesize<=5 then
+ begin
+ list.concat(Taicpu.Op_const_reg(A_SUB,S_L,localsize-4,NR_ESP));
+ for i:=1 to localsize div winstackpagesize do
+ begin
+ reference_reset_base(href,NR_ESP,localsize-i*winstackpagesize);
+ list.concat(Taicpu.op_const_ref(A_MOV,S_L,0,href));
+ end;
+ list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EAX));
+ end
+ else
+ begin
+ objectlibrary.getjumplabel(again);
+ getcpuregister(list,NR_EDI);
+ list.concat(Taicpu.op_const_reg(A_MOV,S_L,localsize div winstackpagesize,NR_EDI));
+ a_label(list,again);
+ list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,NR_ESP));
+ list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EAX));
+ list.concat(Taicpu.op_reg(A_DEC,S_L,NR_EDI));
+ a_jmp_cond(list,OC_NE,again);
+ ungetcpuregister(list,NR_EDI);
+ list.concat(Taicpu.op_const_reg(A_SUB,S_L,localsize mod winstackpagesize,NR_ESP));
+ end
+ end
+ else
+{$endif NOTARGETWIN}
+{$endif i386}
+ list.concat(Taicpu.Op_const_reg(A_SUB,tcgsize2opsize[OS_ADDR],localsize,NR_STACK_POINTER_REG));
+ end;
+ end;
+
+
+ procedure tcgx86.g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);
+ begin
+{$ifdef i386}
+ { interrupt support for i386 }
+ if (po_interrupt in current_procinfo.procdef.procoptions) then
+ begin
+ { .... also the segment registers }
+ list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_GS));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_FS));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_ES));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_DS));
+ { save the registers of an interrupt procedure }
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EDI));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_ESI));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EDX));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_ECX));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EBX));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EAX));
+ end;
+{$endif i386}
+
+ { save old framepointer }
+ if not nostackframe then
+ begin
+ if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+ CGmessage(cg_d_stackframe_omited)
+ else
+ begin
+ list.concat(tai_regalloc.alloc(NR_FRAME_POINTER_REG,nil));
+ include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
+ list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG));
+ { Return address and FP are both on stack }
+ dwarfcfi.cfa_def_cfa_offset(list,2*sizeof(aint));
+ dwarfcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*sizeof(aint)));
+ list.concat(Taicpu.op_reg_reg(A_MOV,tcgsize2opsize[OS_ADDR],NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG));
+ dwarfcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG);
+ end;
+
+ { allocate stackframe space }
+ if localsize<>0 then
+ begin
+ cg.g_stackpointer_alloc(list,localsize);
+ end;
+ end;
+
+ { allocate PIC register }
+ if (cs_create_pic in aktmoduleswitches) and
+ (tf_pic_uses_got in target_info.flags) then
+ begin
+ a_call_name(list,'FPC_GETEIPINEBX');
+ list.concat(taicpu.op_sym_ofs_reg(A_ADD,tcgsize2opsize[OS_ADDR],objectlibrary.newasmsymbol('_GLOBAL_OFFSET_TABLE_',AB_EXTERNAL,AT_DATA),0,NR_PIC_OFFSET_REG));
+ list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
+ current_procinfo.got:=NR_PIC_OFFSET_REG;
+ end;
+ end;
+
+
+ { produces if necessary overflowcode }
+ procedure tcgx86.g_overflowcheck(list: taasmoutput; const l:tlocation;def:tdef);
+ var
+ hl : tasmlabel;
+ ai : taicpu;
+ cond : TAsmCond;
+ begin
+ if not(cs_check_overflow in aktlocalswitches) then
+ exit;
+ objectlibrary.getjumplabel(hl);
+ if not ((def.deftype=pointerdef) or
+ ((def.deftype=orddef) and
+ (torddef(def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
+ bool8bit,bool16bit,bool32bit]))) then
+ cond:=C_NO
+ else
+ cond:=C_NB;
+ ai:=Taicpu.Op_Sym(A_Jcc,S_NO,hl);
+ ai.SetCondition(cond);
+ ai.is_jmp:=true;
+ list.concat(ai);
+
+ a_call_name(list,'FPC_OVERFLOW');
+ a_label(list,hl);
+ end;
+
+
+end.
diff --git a/compiler/x86/cpubase.pas b/compiler/x86/cpubase.pas
new file mode 100644
index 0000000000..78d0ea11d6
--- /dev/null
+++ b/compiler/x86/cpubase.pas
@@ -0,0 +1,471 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Contains the base types for the i386 and x86-64 architecture
+
+ * 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.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+ enumerations of registers, opcodes, sizes, and other
+ such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cutils,cclasses,
+ globtype,
+ cgbase
+ ;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+{$ifdef x86_64}
+ TAsmOp={$i x8664op.inc}
+{$else x86_64}
+ TAsmOp={$i i386op.inc}
+{$endif x86_64}
+
+ { This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ const
+ { First value of opcode enumeration }
+ firstop = low(tasmop);
+ { Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ const
+ { Invalid register number }
+ RS_INVALID = $ff;
+
+ { Integer Super registers }
+ RS_RAX = $00; {EAX}
+ RS_RCX = $01; {ECX}
+ RS_RDX = $02; {EDX}
+ RS_RBX = $03; {EBX}
+ RS_RSI = $04; {ESI}
+ RS_RDI = $05; {EDI}
+ RS_RBP = $06; {EBP}
+ RS_RSP = $07; {ESP}
+ RS_R8 = $08; {R8}
+ RS_R9 = $09; {R9}
+ RS_R10 = $0a; {R10}
+ RS_R11 = $0b; {R11}
+ RS_R12 = $0c; {R12}
+ RS_R13 = $0d; {R13}
+ RS_R14 = $0e; {R14}
+ RS_R15 = $0f; {R15}
+ { create aliases to allow code sharing between x86-64 and i386 }
+ RS_EAX = RS_RAX;
+ RS_EBX = RS_RBX;
+ RS_ECX = RS_RCX;
+ RS_EDX = RS_RDX;
+ RS_ESI = RS_RSI;
+ RS_EDI = RS_RDI;
+ RS_EBP = RS_RBP;
+ RS_ESP = RS_RSP;
+
+ { Number of first imaginary register }
+ first_int_imreg = $10;
+
+ { Float Super registers }
+ RS_ST0 = $00;
+ RS_ST1 = $01;
+ RS_ST2 = $02;
+ RS_ST3 = $03;
+ RS_ST4 = $04;
+ RS_ST5 = $05;
+ RS_ST6 = $06;
+ RS_ST7 = $07;
+
+ { Number of first imaginary register }
+ first_fpu_imreg = $08;
+
+ { MM Super registers }
+ RS_XMM0 = $00;
+ RS_XMM1 = $01;
+ RS_XMM2 = $02;
+ RS_XMM3 = $03;
+ RS_XMM4 = $04;
+ RS_XMM5 = $05;
+ RS_XMM6 = $06;
+ RS_XMM7 = $07;
+ RS_XMM8 = $08;
+ RS_XMM9 = $09;
+ RS_XMM10 = $0a;
+ RS_XMM11 = $0b;
+ RS_XMM12 = $0c;
+ RS_XMM13 = $0d;
+ RS_XMM14 = $0e;
+ RS_XMM15 = $0f;
+
+ { Number of first imaginary register }
+{$ifdef x86_64}
+ first_mm_imreg = $10;
+{$else x86_64}
+ first_mm_imreg = $08;
+{$endif x86_64}
+
+ { The subregister that specifies the entire register }
+{$ifdef x86_64}
+ R_SUBWHOLE = R_SUBQ; {Hammer}
+{$else x86_64}
+ R_SUBWHOLE = R_SUBD; {i386}
+{$endif x86_64}
+
+ { Available Registers }
+{$ifdef x86_64}
+ {$i r8664con.inc}
+{$else x86_64}
+ {$i r386con.inc}
+{$endif x86_64}
+
+ type
+ { Number of registers used for indexing in tables }
+{$ifdef x86_64}
+ tregisterindex=0..{$i r8664nor.inc}-1;
+{$else x86_64}
+ tregisterindex=0..{$i r386nor.inc}-1;
+{$endif x86_64}
+
+ const
+{$warning TODO Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+{$ifdef x86_64}
+ {$i r8664num.inc}
+{$else x86_64}
+ {$i r386num.inc}
+{$endif x86_64}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+{$ifdef x86_64}
+ {$i r8664stab.inc}
+{$else x86_64}
+ {$i r386stab.inc}
+{$endif x86_64}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+{$ifdef x86_64}
+ {$i r8664dwrf.inc}
+{$else x86_64}
+ {$i r386dwrf.inc}
+{$endif x86_64}
+ );
+
+ type
+ totherregisterset = set of tregisterindex;
+
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
+ C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
+ C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
+ );
+
+ const
+ cond2str:array[TAsmCond] of string[3]=('',
+ 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
+ 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
+ 'ns','nz','o','p','pe','po','s','z'
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (F_E,F_NE,F_G,F_L,F_GE,F_LE,F_C,F_NC,
+ F_A,F_AE,F_B,F_BE,
+ F_S,F_NS,F_O,F_NO);
+
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ { declare aliases }
+ LOC_SSEREGISTER = LOC_MMREGISTER;
+ LOC_CSSEREGISTER = LOC_CMMREGISTER;
+
+ max_operands = 3;
+ maxfpuregs = 8;
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ {$i cpubase.inc}
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ function reg2opsize(r:Tregister):topsize;
+ function reg_cgsize(const reg: tregister): tcgsize;
+ function is_calljmp(o:tasmop):boolean;
+ procedure inverse_flags(var f: TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function is_segment_reg(r:tregister):boolean;
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ 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}
+
+implementation
+
+ uses
+ rgbase,verbose;
+
+ const
+ {$ifdef x86_64}
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i r8664std.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i r8664rni.inc}
+ );
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r8664sri.inc}
+ );
+ {$else x86_64}
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i r386std.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i r386rni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r386sri.inc}
+ );
+ {$endif x86_64}
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+ begin
+ case s of
+ OS_8,OS_S8:
+ cgsize2subreg:=R_SUBL;
+ OS_16,OS_S16:
+ cgsize2subreg:=R_SUBW;
+ OS_32,OS_S32:
+ cgsize2subreg:=R_SUBD;
+ OS_64,OS_S64:
+ cgsize2subreg:=R_SUBQ;
+ OS_M64:
+ cgsize2subreg:=R_SUBNONE;
+ OS_F32,OS_F64,OS_C64,
+ OS_M128,OS_MS128:
+ cgsize2subreg:=R_SUBWHOLE;
+ else
+ internalerror(200301231);
+ end;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ const subreg2cgsize:array[Tsubregister] of Tcgsize =
+ (OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO,OS_NO,OS_F32,OS_F64);
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ reg_cgsize:=subreg2cgsize[getsubreg(reg)];
+ R_FPUREGISTER :
+ reg_cgsize:=OS_F80;
+ R_MMXREGISTER:
+ reg_cgsize:=OS_M64;
+ R_MMREGISTER:
+ reg_cgsize:=subreg2cgsize[getsubreg(reg)];
+ R_SPECIALREGISTER :
+ case reg of
+ NR_CS,NR_DS,NR_ES,NR_SS,NR_FS,NR_GS:
+ reg_cgsize:=OS_16
+ else
+ reg_cgsize:=OS_32
+ end
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function reg2opsize(r:Tregister):topsize;
+ const
+ subreg2opsize : array[tsubregister] of topsize =
+ (S_NO,S_B,S_B,S_W,S_L,S_Q,S_NO,S_NO,S_NO,S_NO,S_NO);
+ begin
+ reg2opsize:=S_L;
+ case getregtype(r) of
+ R_INTREGISTER :
+ reg2opsize:=subreg2opsize[getsubreg(r)];
+ R_FPUREGISTER :
+ reg2opsize:=S_FL;
+ R_MMXREGISTER,
+ R_MMREGISTER :
+ reg2opsize:=S_MD;
+ R_SPECIALREGISTER :
+ begin
+ case r of
+ NR_CS,NR_DS,NR_ES,
+ NR_SS,NR_FS,NR_GS :
+ reg2opsize:=S_W;
+ end;
+ end;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ case o of
+ A_CALL,
+ A_JCXZ,
+ A_JECXZ,
+ A_JMP,
+ A_LOOP,
+ A_LOOPE,
+ A_LOOPNE,
+ A_LOOPNZ,
+ A_LOOPZ,
+ A_Jcc :
+ is_calljmp:=true;
+ else
+ is_calljmp:=false;
+ end;
+ end;
+
+
+ procedure inverse_flags(var f: TResFlags);
+ const
+ inv_flags: array[TResFlags] of TResFlags =
+ (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_NC,F_C,
+ F_BE,F_B,F_AE,F_A,
+ F_NS,F_S,F_NO,F_O);
+ begin
+ f:=inv_flags[f];
+ end;
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const
+ flags_2_cond : array[TResFlags] of TAsmCond =
+ (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE,C_S,C_NS,C_O,C_NO);
+ begin
+ result := flags_2_cond[f];
+ end;
+
+
+ function is_segment_reg(r:tregister):boolean;
+ begin
+ result:=false;
+ case r of
+ NR_CS,NR_DS,NR_ES,
+ NR_SS,NR_FS,NR_GS :
+ result:=true;
+ end;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ var
+ hr : tregister;
+ begin
+ { for the name the sub reg doesn't matter }
+ hr:=r;
+ case getsubreg(hr) of
+ R_SUBMMS,R_SUBMMD:
+ setsubreg(hr,R_SUBNONE);
+ end;
+ result:=findreg_by_number_table(hr,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse: array[TAsmCond] of TAsmCond=(C_None,
+ C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
+ C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
+ C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
+ );
+ begin
+ result := inverse[c];
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+
+
+end.
diff --git a/compiler/x86/itcpugas.pas b/compiler/x86/itcpugas.pas
new file mode 100644
index 0000000000..88ba80d8fc
--- /dev/null
+++ b/compiler/x86/itcpugas.pas
@@ -0,0 +1,138 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the i386 AT&T instruction tables
+
+ 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 itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cgbase,cpubase;
+
+ type
+ TAttSuffix = (AttSufNONE,AttSufINT,AttSufFPU,AttSufFPUint);
+
+ const
+{$ifdef x86_64}
+ {x86att.inc contains the name for each x86-64 mnemonic}
+ gas_op2str:op2strtable={$i x8664att.inc}
+ gas_needsuffix:array[tasmop] of TAttSuffix={$i x8664ats.inc}
+{$else x86_64}
+ {x86att.inc contains the name for each i386 mnemonic}
+ gas_op2str:op2strtable={$i i386att.inc}
+ gas_needsuffix:array[tasmop] of TAttSuffix={$i i386atts.inc}
+{$endif x86_64}
+
+{$ifdef x86_64}
+ gas_opsize2str : array[topsize] of string[2] = ('',
+ 'b','w','l','q','bw','bl','wl','bq','wq','lq',
+ 's','l','q',
+ 's','l','t','v','x',
+ 'd',
+ '','','',
+ 't',
+ ''
+ );
+{$else x86_64}
+ gas_opsize2str : array[topsize] of string[2] = ('',
+ 'b','w','l','q','bw','bl','wl',
+ 's','l','q',
+ 's','l','t','v','',
+ 'd',
+ '','','',
+ 't',
+ ''
+ );
+{$endif x86_64}
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose;
+
+ const
+ {$ifdef x86_64}
+ att_regname_table : array[tregisterindex] of string[7] = (
+ {r8664att.inc contains the AT&T name of each register.}
+ {$i r8664att.inc}
+ );
+
+ att_regname_index : array[tregisterindex] of tregisterindex = (
+ {r8664ari.inc contains an index which sorts att_regname_table by
+ ATT name.}
+ {$i r8664ari.inc}
+ );
+ {$else x86_64}
+ att_regname_table : array[tregisterindex] of string[7] = (
+ {r386att.inc contains the AT&T name of each register.}
+ {$i r386att.inc}
+ );
+
+ att_regname_index : array[tregisterindex] of tregisterindex = (
+ {r386ari.inc contains an index which sorts att_regname_table by
+ ATT name.}
+ {$i r386ari.inc}
+ );
+ {$endif x86_64}
+
+ function findreg_by_attname(const s:string):byte;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (att_regname_table[att_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if att_regname_table[att_regname_index[p]]=s then
+ findreg_by_attname:=att_regname_index[p]
+ else
+ findreg_by_attname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_attname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=att_regname_table[p]
+ else
+ result:='%'+generic_regname(r);
+ end;
+
+end.
diff --git a/compiler/x86/itx86int.pas b/compiler/x86/itx86int.pas
new file mode 100644
index 0000000000..182938678d
--- /dev/null
+++ b/compiler/x86/itx86int.pas
@@ -0,0 +1,97 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the i386 AT&T instruction tables
+
+ 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 itx86int;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cgbase;
+
+ function masm_regnum_search(const s:string):Tregister;
+ function masm_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose,
+ cpubase;
+
+ const
+ {$ifdef x86_64}
+ int_regname_table : array[tregisterindex] of string[7] = (
+ {$i r8664int.inc}
+ );
+
+ int_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r8664iri.inc}
+ );
+ {$else x86_64}
+ int_regname_table : array[tregisterindex] of string[7] = (
+ {$i r386int.inc}
+ );
+
+ int_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r386iri.inc}
+ );
+ {$endif x86_64}
+
+
+ function findreg_by_intname(const s:string):byte;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (int_regname_table[int_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if int_regname_table[int_regname_index[p]]=s then
+ findreg_by_intname:=int_regname_index[p]
+ else
+ findreg_by_intname:=0;
+ end;
+
+
+ function masm_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_intname(s)];
+ end;
+
+
+ function masm_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=int_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/compiler/x86/nx86add.pas b/compiler/x86/nx86add.pas
new file mode 100644
index 0000000000..b678fe7c75
--- /dev/null
+++ b/compiler/x86/nx86add.pas
@@ -0,0 +1,1065 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Common code generation for add nodes on the i386 and x86
+
+ 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 nx86add;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase,
+ cpubase,
+ node,nadd,ncgadd;
+
+ type
+ tx86addnode = class(tcgaddnode)
+ protected
+ function getresflags(unsigned : boolean) : tresflags;
+ procedure left_must_be_reg(opsize:TCGSize;noswap:boolean);
+ procedure left_and_right_must_be_fpureg;
+ procedure emit_op_right_left(op:TAsmOp;opsize:TCgSize);
+ procedure emit_generic_code(op:TAsmOp;opsize:TCgSize;unsigned,extra_not,mboverflow:boolean);
+
+ procedure second_cmpfloatsse;
+ procedure second_addfloatsse;
+ procedure second_mul;virtual;abstract;
+ public
+ procedure second_addfloat;override;
+ procedure second_addsmallset;override;
+ procedure second_add64bit;override;
+ procedure second_addordinal;override;
+ procedure second_cmpfloat;override;
+ procedure second_cmpsmallset;override;
+ procedure second_cmp64bit;override;
+ procedure second_cmpordinal;override;
+{$ifdef SUPPORT_MMX}
+ procedure second_opmmxset;override;
+ procedure second_opmmx;override;
+{$endif SUPPORT_MMX}
+ end;
+
+
+ implementation
+
+ uses
+ globtype,globals,
+ verbose,cutils,
+ cpuinfo,
+ aasmbase,aasmtai,aasmcpu,
+ symconst,symdef,
+ cgobj,cgx86,cga,cgutils,
+ paramgr,tgobj,ncgutil,
+ ncon,nset,
+ defutil;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure tx86addnode.emit_generic_code(op:TAsmOp;opsize:TCGSize;unsigned,extra_not,mboverflow:boolean);
+ var
+ power : longint;
+ hl4 : tasmlabel;
+ r : Tregister;
+ begin
+ { at this point, left.location.loc should be LOC_REGISTER }
+ if right.location.loc=LOC_REGISTER then
+ begin
+ { right.location is a LOC_REGISTER }
+ { when swapped another result register }
+ if (nodetype=subn) and (nf_swaped in flags) then
+ begin
+ if extra_not then
+ emit_reg(A_NOT,TCGSize2Opsize[opsize],left.location.register);
+ emit_reg_reg(op,TCGSize2Opsize[opsize],left.location.register,right.location.register);
+ { newly swapped also set swapped flag }
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end
+ else
+ begin
+ if extra_not then
+ emit_reg(A_NOT,TCGSize2Opsize[opsize],right.location.register);
+ if (op=A_ADD) or (op=A_OR) or (op=A_AND) or (op=A_XOR) or (op=A_IMUL) then
+ location_swap(left.location,right.location);
+ emit_reg_reg(op,TCGSize2Opsize[opsize],right.location.register,left.location.register);
+ end;
+ end
+ else
+ begin
+ { right.location is not a LOC_REGISTER }
+ if (nodetype=subn) and (nf_swaped in flags) then
+ begin
+ if extra_not then
+ cg.a_op_reg_reg(exprasmlist,OP_NOT,opsize,left.location.register,left.location.register);
+ r:=cg.getintregister(exprasmlist,opsize);
+ cg.a_load_loc_reg(exprasmlist,opsize,right.location,r);
+ emit_reg_reg(op,TCGSize2Opsize[opsize],left.location.register,r);
+ cg.a_load_reg_reg(exprasmlist,opsize,opsize,r,left.location.register);
+ end
+ else
+ begin
+ { Optimizations when right.location is a constant value }
+ if (op=A_CMP) and
+ (nodetype in [equaln,unequaln]) and
+ (right.location.loc=LOC_CONSTANT) and
+ (right.location.value=0) then
+ begin
+ emit_reg_reg(A_TEST,TCGSize2Opsize[opsize],left.location.register,left.location.register);
+ end
+ else
+ if (op=A_ADD) and
+ (right.location.loc=LOC_CONSTANT) and
+ (right.location.value=1) and
+ not(cs_check_overflow in aktlocalswitches) then
+ begin
+ emit_reg(A_INC,TCGSize2Opsize[opsize],left.location.register);
+ end
+ else
+ if (op=A_SUB) and
+ (right.location.loc=LOC_CONSTANT) and
+ (right.location.value=1) and
+ not(cs_check_overflow in aktlocalswitches) then
+ begin
+ emit_reg(A_DEC,TCGSize2Opsize[opsize],left.location.register);
+ end
+ else
+ if (op=A_IMUL) and
+ (right.location.loc=LOC_CONSTANT) and
+ (ispowerof2(int64(right.location.value),power)) and
+ not(cs_check_overflow in aktlocalswitches) then
+ begin
+ emit_const_reg(A_SHL,TCGSize2Opsize[opsize],power,left.location.register);
+ end
+ else
+ begin
+ if extra_not then
+ begin
+ r:=cg.getintregister(exprasmlist,opsize);
+ cg.a_load_loc_reg(exprasmlist,opsize,right.location,r);
+ emit_reg(A_NOT,TCGSize2Opsize[opsize],r);
+ emit_reg_reg(A_AND,TCGSize2Opsize[opsize],r,left.location.register);
+ end
+ else
+ begin
+ emit_op_right_left(op,opsize);
+ end;
+ end;
+ end;
+ end;
+
+ { only in case of overflow operations }
+ { produce overflow code }
+ { we must put it here directly, because sign of operation }
+ { is in unsigned VAR!! }
+ if mboverflow then
+ begin
+ if cs_check_overflow in aktlocalswitches then
+ begin
+ objectlibrary.getjumplabel(hl4);
+ if unsigned then
+ cg.a_jmp_flags(exprasmlist,F_AE,hl4)
+ else
+ cg.a_jmp_flags(exprasmlist,F_NO,hl4);
+ cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
+ cg.a_label(exprasmlist,hl4);
+ end;
+ end;
+ end;
+
+
+ procedure tx86addnode.left_must_be_reg(opsize:TCGSize;noswap:boolean);
+ begin
+ { left location is not a register? }
+ if (left.location.loc<>LOC_REGISTER) then
+ begin
+ { if right is register then we can swap the locations }
+ if (not noswap) and
+ (right.location.loc=LOC_REGISTER) then
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end
+ else
+ begin
+ { maybe we can reuse a constant register when the
+ operation is a comparison that doesn't change the
+ value of the register }
+ location_force_reg(exprasmlist,left.location,opsize,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
+ end;
+ end;
+ end;
+
+
+ procedure tx86addnode.left_and_right_must_be_fpureg;
+ begin
+ if (right.location.loc<>LOC_FPUREGISTER) then
+ begin
+ cg.a_loadfpu_loc_reg(exprasmlist,right.location,NR_ST);
+ if (right.location.loc <> LOC_CFPUREGISTER) then
+ location_freetemp(exprasmlist,left.location);
+ if (left.location.loc<>LOC_FPUREGISTER) then
+ begin
+ cg.a_loadfpu_loc_reg(exprasmlist,left.location,NR_ST);
+ if (left.location.loc <> LOC_CFPUREGISTER) then
+ location_freetemp(exprasmlist,left.location);
+ end
+ else
+ begin
+ { left was on the stack => swap }
+ toggleflag(nf_swaped);
+ end;
+ end
+ { the nominator in st0 }
+ else if (left.location.loc<>LOC_FPUREGISTER) then
+ begin
+ cg.a_loadfpu_loc_reg(exprasmlist,left.location,NR_ST);
+ if (left.location.loc <> LOC_CFPUREGISTER) then
+ location_freetemp(exprasmlist,left.location);
+ end
+ else
+ begin
+ { fpu operands are always in the wrong order on the stack }
+ toggleflag(nf_swaped);
+ end;
+ end;
+
+
+ procedure tx86addnode.emit_op_right_left(op:TAsmOp;opsize:TCgsize);
+{$ifdef x86_64}
+ var
+ tmpreg : tregister;
+{$endif x86_64}
+ begin
+ { left must be a register }
+ case right.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ exprasmlist.concat(taicpu.op_reg_reg(op,TCGSize2Opsize[opsize],right.location.register,left.location.register));
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ tcgx86(cg).make_simple_ref(exprasmlist,right.location.reference);
+ exprasmlist.concat(taicpu.op_ref_reg(op,TCGSize2Opsize[opsize],right.location.reference,left.location.register));
+ end;
+ LOC_CONSTANT :
+ begin
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (opsize in [OS_S64,OS_64]) and
+ ((right.location.value<low(longint)) or (right.location.value>high(longint))) then
+ begin
+ tmpreg:=cg.getintregister(exprasmlist,opsize);
+ cg.a_load_const_reg(exprasmlist,opsize,right.location.value,tmpreg);
+ exprasmlist.concat(taicpu.op_reg_reg(op,TCGSize2Opsize[opsize],tmpreg,left.location.register));
+ end
+ else
+{$endif x86_64}
+ exprasmlist.concat(taicpu.op_const_reg(op,TCGSize2Opsize[opsize],right.location.value,left.location.register));
+ end;
+ else
+ internalerror(200203232);
+ end;
+ end;
+
+
+ function tx86addnode.getresflags(unsigned : boolean) : tresflags;
+ begin
+ case nodetype of
+ equaln : getresflags:=F_E;
+ unequaln : getresflags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swaped in flags then
+ case nodetype of
+ ltn : getresflags:=F_G;
+ lten : getresflags:=F_GE;
+ gtn : getresflags:=F_L;
+ gten : getresflags:=F_LE;
+ end
+ else
+ case nodetype of
+ ltn : getresflags:=F_L;
+ lten : getresflags:=F_LE;
+ gtn : getresflags:=F_G;
+ gten : getresflags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swaped in flags then
+ case nodetype of
+ ltn : getresflags:=F_A;
+ lten : getresflags:=F_AE;
+ gtn : getresflags:=F_B;
+ gten : getresflags:=F_BE;
+ end
+ else
+ case nodetype of
+ ltn : getresflags:=F_B;
+ lten : getresflags:=F_BE;
+ gtn : getresflags:=F_A;
+ gten : getresflags:=F_AE;
+ end;
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ AddSmallSet
+*****************************************************************************}
+
+ procedure tx86addnode.second_addsmallset;
+ var
+ opsize : TCGSize;
+ op : TAsmOp;
+ extra_not,
+ noswap : boolean;
+ begin
+ pass_left_right;
+
+ noswap:=false;
+ extra_not:=false;
+ opsize:=OS_32;
+ case nodetype of
+ addn :
+ begin
+ { this is a really ugly hack!!!!!!!!!! }
+ { this could be done later using EDI }
+ { as it is done for subn }
+ { instead of two registers!!!! }
+ { adding elements is not commutative }
+ if (nf_swaped in flags) and (left.nodetype=setelementn) then
+ swapleftright;
+ { are we adding set elements ? }
+ if right.nodetype=setelementn then
+ begin
+ { no range support for smallsets! }
+ if assigned(tsetelementnode(right).right) then
+ internalerror(43244);
+ { bts requires both elements to be registers }
+ location_force_reg(exprasmlist,left.location,opsize,false);
+ location_force_reg(exprasmlist,right.location,opsize,true);
+ op:=A_BTS;
+ noswap:=true;
+ end
+ else
+ op:=A_OR;
+ end;
+ symdifn :
+ op:=A_XOR;
+ muln :
+ op:=A_AND;
+ subn :
+ begin
+ op:=A_AND;
+ if (not(nf_swaped in flags)) and
+ (right.location.loc=LOC_CONSTANT) then
+ right.location.value := not(right.location.value)
+ else if (nf_swaped in flags) and
+ (left.location.loc=LOC_CONSTANT) then
+ left.location.value := not(left.location.value)
+ else
+ extra_not:=true;
+ end;
+ xorn :
+ op:=A_XOR;
+ orn :
+ op:=A_OR;
+ andn :
+ op:=A_AND;
+ else
+ internalerror(2003042215);
+ end;
+ { left must be a register }
+ left_must_be_reg(opsize,noswap);
+ emit_generic_code(op,opsize,true,extra_not,false);
+ location_freetemp(exprasmlist,right.location);
+
+ set_result_location_reg;
+ end;
+
+
+ procedure tx86addnode.second_cmpsmallset;
+ var
+ opsize : TCGSize;
+ op : TAsmOp;
+ begin
+ pass_left_right;
+ opsize:=OS_32;
+ case nodetype of
+ equaln,
+ unequaln :
+ op:=A_CMP;
+ lten,gten:
+ begin
+ if (not(nf_swaped in flags) and (nodetype = lten)) or
+ ((nf_swaped in flags) and (nodetype = gten)) then
+ swapleftright;
+ location_force_reg(exprasmlist,left.location,opsize,true);
+ emit_op_right_left(A_AND,opsize);
+ op:=A_CMP;
+ { warning: ugly hack, we need a JE so change the node to equaln }
+ nodetype:=equaln;
+ end;
+ else
+ internalerror(2003042215);
+ end;
+ { left must be a register }
+ left_must_be_reg(opsize,false);
+ emit_generic_code(op,opsize,true,false,false);
+ location_freetemp(exprasmlist,right.location);
+ location_freetemp(exprasmlist,left.location);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+ end;
+
+
+{*****************************************************************************
+ AddMMX
+*****************************************************************************}
+
+{$ifdef SUPPORT_MMX}
+ procedure tx86addnode.second_opmmx;
+ var
+ op : TAsmOp;
+ cmpop : boolean;
+ mmxbase : tmmxtype;
+ hreg,
+ hregister : tregister;
+ begin
+ pass_left_right;
+
+ cmpop:=false;
+ mmxbase:=mmx_type(left.resulttype.def);
+ location_reset(location,LOC_MMXREGISTER,def_cgsize(resulttype.def));
+ case nodetype of
+ addn :
+ begin
+ if (cs_mmx_saturation in aktlocalswitches) then
+ begin
+ case mmxbase of
+ mmxs8bit:
+ op:=A_PADDSB;
+ mmxu8bit:
+ op:=A_PADDUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PADDSB;
+ mmxu16bit:
+ op:=A_PADDUSW;
+ end;
+ end
+ else
+ begin
+ case mmxbase of
+ mmxs8bit,mmxu8bit:
+ op:=A_PADDB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PADDW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PADDD;
+ end;
+ end;
+ end;
+ muln :
+ begin
+ case mmxbase of
+ mmxs16bit,mmxu16bit:
+ op:=A_PMULLW;
+ mmxfixed16:
+ op:=A_PMULHW;
+ end;
+ end;
+ subn :
+ begin
+ if (cs_mmx_saturation in aktlocalswitches) then
+ begin
+ case mmxbase of
+ mmxs8bit:
+ op:=A_PSUBSB;
+ mmxu8bit:
+ op:=A_PSUBUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PSUBSB;
+ mmxu16bit:
+ op:=A_PSUBUSW;
+ end;
+ end
+ else
+ begin
+ case mmxbase of
+ mmxs8bit,mmxu8bit:
+ op:=A_PSUBB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PSUBW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PSUBD;
+ end;
+ end;
+ end;
+ xorn:
+ op:=A_PXOR;
+ orn:
+ op:=A_POR;
+ andn:
+ op:=A_PAND;
+ else
+ internalerror(2003042214);
+ end;
+
+ { left and right no register? }
+ { then one must be demanded }
+ if (left.location.loc<>LOC_MMXREGISTER) then
+ begin
+ if (right.location.loc=LOC_MMXREGISTER) then
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end
+ else
+ begin
+ { register variable ? }
+ if (left.location.loc=LOC_CMMXREGISTER) then
+ begin
+ hregister:=tcgx86(cg).getmmxregister(exprasmlist);
+ emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
+ end
+ else
+ begin
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203245);
+
+ hregister:=tcgx86(cg).getmmxregister(exprasmlist);
+ emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
+ end;
+
+ location_reset(left.location,LOC_MMXREGISTER,OS_NO);
+ left.location.register:=hregister;
+ end;
+ end;
+
+ { at this point, left.location.loc should be LOC_MMXREGISTER }
+ if right.location.loc<>LOC_MMXREGISTER then
+ begin
+ if (nodetype=subn) and (nf_swaped in flags) then
+ begin
+ hreg:=tcgx86(cg).getmmxregister(exprasmlist);
+ if right.location.loc=LOC_CMMXREGISTER then
+ begin
+ emit_reg_reg(A_MOVQ,S_NO,right.location.register,hreg);
+ emit_reg_reg(op,S_NO,left.location.register,hreg);
+ end
+ else
+ begin
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203247);
+ emit_ref_reg(A_MOVQ,S_NO,right.location.reference,hreg);
+ emit_reg_reg(op,S_NO,left.location.register,hreg);
+ end;
+ location.register:=hreg;
+ end
+ else
+ begin
+ if (right.location.loc=LOC_CMMXREGISTER) then
+ emit_reg_reg(op,S_NO,right.location.register,left.location.register)
+ else
+ begin
+ if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203246);
+ emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
+ end;
+ location.register:=left.location.register;
+ end;
+ end
+ else
+ begin
+ { right.location=LOC_MMXREGISTER }
+ if (nodetype=subn) and (nf_swaped in flags) then
+ begin
+ emit_reg_reg(op,S_NO,left.location.register,right.location.register);
+ location_swap(left.location,right.location);
+ toggleflag(nf_swaped);
+ end
+ else
+ begin
+ emit_reg_reg(op,S_NO,right.location.register,left.location.register);
+ end;
+ location.register:=left.location.register;
+ end;
+
+ location_freetemp(exprasmlist,right.location);
+ if cmpop then
+ location_freetemp(exprasmlist,left.location);
+ end;
+{$endif SUPPORT_MMX}
+
+
+{*****************************************************************************
+ addmmxset
+*****************************************************************************}
+
+{$ifdef SUPPORT_MMX}
+ procedure tx86addnode.second_opmmxset;
+
+ var opsize : TCGSize;
+ op : TAsmOp;
+ cmpop,
+ noswap : boolean;
+ begin
+ pass_left_right;
+
+ cmpop:=false;
+ noswap:=false;
+ opsize:=OS_32;
+ case nodetype of
+ addn:
+ begin
+ { are we adding set elements ? }
+ if right.nodetype=setelementn then
+ begin
+ { adding elements is not commutative }
+{ if nf_swaped in flags then
+ swapleftright;}
+ { bts requires both elements to be registers }
+{ location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],false);
+ location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],true);
+ op:=A_BTS;
+ noswap:=true;}
+ end
+ else
+ op:=A_POR;
+ end;
+ symdifn :
+ op:=A_PXOR;
+ muln:
+ op:=A_PAND;
+ subn:
+ op:=A_PANDN;
+ equaln,
+ unequaln :
+ begin
+ op:=A_PCMPEQD;
+ cmpop:=true;
+ end;
+ lten,gten:
+ begin
+ if (not(nf_swaped in flags) and (nodetype = lten)) or
+ ((nf_swaped in flags) and (nodetype = gten)) then
+ swapleftright;
+ location_force_reg(exprasmlist,left.location,opsize,true);
+ emit_op_right_left(A_AND,opsize);
+ op:=A_PCMPEQD;
+ cmpop:=true;
+ { warning: ugly hack, we need a JE so change the node to equaln }
+ nodetype:=equaln;
+ end;
+ xorn :
+ op:=A_PXOR;
+ orn :
+ op:=A_POR;
+ andn :
+ op:=A_PAND;
+ else
+ internalerror(2003042215);
+ end;
+ { left must be a register }
+ left_must_be_reg(opsize,noswap);
+{ emit_generic_code(op,opsize,true,extra_not,false);}
+ location_freetemp(exprasmlist,right.location);
+ if cmpop then
+ location_freetemp(exprasmlist,left.location);
+ end;
+{$endif SUPPORT_MMX}
+
+
+
+{*****************************************************************************
+ AddFloat
+*****************************************************************************}
+
+ procedure tx86addnode.second_addfloatsse;
+ var
+ op : topcg;
+ begin
+ pass_left_right;
+ if (nf_swaped in flags) then
+ swapleftright;
+
+ case nodetype of
+ addn :
+ op:=OP_ADD;
+ muln :
+ op:=OP_MUL;
+ subn :
+ op:=OP_SUB;
+ slashn :
+ op:=OP_DIV;
+ else
+ internalerror(200312231);
+ end;
+
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resulttype.def));
+ { we can use only right as left operand if the operation is commutative }
+ if (right.location.loc=LOC_MMREGISTER) and (op in [OP_ADD,OP_MUL]) then
+ begin
+ location.register:=right.location.register;
+ { force floating point reg. location to be written to memory,
+ we don't force it to mm register because writing to memory
+ allows probably shorter code because there is no direct fpu->mm register
+ copy instruction
+ }
+ if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ location_force_mem(exprasmlist,left.location);
+ cg.a_opmm_loc_reg(exprasmlist,op,location.size,left.location,location.register,mms_movescalar);
+ end
+ else
+ begin
+ location_force_mmregscalar(exprasmlist,left.location,false);
+ location.register:=left.location.register;
+ { force floating point reg. location to be written to memory,
+ we don't force it to mm register because writing to memory
+ allows probably shorter code because there is no direct fpu->mm register
+ copy instruction
+ }
+ if right.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ location_force_mem(exprasmlist,right.location);
+ cg.a_opmm_loc_reg(exprasmlist,op,location.size,right.location,location.register,mms_movescalar);
+ end;
+ end;
+
+
+ procedure tx86addnode.second_cmpfloatsse;
+ var
+ op : tasmop;
+ begin
+ if is_single(left.resulttype.def) then
+ op:=A_COMISS
+ else if is_double(left.resulttype.def) then
+ op:=A_COMISD
+ else
+ internalerror(200402222);
+ pass_left_right;
+
+ location_reset(location,LOC_FLAGS,def_cgsize(resulttype.def));
+ { we can use only right as left operand if the operation is commutative }
+ if (right.location.loc=LOC_MMREGISTER) then
+ begin
+ { force floating point reg. location to be written to memory,
+ we don't force it to mm register because writing to memory
+ allows probably shorter code because there is no direct fpu->mm register
+ copy instruction
+ }
+ if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ location_force_mem(exprasmlist,left.location);
+ case left.location.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ tcgx86(cg).make_simple_ref(exprasmlist,left.location.reference);
+ exprasmlist.concat(taicpu.op_ref_reg(op,S_NO,left.location.reference,right.location.register));
+ end;
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ exprasmlist.concat(taicpu.op_reg_reg(op,S_NO,left.location.register,right.location.register));
+ else
+ internalerror(200402221);
+ end;
+ if nf_swaped in flags then
+ exclude(flags,nf_swaped)
+ else
+ include(flags,nf_swaped)
+ end
+ else
+ begin
+ location_force_mmregscalar(exprasmlist,left.location,false);
+ { force floating point reg. location to be written to memory,
+ we don't force it to mm register because writing to memory
+ allows probably shorter code because there is no direct fpu->mm register
+ copy instruction
+ }
+ if right.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ location_force_mem(exprasmlist,right.location);
+ case right.location.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ tcgx86(cg).make_simple_ref(exprasmlist,right.location.reference);
+ exprasmlist.concat(taicpu.op_ref_reg(op,S_NO,right.location.reference,left.location.register));
+ end;
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ exprasmlist.concat(taicpu.op_reg_reg(op,S_NO,right.location.register,left.location.register));
+ else
+ internalerror(200402223);
+ end;
+ end;
+ location.resflags:=getresflags(true);
+ end;
+
+
+ procedure tx86addnode.second_addfloat;
+ var
+ op : TAsmOp;
+ begin
+ if use_sse(resulttype.def) then
+ begin
+ second_addfloatsse;
+ exit;
+ end;
+
+ pass_left_right;
+
+ case nodetype of
+ addn :
+ op:=A_FADDP;
+ muln :
+ op:=A_FMULP;
+ subn :
+ op:=A_FSUBP;
+ slashn :
+ op:=A_FDIVP;
+ else
+ internalerror(2003042214);
+ end;
+
+ left_and_right_must_be_fpureg;
+
+ { if we swaped the tree nodes, then use the reverse operator }
+ if nf_swaped in flags then
+ begin
+ if (nodetype=slashn) then
+ op:=A_FDIVRP
+ else if (nodetype=subn) then
+ op:=A_FSUBRP;
+ end;
+
+ emit_reg_reg(op,S_NO,NR_ST,NR_ST1);
+ tcgx86(cg).dec_fpu_stack;
+
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ location.register:=NR_ST;
+ end;
+
+
+ procedure tx86addnode.second_cmpfloat;
+ var
+ resflags : tresflags;
+ begin
+ if use_sse(left.resulttype.def) or use_sse(right.resulttype.def) then
+ begin
+ second_cmpfloatsse;
+ exit;
+ end;
+
+ pass_left_right;
+ left_and_right_must_be_fpureg;
+
+{$ifndef x86_64}
+ if aktspecificoptprocessor<ClassPentium2 then
+ begin
+ emit_none(A_FCOMPP,S_NO);
+ tcgx86(cg).dec_fpu_stack;
+ tcgx86(cg).dec_fpu_stack;
+
+ { load fpu flags }
+ cg.getcpuregister(exprasmlist,NR_AX);
+ emit_reg(A_FNSTSW,S_NO,NR_AX);
+ emit_none(A_SAHF,S_NO);
+ cg.ungetcpuregister(exprasmlist,NR_AX);
+ if nf_swaped in flags then
+ begin
+ case nodetype of
+ equaln : resflags:=F_E;
+ unequaln : resflags:=F_NE;
+ ltn : resflags:=F_A;
+ lten : resflags:=F_AE;
+ gtn : resflags:=F_B;
+ gten : resflags:=F_BE;
+ end;
+ end
+ else
+ begin
+ case nodetype of
+ equaln : resflags:=F_E;
+ unequaln : resflags:=F_NE;
+ ltn : resflags:=F_B;
+ lten : resflags:=F_BE;
+ gtn : resflags:=F_A;
+ gten : resflags:=F_AE;
+ end;
+ end;
+ end
+ else
+{$endif x86_64}
+ begin
+ exprasmlist.concat(taicpu.op_reg_reg(A_FCOMIP,S_NO,NR_ST1,NR_ST0));
+ { fcomip pops only one fpu register }
+ exprasmlist.concat(taicpu.op_reg(A_FSTP,S_NO,NR_ST0));
+ tcgx86(cg).dec_fpu_stack;
+ tcgx86(cg).dec_fpu_stack;
+
+ { load fpu flags }
+ if nf_swaped in flags then
+ begin
+ case nodetype of
+ equaln : resflags:=F_E;
+ unequaln : resflags:=F_NE;
+ ltn : resflags:=F_A;
+ lten : resflags:=F_AE;
+ gtn : resflags:=F_B;
+ gten : resflags:=F_BE;
+ end;
+ end
+ else
+ begin
+ case nodetype of
+ equaln : resflags:=F_E;
+ unequaln : resflags:=F_NE;
+ ltn : resflags:=F_B;
+ lten : resflags:=F_BE;
+ gtn : resflags:=F_A;
+ gten : resflags:=F_AE;
+ end;
+ end;
+ end;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=resflags;
+ end;
+
+
+{*****************************************************************************
+ Add64bit
+*****************************************************************************}
+
+ procedure tx86addnode.second_add64bit;
+ begin
+{$ifdef cpu64bit}
+ second_addordinal;
+{$else cpu64bit}
+ { must be implemented separate }
+ internalerror(200402042);
+{$endif cpu64bit}
+ end;
+
+
+ procedure tx86addnode.second_cmp64bit;
+ begin
+{$ifdef cpu64bit}
+ second_cmpordinal;
+{$else cpu64bit}
+ { must be implemented separate }
+ internalerror(200402043);
+{$endif cpu64bit}
+ end;
+
+
+{*****************************************************************************
+ AddOrdinal
+*****************************************************************************}
+
+ procedure tx86addnode.second_addordinal;
+ var
+ mboverflow : boolean;
+ op : tasmop;
+ opsize : tcgsize;
+ { true, if unsigned types are compared }
+ unsigned : boolean;
+ { true, if for sets subtractions the extra not should generated }
+ extra_not : boolean;
+ begin
+ { defaults }
+ extra_not:=false;
+ mboverflow:=false;
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+ opsize:=def_cgsize(left.resulttype.def);
+
+ pass_left_right;
+
+ case nodetype of
+ addn :
+ begin
+ op:=A_ADD;
+ mboverflow:=true;
+ end;
+ muln :
+ begin
+ if unsigned then
+ op:=A_MUL
+ else
+ op:=A_IMUL;
+ mboverflow:=true;
+ end;
+ subn :
+ begin
+ op:=A_SUB;
+ mboverflow:=true;
+ end;
+ xorn :
+ op:=A_XOR;
+ orn :
+ op:=A_OR;
+ andn :
+ op:=A_AND;
+ else
+ internalerror(200304229);
+ end;
+
+ { filter MUL, which requires special handling }
+ if op=A_MUL then
+ begin
+ second_mul;
+ exit;
+ end;
+
+ left_must_be_reg(opsize,false);
+ emit_generic_code(op,opsize,unsigned,extra_not,mboverflow);
+ location_freetemp(exprasmlist,right.location);
+
+ set_result_location_reg;
+ end;
+
+
+ procedure tx86addnode.second_cmpordinal;
+ var
+ opsize : tcgsize;
+ unsigned : boolean;
+ begin
+ unsigned:=not(is_signed(left.resulttype.def)) or
+ not(is_signed(right.resulttype.def));
+ opsize:=def_cgsize(left.resulttype.def);
+
+ pass_left_right;
+
+ left_must_be_reg(opsize,false);
+ emit_generic_code(A_CMP,opsize,unsigned,false,false);
+ location_freetemp(exprasmlist,right.location);
+ location_freetemp(exprasmlist,left.location);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ end;
+
+begin
+ caddnode:=tx86addnode;
+end.
diff --git a/compiler/x86/nx86cnv.pas b/compiler/x86/nx86cnv.pas
new file mode 100644
index 0000000000..904bcea47b
--- /dev/null
+++ b/compiler/x86/nx86cnv.pas
@@ -0,0 +1,392 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate for x86-64 and i386 assembler for type converting 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 nx86cnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgcnv,defutil,defcmp;
+
+ type
+ tx86typeconvnode = class(tcgtypeconvnode)
+ protected
+ function first_real_to_real : tnode;override;
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ function first_int_to_real: tnode; override;
+ procedure second_int_to_real;override;
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+
+implementation
+
+ uses
+ verbose,systems,globals,globtype,
+ aasmbase,aasmtai,aasmcpu,
+ symconst,symdef,
+ cgbase,cga,pass_2,
+ ncon,ncal,ncnv,
+ cpubase,
+ cgutils,cgobj,cgx86,ncgutil,
+ tgobj;
+
+
+ function tx86typeconvnode.first_real_to_real : tnode;
+ begin
+ first_real_to_real:=nil;
+ { comp isn't a floating type }
+ if (tfloatdef(resulttype.def).typ=s64comp) and
+ (tfloatdef(left.resulttype.def).typ<>s64comp) and
+ not (nf_explicit in flags) then
+ CGMessage(type_w_convert_real_2_comp);
+ if use_sse(resulttype.def) then
+ begin
+ if registersmm<1 then
+ registersmm:=1;
+ expectloc:=LOC_MMREGISTER;
+ end
+ else
+ begin
+ if registersfpu<1 then
+ registersfpu:=1;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+ end;
+
+
+ procedure tx86typeconvnode.second_int_to_bool;
+ var
+ hregister : tregister;
+{$ifndef cpu64bit}
+ href : treference;
+{$endif cpu64bit}
+ resflags : tresflags;
+ hlabel,oldtruelabel,oldfalselabel : tasmlabel;
+ begin
+ oldtruelabel:=truelabel;
+ oldfalselabel:=falselabel;
+ objectlibrary.getjumplabel(truelabel);
+ objectlibrary.getjumplabel(falselabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+ { byte(boolean) or word(wordbool) or longint(longbool) must }
+ { be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resulttype.def.size=resulttype.def.size) and
+ (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ begin
+ location_copy(location,left.location);
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ exit;
+ end;
+
+ { Load left node into flag F_NE/F_E }
+ resflags:=F_NE;
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+{$ifndef cpu64bit}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_ref_reg(exprasmlist,OS_32,OS_32,left.location.reference,hregister);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ cg.a_op_ref_reg(exprasmlist,OP_OR,OS_32,href,hregister);
+ end
+ else
+{$endif cpu64bit}
+ begin
+ location_force_reg(exprasmlist,left.location,left.location.size,true);
+ cg.a_op_reg_reg(exprasmlist,OP_OR,left.location.size,left.location.register,left.location.register);
+ end;
+ end;
+ LOC_FLAGS :
+ begin
+ resflags:=left.location.resflags;
+ end;
+ LOC_REGISTER,LOC_CREGISTER :
+ begin
+{$ifndef cpu64bit}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,left.location.register64.reglo,hregister);
+ cg.a_op_reg_reg(exprasmlist,OP_OR,OS_32,left.location.register64.reghi,hregister);
+ end
+ else
+{$endif cpu64bit}
+ cg.a_op_reg_reg(exprasmlist,OP_OR,left.location.size,left.location.register,left.location.register);
+ end;
+ LOC_JUMP :
+ begin
+ hregister:=cg.getintregister(exprasmlist,OS_INT);
+ objectlibrary.getjumplabel(hlabel);
+ cg.a_label(exprasmlist,truelabel);
+ cg.a_load_const_reg(exprasmlist,OS_INT,1,hregister);
+ cg.a_jmp_always(exprasmlist,hlabel);
+ cg.a_label(exprasmlist,falselabel);
+ cg.a_load_const_reg(exprasmlist,OS_INT,0,hregister);
+ cg.a_label(exprasmlist,hlabel);
+ cg.a_op_reg_reg(exprasmlist,OP_OR,OS_INT,hregister,hregister);
+ end;
+ else
+ internalerror(10062);
+ end;
+ { load flags to register }
+ location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
+ location.register:=cg.getintregister(exprasmlist,location.size);
+ cg.g_flags2reg(exprasmlist,location.size,resflags,location.register);
+ truelabel:=oldtruelabel;
+ falselabel:=oldfalselabel;
+ end;
+
+ function tx86typeconvnode.first_int_to_real : tnode;
+
+ begin
+ first_int_to_real:=nil;
+ if registersfpu<1 then
+ registersfpu:=1;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+
+
+ procedure tx86typeconvnode.second_int_to_real;
+
+ var
+ href : treference;
+ hregister : tregister;
+ l1,l2 : tasmlabel;
+ signtested : boolean;
+ hreg : tregister;
+ op : tasmop;
+ begin
+{$ifdef x86_64}
+ if use_sse(resulttype.def) then
+ begin
+ if is_double(resulttype.def) then
+ op:=A_CVTSI2SD
+ else if is_single(resulttype.def) then
+ op:=A_CVTSI2SS
+ else
+ internalerror(200506061);
+
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resulttype.def));
+ location.register:=cg.getmmregister(exprasmlist,def_cgsize(resulttype.def));
+ if (left.location.loc=LOC_REGISTER) and (torddef(left.resulttype.def).typ=u64bit) then
+ begin
+{$ifdef cpu64bit}
+ emit_const_reg(A_BT,S_Q,63,left.location.register);
+{$else cpu64bit}
+ emit_const_reg(A_BT,S_L,31,left.location.register64.reghi);
+{$endif cpu64bit}
+ signtested:=true;
+ end
+ else
+ signtested:=false;
+
+ case torddef(left.resulttype.def).typ of
+ u64bit:
+ begin
+ { unsigned 64 bit ints are harder to handle:
+ we load bits 0..62 and then check bit 63:
+ if it is 1 then we add $80000000 000000000
+ as double }
+ objectlibrary.getdatalabel(l1);
+ objectlibrary.getjumplabel(l2);
+
+ if not(signtested) then
+ begin
+ inc(left.location.reference.offset,4);
+ emit_const_ref(A_BT,S_L,31,left.location.reference);
+ dec(left.location.reference.offset,4);
+ end;
+
+ exprasmlist.concat(taicpu.op_ref_reg(op,S_Q,left.location.reference,location.register));
+
+ cg.a_jmp_flags(exprasmlist,F_NC,l2);
+ asmlist[al_typedconsts].concat(Tai_label.Create(l1));
+ reference_reset_symbol(href,l1,0);
+
+ { I got these constant from a test program (FK) }
+ if is_double(resulttype.def) then
+ begin
+ { double (2^64) }
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit(0));
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit($43f00000));
+ exprasmlist.concat(taicpu.op_ref_reg(A_ADDSD,S_NO,href,location.register));
+ end
+ else if is_single(resulttype.def) then
+ begin
+ { single(2^64) }
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit($5f800000));
+ exprasmlist.concat(taicpu.op_ref_reg(A_ADDSS,S_NO,href,location.register));
+ end
+ else
+ internalerror(200506071);
+ cg.a_label(exprasmlist,l2);
+ end
+ else
+ begin
+ if (left.resulttype.def.size=4) and not(torddef(left.resulttype.def).typ=u32bit) then
+ begin
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ exprasmList.concat(Taicpu.op_ref_reg(op,S_L,left.location.reference,location.register));
+ LOC_CREGISTER,
+ LOC_REGISTER :
+ exprasmList.concat(Taicpu.op_reg_reg(op,S_L,left.location.register,location.register));
+ else
+ internalerror(200506072);
+ end;
+ end
+ else if left.resulttype.def.size=8 then
+ begin
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ exprasmList.concat(Taicpu.op_ref_reg(op,S_Q,left.location.reference,location.register));
+ LOC_CREGISTER,
+ LOC_REGISTER :
+ exprasmList.concat(Taicpu.op_reg_reg(op,S_Q,left.location.register,location.register));
+ else
+ internalerror(200506073);
+ end;
+ end
+ else
+ begin
+ hreg:=cg.getintregister(exprasmlist,OS_64);
+ cg.a_load_loc_reg(exprasmlist,OS_64,left.location,hreg);
+ exprasmList.concat(Taicpu.Op_reg_reg(op,S_NO,hreg,location.register));
+ end
+ end;
+ end;
+ end
+ else
+{$endif x86_64}
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ if (left.location.loc=LOC_REGISTER) and (torddef(left.resulttype.def).typ=u64bit) then
+ begin
+{$ifdef cpu64bit}
+ emit_const_reg(A_BT,S_Q,63,left.location.register);
+{$else cpu64bit}
+ emit_const_reg(A_BT,S_L,31,left.location.register64.reghi);
+{$endif cpu64bit}
+ signtested:=true;
+ end
+ else
+ signtested:=false;
+
+ { We need to load from a reference }
+ location_force_mem(exprasmlist,left.location);
+
+ { For u32bit we need to load it as comp and need to
+ make it 64bits }
+ if (torddef(left.resulttype.def).typ=u32bit) then
+ begin
+ tg.GetTemp(exprasmlist,8,tt_normal,href);
+ location_freetemp(exprasmlist,left.location);
+ cg.a_load_ref_ref(exprasmlist,left.location.size,OS_32,left.location.reference,href);
+ inc(href.offset,4);
+ cg.a_load_const_ref(exprasmlist,OS_32,0,href);
+ dec(href.offset,4);
+ left.location.reference:=href;
+ end;
+
+ { Load from reference to fpu reg }
+ case torddef(left.resulttype.def).typ of
+ u32bit,
+ scurrency,
+ s64bit:
+ exprasmlist.concat(taicpu.op_ref(A_FILD,S_IQ,left.location.reference));
+ u64bit:
+ begin
+ { unsigned 64 bit ints are harder to handle:
+ we load bits 0..62 and then check bit 63:
+ if it is 1 then we add $80000000 000000000
+ as double }
+ objectlibrary.getdatalabel(l1);
+ objectlibrary.getjumplabel(l2);
+
+ if not(signtested) then
+ begin
+ inc(left.location.reference.offset,4);
+ emit_const_ref(A_BT,S_L,31,left.location.reference);
+ dec(left.location.reference.offset,4);
+ end;
+
+ exprasmlist.concat(taicpu.op_ref(A_FILD,S_IQ,left.location.reference));
+ cg.a_jmp_flags(exprasmlist,F_NC,l2);
+ asmlist[al_typedconsts].concat(Tai_label.Create(l1));
+ { I got this constant from a test program (FK) }
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit(0));
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit(longint ($80000000)));
+ asmlist[al_typedconsts].concat(Tai_const.Create_32bit($0000403f));
+ reference_reset_symbol(href,l1,0);
+ exprasmlist.concat(Taicpu.Op_ref(A_FLD,S_FX,href));
+ exprasmlist.concat(Taicpu.Op_reg_reg(A_FADDP,S_NO,NR_ST,NR_ST1));
+ cg.a_label(exprasmlist,l2);
+ end
+ else
+ begin
+ if left.resulttype.def.size<4 then
+ begin
+ tg.GetTemp(exprasmlist,4,tt_normal,href);
+ location_freetemp(exprasmlist,left.location);
+ cg.a_load_ref_ref(exprasmlist,left.location.size,OS_32,left.location.reference,href);
+ left.location.reference:=href;
+ end;
+ exprasmlist.concat(taicpu.op_ref(A_FILD,S_IL,left.location.reference));
+ end;
+ end;
+ location_freetemp(exprasmlist,left.location);
+ tcgx86(cg).inc_fpu_stack;
+ location.register:=NR_ST;
+ end;
+ end;
+
+begin
+ ctypeconvnode:=tx86typeconvnode
+end.
diff --git a/compiler/x86/nx86con.pas b/compiler/x86/nx86con.pas
new file mode 100644
index 0000000000..123f94cde8
--- /dev/null
+++ b/compiler/x86/nx86con.pas
@@ -0,0 +1,91 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for constants
+
+ 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 nx86con;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncon,ncgcon;
+
+ type
+ tx86realconstnode = class(tcgrealconstnode)
+ function pass_1 : tnode;override;
+ procedure pass_2;override;
+ end;
+
+implementation
+
+ uses
+ systems,globals,
+ symdef,
+ defutil,
+ cpubase,
+ cga,cgx86,cgobj,cgbase,cgutils;
+
+{*****************************************************************************
+ TI386REALCONSTNODE
+*****************************************************************************}
+
+ function tx86realconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ if is_number_float(value_real) and not(use_sse(resulttype.def)) and (value_real=1.0) or (value_real=0.0) then
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersfpu:=1;
+ end
+ else
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+ procedure tx86realconstnode.pass_2;
+
+ begin
+ if is_number_float(value_real) then
+ begin
+ if (value_real=1.0) and not(use_sse(resulttype.def)) then
+ begin
+ emit_none(A_FLD1,S_NO);
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ location.register:=NR_ST;
+ tcgx86(cg).inc_fpu_stack;
+ end
+ else if (value_real=0.0) and not(use_sse(resulttype.def)) then
+ begin
+ emit_none(A_FLDZ,S_NO);
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ location.register:=NR_ST;
+ tcgx86(cg).inc_fpu_stack;
+ end
+ else
+ inherited pass_2;
+ end
+ else
+ inherited pass_2;
+ end;
+
+
+begin
+ crealconstnode:=tx86realconstnode;
+end.
diff --git a/compiler/x86/nx86inl.pas b/compiler/x86/nx86inl.pas
new file mode 100644
index 0000000000..31629edf71
--- /dev/null
+++ b/compiler/x86/nx86inl.pas
@@ -0,0 +1,403 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86 inline 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 nx86inl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl,ncginl;
+
+ type
+ tx86inlinenode = class(tcginlinenode)
+ { first pass override
+ so that the code generator will actually generate
+ these nodes.
+ }
+ function first_pi: tnode ; override;
+ function first_arctan_real: tnode; override;
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ function first_sqrt_real: tnode; override;
+ function first_ln_real: tnode; override;
+ function first_cos_real: tnode; override;
+ function first_sin_real: tnode; override;
+ { second pass override to generate these nodes }
+ procedure second_IncludeExclude;override;
+ procedure second_pi; override;
+ procedure second_arctan_real; override;
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_sqrt_real; override;
+ procedure second_ln_real; override;
+ procedure second_cos_real; override;
+ procedure second_sin_real; override;
+
+ procedure second_prefetch;override;
+ private
+ procedure load_fpu_location;
+ end;
+
+implementation
+
+ uses
+ systems,
+ globals,
+ cutils,verbose,
+ symconst,
+ defutil,
+ aasmbase,aasmtai,aasmcpu,
+ symdef,
+ cgbase,pass_2,
+ cpuinfo,cpubase,paramgr,
+ nbas,ncon,ncal,ncnv,nld,ncgutil,
+ cga,cgutils,cgx86,cgobj;
+
+
+{*****************************************************************************
+ TX86INLINENODE
+*****************************************************************************}
+
+ function tx86inlinenode.first_pi : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersfpu:=1;
+ first_pi := nil;
+ end;
+
+
+ function tx86inlinenode.first_arctan_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,2);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_arctan_real := nil;
+ end;
+
+ function tx86inlinenode.first_abs_real : tnode;
+ begin
+ if use_sse(resulttype.def) then
+ begin
+ expectloc:=LOC_MMREGISTER;
+ registersmm:=max(left.registersmm,1);
+ end
+ else
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersfpu:=max(left.registersfpu,1);
+ end;
+ registersint:=left.registersint;
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_abs_real := nil;
+ end;
+
+ function tx86inlinenode.first_sqr_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_sqr_real := nil;
+ end;
+
+ function tx86inlinenode.first_sqrt_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_sqrt_real := nil;
+ end;
+
+ function tx86inlinenode.first_ln_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,2);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_ln_real := nil;
+ end;
+
+ function tx86inlinenode.first_cos_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_cos_real := nil;
+ end;
+
+ function tx86inlinenode.first_sin_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ registersint:=left.registersint;
+ registersfpu:=max(left.registersfpu,1);
+{$ifdef SUPPORT_MMX}
+ registersmmx:=left.registersmmx;
+{$endif SUPPORT_MMX}
+ first_sin_real := nil;
+ end;
+
+
+ procedure tx86inlinenode.second_Pi;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ emit_none(A_FLDPI,S_NO);
+ tcgx86(cg).inc_fpu_stack;
+ location.register:=NR_FPU_RESULT_REG;
+ end;
+
+ { load the FPU into the an fpu register }
+ procedure tx86inlinenode.load_fpu_location;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ location.register:=NR_FPU_RESULT_REG;
+ secondpass(left);
+ case left.location.loc of
+ LOC_FPUREGISTER:
+ ;
+ LOC_CFPUREGISTER:
+ begin
+ cg.a_loadfpu_reg_reg(exprasmlist,left.location.size,
+ left.location.register,location.register);
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ cg.a_loadfpu_ref_reg(exprasmlist,
+ def_cgsize(left.resulttype.def),
+ left.location.reference,location.register);
+ end
+ else
+ internalerror(309991);
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_arctan_real;
+ begin
+ load_fpu_location;
+ emit_none(A_FLD1,S_NO);
+ emit_none(A_FPATAN,S_NO);
+ end;
+
+
+ procedure tx86inlinenode.second_abs_real;
+ var
+ href : treference;
+ begin
+ if use_sse(resulttype.def) then
+ begin
+ secondpass(left);
+ location_force_mmregscalar(exprasmlist,left.location,false);
+ location:=left.location;
+ case tfloatdef(resulttype.def).typ of
+ s32real:
+ reference_reset_symbol(href,
+ objectlibrary.newasmsymbol('FPC_ABSMASK_SINGLE',AB_EXTERNAL,AT_DATA),0);
+ s64real:
+ reference_reset_symbol(href,
+ objectlibrary.newasmsymbol('FPC_ABSMASK_DOUBLE',AB_EXTERNAL,AT_DATA),0);
+ else
+ internalerror(200506081);
+ end;
+ exprasmlist.concat(taicpu.op_ref_reg(A_ANDPS,S_XMM,href,location.register))
+ end
+ else
+ begin
+ load_fpu_location;
+ emit_none(A_FABS,S_NO);
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_sqr_real;
+
+ begin
+ if use_sse(resulttype.def) then
+ begin
+ secondpass(left);
+ location_force_mmregscalar(exprasmlist,left.location,false);
+ location:=left.location;
+ cg.a_opmm_loc_reg(exprasmlist,OP_MUL,left.location.size,left.location,left.location.register,mms_movescalar);
+ end
+ else
+ begin
+ load_fpu_location;
+ emit_reg_reg(A_FMUL,S_NO,NR_ST0,NR_ST0);
+ end;
+ end;
+
+ procedure tx86inlinenode.second_sqrt_real;
+ begin
+ if use_sse(resulttype.def) then
+ begin
+ secondpass(left);
+ location_force_mmregscalar(exprasmlist,left.location,false);
+ location:=left.location;
+ case tfloatdef(resulttype.def).typ of
+ s32real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_SQRTSS,S_XMM,location.register,location.register));
+ s64real:
+ exprasmlist.concat(taicpu.op_reg_reg(A_SQRTSD,S_XMM,location.register,location.register));
+ else
+ internalerror(200510031);
+ end;
+ end
+ else
+ begin
+ load_fpu_location;
+ emit_none(A_FSQRT,S_NO);
+ end;
+ end;
+
+ procedure tx86inlinenode.second_ln_real;
+ begin
+ load_fpu_location;
+ emit_none(A_FLDLN2,S_NO);
+ emit_none(A_FXCH,S_NO);
+ emit_none(A_FYL2X,S_NO);
+ end;
+
+ procedure tx86inlinenode.second_cos_real;
+ begin
+ load_fpu_location;
+ emit_none(A_FCOS,S_NO);
+ end;
+
+ procedure tx86inlinenode.second_sin_real;
+ begin
+ load_fpu_location;
+ emit_none(A_FSIN,S_NO)
+ end;
+
+ procedure tx86inlinenode.second_prefetch;
+ var
+ ref : treference;
+ r : tregister;
+ begin
+{$ifdef i386}
+ if aktspecificoptprocessor>=ClassPentium3 then
+{$endif i386}
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ r:=cg.getintregister(exprasmlist,OS_ADDR);
+ cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,r);
+ reference_reset_base(ref,r,0);
+ exprasmlist.concat(taicpu.op_ref(A_PREFETCHNTA,S_NO,ref));
+ end;
+ else
+ internalerror(200402021);
+ end;
+ end;
+ end;
+
+{*****************************************************************************
+ INCLUDE/EXCLUDE GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tx86inlinenode.second_IncludeExclude;
+ var
+ hregister : tregister;
+ asmop : tasmop;
+ bitsperop,l : longint;
+ cgop : topcg;
+ opsize : tcgsize;
+ begin
+ opsize:=OS_32;
+ bitsperop:=(8*tcgsize2size[opsize]);
+ secondpass(tcallparanode(left).left);
+ if tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn then
+ begin
+ { calculate bit position }
+ l:=1 shl (tordconstnode(tcallparanode(tcallparanode(left).right).left).value mod bitsperop);
+
+ { determine operator }
+ if inlinenumber=in_include_x_y then
+ cgop:=OP_OR
+ else
+ begin
+ cgop:=OP_AND;
+ l:=not(l);
+ end;
+ case tcallparanode(left).left.location.loc of
+ LOC_REFERENCE :
+ begin
+ inc(tcallparanode(left).left.location.reference.offset,
+ (tordconstnode(tcallparanode(tcallparanode(left).right).left).value div bitsperop)*tcgsize2size[opsize]);
+ cg.a_op_const_ref(exprasmlist,cgop,opsize,l,tcallparanode(left).left.location.reference);
+ end;
+ LOC_CREGISTER :
+ cg.a_op_const_reg(exprasmlist,cgop,tcallparanode(left).left.location.size,l,tcallparanode(left).left.location.register);
+ else
+ internalerror(200405022);
+ end;
+ end
+ else
+ begin
+ { generate code for the element to set }
+ secondpass(tcallparanode(tcallparanode(left).right).left);
+ { determine asm operator }
+ if inlinenumber=in_include_x_y then
+ asmop:=A_BTS
+ else
+ asmop:=A_BTR;
+
+ if tcallparanode(tcallparanode(left).right).left.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
+ { we don't need a mod 32 because this is done automatically }
+ { by the bts instruction. For proper checking we would }
+
+ { note: bts doesn't do any mod'ing, that's why we can also use }
+ { it for normalsets! (JM) }
+
+ { need a cmp and jmp, but this should be done by the }
+ { type cast code which does range checking if necessary (FK) }
+ hregister:=cg.makeregsize(exprasmlist,Tcallparanode(Tcallparanode(left).right).left.location.register,opsize)
+ else
+ hregister:=cg.getintregister(exprasmlist,opsize);
+ cg.a_load_loc_reg(exprasmlist,opsize,tcallparanode(tcallparanode(left).right).left.location,hregister);
+ if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
+ emit_reg_ref(asmop,tcgsize2opsize[opsize],hregister,tcallparanode(left).left.location.reference)
+ else
+ emit_reg_reg(asmop,tcgsize2opsize[opsize],hregister,tcallparanode(left).left.location.register);
+ end;
+ end;
+
+
+end.
diff --git a/compiler/x86/nx86mat.pas b/compiler/x86/nx86mat.pas
new file mode 100644
index 0000000000..b547bbb3ed
--- /dev/null
+++ b/compiler/x86/nx86mat.pas
@@ -0,0 +1,317 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86 code for math 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 nx86mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat;
+
+ type
+ tx86unaryminusnode = class(tcgunaryminusnode)
+{$ifdef SUPPORT_MMX}
+ procedure second_mmx;override;
+{$endif SUPPORT_MMX}
+ procedure second_float;override;
+ function pass_1:tnode;override;
+ end;
+
+ tx86notnode = class(tcgnotnode)
+ procedure second_boolean;override;
+{$ifdef SUPPORT_MMX}
+ procedure second_mmx;override;
+{$endif SUPPORT_MMX}
+ end;
+
+ implementation
+
+ uses
+ globtype,
+ systems,
+ cutils,verbose,globals,
+ symconst,symdef,
+ aasmbase,aasmtai,defutil,
+ cgbase,pass_1,pass_2,
+ ncon,
+ cpubase,
+ cga,ncgutil,cgobj,cgx86,cgutils;
+
+
+{*****************************************************************************
+ TI386UNARYMINUSNODE
+*****************************************************************************}
+
+ function tx86unaryminusnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ if (left.resulttype.def.deftype=floatdef) then
+ begin
+ if use_sse(left.resulttype.def) then
+ begin
+ if (registersmm < 1) then
+ registersmm := 1;
+ expectloc:=LOC_MMREGISTER;
+ end
+ else
+ begin
+ if (registersfpu < 1) then
+ registersfpu := 1;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+ end
+{$ifdef SUPPORT_MMX}
+ else
+ if (cs_mmx in aktlocalswitches) and
+ is_mmx_able_array(left.resulttype.def) then
+ begin
+ registersint:=left.registersint;
+ registersfpu:=left.registersfpu;
+ registersmmx:=left.registersmmx;
+ if (left.location.loc<>LOC_MMXREGISTER) and
+ (registersmmx<1) then
+ registersmmx:=1;
+ end
+{$endif SUPPORT_MMX}
+ else
+ inherited pass_1;
+ end;
+
+
+{$ifdef SUPPORT_MMX}
+ procedure tx86unaryminusnode.second_mmx;
+ var
+ op : tasmop;
+ hreg : tregister;
+ begin
+ secondpass(left);
+ location_reset(location,LOC_MMXREGISTER,OS_NO);
+ hreg:=tcgx86(cg).getmmxregister(exprasmlist);
+ emit_reg_reg(A_PXOR,S_NO,hreg,hreg);
+ case left.location.loc of
+ LOC_MMXREGISTER:
+ begin
+ location.register:=left.location.register;
+ end;
+ LOC_CMMXREGISTER:
+ begin
+ location.register:=tcgx86(cg).getmmxregister(exprasmlist);
+ emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ begin
+ location.register:=tcgx86(cg).getmmxregister(exprasmlist);
+ emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
+ end;
+ else
+ internalerror(200203225);
+ end;
+ if cs_mmx_saturation in aktlocalswitches then
+ case mmx_type(resulttype.def) of
+ mmxs8bit:
+ op:=A_PSUBSB;
+ mmxu8bit:
+ op:=A_PSUBUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PSUBSW;
+ mmxu16bit:
+ op:=A_PSUBUSW;
+ end
+ else
+ case mmx_type(resulttype.def) of
+ mmxs8bit,mmxu8bit:
+ op:=A_PSUBB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PSUBW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PSUBD;
+ end;
+ emit_reg_reg(op,S_NO,location.register,hreg);
+ emit_reg_reg(A_MOVQ,S_NO,hreg,location.register);
+ end;
+{$endif SUPPORT_MMX}
+
+
+ procedure tx86unaryminusnode.second_float;
+ var
+ reg : tregister;
+ href : treference;
+ l1 : tasmlabel;
+ begin
+ secondpass(left);
+
+ if expectloc=LOC_MMREGISTER then
+ begin
+ location_force_mmregscalar(exprasmlist,left.location,false);
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resulttype.def));
+
+ { make life of register allocator easier }
+ location.register:=cg.getmmregister(exprasmlist,def_cgsize(resulttype.def));
+ cg.a_loadmm_reg_reg(exprasmlist,def_cgsize(resulttype.def),def_cgsize(resulttype.def),left.location.register,location.register,mms_movescalar);
+
+ reg:=cg.getmmregister(exprasmlist,def_cgsize(resulttype.def));
+
+ objectlibrary.getdatalabel(l1);
+ asmlist[al_typedconsts].concat(Tai_label.Create(l1));
+ case def_cgsize(resulttype.def) of
+ OS_F32:
+ asmlist[al_typedconsts].concat(tai_const.create_32bit(longint(1 shl 31)));
+ OS_F64:
+ begin
+ asmlist[al_typedconsts].concat(tai_const.create_32bit(0));
+ asmlist[al_typedconsts].concat(tai_const.create_32bit(-(1 shl 31)));
+ end
+ else
+ internalerror(2004110215);
+ end;
+
+ reference_reset_symbol(href,l1,0);
+ cg.a_loadmm_ref_reg(exprasmlist,def_cgsize(resulttype.def),def_cgsize(resulttype.def),href,reg,mms_movescalar);
+
+ cg.a_opmm_reg_reg(exprasmlist,OP_XOR,left.location.size,reg,location.register,nil);
+ end
+ else
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+ case left.location.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ begin
+ location.register:=NR_ST;
+ cg.a_loadfpu_ref_reg(exprasmlist,
+ def_cgsize(left.resulttype.def),
+ left.location.reference,location.register);
+ emit_none(A_FCHS,S_NO);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ { "load st,st" is ignored by the code generator }
+ cg.a_loadfpu_reg_reg(exprasmlist,left.location.size,left.location.register,NR_ST);
+ location.register:=NR_ST;
+ emit_none(A_FCHS,S_NO);
+ end;
+ else
+ internalerror(200312241);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TX86NOTNODE
+*****************************************************************************}
+
+ procedure tx86notnode.second_boolean;
+ var
+ hl : tasmlabel;
+ opsize : tcgsize;
+ begin
+ opsize:=def_cgsize(resulttype.def);
+
+ if left.expectloc=LOC_JUMP then
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ secondpass(left);
+ maketojumpbool(exprasmlist,left,lr_load_regvars);
+ hl:=truelabel;
+ truelabel:=falselabel;
+ falselabel:=hl;
+ end
+ else
+ begin
+ { the second pass could change the location of left }
+ { if it is a register variable, so we've to do }
+ { this before the case statement }
+ secondpass(left);
+ case left.expectloc of
+ LOC_FLAGS :
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=left.location.resflags;
+ inverse_flags(location.resflags);
+ end;
+ LOC_CONSTANT,
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location_force_reg(exprasmlist,left.location,opsize,true);
+ emit_reg_reg(A_TEST,TCGSize2Opsize[opsize],left.location.register,left.location.register);
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_E;
+ end;
+ else
+ internalerror(200203224);
+ end;
+ end;
+ end;
+
+
+{$ifdef SUPPORT_MMX}
+ procedure tx86notnode.second_mmx;
+
+ var hreg,r:Tregister;
+
+ begin
+ secondpass(left);
+ location_reset(location,LOC_MMXREGISTER,OS_NO);
+ r:=cg.getintregister(exprasmlist,OS_INT);
+ emit_const_reg(A_MOV,S_L,longint($ffffffff),r);
+ { load operand }
+ case left.location.loc of
+ LOC_MMXREGISTER:
+ location_copy(location,left.location);
+ LOC_CMMXREGISTER:
+ begin
+ location.register:=tcgx86(cg).getmmxregister(exprasmlist);
+ emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ begin
+ location.register:=tcgx86(cg).getmmxregister(exprasmlist);
+ emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
+ end;
+ end;
+ { load mask }
+ hreg:=tcgx86(cg).getmmxregister(exprasmlist);
+ emit_reg_reg(A_MOVD,S_NO,r,hreg);
+ { lower 32 bit }
+ emit_reg_reg(A_PXOR,S_NO,hreg,location.register);
+ { shift mask }
+ emit_const_reg(A_PSLLQ,S_B,32,hreg);
+ { higher 32 bit }
+ emit_reg_reg(A_PXOR,S_NO,hreg,location.register);
+ end;
+{$endif SUPPORT_MMX}
+end.
diff --git a/compiler/x86/nx86set.pas b/compiler/x86/nx86set.pas
new file mode 100644
index 0000000000..0dda7a697b
--- /dev/null
+++ b/compiler/x86/nx86set.pas
@@ -0,0 +1,462 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86 assembler for in/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 nx86set;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nset,pass_1,ncgset;
+
+ type
+
+ tx86innode = class(tinnode)
+ procedure pass_2;override;
+ function pass_1 : tnode;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ verbose,globals,
+ symconst,symdef,defutil,
+ aasmbase,aasmtai,aasmcpu,
+ cgbase,pass_2,tgobj,
+ ncon,
+ cpubase,
+ cga,cgobj,cgutils,ncgutil,
+ cgx86;
+
+{*****************************************************************************
+ TX86INNODE
+*****************************************************************************}
+
+ function tx86innode.pass_1 : tnode;
+ begin
+ result:=nil;
+ { this is the only difference from the generic version }
+ expectloc:=LOC_FLAGS;
+
+ firstpass(right);
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ left_right_max;
+ { a smallset needs maybe an misc. register }
+ if (left.nodetype<>ordconstn) and
+ not(right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) and
+ (right.registersint<1) then
+ inc(registersint);
+ end;
+
+
+
+ procedure tx86innode.pass_2;
+ type
+ Tsetpart=record
+ range : boolean; {Part is a range.}
+ start,stop : byte; {Start/stop when range; Stop=element when an element.}
+ end;
+ var
+ genjumps,
+ use_small,
+ ranges : boolean;
+ hreg,hreg2,
+ pleftreg : tregister;
+ opsize : tcgsize;
+ setparts : array[1..8] of Tsetpart;
+ i,numparts : byte;
+ adjustment : longint;
+ l,l2 : tasmlabel;
+{$ifdef CORRECT_SET_IN_FPC}
+ AM : tasmop;
+{$endif CORRECT_SET_IN_FPC}
+
+ function analizeset(Aset:pconstset;is_small:boolean):boolean;
+ var
+ compares,maxcompares:word;
+ i:byte;
+ begin
+ if tnormalset(Aset^)=[] then
+ {The expression...
+ if expr in []
+ ...is allways false. It should be optimized away in the
+ resulttype pass, and thus never occur here. Since we
+ do generate wrong code for it, do internalerror.}
+ internalerror(2002072301);
+ analizeset:=false;
+ ranges:=false;
+ numparts:=0;
+ compares:=0;
+ { Lots of comparisions take a lot of time, so do not allow
+ too much comparisions. 8 comparisions are, however, still
+ smalller than emitting the set }
+ if cs_littlesize in aktglobalswitches then
+ maxcompares:=8
+ else
+ maxcompares:=5;
+ { when smallset is possible allow only 3 compares the smallset
+ code is for littlesize also smaller when more compares are used }
+ if is_small then
+ maxcompares:=3;
+ for i:=0 to 255 do
+ if i in tnormalset(Aset^) then
+ begin
+ if (numparts=0) or (i<>setparts[numparts].stop+1) then
+ begin
+ {Set element is a separate element.}
+ inc(compares);
+ if compares>maxcompares then
+ exit;
+ inc(numparts);
+ setparts[numparts].range:=false;
+ setparts[numparts].stop:=i;
+ end
+ else
+ {Set element is part of a range.}
+ if not setparts[numparts].range then
+ begin
+ {Transform an element into a range.}
+ setparts[numparts].range:=true;
+ setparts[numparts].start:=setparts[numparts].stop;
+ setparts[numparts].stop:=i;
+ ranges := true;
+ { there's only one compare per range anymore. Only a }
+ { sub is added, but that's much faster than a }
+ { cmp/jcc combo so neglect its effect }
+{ inc(compares);
+ if compares>maxcompares then
+ exit; }
+ end
+ else
+ begin
+ {Extend a range.}
+ setparts[numparts].stop:=i;
+ end;
+ end;
+ analizeset:=true;
+ end;
+
+ begin
+ { We check first if we can generate jumps, this can be done
+ because the resulttype.def is already set in firstpass }
+
+ { check if we can use smallset operation using btl which is limited
+ to 32 bits, the left side may also not contain higher values !! }
+ use_small:=(tsetdef(right.resulttype.def).settype=smallset) and
+ ((left.resulttype.def.deftype=orddef) and (torddef(left.resulttype.def).high<=32) or
+ (left.resulttype.def.deftype=enumdef) and (tenumdef(left.resulttype.def).max<=32));
+
+ { Can we generate jumps? Possible for all types of sets }
+ genjumps:=(right.nodetype=setconstn) and
+ analizeset(tsetconstnode(right).value_set,use_small);
+ { calculate both operators }
+ { the complex one first }
+ firstcomplex(self);
+ secondpass(left);
+ { Only process the right if we are not generating jumps }
+ if not genjumps then
+ begin
+ secondpass(right);
+ end;
+ if codegenerror then
+ exit;
+
+ { ofcourse not commutative }
+ if nf_swaped in flags then
+ swapleftright;
+
+ if genjumps then
+ begin
+ { It gives us advantage to check for the set elements
+ separately instead of using the SET_IN_BYTE procedure.
+ To do: Build in support for LOC_JUMP }
+
+ opsize := def_cgsize(left.resulttype.def);
+ { If register is used, use only lower 8 bits }
+ if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ begin
+ { for ranges we always need a 32bit register, because then we }
+ { use the register as base in a reference (JM) }
+ if ranges then
+ begin
+ pleftreg:=cg.makeregsize(exprasmlist,left.location.register,OS_INT);
+ cg.a_load_reg_reg(exprasmlist,left.location.size,OS_INT,left.location.register,pleftreg);
+ if opsize<>OS_INT then
+ cg.a_op_const_reg(exprasmlist,OP_AND,OS_INT,255,pleftreg);
+ opsize:=OS_INT;
+ end
+ else
+ { otherwise simply use the lower 8 bits (no "and" }
+ { necessary this way) (JM) }
+ begin
+ pleftreg:=cg.makeregsize(exprasmlist,left.location.register,OS_8);
+ opsize := OS_8;
+ end;
+ end
+ else
+ begin
+ { load the value in a register }
+ pleftreg:=cg.getintregister(exprasmlist,OS_32);
+ opsize:=OS_32;
+ cg.a_load_ref_reg(exprasmlist,OS_8,OS_32,left.location.reference,pleftreg);
+ end;
+
+ { Get a label to jump to the end }
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ { It's better to use the zero flag when there are
+ no ranges }
+ if ranges then
+ location.resflags:=F_C
+ else
+ location.resflags:=F_E;
+
+ objectlibrary.getjumplabel(l);
+
+ { how much have we already substracted from the x in the }
+ { "x in [y..z]" expression }
+ adjustment := 0;
+
+ for i:=1 to numparts do
+ if setparts[i].range then
+ { use fact that a <= x <= b <=> cardinal(x-a) <= cardinal(b-a) }
+ begin
+ { is the range different from all legal values? }
+ if (setparts[i].stop-setparts[i].start <> 255) then
+ begin
+ { yes, is the lower bound <> 0? }
+ if (setparts[i].start <> 0) then
+ begin
+ if (left.location.loc = LOC_CREGISTER) then
+ begin
+ hreg:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_reg_reg(exprasmlist,opsize,OS_INT,pleftreg,hreg);
+ pleftreg:=hreg;
+ opsize:=OS_INT;
+ end;
+ cg.a_op_const_reg(exprasmlist,OP_SUB,opsize,setparts[i].start-adjustment,pleftreg);
+ end;
+
+ { new total value substracted from x: }
+ { adjustment + (setparts[i].start - adjustment) }
+ adjustment := setparts[i].start;
+
+ { check if result < b-a+1 (not "result <= b-a", since }
+ { we need a carry in case the element is in the range }
+ { (this will never overflow since we check at the }
+ { beginning whether stop-start <> 255) }
+ cg.a_cmp_const_reg_label(exprasmlist,opsize,OC_B,setparts[i].stop-setparts[i].start+1,pleftreg,l);
+ end
+ else
+ { if setparts[i].start = 0 and setparts[i].stop = 255, }
+ { it's always true since "in" is only allowed for bytes }
+ begin
+ exprasmlist.concat(taicpu.op_none(A_STC,S_NO));
+ cg.a_jmp_always(exprasmlist,l);
+ end;
+ end
+ else
+ begin
+ { Emit code to check if left is an element }
+ exprasmlist.concat(taicpu.op_const_reg(A_CMP,TCGSize2OpSize[opsize],setparts[i].stop-adjustment,
+ pleftreg));
+ { Result should be in carry flag when ranges are used }
+ if ranges then
+ exprasmlist.concat(taicpu.op_none(A_STC,S_NO));
+ { If found, jump to end }
+ cg.a_jmp_flags(exprasmlist,F_E,l);
+ end;
+ if ranges and
+ { if the last one was a range, the carry flag is already }
+ { set appropriately }
+ not(setparts[numparts].range) then
+ exprasmlist.concat(taicpu.op_none(A_CLC,S_NO));
+ { To compensate for not doing a second pass }
+ right.location.reference.symbol:=nil;
+ { Now place the end label }
+ cg.a_label(exprasmlist,l);
+ end
+ else
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ { We will now generated code to check the set itself, no jmps,
+ handle smallsets separate, because it allows faster checks }
+ if use_small then
+ begin
+ if left.nodetype=ordconstn then
+ begin
+ location.resflags:=F_NE;
+ case right.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ emit_const_reg(A_TEST,S_L,
+ 1 shl (tordconstnode(left).value and 31),right.location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ emit_const_ref(A_TEST,S_L,1 shl (tordconstnode(left).value and 31),
+ right.location.reference);
+ end;
+ else
+ internalerror(200203312);
+ end;
+ end
+ else
+ begin
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ hreg:=cg.makeregsize(exprasmlist,left.location.register,OS_32);
+ cg.a_load_reg_reg(exprasmlist,left.location.size,OS_32,left.location.register,hreg);
+ end;
+ else
+ begin
+ { the set element isn't never samller than a byte
+ and because it's a small set we need only 5 bits
+ but 8 bits are easier to load }
+ hreg:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_ref_reg(exprasmlist,OS_8,OS_32,left.location.reference,hreg);
+ end;
+ end;
+
+ case right.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ emit_reg_reg(A_BT,S_L,hreg,right.location.register);
+ end;
+ LOC_CONSTANT :
+ begin
+ { We have to load the value into a register because
+ btl does not accept values only refs or regs (PFV) }
+ hreg2:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_const_reg(exprasmlist,OS_32,right.location.value,hreg2);
+ emit_reg_reg(A_BT,S_L,hreg,hreg2);
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ emit_reg_ref(A_BT,S_L,hreg,right.location.reference);
+ end;
+ else
+ internalerror(2002032210);
+ end;
+ location.resflags:=F_C;
+ end;
+ end
+ else
+ begin
+ if right.location.loc=LOC_CONSTANT then
+ begin
+ location.resflags:=F_C;
+ objectlibrary.getjumplabel(l);
+ objectlibrary.getjumplabel(l2);
+
+ { load constants to a register }
+ if left.nodetype=ordconstn then
+ location_force_reg(exprasmlist,left.location,OS_INT,true);
+
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ hreg:=cg.makeregsize(exprasmlist,left.location.register,OS_32);
+ cg.a_load_reg_reg(exprasmlist,left.location.size,OS_32,left.location.register,hreg);
+ cg.a_cmp_const_reg_label(exprasmlist,OS_32,OC_BE,31,hreg,l);
+ { reset carry flag }
+ exprasmlist.concat(taicpu.op_none(A_CLC,S_NO));
+ cg.a_jmp_always(exprasmlist,l2);
+ cg.a_label(exprasmlist,l);
+ { We have to load the value into a register because
+ btl does not accept values only refs or regs (PFV) }
+ hreg2:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_const_reg(exprasmlist,OS_32,right.location.value,hreg2);
+ emit_reg_reg(A_BT,S_L,hreg,hreg2);
+ end;
+ else
+ begin
+{$ifdef CORRECT_SET_IN_FPC}
+ if m_tp in aktmodeswitches then
+ begin
+ {***WARNING only correct if
+ reference is 32 bits (PM) *****}
+ emit_const_ref(A_CMP,S_L,31,reference_copy(left.location.reference));
+ end
+ else
+{$endif CORRECT_SET_IN_FPC}
+ begin
+ emit_const_ref(A_CMP,S_B,31,left.location.reference);
+ end;
+ cg.a_jmp_flags(exprasmlist,F_BE,l);
+ { reset carry flag }
+ exprasmlist.concat(taicpu.op_none(A_CLC,S_NO));
+ cg.a_jmp_always(exprasmlist,l2);
+ cg.a_label(exprasmlist,l);
+ hreg:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_ref_reg(exprasmlist,OS_32,OS_32,left.location.reference,hreg);
+ { We have to load the value into a register because
+ btl does not accept values only refs or regs (PFV) }
+ hreg2:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_const_reg(exprasmlist,OS_32,right.location.value,hreg2);
+ emit_reg_reg(A_BT,S_L,hreg,hreg2);
+ end;
+ end;
+ cg.a_label(exprasmlist,l2);
+ end { of right.location.loc=LOC_CONSTANT }
+ { do search in a normal set which could have >32 elementsm
+ but also used if the left side contains higher values > 32 }
+ else if left.nodetype=ordconstn then
+ begin
+ location.resflags:=F_NE;
+ inc(right.location.reference.offset,tordconstnode(left).value shr 3);
+ emit_const_ref(A_TEST,S_B,1 shl (tordconstnode(left).value and 7),right.location.reference);
+ end
+ else
+ begin
+ if (left.location.loc=LOC_REGISTER) then
+ pleftreg:=cg.makeregsize(exprasmlist,left.location.register,OS_32)
+ else
+ pleftreg:=cg.getintregister(exprasmlist,OS_32);
+ cg.a_load_loc_reg(exprasmlist,OS_32,left.location,pleftreg);
+ location_freetemp(exprasmlist,left.location);
+ emit_reg_ref(A_BT,S_L,pleftreg,right.location.reference);
+ { tg.ungetiftemp(exprasmlist,right.location.reference) happens below }
+ location.resflags:=F_C;
+ end;
+ end;
+ end;
+ if not genjumps then
+ location_freetemp(exprasmlist,right.location);
+ end;
+
+begin
+ cinnode:=tx86innode;
+end.
diff --git a/compiler/x86/rax86.pas b/compiler/x86/rax86.pas
new file mode 100644
index 0000000000..f176bd5fbd
--- /dev/null
+++ b/compiler/x86/rax86.pas
@@ -0,0 +1,715 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Handles the common x86 assembler reader routines
+
+ 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.
+
+ ****************************************************************************
+}
+{
+ Contains the common x86 (i386 and x86-64) assembler reader routines.
+}
+unit rax86;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,rautils,cclasses;
+
+{ Parser helpers }
+function is_prefix(t:tasmop):boolean;
+function is_override(t:tasmop):boolean;
+Function CheckPrefix(prefixop,op:tasmop): Boolean;
+Function CheckOverride(overrideop,op:tasmop): Boolean;
+Procedure FWaitWarning;
+
+type
+ Tx86Operand=class(TOperand)
+ opsize : topsize;
+ Procedure SetSize(_size:longint;force:boolean);override;
+ Procedure SetCorrectSize(opcode:tasmop);override;
+ end;
+
+ Tx86Instruction=class(TInstruction)
+ OpOrder : TOperandOrder;
+ opsize : topsize;
+ constructor Create(optype : tcoperand);override;
+ { Operand sizes }
+ procedure AddReferenceSizes;
+ procedure SetInstructionOpsize;
+ procedure CheckOperandSizes;
+ procedure CheckNonCommutativeOpcodes;
+ procedure SwapOperands;
+ { opcode adding }
+ function ConcatInstruction(p : taasmoutput) : tai;override;
+ end;
+
+const
+ AsmPrefixes = 6;
+ AsmPrefix : array[0..AsmPrefixes-1] of TasmOP =(
+ A_LOCK,A_REP,A_REPE,A_REPNE,A_REPNZ,A_REPZ
+ );
+
+ AsmOverrides = 6;
+ AsmOverride : array[0..AsmOverrides-1] of TasmOP =(
+ A_SEGCS,A_SEGES,A_SEGDS,A_SEGFS,A_SEGGS,A_SEGSS
+ );
+
+ CondAsmOps=3;
+ CondAsmOp:array[0..CondAsmOps-1] of TasmOp=(
+ A_CMOVcc, A_Jcc, A_SETcc
+ );
+ CondAsmOpStr:array[0..CondAsmOps-1] of string[4]=(
+ 'CMOV','J','SET'
+ );
+
+implementation
+
+uses
+ globtype,globals,systems,verbose,
+ cpuinfo,cgbase,cgutils,
+ itcpugas,cgx86;
+
+
+{*****************************************************************************
+ Parser Helpers
+*****************************************************************************}
+
+function is_prefix(t:tasmop):boolean;
+var
+ i : longint;
+Begin
+ is_prefix:=false;
+ for i:=1 to AsmPrefixes do
+ if t=AsmPrefix[i-1] then
+ begin
+ is_prefix:=true;
+ exit;
+ end;
+end;
+
+
+function is_override(t:tasmop):boolean;
+var
+ i : longint;
+Begin
+ is_override:=false;
+ for i:=1 to AsmOverrides do
+ if t=AsmOverride[i-1] then
+ begin
+ is_override:=true;
+ exit;
+ end;
+end;
+
+
+Function CheckPrefix(prefixop,op:tasmop): Boolean;
+{ Checks if the prefix is valid with the following opcode }
+{ return false if not, otherwise true }
+Begin
+ CheckPrefix := TRUE;
+(* Case prefix of
+ A_REP,A_REPNE,A_REPE:
+ Case opcode Of
+ A_SCASB,A_SCASW,A_SCASD,
+ A_INS,A_OUTS,A_MOVS,A_CMPS,A_LODS,A_STOS:;
+ Else
+ Begin
+ CheckPrefix := FALSE;
+ exit;
+ end;
+ end; { case }
+ A_LOCK:
+ Case opcode Of
+ A_BT,A_BTS,A_BTR,A_BTC,A_XCHG,A_ADD,A_OR,A_ADC,A_SBB,A_AND,A_SUB,
+ A_XOR,A_NOT,A_NEG,A_INC,A_DEC:;
+ Else
+ Begin
+ CheckPrefix := FALSE;
+ Exit;
+ end;
+ end; { case }
+ A_NONE: exit; { no prefix here }
+ else
+ CheckPrefix := FALSE;
+ end; { end case } *)
+end;
+
+
+Function CheckOverride(overrideop,op:tasmop): Boolean;
+{ Check if the override is valid, and if so then }
+{ update the instr variable accordingly. }
+Begin
+ CheckOverride := true;
+{ Case instr.getinstruction of
+ A_MOVS,A_XLAT,A_CMPS:
+ Begin
+ CheckOverride := TRUE;
+ Message(assem_e_segment_override_not_supported);
+ end
+ end }
+end;
+
+
+Procedure FWaitWarning;
+begin
+ if (target_info.system=system_i386_GO32V2) and (cs_fp_emulation in aktmoduleswitches) then
+ Message(asmr_w_fwait_emu_prob);
+end;
+
+{*****************************************************************************
+ TX86Operand
+*****************************************************************************}
+
+Procedure Tx86Operand.SetSize(_size:longint;force:boolean);
+begin
+ inherited SetSize(_size,force);
+ { OS_64 will be set to S_L and be fixed later
+ in SetCorrectSize }
+ opsize:=TCGSize2Opsize[size];
+end;
+
+
+Procedure Tx86Operand.SetCorrectSize(opcode:tasmop);
+begin
+ if gas_needsuffix[opcode]=attsufFPU then
+ begin
+ case size of
+ OS_32 : opsize:=S_FS;
+ OS_64 : opsize:=S_FL;
+ end;
+ end
+ else if gas_needsuffix[opcode]=attsufFPUint then
+ begin
+ case size of
+ OS_16 : opsize:=S_IS;
+ OS_32 : opsize:=S_IL;
+ OS_64 : opsize:=S_IQ;
+ end;
+ end;
+end;
+
+
+{*****************************************************************************
+ T386Instruction
+*****************************************************************************}
+
+constructor Tx86Instruction.Create(optype : tcoperand);
+begin
+ inherited Create(optype);
+ Opsize:=S_NO;
+end;
+
+
+procedure Tx86Instruction.SwapOperands;
+begin
+ Inherited SwapOperands;
+ { mark the correct order }
+ if OpOrder=op_intel then
+ OpOrder:=op_att
+ else
+ OpOrder:=op_intel;
+end;
+
+
+procedure Tx86Instruction.AddReferenceSizes;
+{ this will add the sizes for references like [esi] which do not
+ have the size set yet, it will take only the size if the other
+ operand is a register }
+var
+ operand2,i : longint;
+ s : tasmsymbol;
+ so : aint;
+begin
+ for i:=1 to ops do
+ begin
+ operands[i].SetCorrectSize(opcode);
+ if tx86operand(operands[i]).opsize=S_NO then
+ begin
+ case operands[i].Opr.Typ of
+ OPR_LOCAL,
+ OPR_REFERENCE :
+ begin
+ if i=2 then
+ operand2:=1
+ else
+ operand2:=2;
+ if operand2<ops then
+ begin
+ { Only allow register as operand to take the size from }
+ if operands[operand2].opr.typ=OPR_REGISTER then
+ begin
+ if ((opcode<>A_MOVD) and
+ (opcode<>A_CVTSI2SS)) then
+ tx86operand(operands[i]).opsize:=tx86operand(operands[operand2]).opsize;
+ end
+ else
+ begin
+ { if no register then take the opsize (which is available with ATT),
+ if not availble then give an error }
+ if opsize<>S_NO then
+ tx86operand(operands[i]).opsize:=opsize
+ else
+ begin
+ if (m_delphi in aktmodeswitches) then
+ Message(asmr_w_unable_to_determine_reference_size_using_dword)
+ else
+ Message(asmr_e_unable_to_determine_reference_size);
+ { recovery }
+ tx86operand(operands[i]).opsize:=S_L;
+ end;
+ end;
+ end
+ else
+ begin
+ if opsize<>S_NO then
+ tx86operand(operands[i]).opsize:=opsize
+ end;
+ end;
+ OPR_SYMBOL :
+ begin
+ { Fix lea which need a reference }
+ if opcode=A_LEA then
+ begin
+ s:=operands[i].opr.symbol;
+ so:=operands[i].opr.symofs;
+ operands[i].opr.typ:=OPR_REFERENCE;
+ Fillchar(operands[i].opr.ref,sizeof(treference),0);
+ operands[i].opr.ref.symbol:=s;
+ operands[i].opr.ref.offset:=so;
+ end;
+{$ifdef x86_64}
+ tx86operand(operands[i]).opsize:=S_Q;
+{$else x86_64}
+ tx86operand(operands[i]).opsize:=S_L;
+{$endif x86_64}
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+procedure Tx86Instruction.SetInstructionOpsize;
+begin
+ if opsize<>S_NO then
+ exit;
+ if (OpOrder=op_intel) then
+ SwapOperands;
+ case ops of
+ 0 : ;
+ 1 :
+ begin
+ { "push es" must be stored as a long PM }
+ if ((opcode=A_PUSH) or
+ (opcode=A_POP)) and
+ (operands[1].opr.typ=OPR_REGISTER) and
+ is_segment_reg(operands[1].opr.reg) then
+ opsize:=S_L
+ else
+ opsize:=tx86operand(operands[1]).opsize;
+ end;
+ 2 :
+ begin
+ case opcode of
+ A_MOVZX,A_MOVSX :
+ begin
+ case tx86operand(operands[1]).opsize of
+ S_W :
+ case tx86operand(operands[2]).opsize of
+ S_L :
+ opsize:=S_WL;
+ end;
+ S_B :
+ case tx86operand(operands[2]).opsize of
+ S_W :
+ opsize:=S_BW;
+ S_L :
+ opsize:=S_BL;
+ end;
+ end;
+ end;
+ A_MOVD : { movd is a move from a mmx register to a
+ 32 bit register or memory, so no opsize is correct here PM }
+ exit;
+ A_OUT :
+ opsize:=tx86operand(operands[1]).opsize;
+ else
+ opsize:=tx86operand(operands[2]).opsize;
+ end;
+ end;
+ 3 :
+ opsize:=tx86operand(operands[3]).opsize;
+ end;
+end;
+
+
+procedure Tx86Instruction.CheckOperandSizes;
+var
+ sizeerr : boolean;
+ i : longint;
+begin
+ { Check only the most common opcodes here, the others are done in
+ the assembler pass }
+ case opcode of
+ A_PUSH,A_POP,A_DEC,A_INC,A_NOT,A_NEG,
+ A_CMP,A_MOV,
+ A_ADD,A_SUB,A_ADC,A_SBB,
+ A_AND,A_OR,A_TEST,A_XOR: ;
+ else
+ exit;
+ end;
+ { Handle the BW,BL,WL separatly }
+ sizeerr:=false;
+ { special push/pop selector case }
+ if ((opcode=A_PUSH) or
+ (opcode=A_POP)) and
+ (operands[1].opr.typ=OPR_REGISTER) and
+ is_segment_reg(operands[1].opr.reg) then
+ exit;
+ if opsize in [S_BW,S_BL,S_WL] then
+ begin
+ if ops<>2 then
+ sizeerr:=true
+ else
+ begin
+ case opsize of
+ S_BW :
+ sizeerr:=(tx86operand(operands[1]).opsize<>S_B) or (tx86operand(operands[2]).opsize<>S_W);
+ S_BL :
+ sizeerr:=(tx86operand(operands[1]).opsize<>S_B) or (tx86operand(operands[2]).opsize<>S_L);
+ S_WL :
+ sizeerr:=(tx86operand(operands[1]).opsize<>S_W) or (tx86operand(operands[2]).opsize<>S_L);
+ end;
+ end;
+ end
+ else
+ begin
+ for i:=1 to ops do
+ begin
+ if (operands[i].opr.typ<>OPR_CONSTANT) and
+ (tx86operand(operands[i]).opsize in [S_B,S_W,S_L]) and
+ (tx86operand(operands[i]).opsize<>opsize) then
+ sizeerr:=true;
+ end;
+ end;
+ if sizeerr then
+ begin
+ { if range checks are on then generate an error }
+ if (cs_compilesystem in aktmoduleswitches) or
+ not (cs_check_range in aktlocalswitches) then
+ Message(asmr_w_size_suffix_and_dest_dont_match)
+ else
+ Message(asmr_e_size_suffix_and_dest_dont_match);
+ 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 }
+procedure Tx86Instruction.CheckNonCommutativeOpcodes;
+begin
+ if (OpOrder=op_intel) then
+ SwapOperands;
+ if (
+ (ops=2) and
+ (operands[1].opr.typ=OPR_REGISTER) and
+ (operands[2].opr.typ=OPR_REGISTER) and
+ { if the first is ST and the second is also a register
+ it is necessarily ST1 .. ST7 }
+ ((operands[1].opr.reg=NR_ST) or
+ (operands[1].opr.reg=NR_ST0))
+ ) or
+ (ops=0) then
+ if opcode=A_FSUBR then
+ opcode:=A_FSUB
+ else if opcode=A_FSUB then
+ opcode:=A_FSUBR
+ else if opcode=A_FDIVR then
+ opcode:=A_FDIV
+ else if opcode=A_FDIV then
+ opcode:=A_FDIVR
+ else if opcode=A_FSUBRP then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBP then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIVRP then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVP then
+ opcode:=A_FDIVRP;
+ if (
+ (ops=1) and
+ (operands[1].opr.typ=OPR_REGISTER) and
+ (getregtype(operands[1].opr.reg)=R_FPUREGISTER) and
+ (operands[1].opr.reg<>NR_ST) and
+ (operands[1].opr.reg<>NR_ST0)
+ ) then
+ if opcode=A_FSUBRP then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBP then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIVRP then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVP then
+ opcode:=A_FDIVRP;
+end;
+
+{*****************************************************************************
+ opcode Adding
+*****************************************************************************}
+
+function Tx86Instruction.ConcatInstruction(p : taasmoutput) : tai;
+var
+ siz : topsize;
+ i,asize : longint;
+ ai : taicpu;
+begin
+ if (OpOrder=op_intel) then
+ SwapOperands;
+
+{ Get Opsize }
+ if (opsize<>S_NO) or (Ops=0) then
+ siz:=opsize
+ else
+ begin
+ if (Ops=2) and (operands[1].opr.typ=OPR_REGISTER) then
+ siz:=tx86operand(operands[1]).opsize
+ else
+ siz:=tx86operand(operands[Ops]).opsize;
+ { MOVD should be of size S_LQ or S_QL, but these do not exist PM }
+ if (ops=2) and
+ (tx86operand(operands[1]).opsize<>S_NO) and
+ (tx86operand(operands[2]).opsize<>S_NO) and
+ (tx86operand(operands[1]).opsize<>tx86operand(operands[2]).opsize) then
+ siz:=S_NO;
+ end;
+
+ if ((opcode=A_MOVD)or
+ (opcode=A_CVTSI2SS)) and
+ ((tx86operand(operands[1]).opsize=S_NO) or
+ (tx86operand(operands[2]).opsize=S_NO)) then
+ siz:=S_NO;
+ { NASM does not support FADD without args
+ as alias of FADDP
+ and GNU AS interprets FADD without operand differently
+ for version 2.9.1 and 2.9.5 !! }
+ if (ops=0) and
+ ((opcode=A_FADD) or
+ (opcode=A_FMUL) or
+ (opcode=A_FSUB) or
+ (opcode=A_FSUBR) or
+ (opcode=A_FDIV) or
+ (opcode=A_FDIVR)) then
+ begin
+ if opcode=A_FADD then
+ opcode:=A_FADDP
+ else if opcode=A_FMUL then
+ opcode:=A_FMULP
+ else if opcode=A_FSUB then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBR then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIV then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVR then
+ opcode:=A_FDIVRP;
+ message1(asmr_w_fadd_to_faddp,std_op2str[opcode]);
+ end;
+
+ {It is valid to specify some instructions without operand size.}
+ if siz=S_NO then
+ begin
+ if (ops=1) and (opcode=A_INT) then
+ siz:=S_B;
+ if (ops=1) and (opcode=A_RET) or (opcode=A_RETN) or (opcode=A_RETF) then
+ siz:=S_W;
+ if (ops=1) and (opcode=A_PUSH) then
+ begin
+ {We are a 32 compiler, assume 32-bit by default. This is Delphi
+ compatible but bad coding practise.}
+ siz:=S_L;
+ message(asmr_w_unable_to_determine_reference_size_using_dword);
+ end;
+ if (opcode=A_JMP) or (opcode=A_JCC) or (opcode=A_CALL) then
+ if ops=1 then
+ siz:=S_NEAR
+ else
+ siz:=S_FAR;
+ end;
+
+
+ { GNU AS interprets FDIV without operand differently
+ for version 2.9.1 and 2.10
+ we add explicit args to it !! }
+ if (ops=0) and
+ ((opcode=A_FSUBP) or
+ (opcode=A_FSUBRP) or
+ (opcode=A_FDIVP) or
+ (opcode=A_FDIVRP) or
+ (opcode=A_FSUB) or
+ (opcode=A_FSUBR) or
+ (opcode=A_FADD) or
+ (opcode=A_FADDP) or
+ (opcode=A_FDIV) or
+ (opcode=A_FDIVR)) then
+ begin
+ message1(asmr_w_adding_explicit_args_fXX,std_op2str[opcode]);
+ ops:=2;
+ operands[1].opr.typ:=OPR_REGISTER;
+ operands[2].opr.typ:=OPR_REGISTER;
+ operands[1].opr.reg:=NR_ST0;
+ operands[2].opr.reg:=NR_ST1;
+ end;
+ if (ops=1) and
+ (
+ (operands[1].opr.typ=OPR_REGISTER) and
+ (getregtype(operands[1].opr.reg)=R_FPUREGISTER) and
+ (operands[1].opr.reg<>NR_ST) and
+ (operands[1].opr.reg<>NR_ST0)
+ ) and
+ (
+ (opcode=A_FSUBP) or
+ (opcode=A_FSUBRP) or
+ (opcode=A_FDIVP) or
+ (opcode=A_FDIVRP) or
+ (opcode=A_FADDP) or
+ (opcode=A_FMULP)
+ ) then
+ begin
+ message1(asmr_w_adding_explicit_first_arg_fXX,std_op2str[opcode]);
+ ops:=2;
+ operands[2].opr.typ:=OPR_REGISTER;
+ operands[2].opr.reg:=operands[1].opr.reg;
+ operands[1].opr.reg:=NR_ST0;
+ end;
+
+ if (ops=1) and
+ (
+ (operands[1].opr.typ=OPR_REGISTER) and
+ (getregtype(operands[1].opr.reg)=R_FPUREGISTER) and
+ (operands[1].opr.reg<>NR_ST) and
+ (operands[1].opr.reg<>NR_ST0)
+ ) and
+ (
+ (opcode=A_FSUB) or
+ (opcode=A_FSUBR) or
+ (opcode=A_FDIV) or
+ (opcode=A_FDIVR) or
+ (opcode=A_FADD) or
+ (opcode=A_FMUL)
+ ) then
+ begin
+ message1(asmr_w_adding_explicit_second_arg_fXX,std_op2str[opcode]);
+ ops:=2;
+ operands[2].opr.typ:=OPR_REGISTER;
+ operands[2].opr.reg:=NR_ST0;
+ end;
+
+ { I tried to convince Linus Torvalds to add
+ code to support ENTER instruction
+ (when raising a stack page fault)
+ but he replied that ENTER is a bad instruction and
+ Linux does not need to support it
+ So I think its at least a good idea to add a warning
+ if someone uses this in assembler code
+ FPC itself does not use it at all PM }
+ if (opcode=A_ENTER) and
+ (target_info.system in [system_i386_linux,system_i386_FreeBSD]) then
+ Message(asmr_w_enter_not_supported_by_linux);
+
+ ai:=taicpu.op_none(opcode,siz);
+ ai.SetOperandOrder(OpOrder);
+ ai.Ops:=Ops;
+ ai.Allocate_oper(Ops);
+ for i:=1 to Ops do
+ case operands[i].opr.typ of
+ OPR_CONSTANT :
+ ai.loadconst(i-1,operands[i].opr.val);
+ OPR_REGISTER:
+ ai.loadreg(i-1,operands[i].opr.reg);
+ OPR_SYMBOL:
+ ai.loadsymbol(i-1,operands[i].opr.symbol,operands[i].opr.symofs);
+ OPR_LOCAL :
+ with operands[i].opr do
+ ai.loadlocal(i-1,localsym,localsymofs,localindexreg,
+ localscale,localgetoffset,localforceref);
+ OPR_REFERENCE:
+ begin
+ ai.loadref(i-1,operands[i].opr.ref);
+ if operands[i].size<>OS_NO then
+ begin
+ asize:=0;
+ case operands[i].size of
+ OS_8,OS_S8 :
+ asize:=OT_BITS8;
+ OS_16,OS_S16 :
+ asize:=OT_BITS16;
+ OS_32,OS_S32,OS_F32 :
+ asize:=OT_BITS32;
+ OS_64,OS_S64:
+ begin
+ { Only FPU operations know about 64bit values, for all
+ integer operations it is seen as 32bit }
+ if gas_needsuffix[opcode] in [attsufFPU,attsufFPUint] then
+ asize:=OT_BITS64
+ else
+ asize:=OT_BITS32;
+ end;
+ OS_F64,OS_C64 :
+ asize:=OT_BITS64;
+ OS_F80 :
+ asize:=OT_BITS80;
+ end;
+ if asize<>0 then
+ ai.oper[i-1]^.ot:=(ai.oper[i-1]^.ot and not OT_SIZE_MASK) or asize;
+ end;
+ end;
+ end;
+
+ {This is dead code since opcode and opsize aren't used from here!
+ Commented out...
+ if (opcode=A_CALL) and (opsize=S_FAR) then
+ opcode:=A_LCALL;
+ if (opcode=A_JMP) and (opsize=S_FAR) then
+ opcode:=A_LJMP;
+ if (opcode=A_LCALL) or (opcode=A_LJMP) then
+ opsize:=S_FAR;}
+
+ { Condition ? }
+ if condition<>C_None then
+ ai.SetCondition(condition);
+
+ { Concat the opcode or give an error }
+ if assigned(ai) then
+ begin
+ { Check the instruction if it's valid }
+{$ifndef NOAG386BIN}
+{$ifndef x86_64}
+ ai.CheckIfValid;
+{$endif x86_64}
+{$endif NOAG386BIN}
+ p.concat(ai);
+ end
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ result:=ai;
+end;
+
+end.
diff --git a/compiler/x86/rax86att.pas b/compiler/x86/rax86att.pas
new file mode 100644
index 0000000000..0cb092c955
--- /dev/null
+++ b/compiler/x86/rax86att.pas
@@ -0,0 +1,808 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the x86 GNU AS styled inline assembler.
+
+ 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 rax86att;
+
+{$i fpcdefs.inc}
+
+Interface
+
+ uses
+ cpubase,
+ raatt,rax86;
+
+ type
+ tx86attreader = class(tattreader)
+ ActOpsize : topsize;
+ function is_asmopcode(const s: string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tx86operand);
+ procedure BuildOperand(oper : tx86operand);
+ procedure BuildOpCode(instr : tx86instruction);
+ procedure handlepercent;override;
+ end;
+
+
+Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,verbose,
+ systems,
+ { aasm }
+ aasmbase,aasmtai,aasmcpu,
+ { symtable }
+ symconst,
+ { parser }
+ scanner,
+ procinfo,
+ itcpugas,
+ rabase,rautils,
+ cgbase
+ ;
+
+ procedure tx86attreader.handlepercent;
+ var
+ len : longint;
+ begin
+ len:=1;
+ actasmpattern[len]:='%';
+ c:=current_scanner.asmgetchar;
+ { to be a register there must be a letter and not a number }
+ if c in ['0'..'9'] then
+ begin
+ actasmtoken:=AS_MOD;
+ end
+ else
+ begin
+ while c in ['a'..'z','A'..'Z','0'..'9'] do
+ Begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ uppervar(actasmpattern);
+ if (actasmpattern = '%ST') and (c='(') then
+ Begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ if c in ['0'..'9'] then
+ actasmpattern:=actasmpattern + c
+ else
+ Message(asmr_e_invalid_fpu_register);
+ c:=current_scanner.asmgetchar;
+ if c <> ')' then
+ Message(asmr_e_invalid_fpu_register)
+ else
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar; { let us point to next character. }
+ end;
+ end;
+ if is_register(actasmpattern) then
+ exit;
+ Message(asmr_e_invalid_register);
+ actasmtoken:=raatt.AS_NONE;
+ end;
+ end;
+
+
+ Procedure tx86attreader.BuildReference(oper : tx86operand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken <> AS_RPAREN then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+
+ procedure Consume_Scale;
+ var
+ l : aint;
+ begin
+ { we have to process the scaling }
+ l:=BuildConstExpression(false,true);
+ if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
+ oper.opr.ref.scalefactor:=l
+ else
+ Begin
+ Message(asmr_e_wrong_scale_factor);
+ oper.opr.ref.scalefactor:=0;
+ end;
+ end;
+
+
+ begin
+ oper.InitRef;
+ Consume(AS_LPAREN);
+ Case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS: { absolute offset, such as fs:(0x046c) }
+ Begin
+ { offset(offset) is invalid }
+ If oper.opr.Ref.Offset <> 0 Then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ End
+ Else
+ Begin
+ oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+ Consume_RParen;
+ end;
+ exit;
+ End;
+ AS_REGISTER: { (reg ... }
+ Begin
+ { Check if there is already a base (mostly ebp,esp) than this is
+ not allowed, because it will give crashing code }
+ if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
+ ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
+ message(asmr_e_cannot_index_relative_var);
+ oper.opr.ref.base:=actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { (reg) }
+ if actasmtoken=AS_RPAREN then
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ { (reg,reg .. }
+ Consume(AS_COMMA);
+ if actasmtoken=AS_REGISTER then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ case actasmtoken of
+ AS_RPAREN:
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ AS_COMMA:
+ Begin
+ Consume(AS_COMMA);
+ Consume_Scale;
+ Consume_RParen;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; { end case }
+ end
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; {end case }
+ AS_COMMA: { (, ... can either be scaling, or index }
+ Begin
+ Consume(AS_COMMA);
+ { Index }
+ if (actasmtoken=AS_REGISTER) then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ case actasmtoken of
+ AS_RPAREN:
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ AS_COMMA:
+ Begin
+ Consume(AS_COMMA);
+ Consume_Scale;
+ Consume_RParen;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; {end case }
+ end
+ { Scaling }
+ else
+ Begin
+ Consume_Scale;
+ Consume_RParen;
+ exit;
+ end;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ end;
+
+
+ Procedure tx86attreader.BuildOperand(oper : tx86operand);
+ var
+ tempstr,
+ expr : string;
+ typesize,l,k : aint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (oper.opr.localsym.owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ procedure handleat;
+ begin
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k);
+ inc(oper.opr.ref.offset,l);
+ end;
+ if actasmtoken=AS_AT then
+ begin
+ consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ if actasmpattern='GOTPCREL' then
+ oper.opr.ref.refaddr:=addr_pic
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+ var
+ tempreg : tregister;
+ hl : tasmlabel;
+ Begin
+ expr:='';
+ case actasmtoken of
+ AS_LPAREN: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_DOLLAR: { Constant expression }
+ Begin
+ Consume(AS_DOLLAR);
+ BuildConstantOperand(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+
+ AS_STAR: { Call from memory address }
+ Begin
+ Consume(AS_STAR);
+ if actasmtoken=AS_REGISTER then
+ begin
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=actasmregister;
+ oper.SetSize(tcgsize2size[reg_cgsize(actasmregister)],true);
+ Consume(AS_REGISTER);
+ end
+ else
+ begin
+ oper.InitRef;
+ if not MaybeBuildReference then
+ Message(asmr_e_syn_operand);
+ end;
+ { this is only allowed for call's and jmp's }
+ if not is_calljmp(actopcode) then
+ Message(asmr_e_syn_operand);
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr,false) then
+ begin
+ if actasmtoken=AS_AT then
+ begin
+ consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ if actasmpattern='GOTPCREL' then
+ begin
+ oper.opr.ref.refaddr:=addr_pic;
+ consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end
+ else
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if actasmtoken = AS_COLON then
+ Begin
+ Consume(AS_COLON);
+ oper.InitRef;
+ oper.opr.ref.segment:=tempreg;
+ { This must absolutely be followed by a reference }
+ if not MaybeBuildReference then
+ Begin
+ Message(asmr_e_invalid_seg_override);
+ Consume(actasmtoken);
+ end;
+ end
+ { Simple register }
+ else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ oper.SetSize(tcgsize2size[reg_cgsize(oper.opr.reg)],true);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+ procedure tx86attreader.BuildOpCode(instr : tx86instruction);
+ var
+ operandnum : longint;
+ PrefixOp,OverrideOp: tasmop;
+ Begin
+ PrefixOp:=A_None;
+ OverrideOp:=A_None;
+ { prefix seg opcode / prefix opcode }
+ repeat
+ if is_prefix(actopcode) then
+ begin
+ PrefixOp:=ActOpcode;
+ with instr do
+ begin
+ opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ ConcatInstruction(curlist);
+ end;
+ Consume(AS_OPCODE);
+ end
+ else
+ if is_override(actopcode) then
+ begin
+ OverrideOp:=ActOpcode;
+ with instr do
+ begin
+ opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ ConcatInstruction(curlist);
+ end;
+ Consume(AS_OPCODE);
+ end
+ else
+ break;
+ { allow for newline as in gas styled syntax }
+ while actasmtoken=AS_SEPARATOR do
+ Consume(AS_SEPARATOR);
+ until (actasmtoken<>AS_OPCODE);
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ end;
+
+ { Valid combination of prefix/override and instruction ? }
+
+ if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
+ Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
+
+ if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
+ Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum > Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tx86operand);
+ end; { end case }
+ until false;
+ instr.Ops:=operandnum;
+ end;
+
+
+ function tx86attreader.is_asmopcode(const s: string):boolean;
+ const
+ { We need first to check the long prefixes, else we get probs
+ with things like movsbl }
+ att_sizesuffixstr : array[0..9] of string[2] = (
+ '','BW','BL','WL','B','W','L','S','Q','T'
+ );
+ att_sizesuffix : array[0..9] of topsize = (
+ S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
+ );
+ att_sizefpusuffix : array[0..9] of topsize = (
+ S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
+ );
+ att_sizefpuintsuffix : array[0..9] of topsize = (
+ S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
+ );
+ var
+ str2opentry: tstr2opentry;
+ cond : string[4];
+ cnd : tasmcond;
+ len,
+ j,
+ sufidx : longint;
+ Begin
+ is_asmopcode:=FALSE;
+
+ actopcode:=A_None;
+ actcondition:=C_None;
+ actopsize:=S_NO;
+
+ { search for all possible suffixes }
+ for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
+ begin
+ len:=length(s)-length(att_sizesuffixstr[sufidx]);
+ if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
+ begin
+ { here we search the entire table... }
+ str2opentry:=nil;
+ if {(length(s)>0) and} (len>0) then
+ str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
+ if assigned(str2opentry) then
+ begin
+ actopcode:=str2opentry.op;
+ if gas_needsuffix[actopcode]=attsufFPU then
+ actopsize:=att_sizefpusuffix[sufidx]
+ else if gas_needsuffix[actopcode]=attsufFPUint then
+ actopsize:=att_sizefpuintsuffix[sufidx]
+ else
+ actopsize:=att_sizesuffix[sufidx];
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=TRUE;
+ exit;
+ end;
+ { not found, check condition opcodes }
+ j:=0;
+ while (j<CondAsmOps) do
+ begin
+ if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
+ begin
+ cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
+ if cond<>'' then
+ begin
+ for cnd:=low(TasmCond) to high(TasmCond) do
+ if Cond=Upper(cond2str[cnd]) then
+ begin
+ actopcode:=CondASmOp[j];
+ if gas_needsuffix[actopcode]=attsufFPU then
+ actopsize:=att_sizefpusuffix[sufidx]
+ else if gas_needsuffix[actopcode]=attsufFPUint then
+ actopsize:=att_sizefpuintsuffix[sufidx]
+ else
+ actopsize:=att_sizesuffix[sufidx];
+ actcondition:=cnd;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=TRUE;
+ exit;
+ end;
+ end;
+ end;
+ inc(j);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tx86attreader.handleopcode;
+ var
+ instr : Tx86Instruction;
+ begin
+ instr:=Tx86Instruction.Create(Tx86Operand);
+ instr.OpOrder:=op_att;
+ BuildOpcode(instr);
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+
+end.
diff --git a/compiler/x86/rgx86.pas b/compiler/x86/rgx86.pas
new file mode 100644
index 0000000000..725ba50022
--- /dev/null
+++ b/compiler/x86/rgx86.pas
@@ -0,0 +1,346 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the x86 specific class for the register
+ allocator
+
+ 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 rgx86;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,globtype,
+ cpubase,cpuinfo,cgbase,cgutils,
+ aasmbase,aasmtai,aasmcpu,
+ rgobj;
+
+ type
+ trgx86 = class(trgobj)
+ function get_spill_subreg(r : tregister) : tsubregister;override;
+ function do_spill_replace(list:Taasmoutput;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;override;
+ end;
+
+ tpushedsavedloc = record
+ case byte of
+ 0: (pushed: boolean);
+ 1: (ofs: longint);
+ end;
+
+ tpushedsavedfpu = array[tsuperregister] of tpushedsavedloc;
+
+ trgx86fpu = class
+ { The "usableregsxxx" contain all registers of type "xxx" that }
+ { aren't currently allocated to a regvar. The "unusedregsxxx" }
+ { contain all registers of type "xxx" that aren't currently }
+ { allocated }
+ unusedregsfpu,usableregsfpu : Tsuperregisterset;
+ { these counters contain the number of elements in the }
+ { unusedregsxxx/usableregsxxx sets }
+ countunusedregsfpu : byte;
+
+ { Contains the registers which are really used by the proc itself.
+ It doesn't take care of registers used by called procedures
+ }
+ used_in_proc : tcpuregisterset;
+
+ {reg_pushes_other : regvarother_longintarray;
+ is_reg_var_other : regvarother_booleanarray;
+ regvar_loaded_other : regvarother_booleanarray;}
+
+ { tries to hold the amount of times which the current tree is processed }
+ t_times: longint;
+
+ fpuvaroffset : byte;
+
+ constructor create;
+
+ function getregisterfpu(list: taasmoutput) : tregister;
+ procedure ungetregisterfpu(list: taasmoutput; r : tregister);
+
+ { pushes and restores registers }
+ procedure saveusedfpuregisters(list:Taasmoutput;
+ var saved:Tpushedsavedfpu;
+ const s:Tcpuregisterset);
+ procedure restoreusedfpuregisters(list:Taasmoutput;
+ const saved:Tpushedsavedfpu);
+
+ { corrects the fpu stack register by ofs }
+ function correct_fpuregister(r : tregister;ofs : byte) : tregister;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose;
+
+ const
+ { This value is used in tsaved. If the array value is equal
+ to this, then this means that this register is not used.}
+ reg_not_saved = $7fffffff;
+
+
+{******************************************************************************
+ Trgcpu
+******************************************************************************}
+
+ function trgx86.get_spill_subreg(r : tregister) : tsubregister;
+ begin
+ result:=getsubreg(r);
+ end;
+
+
+ function trgx86.do_spill_replace(list:Taasmoutput;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
+ var
+ replaceoper : longint;
+ begin
+ result:=false;
+ with instr do
+ begin
+ replaceoper:=-1;
+ case ops of
+ 1 :
+ begin
+ if (oper[0]^.typ=top_reg) then
+ begin
+ if getsupreg(oper[0]^.reg)<>orgreg then
+ internalerror(200410101);
+ replaceoper:=0;
+ end;
+ end;
+ 2,3 :
+ begin
+ { We can handle opcodes with 2 and 3 operands the same way. The opcodes
+ with 3 registers are shrd/shld, where the 3rd operand is const or CL,
+ that doesn't need spilling }
+ if (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (getsupreg(oper[0]^.reg)<>getsupreg(oper[1]^.reg)) then
+ begin
+ { One of the arguments shall be able to be replaced }
+ if (getregtype(oper[0]^.reg)=regtype) and
+ (getsupreg(oper[0]^.reg)=orgreg) then
+ replaceoper:=0
+ else
+ if (getregtype(oper[1]^.reg)=regtype) and
+ (getsupreg(oper[1]^.reg)=orgreg) then
+ replaceoper:=1
+ else
+ internalerror(200410106);
+ case replaceoper of
+ 0 :
+ begin
+ { Some instructions don't allow memory references
+ for source }
+ case instr.opcode of
+ A_BT,
+ A_BTS,
+ A_BTC,
+ A_BTR :
+ replaceoper:=-1;
+ end;
+ end;
+ 1 :
+ begin
+ { Some instructions don't allow memory references
+ for destination }
+ case instr.opcode of
+ A_MOVZX,
+ A_MOVSX,
+ A_MULSS,
+ A_MULSD,
+ A_SUBSS,
+ A_SUBSD,
+ A_ADDSD,
+ A_ADDSS,
+ A_DIVSD,
+ A_DIVSS,
+ A_SHLD,
+ A_SHRD,
+ A_CVTDQ2PD,
+ A_CVTDQ2PS,
+ A_CVTPD2DQ,
+ A_CVTPD2PI,
+ A_CVTPD2PS,
+ A_CVTPI2PD,
+ A_CVTPS2DQ,
+ A_CVTPS2PD,
+ A_CVTSD2SI,
+ A_CVTSD2SS,
+ A_CVTSI2SD,
+ A_CVTSS2SD,
+ A_CVTTPD2PI,
+ A_CVTTPD2DQ,
+ A_CVTTPS2DQ,
+ A_CVTTSD2SI,
+ A_CVTPI2PS,
+ A_CVTPS2PI,
+ A_CVTSI2SS,
+ A_CVTSS2SI,
+ A_CVTTPS2PI,
+ A_CVTTSS2SI,
+ A_IMUL :
+ replaceoper:=-1;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ { Replace register with spill reference }
+ if replaceoper<>-1 then
+ begin
+ oper[replaceoper]^.typ:=top_ref;
+ new(oper[replaceoper]^.ref);
+ oper[replaceoper]^.ref^:=spilltemp;
+ result:=true;
+ end;
+ end;
+ end;
+
+
+{******************************************************************************
+ Trgx86fpu
+******************************************************************************}
+
+ constructor Trgx86fpu.create;
+ begin
+ used_in_proc:=[];
+ t_times := 0;
+ unusedregsfpu:=usableregsfpu;
+ end;
+
+
+ function trgx86fpu.getregisterfpu(list: taasmoutput) : tregister;
+ begin
+ { note: don't return R_ST0, see comments above implementation of }
+ { a_loadfpu_* methods in cgcpu (JM) }
+ result:=NR_ST;
+ end;
+
+
+ procedure trgx86fpu.ungetregisterfpu(list : taasmoutput; r : tregister);
+ begin
+ { nothing to do, fpu stack management is handled by the load/ }
+ { store operations in cgcpu (JM) }
+ end;
+
+
+
+ function trgx86fpu.correct_fpuregister(r : tregister;ofs : byte) : tregister;
+ begin
+ correct_fpuregister:=r;
+ setsupreg(correct_fpuregister,ofs);
+ end;
+
+
+ procedure trgx86fpu.saveusedfpuregisters(list: taasmoutput;
+ var saved : tpushedsavedfpu;
+ const s: tcpuregisterset);
+ var
+ r : tregister;
+ hr : treference;
+ begin
+ used_in_proc:=used_in_proc+s;
+
+{$warning TODO firstsavefpureg}
+(*
+ { don't try to save the fpu registers if not desired (e.g. for }
+ { the 80x86) }
+ if firstsavefpureg <> R_NO then
+ for r.enum:=firstsavefpureg to lastsavefpureg do
+ begin
+ saved[r.enum].ofs:=reg_not_saved;
+ { if the register is used by the calling subroutine and if }
+ { it's not a regvar (those are handled separately) }
+ if not is_reg_var_other[r.enum] and
+ (r.enum in s) and
+ { and is present in use }
+ not(r.enum in unusedregsfpu) then
+ begin
+ { then save it }
+ tg.GetTemp(list,extended_size,tt_persistent,hr);
+ saved[r.enum].ofs:=hr.offset;
+ cg.a_loadfpu_reg_ref(list,OS_FLOAT,r,hr);
+ cg.a_reg_dealloc(list,r);
+ include(unusedregsfpu,r.enum);
+ inc(countunusedregsfpu);
+ end;
+ end;
+*)
+ end;
+
+
+ procedure trgx86fpu.restoreusedfpuregisters(list : taasmoutput;
+ const saved : tpushedsavedfpu);
+
+ var
+ r,r2 : tregister;
+ hr : treference;
+
+ begin
+{$warning TODO firstsavefpureg}
+(*
+ if firstsavefpureg <> R_NO then
+ for r.enum:=lastsavefpureg downto firstsavefpureg do
+ begin
+ if saved[r.enum].ofs <> reg_not_saved then
+ begin
+ r2.enum:=R_INTREGISTER;
+ r2.number:=NR_FRAME_POINTER_REG;
+ reference_reset_base(hr,r2,saved[r.enum].ofs);
+ cg.a_reg_alloc(list,r);
+ cg.a_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
+ if not (r.enum in unusedregsfpu) then
+ { internalerror(10)
+ in n386cal we always save/restore the reg *state*
+ using save/restoreunusedstate -> the current state
+ may not be real (JM) }
+ else
+ begin
+ dec(countunusedregsfpu);
+ exclude(unusedregsfpu,r.enum);
+ end;
+ tg.UnGetTemp(list,hr);
+ end;
+ end;
+*)
+ end;
+
+(*
+ procedure Trgx86fpu.saveotherregvars(list: taasmoutput; const s: totherregisterset);
+ var
+ r: Tregister;
+ begin
+ if not(cs_regvars in aktglobalswitches) then
+ exit;
+ if firstsavefpureg <> NR_NO then
+ for r.enum := firstsavefpureg to lastsavefpureg do
+ if is_reg_var_other[r.enum] and
+ (r.enum in s) then
+ store_regvar(list,r);
+ end;
+*)
+
+end.
diff --git a/compiler/x86/x86ins.dat b/compiler/x86/x86ins.dat
new file mode 100644
index 0000000000..0d5324135b
--- /dev/null
+++ b/compiler/x86/x86ins.dat
@@ -0,0 +1,3421 @@
+;
+; Table of assembler instructions for Free Pascal
+; adapted from Netwide Assembler by Peter Vreman
+;
+; The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+; Julian Hall. All rights reserved.
+;
+; Layout
+; [OPCODE,attnameX] (X means suffix in att name)
+; arguments bytes flags
+;
+
+[NONE]
+(Ch_None, Ch_None, Ch_None)
+void void none
+
+[AAA]
+(Ch_MEAX, Ch_WFlags, Ch_None)
+void \1\x37 8086
+
+[AAD,aadX]
+(Ch_MEAX, Ch_WFlags, Ch_None)
+void \2\xD5\x0A 8086
+imm \1\xD5\24 8086,SB
+
+[AAM,aamX]
+(Ch_MEAX, Ch_WFlags, Ch_None)
+void \2\xD4\x0A 8086
+imm \1\xD4\24 8086,SB
+
+[AAS]
+(Ch_MEAX, Ch_WFlags, Ch_None)
+void \1\x3F 8086
+
+[ADC,adcX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+mem,reg8 \300\1\x10\101 8086,SM
+reg8,reg8 \300\1\x10\101 8086
+mem,reg16 \320\300\1\x11\101 8086,SM
+reg16,reg16 \320\300\1\x11\101 8086
+mem,reg32 \321\300\1\x11\101 386,SM
+reg32,reg32 \321\300\1\x11\101 386
+reg8,mem \301\1\x12\110 8086,SM
+reg8,reg8 \301\1\x12\110 8086
+reg16,mem \320\301\1\x13\110 8086,SM
+reg16,reg16 \320\301\1\x13\110 8086
+reg32,mem \321\301\1\x13\110 386,SM
+reg32,reg32 \321\301\1\x13\110 386
+rm16,imm8 \320\300\1\x83\202\15 8086
+rm32,imm8 \321\300\1\x83\202\15 386
+reg_al,imm \1\x14\21 8086,SM
+reg_ax,imm \320\1\x15\31 8086,SM
+reg_eax,imm \321\1\x15\41 386,SM
+rm8,imm \300\1\x80\202\21 8086,SM
+rm16,imm \320\300\1\x81\202\31 8086,SM
+rm32,imm \321\300\1\x81\202\41 386,SM
+mem,imm8 \300\1\x80\202\21 8086,SM
+mem,imm16 \320\300\1\x81\202\31 8086,SM
+mem,imm32 \321\300\1\x81\202\41 386,SM
+
+[ADD,addX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+mem,reg8 \300\17\101 8086,SM
+reg8,reg8 \300\17\101 8086
+mem,reg16 \320\300\1\x01\101 8086,SM
+reg16,reg16 \320\300\1\x01\101 8086
+mem,reg32 \321\300\1\x01\101 386,SM
+reg32,reg32 \321\300\1\x01\101 386
+reg8,mem \301\1\x02\110 8086,SM
+reg8,reg8 \301\1\x02\110 8086
+reg16,mem \320\301\1\x03\110 8086,SM
+reg16,reg16 \320\301\1\x03\110 8086
+reg32,mem \321\301\1\x03\110 386,SM
+reg32,reg32 \321\301\1\x03\110 386
+rm16,imm8 \320\300\1\x83\200\15 8086
+rm32,imm8 \321\300\1\x83\200\15 386
+reg_al,imm \1\x04\21 8086,SM
+reg_ax,imm \320\1\x05\31 8086,SM
+reg_eax,imm \321\1\x05\41 386,SM
+rm8,imm \300\1\x80\200\21 8086,SM
+rm16,imm \320\300\1\x81\200\31 8086,SM
+rm32,imm \321\300\1\x81\200\41 386,SM
+mem,imm8 \300\1\x80\200\21 8086,SM
+mem,imm16 \320\300\1\x81\200\31 8086,SM
+mem,imm32 \321\300\1\x81\200\41 386,SM
+
+[AND,andX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+mem,reg8 \300\1\x20\101 8086,SM
+reg8,reg8 \300\1\x20\101 8086
+mem,reg16 \320\300\1\x21\101 8086,SM
+reg16,reg16 \320\300\1\x21\101 8086
+mem,reg32 \321\300\1\x21\101 386,SM
+reg32,reg32 \321\300\1\x21\101 386
+reg8,mem \301\1\x22\110 8086,SM
+reg8,reg8 \301\1\x22\110 8086
+reg16,mem \320\301\1\x23\110 8086,SM
+reg16,reg16 \320\301\1\x23\110 8086
+reg32,mem \321\301\1\x23\110 386,SM
+reg32,reg32 \321\301\1\x23\110 386
+rm16,imm8 \320\300\1\x83\204\15 8086
+rm32,imm8 \321\300\1\x83\204\15 386
+reg_al,imm \1\x24\21 8086,SM
+reg_ax,imm \320\1\x25\31 8086,SM
+reg_eax,imm \321\1\x25\41 386,SM
+rm8,imm \300\1\x80\204\21 8086,SM
+rm16,imm \320\300\1\x81\204\31 8086,SM
+rm32,imm \321\300\1\x81\204\41 386,SM
+mem,imm8 \300\1\x80\204\21 8086,SM
+mem,imm16 \320\300\1\x81\204\31 8086,SM
+mem,imm32 \321\300\1\x81\204\41 386,SM
+
+[ARPL,arplX]
+(Ch_WFlags, Ch_None, Ch_None)
+mem,reg16 \300\1\x63\101 286,PROT,SM
+reg16,reg16 \300\1\x63\101 286,PROT
+
+[BOUND,boundX]
+(Ch_Rop1, Ch_None, Ch_None)
+reg16,mem \320\301\1\x62\110 186
+reg32,mem \321\301\1\x62\110 386
+
+[BSF,bsfX]
+(Ch_Wop2, Ch_WFlags, Ch_Rop1)
+reg16,mem \320\301\2\x0F\xBC\110 386,SM
+reg16,reg16 \320\301\2\x0F\xBC\110 386
+reg32,mem \321\301\2\x0F\xBC\110 386,SM
+reg32,reg32 \321\301\2\x0F\xBC\110 386
+
+[BSR,bsrX]
+(Ch_Wop2, Ch_WFlags, Ch_Rop1)
+reg16,mem \320\301\2\x0F\xBD\110 386,SM
+reg16,reg16 \320\301\2\x0F\xBD\110 386
+reg32,mem \321\301\2\x0F\xBD\110 386,SM
+reg32,reg32 \321\301\2\x0F\xBD\110 386
+
+[BSWAP,bswapX]
+(Ch_MOp1, Ch_None, Ch_None)
+reg32 \321\1\x0F\10\xC8 486
+
+[BT,btX]
+(Ch_WFlags, Ch_Rop1, Ch_Rop2)
+mem,reg16 \320\300\2\x0F\xA3\101 386,SM
+reg16,reg16 \320\300\2\x0F\xA3\101 386
+mem,reg32 \321\300\2\x0F\xA3\101 386,SM
+reg32,reg32 \321\300\2\x0F\xA3\101 386
+rm16,imm \320\300\2\x0F\xBA\204\25 386,SB
+rm32,imm \321\300\2\x0F\xBA\204\25 386,SB
+
+[BTC,btcX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+mem,reg16 \320\300\2\x0F\xBB\101 386,SM
+reg16,reg16 \320\300\2\x0F\xBB\101 386
+mem,reg32 \321\300\2\x0F\xBB\101 386,SM
+reg32,reg32 \321\300\2\x0F\xBB\101 386
+rm16,imm \320\300\2\x0F\xBA\207\25 386,SB
+rm32,imm \321\300\2\x0F\xBA\207\25 386,SB
+
+[BTR,btrX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+mem,reg16 \320\300\2\x0F\xB3\101 386,SM
+reg16,reg16 \320\300\2\x0F\xB3\101 386
+mem,reg32 \321\300\2\x0F\xB3\101 386,SM
+reg32,reg32 \321\300\2\x0F\xB3\101 386
+rm16,imm \320\300\2\x0F\xBA\206\25 386,SB
+rm32,imm \321\300\2\x0F\xBA\206\25 386,SB
+
+[BTS,btsX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+mem,reg16 \320\300\2\x0F\xAB\101 386,SM
+reg16,reg16 \320\300\2\x0F\xAB\101 386
+mem,reg32 \321\300\2\x0F\xAB\101 386,SM
+reg32,reg32 \321\300\2\x0F\xAB\101 386
+rm16,imm \320\300\2\x0F\xBA\205\25 386,SB
+rm32,imm \321\300\2\x0F\xBA\205\25 386,SB
+
+[CALL,call]
+; don't know value of any register
+(Ch_ROp1, Ch_All, Ch_None)
+imm \323\1\xE8\64 8086
+imm|near \323\1\xE8\64 8086
+imm|far \323\1\x9A\34\37 8086,ND
+imm16 \320\1\xE8\64 8086
+imm16|near \320\1\xE8\64 8086
+imm16|far \320\1\x9A\34\37 8086,ND
+imm32 \321\1\xE8\64 8086
+imm32|near \321\1\xE8\64 8086
+imm32|far \321\1\x9A\34\37 8086,ND
+imm:imm \323\1\x9A\35\30 8086
+imm16:imm \320\1\x9A\31\30 8086
+imm:imm16 \320\1\x9A\31\30 8086
+imm32:imm \321\1\x9A\41\30 386
+imm:imm32 \321\1\x9A\41\30 386
+mem|far \323\300\1\xFF\203 8086
+mem16|far \320\300\1\xFF\203 8086
+mem32|far \321\300\1\xFF\203 386
+mem|near \323\300\1\xFF\202 8086
+mem16|near \320\300\1\xFF\202 8086
+mem32|near \321\300\1\xFF\202 386
+reg16 \320\300\1\xFF\202 8086
+reg32 \321\300\1\xFF\202 386
+mem \323\300\1\xFF\202 8086
+mem16 \320\300\1\xFF\202 8086
+mem32 \321\300\1\xFF\202 386
+
+[CBW,cbtw]
+(Ch_MEAX, Ch_None, Ch_None)
+void \320\1\x98 8086
+
+[CDQ,cltd]
+(Ch_MEAX, Ch_WEDX, Ch_None)
+void \321\1\x99 386
+
+[CLC]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xF8 8086
+
+[CLD]
+(Ch_CDirFlag, Ch_None, Ch_None)
+void \1\xFC 8086
+
+[CLI]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xFA 8086
+
+[CLTS]
+(Ch_None, Ch_None, Ch_None)
+void \2\x0F\x06 286,PRIV
+
+[CMC]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xF5 8086
+
+[CMP,cmpX]
+(Ch_ROp1, Ch_ROp2, Ch_WFlags)
+mem,reg8 \300\1\x38\101 8086,SM
+reg8,reg8 \300\1\x38\101 8086
+mem,reg16 \320\300\1\x39\101 8086,SM
+reg16,reg16 \320\300\1\x39\101 8086
+mem,reg32 \321\300\1\x39\101 386,SM
+reg32,reg32 \321\300\1\x39\101 386
+reg8,mem \301\1\x3A\110 8086,SM
+reg8,reg8 \301\1\x3A\110 8086
+reg16,mem \320\301\1\x3B\110 8086,SM
+reg16,reg16 \320\301\1\x3B\110 8086
+reg32,mem \321\301\1\x3B\110 386,SM
+reg32,reg32 \321\301\1\x3B\110 386
+rm16,imm8 \320\300\1\x83\207\15 8086
+rm32,imm8 \321\300\1\x83\207\15 386
+reg_al,imm \1\x3C\21 8086,SM
+reg_ax,imm \320\1\x3D\31 8086,SM
+reg_eax,imm \321\1\x3D\41 386,SM
+rm8,imm \300\1\x80\207\21 8086,SM
+rm16,imm \320\300\1\x81\207\31 8086,SM
+rm32,imm \321\300\1\x81\207\41 386,SM
+mem,imm8 \300\1\x80\207\21 8086,SM
+mem,imm16 \320\300\1\x81\207\31 8086,SM
+mem,imm32 \321\300\1\x81\207\41 386,SM
+
+[CMPSB]
+(Ch_All, Ch_None, Ch_None)
+void \332\1\xA6 8086
+
+[CMPSD,cmpsl]
+(Ch_All, Ch_None, Ch_None)
+void \332\321\1\xA7 386
+xmmreg,xmmreg,imm \331\3\xF2\x0F\xC2\110\26 WILLAMETTE,SSE2,SB,AR2
+xmmreg,mem,imm \301\331\3\xF2\x0F\xC2\110\26 WILLAMETTE,SSE2,SB,AR2
+
+[CMPSW]
+(Ch_All, Ch_None, Ch_None)
+void \332\320\1\xA7 8086
+
+[CMPXCHG,cmpxchgX]
+(Ch_All, Ch_None, Ch_None)
+mem,reg8 \300\2\x0F\xB0\101 PENT,SM
+reg8,reg8 \300\2\x0F\xB0\101 PENT
+mem,reg16 \320\300\2\x0F\xB1\101 PENT,SM
+reg16,reg16 \320\300\2\x0F\xB1\101 PENT
+mem,reg32 \321\300\2\x0F\xB1\101 PENT,SM
+reg32,reg32 \321\300\2\x0F\xB1\101 PENT
+
+[CMPXCHG486,cmpxchg486X]
+(Ch_All, Ch_None, Ch_None)
+mem,reg8 \300\2\x0F\xA6\101 486,SM,UNDOC
+reg8,reg8 \300\2\x0F\xA6\101 486,UNDOC
+mem,reg16 \320\300\2\x0F\xA7\101 486,SM,UNDOC
+reg16,reg16 \320\300\2\x0F\xA7\101 486,UNDOC
+mem,reg32 \321\300\2\x0F\xA7\101 486,SM,UNDOC
+reg32,reg32 \321\300\2\x0F\xA7\101 486,UNDOC
+
+[CMPXCHG8B,cmpxchg8bX]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\xC7\201 PENT
+
+[CPUID]
+(Ch_All, Ch_None, Ch_none)
+void \2\x0F\xA2 PENT
+
+[CWD]
+(Ch_MEAX, Ch_WEDX, Ch_None)
+void \320\1\x99 8086
+
+[CWDE,cwtl]
+(Ch_MEAX, Ch_None, Ch_None)
+void \321\1\x98 386
+
+[DAA]
+(Ch_MEAX, Ch_None, Ch_None)
+void \1\x27 8086
+
+[DAS]
+(Ch_MEAX, Ch_None, Ch_None)
+void \1\x2F 8086
+
+[DEC,decX]
+(Ch_Mop1, Ch_WFlags, Ch_None)
+reg16 \320\10\x48 8086
+reg32 \321\10\x48 386
+rm8 \300\1\xFE\201 8086
+rm16 \320\300\1\xFF\201 8086
+rm32 \321\300\1\xFF\201 386
+
+[DIV,divX]
+(Ch_RWEAX, Ch_WEDX, Ch_WFlags)
+rm8 \300\1\xF6\206 8086
+rm16 \320\300\1\xF7\206 8086
+rm32 \321\300\1\xF7\206 386
+
+[EMMS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\x0F\x77 PENT,MMX
+
+[ENTER,enterX]
+(Ch_RWESP, Ch_None, Ch_None)
+imm,imm \1\xC8\30\25 186
+
+[F2XM1]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF0 8086,FPU
+
+[FABS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE1 8086,FPU
+
+[FADD,faddF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem32 \300\1\xD8\200 8086,FPU
+mem64 \300\1\xDC\200 8086,FPU
+void \2\xDE\xC1 8086,FPU
+fpureg|to \1\xDC\10\xC0 8086,FPU
+fpureg,fpu0 \1\xDC\10\xC0 8086,FPU
+fpureg \1\xD8\10\xC0 8086,FPU
+fpu0,fpureg \1\xD8\11\xC0 8086,FPU
+
+[FADDP,faddpF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+void \2\xDE\xC1 8086,FPU
+fpureg \1\xDE\10\xC0 8086,FPU
+fpureg,fpu0 \1\xDE\10\xC0 8086,FPU
+
+[FBLD,fbldF]
+(Ch_Rop1, Ch_FPU, Ch_None)
+mem80 \300\1\xDF\204 8086,FPU
+mem \300\1\xDF\204 8086,FPU
+
+[FBSTP,fbstpF]
+(Ch_Wop1, Ch_FPU, Ch_None)
+mem80 \300\1\xDF\206 8086,FPU
+mem \300\1\xDF\206 8086,FPU
+
+[FCHS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE0 8086,FPU
+
+[FCLEX]
+(Ch_FPU, Ch_None, Ch_None)
+void \3\x9B\xDB\xE2 8086,FPU
+
+[FCMOVB,fcmovbF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDA\xC1 P6,FPU
+fpureg \1\xDA\10\xC0 P6,FPU
+fpu0,fpureg \1\xDA\11\xC0 P6,FPU
+
+[FCMOVBE,fcmovbeF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDA\xD1 P6,FPU
+fpureg \1\xDA\10\xD0 P6,FPU
+fpu0,fpureg \1\xDA\11\xD0 P6,FPU
+
+[FCMOVE,fcmoveF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDA\xC9 P6,FPU
+fpureg \1\xDA\10\xC8 P6,FPU
+fpu0,fpureg \1\xDA\11\xC8 P6,FPU
+
+[FCMOVNB,fcmovnbF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDB\xC1 P6,FPU
+fpureg \1\xDB\10\xC0 P6,FPU
+fpu0,fpureg \1\xDB\11\xC0 P6,FPU
+
+[FCMOVNBE,fcmovnbeF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDB\xD1 P6,FPU
+fpureg \1\xDB\10\xD0 P6,FPU
+fpu0,fpureg \1\xDB\11\xD0 P6,FPU
+
+[FCMOVNE,fcmovneF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDB\xC9 P6,FPU
+fpureg \1\xDB\10\xC8 P6,FPU
+fpu0,fpureg \1\xDB\11\xC8 P6,FPU
+
+[FCMOVNU,fcmovnuF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDB\xD9 P6,FPU
+fpureg \1\xDB\10\xD8 P6,FPU
+fpu0,fpureg \1\xDB\11\xD8 P6,FPU
+
+[FCMOVU,fcmovuF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDA\xD9 P6,FPU
+fpureg \1\xDA\10\xD8 P6,FPU
+fpu0,fpureg \1\xDA\11\xD8 P6,FPU
+
+[FCOM,fcomF]
+(Ch_FPU, Ch_None, Ch_None)
+mem32 \300\1\xD8\202 8086,FPU
+mem64 \300\1\xDC\202 8086,FPU
+void \2\xD8\xD1 8086,FPU
+fpureg \1\xD8\10\xD0 8086,FPU
+fpu0,fpureg \1\xD8\11\xD0 8086,FPU
+
+[FCOMI,fcomiF]
+(Ch_WFLAGS, Ch_None, Ch_None)
+void \2\xDB\xF1 P6,FPU
+fpureg \1\xDB\10\xF0 P6,FPU
+fpu0,fpureg \1\xDB\11\xF0 P6,FPU
+
+[FCOMIP,fcomipF]
+(Ch_FPU, Ch_WFLAGS, Ch_None)
+void \2\xDF\xF1 P6,FPU
+fpureg \1\xDF\10\xF0 P6,FPU
+fpu0,fpureg \1\xDF\11\xF0 P6,FPU
+
+[FCOMP,fcompF]
+(Ch_FPU, Ch_None, Ch_None)
+mem32 \300\1\xD8\203 8086,FPU
+mem64 \300\1\xDC\203 8086,FPU
+void \2\xD8\xD9 8086,FPU
+fpureg \1\xD8\10\xD8 8086,FPU
+fpu0,fpureg \1\xD8\11\xD8 8086,FPU
+
+[FCOMPP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDE\xD9 8086,FPU
+
+[FCOS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFF 386,FPU
+
+[FDECSTP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF6 8086,FPU
+
+[FDISI]
+(Ch_FPU, Ch_None, Ch_None)
+void \3\x9B\xDB\xE1 8086,FPU
+
+[FDIV,fdivF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem32 \300\1\xD8\206 8086,FPU
+mem64 \300\1\xDC\206 8086,FPU
+void \2\xDC\xF1 8086,FPU
+fpureg|to \1\xDC\10\xF0 8086,FPU
+fpureg,fpu0 \1\xDC\10\xF0 8086,FPU
+fpureg \1\xD8\10\xF0 8086,FPU
+fpu0,fpureg \1\xD8\11\xF0 8086,FPU
+
+[FDIVP,fdivpF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+void \2\xDE\xF1 8086,FPU
+fpureg,fpu0 \1\xDE\10\xF0 8086,FPU
+fpureg \1\xDE\10\xF0 8086,FPU
+
+[FDIVR,fdivrF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem32 \300\1\xD8\207 8086,FPU
+mem64 \300\1\xDC\207 8086,FPU
+void \2\xDC\xF9 8086,FPU
+fpureg|to \1\xDC\10\xF8 8086,FPU
+fpureg,fpu0 \1\xDC\10\xF8 8086,FPU
+fpureg \1\xD8\10\xF8 8086,FPU
+fpu0,fpureg \1\xD8\11\xF8 8086,FPU
+
+[FDIVRP,fdivrpF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+void \2\xDE\xF9 8086,FPU
+fpureg \1\xDE\10\xF8 8086,FPU
+fpureg,fpu0 \1\xDE\10\xF8 8086,FPU
+
+[FEMMS]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x0E PENT,3DNOW
+
+[FENI]
+(Ch_FPU, Ch_None, Ch_None)
+void \3\x9B\xDB\xE0 8086,FPU
+
+[FFREE]
+(Ch_FPU, Ch_None, Ch_None)
+fpureg \1\xDD\10\xC0 8086,FPU
+
+[FIADD,fiaddR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \300\1\xDE\200 8086,FPU
+mem32 \300\1\xDA\200 8086,FPU
+
+[FICOM,ficomR]
+(Ch_FPU, Ch_None, Ch_None)
+mem16 \300\1\xDE\202 8086,FPU
+mem32 \300\1\xDA\202 8086,FPU
+
+[FICOMP,ficompR]
+(Ch_FPU, Ch_None, Ch_None)
+mem16 \300\1\xDE\203 8086,FPU
+mem32 \300\1\xDA\203 8086,FPU
+
+[FIDIV,fidivR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \300\1\xDE\206 8086,FPU
+mem32 \300\1\xDA\206 8086,FPU
+
+[FIDIVR,fidivrR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \300\1\xDE\207 8086,FPU
+mem32 \300\1\xDA\207 8086,FPU
+
+[FILD,fildR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem32 \300\1\xDB\200 8086,FPU
+mem16 \320\300\1\xDF\200 8086,FPU
+mem64 \300\1\xDF\205 8086,FPU
+
+[FIMUL,fimulR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \300\1\xDE\201 8086,FPU
+mem32 \300\1\xDA\201 8086,FPU
+
+[FINCSTP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF7 8086,FPU
+
+[FINIT]
+(Ch_FPU, Ch_None, Ch_None)
+void \3\x9B\xDB\xE3 8086,FPU
+
+[FIST,fistR]
+(Ch_Wop1, Ch_None, Ch_None)
+mem32 \300\1\xDB\202 8086,FPU
+mem16 \320\300\1\xDF\202 8086,FPU
+
+[FISTP,fistpR]
+(Ch_Wop1, Ch_None, Ch_None)
+mem32 \300\1\xDB\203 8086,FPU
+mem16 \320\300\1\xDF\203 8086,FPU
+mem64 \300\1\xDF\207 8086,FPU
+
+[FISTTP]
+(Ch_Wop1, Ch_None, Ch_None)
+mem32 \300\1\xDD\201 PRESCOTT,FPU
+mem16 \300\1\xDB\201 PRESCOTT,FPU
+mem64 \300\1\xDF\201 PRESCOTT,FPU
+
+[FISUB,fisubR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \300\1\xDE\204 8086,FPU
+mem32 \300\1\xDA\204 8086,FPU
+
+[FISUBR,fisubrR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \300\1\xDE\205 8086,FPU
+mem32 \300\1\xDA\205 8086,FPU
+
+[FLD,fldF]
+(Ch_Rop1, Ch_FPU, Ch_None)
+mem32 \300\1\xD9\200 8086,FPU
+mem64 \300\1\xDD\200 8086,FPU
+mem80 \300\1\xDB\205 8086,FPU
+fpureg \1\xD9\10\xC0 8086,FPU
+
+[FLD1]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE8 8086,FPU
+
+[FLDCW,fldcwX]
+(Ch_FPU, Ch_None, Ch_None)
+mem \300\1\xD9\205 8086,FPU,SW
+
+[FLDENV,fldenv]
+(Ch_FPU, Ch_None, Ch_None)
+mem \300\1\xD9\204 8086,FPU
+
+[FLDL2E]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xEA 8086,FPU
+
+[FLDL2T]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE9 8086,FPU
+
+[FLDLG2]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xEC 8086,FPU
+
+[FLDLN2]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xED 8086,FPU
+
+[FLDPI]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xEB 8086,FPU
+
+[FLDZ]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xEE 8086,FPU
+
+[FMUL,fmulF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+mem32 \300\1\xD8\201 8086,FPU
+mem64 \300\1\xDC\201 8086,FPU
+void \2\xDC\xC9 8086,FPU
+fpureg|to \1\xDC\10\xC8 8086,FPU
+fpureg,fpu0 \1\xDC\10\xC8 8086,FPU
+fpureg \1\xD8\10\xC8 8086,FPU
+fpu0,fpureg \1\xD8\11\xC8 8086,FPU
+
+[FMULP,fmulpF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+void \2\xDE\xC9 8086,FPU
+fpureg \1\xDE\10\xC8 8086,FPU
+fpureg,fpu0 \1\xDE\10\xC8 8086,FPU
+
+[FNCLEX]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE2 8086,FPU
+
+[FNDISI]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE1 8086,FPU
+
+[FNENI]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE0 8086,FPU
+
+[FNINIT]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE3 8086,FPU
+
+[FNOP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xD0 8086,FPU
+
+[FNSAVE,fnsave]
+(Ch_FPU, Ch_None, Ch_None)
+mem \300\1\xDD\206 8086,FPU
+
+[FNSTCW,fnstcwX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\1\xD9\207 8086,FPU,SW
+
+[FNSTENV,fnstenv]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\1\xD9\206 8086,FPU
+
+[FNSTSW,fnstswX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\1\xDD\207 8086,FPU,SW
+reg_ax \2\xDF\xE0 286,FPU
+
+[FPATAN]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF3 8086,FPU
+
+[FPREM]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF8 8086,FPU
+
+[FPREM1]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF5 386,FPU
+
+[FPTAN]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF2 8086,FPU
+
+[FRNDINT]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFC 8086,FPU
+
+[FRSTOR,frstor]
+(Ch_FPU, Ch_None, Ch_None)
+mem \300\1\xDD\204 8086,FPU
+
+[FSAVE,fsave]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\2\x9B\xDD\206 8086,FPU
+
+[FSCALE]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFD 8086,FPU
+
+[FSETPM]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE4 286,FPU
+
+[FSIN]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFE 386,FPU
+
+[FSINCOS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFB 386,FPU
+
+[FSQRT]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFA 8086,FPU
+
+[FST,fstF]
+(Ch_Wop1, Ch_None, Ch_None)
+mem32 \300\1\xD9\202 8086,FPU
+mem64 \300\1\xDD\202 8086,FPU
+fpureg \1\xDD\10\xD0 8086,FPU
+
+[FSTCW,fstcwX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\2\x9B\xD9\207 8086,FPU,SW
+
+[FSTENV,fstenv]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\2\x9B\xD9\206 8086,FPU
+
+[FSTP,fstpF]
+(Ch_Wop1, Ch_FPU, Ch_None)
+mem32 \300\1\xD9\203 8086,FPU
+mem64 \300\1\xDD\203 8086,FPU
+mem80 \300\1\xDB\207 8086,FPU
+fpureg \1\xDD\10\xD8 8086,FPU
+
+[FSTSW,fstswX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\2\x9B\xDD\207 8086,FPU,SW
+void \3\x9B\xDF\xE0 286,FPU
+reg_ax \3\x9B\xDF\xE0 286,FPU
+
+[FSUB,fsubF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+mem32 \300\1\xD8\204 8086,FPU
+mem64 \300\1\xDC\204 8086,FPU
+void \2\xDC\xE1 8086,FPU
+fpureg|to \1\xDC\10\xE0 8086,FPU
+fpureg,fpu0 \1\xDC\10\xE0 8086,FPU
+fpureg \1\xD8\10\xE0 8086,FPU
+fpu0,fpureg \1\xD8\11\xE0 8086,FPU
+
+[FSUBP,fsubpF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+void \2\xDE\xE1 8086,FPU
+fpureg \1\xDE\10\xE0 8086,FPU
+fpureg,fpu0 \1\xDE\10\xE0 8086,FPU
+
+[FSUBR,fsubrF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+mem32 \300\1\xD8\205 8086,FPU
+mem64 \300\1\xDC\205 8086,FPU
+void \2\xDC\xE9 8086,FPU
+fpureg|to \1\xDC\10\xE8 8086,FPU
+fpureg,fpu0 \1\xDC\10\xE8 8086,FPU
+fpureg \1\xD8\10\xE8 8086,FPU
+fpu0,fpureg \1\xD8\11\xE8 8086,FPU
+
+[FSUBRP,fsubrpF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+void \2\xDE\xE9 8086,FPU
+fpureg \1\xDE\10\xE8 8086,FPU
+fpureg,fpu0 \1\xDE\10\xE8 8086,FPU
+
+[FTST]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE4 8086,FPU
+
+[FUCOM,fucomF]
+(Ch_None, Ch_None, Ch_None)
+void \2\xDD\xE1 386,FPU
+fpureg \1\xDD\10\xE0 386,FPU
+fpu0,fpureg \1\xDD\11\xE0 386,FPU
+
+[FUCOMI,fucomiF]
+(Ch_WFLAGS, Ch_None, Ch_None)
+void \2\xDB\xE9 P6,FPU
+fpureg \1\xDB\10\xE8 P6,FPU
+fpu0,fpureg \1\xDB\11\xE8 P6,FPU
+
+[FUCOMIP,fucomipF]
+(Ch_FPU, Ch_WFLAGS, Ch_None)
+void \2\xDF\xE9 P6,FPU
+fpureg \1\xDF\10\xE8 P6,FPU
+fpu0,fpureg \1\xDF\11\xE8 P6,FPU
+
+[FUCOMP,fucompF]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDD\xE9 386,FPU
+fpureg \1\xDD\10\xE8 386,FPU
+fpu0,fpureg \1\xDD\11\xE8 386,FPU
+
+[FUCOMPP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDA\xE9 386,FPU
+
+[FWAIT]
+(Ch_FPU, Ch_None, Ch_None)
+void \1\x9B 8086,FPU
+
+[FXAM]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE5 8086,FPU
+
+[FXCH,fxchF]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xC9 8086,FPU
+fpureg \1\xD9\10\xC8 8086,FPU
+fpureg,fpu0 \1\xD9\10\xC8 8086,FPU
+fpu0,fpureg \1\xD9\11\xC8 8086,FPU
+
+[FXTRACT]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF4 8086,FPU
+
+[FYL2X]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF1 8086,FPU
+
+[FYL2XP1]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF9 8086,FPU
+
+[HLT]
+(Ch_None, Ch_None, Ch_None)
+void \1\xF4 8086,PRIV
+
+[IBTS,ibtsX]
+(Ch_All, Ch_None, Ch_None)
+mem,reg16 \320\300\2\x0F\xA7\101 386,SW,UNDOC,ND
+reg16,reg16 \320\300\2\x0F\xA7\101 386,UNDOC,ND
+mem,reg32 \321\300\2\x0F\xA7\101 386,SD,UNDOC,ND
+reg32,reg32 \321\300\2\x0F\xA7\101 386,UNDOC,ND
+
+[ICEBP]
+(Ch_All, Ch_None, Ch_None)
+void \1\xF1 386,ND
+
+[IDIV,idivX]
+(Ch_RWEAX, Ch_WEDX, Ch_WFlags)
+rm8 \300\1\xF6\207 8086
+rm16 \320\300\1\xF7\207 8086
+rm32 \321\300\1\xF7\207 386
+
+[IMUL,imulX]
+(Ch_RWEAX, Ch_WEDX, Ch_WFlags)
+rm8 \300\1\xF6\205 8086
+rm16 \320\300\1\xF7\205 8086
+rm32 \321\300\1\xF7\205 386
+reg16,mem \320\301\2\x0F\xAF\110 386,SM
+reg16,reg16 \320\301\2\x0F\xAF\110 386
+reg32,mem \321\301\2\x0F\xAF\110 386,SM
+reg32,reg32 \321\301\2\x0F\xAF\110 386
+reg16,mem,imm8 \320\301\1\x6B\110\16 286,SM
+reg16,reg16,imm8 \320\301\1\x6B\110\16 286
+reg16,mem,imm \320\301\1\x69\110\32 286,SM
+reg16,reg16,imm \320\301\1\x69\110\32 286,SM
+reg32,mem,imm8 \321\301\1\x6B\110\16 386,SM
+reg32,reg32,imm8 \321\301\1\x6B\110\16 386
+reg32,mem,imm \321\301\1\x69\110\42 386,SM
+reg32,reg32,imm \321\301\1\x69\110\42 386,SM
+reg16,imm8 \320\1\x6B\100\15 286
+reg16,imm \320\1\x69\100\31 286,SM
+reg32,imm8 \321\1\x6B\100\15 386
+reg32,imm \321\1\x69\100\41 386,SM
+
+[IN,inX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg_al,imm \1\xE4\25 8086,SB
+reg_ax,imm \320\1\xE5\25 8086,SB
+reg_eax,imm \321\1\xE5\25 386,SB
+reg_al,reg_dx \1\xEC 8086
+reg_ax,reg_dx \320\1\xED 8086
+reg_eax,reg_dx \321\1\xED 386
+
+[INC,incX]
+(Ch_Mop1, Ch_WFlags, Ch_None)
+reg16 \320\10\x40 8086
+reg32 \321\10\x40 386
+rm8 \300\1\xFE\200 8086
+rm16 \320\300\1\xFF\200 8086
+rm32 \321\300\1\xFF\200 386
+
+[INSB]
+(Ch_WMemEDI, Ch_RWEDI, Ch_REDX)
+void \1\x6C 186
+
+[INSD,insl]
+(Ch_WMemEDI, Ch_RWEDI, Ch_REDX)
+void \321\1\x6D 386
+
+[INSW]
+(Ch_WMemEDI, Ch_RWEDI, Ch_REDX)
+void \320\1\x6D 186
+
+[INT]
+(Ch_All, Ch_None, Ch_None)
+imm \1\xCD\24 8086,SB
+
+[INT01]
+(Ch_All, Ch_None, Ch_None)
+void \1\xF1 386,ND
+
+[INT1]
+(Ch_All, Ch_None, Ch_None)
+void \1\xF1 386
+
+[INT03]
+(Ch_None, Ch_None, Ch_None)
+void \1\xCC 8086,ND
+
+[INT3]
+(Ch_None, Ch_None, Ch_None)
+void \1\xCC 8086
+
+[INTO]
+(Ch_All, Ch_None, Ch_None)
+void \1\xCE 8086
+
+[INVD]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x08 486,PRIV
+
+[INVLPG,invlpgX]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\x01\207 486,PRIV
+
+[IRET]
+(Ch_All, Ch_None, Ch_None)
+void \323\1\xCF 8086
+
+[IRETD,iret]
+(Ch_All, Ch_None, Ch_None)
+void \321\1\xCF 386
+
+[IRETW]
+(Ch_All, Ch_None, Ch_None)
+void \320\1\xCF 8086
+
+[JCXZ]
+(Ch_RECX, Ch_None, Ch_None)
+imm \320\1\xE3\50 8086
+
+[JECXZ]
+(Ch_RECX, Ch_None, Ch_None)
+imm \321\1\xE3\50 386
+
+[JMP,jmpX]
+(Ch_ROp1, Ch_None, Ch_None)
+imm|short \1\xEB\50 8086,PASS2
+imm \323\1\xE9\64 8086,PASS2
+imm|near \323\1\xE9\64 8086,ND,PASS2
+imm|far \323\1\xEA\34\37 8086,ND,PASS2
+imm16 \320\1\xE9\64 8086,PASS2
+imm16|near \320\1\xE9\64 8086,ND,PASS2
+imm16|far \320\1\xEA\34\37 8086,ND,PASS2
+imm32 \321\1\xE9\64 8086,PASS2
+imm32|near \321\1\xE9\64 8086,ND,PASS2
+imm32|far \321\1\xEA\34\37 8086,ND,PASS2
+imm:imm \323\1\xEA\35\30 8086
+;???? imm16:imm \320\1\xEA\31\30 8086
+imm:imm16 \320\1\xEA\31\30 8086
+;???? imm32:imm \321\1\xEA\41\30 386
+imm:imm32 \321\1\xEA\41\30 386
+mem|far \323\300\1\xFF\205 8086
+mem16|far \320\300\1\xFF\205 8086
+mem32|far \321\300\1\xFF\205 386
+mem|near \323\300\1\xFF\204 8086
+mem16|near \320\300\1\xFF\204 8086
+mem32|near \321\300\1\xFF\204 386
+reg16 \320\300\1\xFF\204 8086
+reg32 \321\300\1\xFF\204 386
+mem \323\300\1\xFF\204 8086
+mem16 \320\300\1\xFF\204 8086
+mem32 \321\300\1\xFF\204 386
+
+[LAHF]
+(Ch_WEAX, Ch_RFlags, Ch_None)
+void \1\x9F 8086
+
+[LAR,larX]
+(Ch_Wop2, Ch_None, Ch_None)
+reg16,mem \320\301\2\x0F\x02\110 286,PROT,SM
+reg16,reg16 \320\301\2\x0F\x02\110 286,PROT
+reg32,mem \321\301\2\x0F\x02\110 286,PROT,SM
+reg32,reg32 \321\301\2\x0F\x02\110 286,PROT
+
+[LCALL,lcall]
+; don't know value of any register
+(Ch_All, Ch_None, Ch_None)
+mem|far \323\300\1\xFF\203 8086
+mem16|far \320\300\1\xFF\203 8086
+mem32|far \321\300\1\xFF\203 386
+mem|near \323\300\1\xFF\202 8086
+mem16|near \320\300\1\xFF\202 8086
+mem32|near \321\300\1\xFF\202 386
+reg16 \320\300\1\xFF\202 8086
+reg32 \321\300\1\xFF\202 386
+mem \323\300\1\xFF\202 8086
+mem16 \320\300\1\xFF\202 8086
+mem32 \321\300\1\xFF\202 386
+
+[LDS,ldsX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16,mem \320\301\1\xC5\110 8086
+reg32,mem \321\301\1\xC5\110 8086
+
+[LEA,leaX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16,mem \320\301\1\x8D\110 8086
+reg32,mem \321\301\1\x8D\110 8086
+reg32,imm32 \321\301\1\x8D\110 8086
+
+[LEAVE]
+(Ch_RWESP, Ch_WEBP, Ch_None)
+void \1\xC9 186
+
+[LES,lesX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16,mem \320\301\1\xC4\110 8086
+reg32,mem \321\301\1\xC4\110 8086
+
+[LFS,lfsX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16,mem \320\301\2\x0F\xB4\110 386
+reg32,mem \321\301\2\x0F\xB4\110 386
+
+[LGDT,lgdtX]
+(Ch_None, Ch_None, Ch_None)
+mem \300\2\x0F\x01\202 286,PRIV
+
+[LGS,lgsX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16,mem \320\301\2\x0F\xB5\110 386
+reg32,mem \321\301\2\x0F\xB5\110 386
+
+[LIDT,lidtX]
+(Ch_None, Ch_None, Ch_None)
+mem \300\2\x0F\x01\203 286,PRIV
+
+[LJMP,ljmp]
+(Ch_ROp1, Ch_None, Ch_None)
+mem|far \323\300\1\xFF\205 8086
+mem16|far \320\300\1\xFF\205 8086
+mem32|far \321\300\1\xFF\205 386
+mem|near \323\300\1\xFF\204 8086
+mem16|near \320\300\1\xFF\204 8086
+mem32|near \321\300\1\xFF\204 386
+reg16 \320\300\1\xFF\204 8086
+reg32 \321\300\1\xFF\204 386
+mem \323\300\1\xFF\204 8086
+mem16 \320\300\1\xFF\204 8086
+mem32 \321\300\1\xFF\204 386
+
+[LLDT,lldtX]
+(Ch_None, Ch_None, Ch_None)
+mem \300\1\x0F\17\202 286,PROT,PRIV
+mem16 \300\1\x0F\17\202 286,PROT,PRIV
+reg16 \300\1\x0F\17\202 286,PROT,PRIV
+
+[LMSW,lmswX]
+(Ch_None, Ch_None, Ch_None)
+mem \300\2\x0F\x01\206 286,PRIV
+mem16 \300\2\x0F\x01\206 286,PRIV
+reg16 \300\2\x0F\x01\206 286,PRIV
+
+[LOADALL]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x07 386,UNDOC
+
+[LOADALL286]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x05 286,UNDOC
+
+[LOCK]
+(Ch_None, Ch_None, Ch_None)
+void \1\xF0 8086,PRE
+
+[LODSB]
+(Ch_WEAX, Ch_RWESI, Ch_None)
+void \1\xAC 8086
+
+[LODSD,lodsl]
+(Ch_WEAX, Ch_RWESI, Ch_None)
+void \321\1\xAD 386
+
+[LODSW]
+(Ch_WEAX, Ch_RWESI, Ch_None)
+void \320\1\xAD 8086
+
+[LOOP]
+(Ch_RWECX, Ch_None, Ch_None)
+imm \312\1\xE2\50 8086
+imm,reg_cx \310\1\xE2\50 8086
+imm,reg_ecx \311\1\xE2\50 386
+
+[LOOPE]
+(Ch_RWECX, Ch_RFlags, Ch_None)
+imm \312\1\xE1\50 8086
+imm,reg_cx \310\1\xE1\50 8086
+imm,reg_ecx \311\1\xE1\50 386
+
+[LOOPNE]
+(Ch_RWECX, Ch_RFlags, Ch_None)
+imm \312\1\xE0\50 8086
+imm,reg_cx \310\1\xE0\50 8086
+imm,reg_ecx \311\1\xE0\50 386
+
+[LOOPNZ]
+(Ch_RWECX, Ch_RFlags, Ch_None)
+imm \312\1\xE0\50 8086
+imm,reg_cx \310\1\xE0\50 8086
+imm,reg_ecx \311\1\xE0\50 386
+
+[LOOPZ]
+(Ch_RWECX, Ch_RFlags, Ch_None)
+imm \312\1\xE1\50 8086
+imm,reg_cx \310\1\xE1\50 8086
+imm,reg_ecx \311\1\xE1\50 386
+
+[LSL,lslX]
+(Ch_Wop2, Ch_WFlags, Ch_None)
+reg16,mem \320\301\2\x0F\x03\110 286,PROT,SM
+reg16,reg16 \320\301\2\x0F\x03\110 286,PROT
+reg32,mem \321\301\2\x0F\x03\110 286,PROT,SM
+reg32,reg32 \321\301\2\x0F\x03\110 286,PROT
+
+[LSS,lssX]
+(Ch_Wop2, Ch_ROP1, Ch_None)
+reg16,mem \320\301\2\x0F\xB2\110 386
+reg32,mem \321\301\2\x0F\xB2\110 386
+
+[LTR,ltrX]
+(Ch_None, Ch_None, Ch_None)
+mem \300\1\x0F\17\203 286,PROT,PRIV
+mem16 \300\1\x0F\17\203 286,PROT,PRIV
+reg16 \300\1\x0F\17\203 286,PROT,PRIV
+
+[MONITOR]
+(Ch_None, Ch_None, Ch_None)
+void \3\x0F\x01\xC8 PRESCOTT
+reg_eax,reg_ecx,reg_edx \3\x0F\x01\xC8 PRESCOTT,ND
+
+[MOV,movX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mem,reg_cs \320\300\1\x8C\201 8086,SM
+mem,reg_dess \320\300\1\x8C\101 8086,SM
+mem,reg_fsgs \320\300\1\x8C\101 386,SM
+reg16,reg_cs \320\300\1\x8C\201 8086
+reg16,reg_dess \320\300\1\x8C\101 8086
+reg16,reg_fsgs \320\300\1\x8C\101 386
+rm32,reg_cs \321\300\1\x8C\201 8086
+rm32,reg_dess \321\300\1\x8C\101 8086
+rm32,reg_fsgs \321\300\1\x8C\101 386
+reg_dess,mem \320\301\1\x8E\110 8086,SM
+reg_fsgs,mem \320\301\1\x8E\110 386,SM
+reg_dess,reg16 \320\301\1\x8E\110 8086
+reg_fsgs,reg16 \320\301\1\x8E\110 386
+reg_dess,rm32 \321\301\1\x8E\110 8086
+reg_fsgs,rm32 \321\301\1\x8E\110 386
+reg_al,mem_offs \301\1\xA0\35 8086,SM,NOX86_64
+reg_ax,mem_offs \301\320\1\xA1\35 8086,SM,NOX86_64
+reg_eax,mem_offs \301\321\1\xA1\35 386,SM,NOX86_64
+mem_offs,reg_al \300\1\xA2\34 8086,SM,NOX86_64
+mem_offs,reg_ax \300\320\1\xA3\34 8086,SM,NOX86_64
+mem_offs,reg_eax \300\321\1\xA3\34 386,SM,NOX86_64
+reg32,reg_cr4 \2\x0F\x20\204 PENT,PRIV,NOX86_64
+reg32,reg_creg \2\x0F\x20\101 386,PRIV,NOX86_64
+reg32,reg_dreg \2\x0F\x21\101 386,PRIV,NOX86_64
+reg32,reg_treg \2\x0F\x24\101 386,PRIV,NOX86_64
+reg64,reg_cr4 \2\x0F\x20\204 PENT,PRIV,X86_64
+reg64,reg_creg \2\x0F\x20\101 386,PRIV,X86_64
+reg64,reg_dreg \2\x0F\x21\101 386,PRIV,X86_64
+reg64,reg_treg \2\x0F\x24\101 386,PRIV,X86_64
+reg_cr4,reg32 \2\x0F\x22\214 PENT,PRIV
+reg_creg,reg32 \2\x0F\x22\110 386,PRIV
+reg_dreg,reg32 \2\x0F\x23\110 386,PRIV
+reg_treg,reg32 \2\x0F\x26\110 386,PRIV
+mem,reg8 \300\1\x88\101 8086,SM
+reg8,reg8 \300\1\x88\101 8086
+mem,reg16 \320\300\1\x89\101 8086,SM
+reg16,reg16 \320\300\1\x89\101 8086
+mem,reg32 \321\300\1\x89\101 386,SM
+reg32,reg32 \321\300\1\x89\101 386
+reg8,mem \301\1\x8A\110 8086,SM
+reg8,reg8 \301\1\x8A\110 8086
+reg16,mem \320\301\1\x8B\110 8086,SM
+reg16,reg16 \320\301\1\x8B\110 8086
+reg32,mem \321\301\1\x8B\110 386,SM
+reg32,reg32 \321\301\1\x8B\110 386
+reg8,imm \10\xB0\21 8086,SM
+reg16,imm \320\10\xB8\31 8086,SM
+reg32,imm \321\10\xB8\41 386,SM
+rm8,imm \300\1\xC6\200\21 8086,SM
+rm16,imm \320\300\1\xC7\200\31 8086,SM
+rm32,imm \321\300\1\xC7\200\41 386,SM
+mem,imm8 \300\1\xC6\200\21 8086,SM
+mem,imm16 \320\300\1\xC7\200\31 8086,SM
+mem,imm32 \321\300\1\xC7\200\41 386,SM
+
+[MOVD,movd]
+(Ch_Rop1, Ch_Wop2, Ch_None)
+mmxreg,mem \301\2\x0F\x6E\110 PENT,MMX,SD
+mmxreg,reg32 \2\x0F\x6E\110 PENT,MMX
+mem,mmxreg \300\2\x0F\x7E\101 PENT,MMX,SD
+reg32,mmxreg \2\x0F\x7E\101 PENT,MMX
+xmmreg,reg32 \3\x66\x0F\x6E\110 WILLAMETTE,SSE2
+reg32,xmmreg \3\x66\x0F\x7E\101 WILLAMETTE,SSE2
+mem,xmmreg \300\3\x66\x0F\x7E\101 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x6E\110 WILLAMETTE,SSE2
+
+[MOVQ,movq]
+(Ch_Rop1, Ch_Wop2, Ch_None)
+mmxreg,mem \301\2\x0F\x6F\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x6F\110 PENT,MMX
+mem,mmxreg \300\2\x0F\x7F\101 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x7F\101 PENT,MMX
+xmmreg,xmmreg \333\2\x0F\x7E\110 WILLAMETTE,SSE2
+xmmreg,xmmreg \3\x66\x0F\xD6\110 WILLAMETTE,SSE2
+mem,xmmreg \300\3\x66\x0F\xD6\101 WILLAMETTE,SSE2
+xmmreg,mem \301\333\2\x0F\x7E\110 WILLAMETTE,SSE2
+
+
+[MOVSB]
+(Ch_All, Ch_None, Ch_None)
+void \1\xA4 8086
+
+[MOVSD,movsl]
+; Ch_All isn't correct for the sse move, but how can it be solved? (FK)
+(Ch_All, Ch_None, Ch_None)
+void \321\1\xA5 386
+xmmreg,xmmreg \3\xF2\x0F\x10\110 WILLAMETTE,SSE2
+xmmreg,xmmreg \3\xF2\x0F\x11\110 WILLAMETTE,SSE2
+mem,xmmreg \300\3\xF2\x0F\x11\101 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x10\110 WILLAMETTE,SSE2
+
+[MOVSQ]
+(Ch_All, Ch_None, Ch_None)
+void \322\1\xA5 X86_64
+
+[MOVSW]
+(Ch_All, Ch_None, Ch_None)
+void \320\1\xA5 8086
+
+[MOVSX,movsX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16,mem \320\301\2\x0F\xBE\110 386,SB
+reg16,reg8 \320\301\2\x0F\xBE\110 386
+reg32,rm8 \321\301\2\x0F\xBE\110 386
+reg32,rm16 \321\301\2\x0F\xBF\110 386
+reg64,rm16 \321\301\2\x0F\xBF\110 X86_64
+
+[MOVZX,movzX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16,mem \320\301\2\x0F\xB6\110 386,SB
+reg16,reg8 \320\301\2\x0F\xB6\110 386
+reg32,rm8 \321\301\2\x0F\xB6\110 386
+reg32,rm16 \321\301\2\x0F\xB7\110 386
+
+[MUL,mulX]
+(Ch_RWEAX, Ch_WEDX, Ch_WFlags)
+rm8 \300\1\xF6\204 8086
+rm16 \320\300\1\xF7\204 8086
+rm32 \321\300\1\xF7\204 386
+
+[MWAIT]
+(Ch_None, Ch_None, Ch_None)
+void \3\x0F\x01\xC9 PRESCOTT
+reg_eax,reg_ecx \3\x0F\x01\xC9 PRESCOTT,ND
+
+
+[NEG,negX]
+(Ch_Mop1, Ch_None, Ch_None)
+rm8 \300\1\xF6\203 8086
+rm16 \320\300\1\xF7\203 8086
+rm32 \321\300\1\xF7\203 386
+
+[NOP]
+(Ch_None, Ch_None, Ch_None)
+void \1\x90 8086
+
+[NOT,notX]
+(Ch_Mop1, Ch_WFlags, Ch_None)
+rm8 \300\1\xF6\202 8086
+rm16 \320\300\1\xF7\202 8086
+rm32 \321\300\1\xF7\202 386
+
+[OR,orX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+mem,reg8 \300\1\x08\101 8086,SM
+reg8,reg8 \300\1\x08\101 8086
+mem,reg16 \320\300\1\x09\101 8086,SM
+reg16,reg16 \320\300\1\x09\101 8086
+mem,reg32 \321\300\1\x09\101 386,SM
+reg32,reg32 \321\300\1\x09\101 386
+reg8,mem \301\1\x0A\110 8086,SM
+reg8,reg8 \301\1\x0A\110 8086
+reg16,mem \320\301\1\x0B\110 8086,SM
+reg16,reg16 \320\301\1\x0B\110 8086
+reg32,mem \321\301\1\x0B\110 386,SM
+reg32,reg32 \321\301\1\x0B\110 386
+rm16,imm8 \320\300\1\x83\201\15 8086
+rm32,imm8 \321\300\1\x83\201\15 386
+reg_al,imm \1\x0C\21 8086,SM
+reg_ax,imm \320\1\x0D\31 8086,SM
+reg_eax,imm \321\1\x0D\41 386,SM
+rm8,imm \300\1\x80\201\21 8086,SM
+rm16,imm \320\300\1\x81\201\31 8086,SM
+rm32,imm \321\300\1\x81\201\41 386,SM
+mem,imm8 \300\1\x80\201\21 8086,SM
+mem,imm16 \320\300\1\x81\201\31 8086,SM
+mem,imm32 \321\300\1\x81\201\41 386,SM
+
+[OUT,outX]
+(Ch_Rop1, Ch_Rop2, Ch_None)
+imm,reg_al \1\xE6\24 8086,SB
+imm,reg_ax \320\1\xE7\24 8086,SB
+imm,reg_eax \321\1\xE7\24 386,SB
+reg_dx,reg_al \1\xEE 8086
+reg_dx,reg_ax \320\1\xEF 8086
+reg_dx,reg_eax \321\1\xEF 386
+
+[OUTSB]
+(Ch_All, Ch_None, Ch_None)
+void \1\x6E 186
+
+[OUTSD,outsl]
+(Ch_All, Ch_None, Ch_None)
+void \321\1\x6F 386
+
+[OUTSW]
+(Ch_All, Ch_None, Ch_None)
+void \320\1\x6F 186
+
+[PACKSSDW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x6B\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x6B\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x6B\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x6B\110 WILLAMETTE,SSE2,SM
+
+[PACKSSWB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x63\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x63\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x63\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x63\110 WILLAMETTE,SSE2,SM
+
+[PACKUSWB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x67\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x67\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x67\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x67\110 WILLAMETTE,SSE2,SM
+
+[PADDB]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mem \301\2\x0F\xFC\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xFC\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\xFC\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xFC\110 WILLAMETTE,SSE2,SM
+
+[PADDD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mem \301\2\x0F\xFE\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xFE\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\xFE\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xFE\110 WILLAMETTE,SSE2,SM
+
+[PADDSB]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mem \301\2\x0F\xEC\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xEC\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xEC\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xEC\110 WILLAMETTE,SSE2
+
+[PADDSIW]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mem \301\2\x0F\x51\110 PENT,MMX,SM,CYRIX
+mmxreg,mmxreg \2\x0F\x51\110 PENT,MMX,CYRIX
+
+[PADDSW]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mem \301\2\x0F\xED\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xED\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xED\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xED\110 WILLAMETTE,SSE2
+
+[PADDUSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xDC\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xDC\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xDC\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xDC\110 WILLAMETTE,SSE2
+
+[PADDUSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xDD\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xDD\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xDD\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xDD\110 WILLAMETTE,SSE2
+
+[PADDW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xFD\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xFD\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\xFD\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xFD\110 WILLAMETTE,SSE2,SM
+
+[PAND]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xDB\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xDB\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\xDB\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xDB\110 WILLAMETTE,SSE2,SM
+
+[PANDN]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xDF\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xDF\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\xDF\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xDF\110 WILLAMETTE,SSE2,SM
+
+[PAVEB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x50\110 PENT,MMX,SM,CYRIX
+mmxreg,mmxreg \2\x0F\x50\110 PENT,MMX,CYRIX
+
+[PAVGUSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xBF PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xBF PENT,3DNOW
+
+[PCMPEQB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x74\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x74\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x74\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x74\110 WILLAMETTE,SSE2,SM
+
+[PCMPEQD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x76\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x76\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x76\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x76\110 WILLAMETTE,SSE2,SM
+
+[PCMPEQW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x75\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x75\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x75\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x75\110 WILLAMETTE,SSE2,SM
+
+[PCMPGTB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x64\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x64\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x64\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x64\110 WILLAMETTE,SSE2,SM
+
+[PCMPGTD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x66\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x66\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x66\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x66\110 WILLAMETTE,SSE2,SM
+
+[PCMPGTW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x65\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x65\110 PENT,MMX
+xmmreg,xmmreg \3\x66\x0F\x65\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x65\110 WILLAMETTE,SSE2,SM
+
+[PDISTIB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x54\110 PENT,MMX,SM,CYRIX
+
+[PF2ID]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x1D PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x1D PENT,3DNOW
+
+[PFACC]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xAE PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xAE PENT,3DNOW
+
+[PFADD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x9E PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x9E PENT,3DNOW
+
+[PFCMPEQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xB0 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xB0 PENT,3DNOW
+
+[PFCMPGE]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x90 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x90 PENT,3DNOW
+
+[PFCMPGT]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xA0 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xA0 PENT,3DNOW
+
+[PFMAX]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xA4 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xA4 PENT,3DNOW
+
+[PFMIN]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x94 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x94 PENT,3DNOW
+
+[PFMUL]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xB4 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xB4 PENT,3DNOW
+
+[PFRCP]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x96 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x96 PENT,3DNOW
+
+[PFRCPIT1]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xA6 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xA6 PENT,3DNOW
+
+[PFRCPIT2]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xB6 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xB6 PENT,3DNOW
+
+[PFRSQIT1]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xA7 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xA7 PENT,3DNOW
+
+[PFRSQRT]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x97 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x97 PENT,3DNOW
+
+[PFSUB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x9A PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x9A PENT,3DNOW
+
+[PFSUBR]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xAA PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xAA PENT,3DNOW
+
+[PI2FD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x0D PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x0D PENT,3DNOW
+
+[PMACHRIW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x5E\110 PENT,MMX,SM,CYRIX
+
+[PMADDWD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xF5\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xF5\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xF5\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xF5\110 WILLAMETTE,SSE2
+
+[PMAGW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x52\110 PENT,MMX,SM,CYRIX
+mmxreg,mmxreg \2\x0F\x52\110 PENT,MMX,CYRIX
+
+[PMULHRIW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x5D\110 PENT,MMX,SM,CYRIX
+mmxreg,mmxreg \2\x0F\x5D\110 PENT,MMX,CYRIX
+
+[PMULHRWA]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\1\xB7 PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\1\xB7 PENT,3DNOW
+
+[PMULHRWC]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x59\110 PENT,MMX,SM,CYRIX
+mmxreg,mmxreg \2\x0F\x59\110 PENT,MMX,CYRIX
+
+[PMULHW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xE5\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xE5\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xE5\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xE5\110 WILLAMETTE,SSE2
+
+[PMULLW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xD5\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xD5\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xD5\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xD5\110 WILLAMETTE,SSE2
+
+[PMVGEZB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x5C\110 PENT,MMX,SM,CYRIX
+
+[PMVLZB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x5B\110 PENT,MMX,SM,CYRIX
+
+[PMVNZB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x5A\110 PENT,MMX,SM,CYRIX
+
+[PMVZB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x58\110 PENT,MMX,SM,CYRIX
+
+[POP,popX]
+(Ch_Wop1, Ch_RWESP, Ch_None)
+reg16 \320\10\x58 8086
+reg32 \321\10\x58 386
+rm16 \320\300\1\x8F\200 8086
+rm32 \321\300\1\x8F\200 386
+reg_cs \1\x0F 8086,UNDOC,ND
+reg_dess \4 8086
+reg_fsgs \1\x0F\5 386
+
+[POPA,popaX]
+(Ch_All, Ch_None, Ch_None)
+void \323\1\x61 186
+
+[POPAD,popal]
+(Ch_All, Ch_None, Ch_None)
+void \321\1\x61 386
+
+[POPAW]
+(Ch_All, Ch_None, Ch_None)
+void \320\1\x61 186
+
+[POPF]
+(Ch_RWESP, Ch_WFlags, Ch_None)
+void \323\1\x9D 186
+
+[POPFD,popfl]
+(Ch_RWESP, Ch_WFlags, Ch_None)
+void \321\1\x9D 386
+
+[POPFW]
+(Ch_RWESP, Ch_WFLAGS, Ch_None)
+void \320\1\x9D 186
+
+[POR]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xEB\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xEB\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xEB\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xEB\110 WILLAMETTE,SSE2
+
+[PREFETCH,prefetchX]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x0D\200 PENT,3DNOW,SM
+
+[PREFETCHW,prefetchwX]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x0D\201 PENT,3DNOW,SM
+
+[PSLLD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xF2\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xF2\110 PENT,MMX
+mmxreg,imm \2\x0F\x72\206\25 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xF2\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xF2\110 WILLAMETTE,SSE2
+xmmreg,imm \3\x66\x0F\x72\206\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSLLDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,imm \3\x66\x0F\x73\207\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSLLQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xF3\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xF3\110 PENT,MMX
+mmxreg,imm \2\x0F\x73\206\25 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xF3\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xF3\110 WILLAMETTE,SSE2
+xmmreg,imm \3\x66\x0F\x73\206\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSLLW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xF1\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xF1\110 PENT,MMX
+mmxreg,imm \2\x0F\x71\206\25 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xF1\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xF1\110 WILLAMETTE,SSE2
+xmmreg,imm \3\x66\x0F\x71\206\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRAD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xE2\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xE2\110 PENT,MMX
+mmxreg,imm \2\x0F\x72\204\25 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xE2\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xE2\110 WILLAMETTE,SSE2
+xmmreg,imm \3\x66\x0F\x72\204\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRAW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xE1\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xE1\110 PENT,MMX
+mmxreg,imm \2\x0F\x71\204\25 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xE1\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xE1\110 WILLAMETTE,SSE2
+xmmreg,imm \3\x66\x0F\x71\204\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRLD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xD2\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xD2\110 PENT,MMX
+mmxreg,imm \2\x0F\x72\202\25 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xD2\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xD2\110 WILLAMETTE,SSE2
+xmmreg,imm \3\x66\x0F\x72\202\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRLQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xD3\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xD3\110 PENT,MMX
+mmxreg,imm \2\x0F\x73\202\25 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xD3\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xD3\110 WILLAMETTE,SSE2
+xmmreg,imm \3\x66\x0F\x73\202\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRLW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xD1\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xD1\110 PENT,MMX
+mmxreg,imm \2\x0F\x71\202\25 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xD1\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xD1\110 WILLAMETTE,SSE2
+xmmreg,imm \3\x66\x0F\x71\202\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSUBB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xF8\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xF8\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xF8\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xF8\110 WILLAMETTE,SSE2
+
+[PSUBD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xFA\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xFA\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xFA\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xFA\110 WILLAMETTE,SSE2
+
+[PSUBSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xE8\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xE8\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xE8\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xE8\110 WILLAMETTE,SSE2
+
+[PSUBSIW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x55\110 PENT,MMX,SM,CYRIX
+mmxreg,mmxreg \2\x0F\x55\110 PENT,MMX,CYRIX
+
+[PSUBSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xE9\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xE9\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xE9\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xE9\110 WILLAMETTE,SSE2
+
+[PSUBUSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xD8\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xD8\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xD8\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xD8\110 WILLAMETTE,SSE2
+
+[PSUBUSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xD9\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xD9\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xD9\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xD9\110 WILLAMETTE,SSE2
+
+[PSUBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\xF9\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xF9\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xF9\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xF9\110 WILLAMETTE,SSE2
+
+[PUNPCKHBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x68\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x68\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\x68\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\x68\110 WILLAMETTE,SSE2
+
+[PUNPCKHDQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x6A\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x6A\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\x6A\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\x6A\110 WILLAMETTE,SSE2
+
+[PUNPCKHWD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x69\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x69\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\x69\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\x69\110 WILLAMETTE,SSE2
+
+[PUNPCKLBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x60\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x60\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\x60\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\x60\110 WILLAMETTE,SSE2
+
+[PUNPCKLDQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x62\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x62\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\x62\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\x62\110 WILLAMETTE,SSE2
+
+[PUNPCKLWD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x61\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\x61\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\x61\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\x61\110 WILLAMETTE,SSE2
+
+[PUSH,pushX]
+(Ch_Rop1, Ch_RWESP, Ch_None)
+reg16 \320\10\x50 8086,NOX86_64
+reg32 \321\10\x50 386,NOX86_64
+rm16 \320\300\1\xFF\206 8086,NOX86_64
+rm32 \321\300\1\xFF\206 386,NOX86_64
+reg_fsgs \1\x0F\7 386,NOX86_64
+reg_sreg \6 8086,NOX86_64
+imm8 \1\x6A\14 286,NOX86_64
+imm16 \320\1\x68\30 286,NOX86_64
+imm32 \321\1\x68\40 386,NOX86_64
+
+[PUSHA,pushaX]
+(Ch_All, Ch_None, Ch_None)
+void \323\1\x60 186
+
+[PUSHAD,pushal]
+(Ch_All, Ch_None, Ch_None)
+void \321\1\x60 386
+
+[PUSHAW]
+(Ch_All, Ch_None, Ch_None)
+void \320\1\x60 186
+
+[PUSHF]
+(Ch_RWESP, Ch_RFlags, Ch_None)
+void \323\1\x9C 186
+
+[PUSHFD,pushfl]
+(Ch_RWESP, Ch_RFlags, Ch_None)
+void \321\1\x9C 386
+
+[PUSHFW]
+(Ch_RWESP, Ch_RFLAGS, Ch_None)
+void \320\1\x9C 186
+
+[PXOR]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mem \301\2\x0F\xEF\110 PENT,MMX,SM
+mmxreg,mmxreg \2\x0F\xEF\110 PENT,MMX
+xmmreg,mem \301\3\x66\x0F\xEF\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xEF\110 WILLAMETTE,SSE2
+
+[RCL,rclX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm8,unity \300\1\xD0\202 8086
+rm8,reg_cl \300\1\xD2\202 8086
+rm8,imm \300\1\xC0\202\25 186,SB
+rm16,unity \320\300\1\xD1\202 8086
+rm16,reg_cl \320\300\1\xD3\202 8086
+rm16,imm \320\300\1\xC1\202\25 186,SB
+rm32,unity \321\300\1\xD1\202 386
+rm32,reg_cl \321\300\1\xD3\202 386
+rm32,imm \321\300\1\xC1\202\25 386,SB
+
+[RCR,rcrX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm8,unity \300\1\xD0\203 8086
+rm8,reg_cl \300\1\xD2\203 8086
+rm8,imm \300\1\xC0\203\25 186,SB
+rm16,unity \320\300\1\xD1\203 8086
+rm16,reg_cl \320\300\1\xD3\203 8086
+rm16,imm \320\300\1\xC1\203\25 186,SB
+rm32,unity \321\300\1\xD1\203 386
+rm32,reg_cl \321\300\1\xD3\203 386
+rm32,imm \321\300\1\xC1\203\25 386,SB
+
+[RDSHR]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x36 P6,CYRIX,SMM
+
+[RDMSR]
+(Ch_WEAX, Ch_WEDX, Ch_None)
+void \2\x0F\x32 PENT,PRIV
+
+[RDPMC]
+(Ch_WEAX, Ch_WEDX, Ch_None)
+void \2\x0F\x33 P6
+
+[RDTSC]
+(Ch_WEAX, Ch_WEDX, Ch_None)
+void \2\x0F\x31 PENT
+
+[REP]
+(Ch_RWECX, Ch_RWFlags, Ch_None)
+void \1\xF3 8086,PRE
+
+[REPE]
+(Ch_RWECX, Ch_RWFlags, Ch_None)
+void \1\xF3 8086,PRE
+
+[REPNE]
+(Ch_RWECX, Ch_RWFlags, Ch_None)
+void \1\xF2 8086,PRE
+
+[REPNZ]
+(Ch_RWECX, Ch_RWFLAGS, Ch_None)
+void \1\xF2 8086,PRE
+
+[REPZ]
+(Ch_RWECX, Ch_RWFLAGS, Ch_None)
+void \1\xF3 8086,PRE
+
+[RET]
+(Ch_All, Ch_None, Ch_None)
+void \1\xC3 8086
+imm \1\xC2\30 8086,SW
+
+[RETF,lret]
+(Ch_All, Ch_None, Ch_None)
+void \1\xCB 8086
+imm \1\xCA\30 8086,SW
+
+[RETN,ret]
+(Ch_All, Ch_None, Ch_None)
+void \1\xC3 8086
+imm \1\xC2\30 8086,SW
+
+[ROL,rolX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm8,unity \300\1\xD0\200 8086
+rm8,reg_cl \300\1\xD2\200 8086
+rm8,imm \300\1\xC0\200\25 186,SB
+rm16,unity \320\300\1\xD1\200 8086
+rm16,reg_cl \320\300\1\xD3\200 8086
+rm16,imm \320\300\1\xC1\200\25 186,SB
+rm32,unity \321\300\1\xD1\200 386
+rm32,reg_cl \321\300\1\xD3\200 386
+rm32,imm \321\300\1\xC1\200\25 386,SB
+
+[ROR,rorX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm8,unity \300\1\xD0\201 8086
+rm8,reg_cl \300\1\xD2\201 8086
+rm8,imm \300\1\xC0\201\25 186,SB
+rm16,unity \320\300\1\xD1\201 8086
+rm16,reg_cl \320\300\1\xD3\201 8086
+rm16,imm \320\300\1\xC1\201\25 186,SB
+rm32,unity \321\300\1\xD1\201 386
+rm32,reg_cl \321\300\1\xD3\201 386
+rm32,imm \321\300\1\xC1\201\25 386,SB
+
+[RSDC]
+(Ch_All, Ch_None, Ch_None)
+reg_sreg,mem80 \301\2\x0F\x79\101 486,CYRIX,SMM
+
+[RSLDT]
+(Ch_All, Ch_None, Ch_None)
+mem80 \300\2\x0F\x7B\200 486,CYRIX,SMM
+
+[RSM]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\xAA PENT,SMM
+
+[SAHF]
+(Ch_WFlags, Ch_REAX, Ch_None)
+void \1\x9E 8086,NOX86_64
+
+[SAL,salX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm8,unity \300\1\xD0\204 8086,ND
+rm8,reg_cl \300\1\xD2\204 8086,ND
+rm8,imm \300\1\xC0\204\25 186,ND,SB
+rm16,unity \320\300\1\xD1\204 8086,ND
+rm16,reg_cl \320\300\1\xD3\204 8086,ND
+rm16,imm \320\300\1\xC1\204\25 186,ND,SB
+rm32,unity \321\300\1\xD1\204 386,ND
+rm32,reg_cl \321\300\1\xD3\204 386,ND
+rm32,imm \321\300\1\xC1\204\25 386,ND,SB
+
+[SALC]
+(Ch_WEAX, Ch_RFLAGS, Ch_None)
+void \1\xD6 8086,UNDOC
+
+[SAR,sarX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+rm8,unity \300\1\xD0\207 8086
+rm8,reg_cl \300\1\xD2\207 8086
+rm8,imm \300\1\xC0\207\25 186,SB
+rm16,unity \320\300\1\xD1\207 8086
+rm16,reg_cl \320\300\1\xD3\207 8086
+rm16,imm \320\300\1\xC1\207\25 186,SB
+rm32,unity \321\300\1\xD1\207 386
+rm32,reg_cl \321\300\1\xD3\207 386
+rm32,imm \321\300\1\xC1\207\25 386,SB
+
+[SBB,sbbX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+mem,reg8 \300\1\x18\101 8086,SM
+reg8,reg8 \300\1\x18\101 8086
+mem,reg16 \320\300\1\x19\101 8086,SM
+reg16,reg16 \320\300\1\x19\101 8086
+mem,reg32 \321\300\1\x19\101 386,SM
+reg32,reg32 \321\300\1\x19\101 386
+reg8,mem \301\1\x1A\110 8086,SM
+reg8,reg8 \301\1\x1A\110 8086
+reg16,mem \320\301\1\x1B\110 8086,SM
+reg16,reg16 \320\301\1\x1B\110 8086
+reg32,mem \321\301\1\x1B\110 386,SM
+reg32,reg32 \321\301\1\x1B\110 386
+rm16,imm8 \320\300\1\x83\203\15 8086
+rm32,imm8 \321\300\1\x83\203\15 8086
+reg_al,imm \1\x1C\21 8086,SM
+reg_ax,imm \320\1\x1D\31 8086,SM
+reg_eax,imm \321\1\x1D\41 386,SM
+rm8,imm \300\1\x80\203\21 8086,SM
+rm16,imm \320\300\1\x81\203\31 8086,SM
+rm32,imm \321\300\1\x81\203\41 386,SM
+mem,imm8 \300\1\x80\203\21 8086,SM
+mem,imm16 \320\300\1\x81\203\31 8086,SM
+mem,imm32 \321\300\1\x81\203\41 386,SM
+
+[SCASB]
+(Ch_All, Ch_None, Ch_None)
+void \332\1\xAE 8086
+
+[SCASD,scasl]
+(Ch_All, Ch_None, Ch_None)
+void \332\321\1\xAF 386
+
+[SCASW]
+(Ch_All, Ch_None, Ch_None)
+void \332\320\1\xAF 8086
+
+[SEGCS,cs]
+(Ch_None, Ch_None, Ch_None)
+void \1\x2E 8086,PRE
+
+[SEGDS,ds]
+(Ch_None, Ch_None, Ch_None)
+void \1\x3E 8086,PRE
+
+[SEGES,es]
+(Ch_None, Ch_None, Ch_None)
+void \1\x26 8086,PRE
+
+[SEGFS,fs]
+(Ch_None, Ch_None, Ch_None)
+void \1\x64 8086,PRE
+
+[SEGGS,gs]
+(Ch_None, Ch_None, Ch_None)
+void \1\x65 8086,PRE
+
+[SEGSS,ss]
+(Ch_None, Ch_None, Ch_None)
+void \1\x36 8086,PRE
+
+[SGDT]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\2\x0F\x01\200 286
+
+[SHL,shlX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+rm8,unity \300\1\xD0\204 8086
+rm8,reg_cl \300\1\xD2\204 8086
+rm8,imm \300\1\xC0\204\25 186,SB
+rm16,unity \320\300\1\xD1\204 8086
+rm16,reg_cl \320\300\1\xD3\204 8086
+rm16,imm \320\300\1\xC1\204\25 186,SW
+rm32,unity \321\300\1\xD1\204 386
+rm32,reg_cl \321\300\1\xD3\204 386
+rm32,imm \321\300\1\xC1\204\25 386,SD
+
+[SHLD,shldX]
+(Ch_MOp3, Ch_RWFlags, Ch_Rop2)
+mem,reg16,imm \300\320\2\x0F\xA4\101\26 386,SM2,SB,AR2
+reg16,reg16,imm \300\320\2\x0F\xA4\101\26 386,SM2,SB,AR2
+mem,reg32,imm \300\321\2\x0F\xA4\101\26 386,SM2,SB,AR2
+reg32,reg32,imm \300\321\2\x0F\xA4\101\26 386,SM2,SB,AR2
+mem,reg16,reg_cl \300\320\2\x0F\xA5\101 386,SM
+reg16,reg16,reg_cl \300\320\2\x0F\xA5\101 386
+mem,reg32,reg_cl \300\321\2\x0F\xA5\101 386,SM
+reg32,reg32,reg_cl \300\321\2\x0F\xA5\101 386
+
+[SHR,shrX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+rm8,unity \300\1\xD0\205 8086
+rm8,reg_cl \300\1\xD2\205 8086
+rm8,imm \300\1\xC0\205\25 186,SB
+rm16,unity \320\300\1\xD1\205 8086
+rm16,reg_cl \320\300\1\xD3\205 8086
+rm16,imm \320\300\1\xC1\205\25 186,SW
+rm32,unity \321\300\1\xD1\205 386
+rm32,reg_cl \321\300\1\xD3\205 386
+rm32,imm \321\300\1\xC1\205\25 386,SD
+
+[SHRD,shrdX]
+(Ch_MOp3, Ch_RWFlags, Ch_Rop2)
+mem,reg16,imm \300\320\2\x0F\xAC\101\26 386,SM2,SB,AR2
+reg16,reg16,imm \300\320\2\x0F\xAC\101\26 386,SM2,SB,AR2
+mem,reg32,imm \300\321\2\x0F\xAC\101\26 386,SM2,SB,AR2
+reg32,reg32,imm \300\321\2\x0F\xAC\101\26 386,SM2,SB,AR2
+mem,reg16,reg_cl \300\320\2\x0F\xAD\101 386,SM
+reg16,reg16,reg_cl \300\320\2\x0F\xAD\101 386
+mem,reg32,reg_cl \300\321\2\x0F\xAD\101 386,SM
+reg32,reg32,reg_cl \300\321\2\x0F\xAD\101 386
+
+[SIDT,sidtX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\2\x0F\x01\201 286
+
+[SLDT,sldtX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\1\x0F\17\200 286
+mem16 \300\1\x0F\17\200 286
+reg16 \320\1\x0F\17\200 286
+reg32 \321\1\x0F\17\200 386
+
+[SMI]
+(Ch_All, Ch_None, Ch_None)
+void \1\xF1 386,UNDOC
+
+[SMINT]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x38 P6,CYRIX
+
+[SMINTOLD]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x7E 486,CYRIX,ND
+
+[SMSW,smswX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\2\x0F\x01\204 286
+mem16 \300\2\x0F\x01\204 286
+reg16 \320\2\x0F\x01\204 286
+reg32 \321\2\x0F\x01\204 386
+
+[STC]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xF9 8086
+
+[STD]
+(Ch_SDirFlag, Ch_None, Ch_None)
+void \1\xFD 8086
+
+[STI]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xFB 8086
+
+[STOSB]
+(Ch_REAX, Ch_WMemEDI, Ch_RWEDI)
+void \1\xAA 8086
+
+[STOSD,stosl]
+(Ch_REAX, Ch_WMemEDI, Ch_RWEDI)
+void \321\1\xAB 386
+
+[STOSW]
+(Ch_REAX, Ch_WMemEDI, Ch_RWEDI)
+void \320\1\xAB 8086
+
+[STR,strX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \300\1\x0F\17\201 286,PROT
+mem16 \300\1\x0F\17\201 286,PROT
+reg16 \320\1\x0F\17\201 286,PROT
+reg32 \321\1\x0F\17\201 386,PROT
+
+[SUB,subX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+mem,reg8 \300\1\x28\101 8086,SM
+reg8,reg8 \300\1\x28\101 8086
+mem,reg16 \320\300\1\x29\101 8086,SM
+reg16,reg16 \320\300\1\x29\101 8086
+mem,reg32 \321\300\1\x29\101 386,SM
+reg32,reg32 \321\300\1\x29\101 386
+reg8,mem \301\1\x2A\110 8086,SM
+reg8,reg8 \301\1\x2A\110 8086
+reg16,mem \320\301\1\x2B\110 8086,SM
+reg16,reg16 \320\301\1\x2B\110 8086
+reg32,mem \321\301\1\x2B\110 386,SM
+reg32,reg32 \321\301\1\x2B\110 386
+rm16,imm8 \320\300\1\x83\205\15 8086
+rm32,imm8 \321\300\1\x83\205\15 386
+reg_al,imm \1\x2C\21 8086,SM
+reg_ax,imm \320\1\x2D\31 8086,SM
+reg_eax,imm \321\1\x2D\41 386,SM
+rm8,imm \300\1\x80\205\21 8086,SM
+rm16,imm \320\300\1\x81\205\31 8086,SM
+rm32,imm \321\300\1\x81\205\41 386,SM
+mem,imm8 \300\1\x80\205\21 8086,SM
+mem,imm16 \320\300\1\x81\205\31 8086,SM
+mem,imm32 \321\300\1\x81\205\41 386,SM
+
+[SVDC,svdcX]
+(Ch_All, Ch_None, Ch_None)
+mem80,reg_sreg \300\2\x0F\x78\101 486,CYRIX,SMM
+
+[SVLDT,svldtX]
+(Ch_All, Ch_None, Ch_None)
+mem80 \300\2\x0F\x7A\200 486,CYRIX,SMM
+
+[SVTS,svtsX]
+(Ch_All, Ch_None, Ch_None)
+mem80 \300\2\x0F\x7C\200 486,CYRIX,SMM
+
+[SYSCALL]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x05 P6,AMD
+
+[SYSENTER]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x34 P6
+
+[SYSEXIT]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x35 P6,PRIV
+
+[SYSRET]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x07 P6,PRIV,AMD
+
+[TEST,testX]
+(Ch_WFlags, Ch_Rop1, Ch_Rop2)
+mem,reg8 \300\1\x84\101 8086,SM
+reg8,reg8 \300\1\x84\101 8086
+mem,reg16 \320\300\1\x85\101 8086,SM
+reg16,reg16 \320\300\1\x85\101 8086
+mem,reg32 \321\300\1\x85\101 386,SM
+reg32,reg32 \321\300\1\x85\101 386
+reg8,mem \301\1\x84\110 8086,SM
+reg16,mem \320\301\1\x85\110 8086,SM
+reg32,mem \321\301\1\x85\110 386,SM
+reg_al,imm \1\xA8\21 8086,SM
+reg_ax,imm \320\1\xA9\31 8086,SM
+reg_eax,imm \321\1\xA9\41 386,SM
+rm8,imm \300\1\xF6\200\21 8086,SM
+rm16,imm \320\300\1\xF7\200\31 8086,SM
+rm32,imm \321\300\1\xF7\200\41 386,SM
+mem,imm8 \300\1\xF6\200\21 8086,SM
+mem,imm16 \320\300\1\xF7\200\31 8086,SM
+mem,imm32 \321\300\1\xF7\200\41 386,SM
+
+[UD1]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\xB9 286,UNDOC
+
+[UD2]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x0B 286
+
+[UMOV,umovX]
+(Ch_All, Ch_None, Ch_None)
+mem,reg8 \300\2\x0F\x10\101 386,UNDOC,SM
+reg8,reg8 \300\2\x0F\x10\101 386,UNDOC
+mem,reg16 \320\300\2\x0F\x11\101 386,UNDOC,SM
+reg16,reg16 \320\300\2\x0F\x11\101 386,UNDOC
+mem,reg32 \321\300\2\x0F\x11\101 386,UNDOC,SM
+reg32,reg32 \321\300\2\x0F\x11\101 386,UNDOC
+reg8,mem \301\2\x0F\x12\110 386,UNDOC,SM
+reg8,reg8 \301\2\x0F\x12\110 386,UNDOC
+reg16,mem \320\301\2\x0F\x13\110 386,UNDOC,SM
+reg16,reg16 \320\301\2\x0F\x13\110 386,UNDOC
+reg32,mem \321\301\2\x0F\x13\110 386,UNDOC,SM
+reg32,reg32 \321\301\2\x0F\x13\110 386,UNDOC
+
+[VERR,verrX]
+(Ch_WFlags, Ch_None, Ch_None)
+mem \300\1\x0F\17\204 286,PROT
+mem16 \300\1\x0F\17\204 286,PROT
+reg16 \300\1\x0F\17\204 286,PROT
+
+[VERW]
+(Ch_WFlags, Ch_None, Ch_None)
+mem \300\1\x0F\17\205 286,PROT
+mem16 \300\1\x0F\17\205 286,PROT
+reg16 \300\1\x0F\17\205 286,PROT
+
+[WAIT]
+(Ch_None, Ch_None, Ch_None)
+void \1\x9B 8086
+
+[WBINVD]
+(Ch_None, Ch_None, Ch_None)
+void \2\x0F\x09 486,PRIV
+
+[WRSHR]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x37 P6,CYRIX,SMM
+
+[WRMSR]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x30 PENT,PRIV
+
+[XADD,xaddX]
+(Ch_All, Ch_None, Ch_None)
+mem,reg8 \300\2\x0F\xC0\101 486,SM
+reg8,reg8 \300\2\x0F\xC0\101 486
+mem,reg16 \320\300\2\x0F\xC1\101 486,SM
+reg16,reg16 \320\300\2\x0F\xC1\101 486
+mem,reg32 \321\300\2\x0F\xC1\101 486,SM
+reg32,reg32 \321\300\2\x0F\xC1\101 486
+
+[XBTS,xbtsX]
+(Ch_All, Ch_None, Ch_None)
+reg16,mem \320\301\2\x0F\xA6\110 386,SW,UNDOC,ND
+reg16,reg16 \320\301\2\x0F\xA6\110 386,UNDOC,ND
+reg32,mem \321\301\2\x0F\xA6\110 386,SD,UNDOC,ND
+reg32,reg32 \321\301\2\x0F\xA6\110 386,UNDOC,ND
+
+[XCHG,xchgX]
+(Ch_RWop1, Ch_RWop2, Ch_None)
+reg_ax,reg16 \320\11\x90 8086
+reg_eax,reg32 \321\11\x90 386
+reg16,reg_ax \320\10\x90 8086
+reg32,reg_eax \321\10\x90 386
+reg8,mem \301\1\x86\110 8086,SM
+reg8,reg8 \301\1\x86\110 8086
+reg16,mem \320\301\1\x87\110 8086,SM
+reg16,reg16 \320\301\1\x87\110 8086
+reg32,mem \321\301\1\x87\110 386,SM
+reg32,reg32 \321\301\1\x87\110 386
+mem,reg8 \300\1\x86\101 8086,SM
+reg8,reg8 \300\1\x86\101 8086
+mem,reg16 \320\300\1\x87\101 8086,SM
+reg16,reg16 \320\300\1\x87\101 8086
+mem,reg32 \321\300\1\x87\101 386,SM
+reg32,reg32 \321\300\1\x87\101 386
+
+[XLAT]
+(Ch_WEAX, Ch_REBX, Ch_None)
+void \1\xD7 8086
+
+[XLATB]
+(Ch_WEAX, Ch_REBX, Ch_None)
+void \1\xD7 8086
+
+[XOR,xorX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+mem,reg8 \300\1\x30\101 8086,SM
+reg8,reg8 \300\1\x30\101 8086
+mem,reg16 \320\300\1\x31\101 8086,SM
+reg16,reg16 \320\300\1\x31\101 8086
+mem,reg32 \321\300\1\x31\101 386,SM
+reg32,reg32 \321\300\1\x31\101 386
+reg8,mem \301\1\x32\110 8086,SM
+reg8,reg8 \301\1\x32\110 8086
+reg16,mem \320\301\1\x33\110 8086,SM
+reg16,reg16 \320\301\1\x33\110 8086
+reg32,mem \321\301\1\x33\110 386,SM
+reg32,reg32 \321\301\1\x33\110 386
+rm16,imm8 \320\300\1\x83\206\15 8086
+rm32,imm8 \321\300\1\x83\206\15 386
+reg_al,imm \1\x34\21 8086,SM
+reg_ax,imm \320\1\x35\31 8086,SM
+reg_eax,imm \321\1\x35\41 386,SM
+rm8,imm \300\1\x80\206\21 8086,SM
+rm16,imm \320\300\1\x81\206\31 8086,SM
+rm32,imm \321\300\1\x81\206\41 386,SM
+mem,imm8 \300\1\x80\206\21 8086,SM
+mem,imm16 \320\300\1\x81\206\31 8086,SM
+mem,imm32 \321\300\1\x81\206\41 386,SM
+
+[XSTORE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\xA7\xC0 P6,CYRIX
+
+
+[CMOVcc,cmovCCX]
+(Ch_ROp1, Ch_WOp2, Ch_RFLAGS)
+reg16,mem \320\301\1\x0F\330\x40\110 P6,SM
+reg16,reg16 \320\301\1\x0F\330\x40\110 P6
+reg32,mem \321\301\1\x0F\330\x40\110 P6,SM
+reg32,reg32 \321\301\1\x0F\330\x40\110 P6
+
+[Jcc]
+(Ch_None, Ch_None, Ch_None)
+imm|near \323\1\x0F\330\x80\64 386,PASS2
+imm16|near \320\1\x0F\330\x80\64 386,PASS2
+imm32|near \321\1\x0F\330\x80\64 386,PASS2
+imm \330\x70\50 8086
+imm|short \330\x70\50 8086,ND
+
+[SETcc,setCCX]
+(Ch_RFLAGS, Ch_WOp1, Ch_None)
+mem \300\1\x0F\330\x90\200 386,SB
+reg8 \300\1\x0F\330\x90\200 386
+
+;
+; Katmai Streaming SIMD instructions (SSE -- a.k.a. KNI, XMM, MMX2)
+;
+
+[ADDPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\331\2\x0F\x58\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x58\110 KATMAI,SSE
+
+[ADDSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\333\2\x0F\x58\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x58\110 KATMAI,SSE
+
+[ANDNPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\2\x0F\x55\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x55\110 KATMAI,SSE
+
+[ANDPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\2\x0F\x54\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x54\110 KATMAI,SSE
+
+[CMPEQPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\xC2\110\1\x00 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\xC2\110\1\x00 KATMAI,SSE
+
+[CMPEQSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\xC2\110\1\x00 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\xC2\110\1\x00 KATMAI,SSE
+
+[CMPLEPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\xC2\110\1\x02 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\xC2\110\1\x02 KATMAI,SSE
+
+[CMPLESS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\xC2\110\1\x02 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\xC2\110\1\x02 KATMAI,SSE
+
+[CMPLTPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\xC2\110\1\x01 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\xC2\110\1\x01 KATMAI,SSE
+
+[CMPLTSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\xC2\110\1\x01 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\xC2\110\1\x01 KATMAI,SSE
+
+[CMPNEQPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\xC2\110\1\x04 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\xC2\110\1\x04 KATMAI,SSE
+
+[CMPNEQSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\xC2\110\1\x04 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\xC2\110\1\x04 KATMAI,SSE
+
+[CMPNLEPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\xC2\110\1\x06 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\xC2\110\1\x06 KATMAI,SSE
+
+[CMPNLESS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\xC2\110\1\x06 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\xC2\110\1\x06 KATMAI,SSE
+
+[CMPNLTPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\xC2\110\1\x05 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\xC2\110\1\x05 KATMAI,SSE
+
+[CMPNLTSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\xC2\110\1\x05 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\xC2\110\1\x05 KATMAI,SSE
+
+[CMPORDPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\xC2\110\1\x07 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\xC2\110\1\x07 KATMAI,SSE
+
+[CMPORDSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\xC2\110\1\x07 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\xC2\110\1\x07 KATMAI,SSE
+
+[CMPUNORDPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\xC2\110\1\x03 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\xC2\110\1\x03 KATMAI,SSE
+
+[CMPUNORDSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\xC2\110\1\x03 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\xC2\110\1\x03 KATMAI,SSE
+
+;
+; CMPPS/CMPSS must come after the specific ops; that way the disassembler will find the
+; specific ops first and only disassemble illegal ones as cmpps.
+;
+
+[CMPPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem,imm \301\331\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
+xmmreg,xmmreg,imm \331\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
+
+[CMPSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem,imm \301\333\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
+xmmreg,xmmreg,imm \333\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
+
+[COMISS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\2\x0F\x2F\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x2F\110 KATMAI,SSE
+
+[CVTPI2PS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\331\2\x0F\x2A\110 KATMAI,SSE,MMX
+xmmreg,mmxreg \331\2\x0F\x2A\110 KATMAI,SSE,MMX
+
+[CVTPS2PI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mmxreg,mem \301\331\2\x0F\x2D\110 KATMAI,SSE,MMX
+mmxreg,xmmreg \331\2\x0F\x2D\110 KATMAI,SSE,MMX
+
+[CVTSI2SS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\333\2\x0F\x2A\110 KATMAI,SSE,SD,AR1
+xmmreg,reg32 \333\2\x0F\x2A\110 KATMAI,SSE
+
+[CVTSS2SI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32,mem \301\333\2\x0F\x2D\110 KATMAI,SSE
+reg32,xmmreg \333\2\x0F\x2D\110 KATMAI,SSE
+
+[CVTTPS2PI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mmxreg,mem \301\331\2\x0F\x2C\110 KATMAI,SSE,MMX
+mmxreg,xmmreg \331\2\x0F\x2C\110 KATMAI,SSE,MMX
+
+[CVTTSS2SI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32,mem \301\333\2\x0F\x2C\110 KATMAI,SSE
+reg32,xmmreg \333\2\x0F\x2C\110 KATMAI,SSE
+
+[DIVPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\331\2\x0F\x5E\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x5E\110 KATMAI,SSE
+
+[DIVSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\333\2\x0F\x5E\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x5E\110 KATMAI,SSE
+
+[LDMXCSR]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\xAE\202 KATMAI,SSE,SD
+
+[MAXPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\x5F\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x5F\110 KATMAI,SSE
+
+[MAXSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\x5F\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x5F\110 KATMAI,SSE
+
+[MINPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\x5D\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x5D\110 KATMAI,SSE
+
+[MINSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\x5D\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x5D\110 KATMAI,SSE
+
+[MOVAPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\2\x0F\x28\110 KATMAI,SSE
+mem,xmmreg \300\2\x0F\x29\101 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x28\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x29\101 KATMAI,SSE
+
+[MOVHPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\2\x0F\x16\110 KATMAI,SSE
+mem,xmmreg \300\2\x0F\x17\101 KATMAI,SSE
+
+[MOVLHPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \2\x0F\x16\110 KATMAI,SSE
+
+[MOVLPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\2\x0F\x12\110 KATMAI,SSE
+mem,xmmreg \300\2\x0F\x13\101 KATMAI,SSE
+
+[MOVHLPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \2\x0F\x12\110 KATMAI,SSE
+
+[MOVMSKPS]
+(Ch_All, Ch_None, Ch_None)
+reg32,xmmreg \2\x0F\x50\110 KATMAI,SSE
+
+[MOVNTPS]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \2\x0F\x2B\101 KATMAI,SSE
+
+[MOVSS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\333\2\x0F\x10\110 KATMAI,SSE
+mem,xmmreg \300\333\2\x0F\x11\101 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x10\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x11\101 KATMAI,SSE
+
+[MOVUPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\x10\110 KATMAI,SSE
+mem,xmmreg \300\331\2\x0F\x11\101 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x10\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x11\101 KATMAI,SSE
+
+[MULPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\2\x0F\x59\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x59\110 KATMAI,SSE
+
+[MULSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\333\2\x0F\x59\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x59\110 KATMAI,SSE
+
+[ORPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\2\x0F\x56\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x56\110 KATMAI,SSE
+
+[RCPPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\x53\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x53\110 KATMAI,SSE
+
+[RCPSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\x53\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x53\110 KATMAI,SSE
+
+[RSQRTPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\2\x0F\x52\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x52\110 KATMAI,SSE
+
+[RSQRTSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\333\2\x0F\x52\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x52\110 KATMAI,SSE
+
+[SHUFPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem,imm \301\2\x0F\xC6\110\22 KATMAI,SSE,SB,AR2
+xmmreg,xmmreg,imm \2\x0F\xC6\110\22 KATMAI,SSE,SB,AR2
+
+[SQRTPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\331\2\x0F\x51\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x51\110 KATMAI,SSE
+
+[SQRTSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\333\2\x0F\x51\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x51\110 KATMAI,SSE
+
+[STMXCSR]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\xAE\203 KATMAI,SSE,SD
+
+[SUBPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\331\2\x0F\x5C\110 KATMAI,SSE
+xmmreg,xmmreg \331\2\x0F\x5C\110 KATMAI,SSE
+
+[SUBSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\333\2\x0F\x5C\110 KATMAI,SSE
+xmmreg,xmmreg \333\2\x0F\x5C\110 KATMAI,SSE
+
+[UCOMISS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\2\x0F\x2E\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x2E\110 KATMAI,SSE
+
+[UNPCKHPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\2\x0F\x15\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x15\110 KATMAI,SSE
+
+[UNPCKLPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\2\x0F\x14\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x14\110 KATMAI,SSE
+
+[XORPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\2\x0F\x57\110 KATMAI,SSE
+xmmreg,xmmreg \2\x0F\x57\110 KATMAI,SSE
+
+;
+; Introduced in Dechutes but necessary for SSE support
+;
+
+[FXRSTOR]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\xAE\201 P6,SSE,FPU
+
+[FXSAVE]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\xAE\200 P6,SSE,FPU
+
+;
+; These instructions aren't SSE-specific; they are generic memory operations
+; and work even if CR4.OSFXFR == 0
+;
+
+[PREFETCHNTA]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\x18\200 KATMAI
+
+[PREFETCHT0]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\x18\201 KATMAI
+
+[PREFETCHT1]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\x18\202 KATMAI
+
+[PREFETCHT2]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\x18\203 KATMAI
+
+[SFENCE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\xAE\xF8 KATMAI
+
+;
+; New MMX instructions introduced in Katmai
+;
+
+[MASKMOVQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xF7\110 KATMAI,MMX
+
+[MOVNTQ]
+(Ch_All, Ch_None, Ch_None)
+mem,mmxreg \2\x0F\xE7\101 KATMAI,MMX,SM
+
+[PAVGB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xE0\110 KATMAI,MMX
+mmxreg,mem \301\2\x0F\xE0\110 KATMAI,MMX,SM
+xmmreg,xmmreg \3\x66\x0F\xE0\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xE0\110 WILLAMETTE,SSE2,SM
+
+[PAVGW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xE3\110 KATMAI,MMX
+mmxreg,mem \301\2\x0F\xE3\110 KATMAI,MMX,SM
+xmmreg,xmmreg \3\x66\x0F\xE3\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xE3\110 WILLAMETTE,SSE2,SM
+
+[PEXTRW]
+(Ch_All, Ch_None, Ch_None)
+reg32,mmxreg,imm \2\x0F\xC5\110\22 KATMAI,MMX,SB,AR2
+reg32,xmmreg,imm \3\x66\x0F\xC5\110\26 WILLAMETTE,SSE2,SB,AR2
+
+[PINSRW]
+(Ch_All, Ch_None, Ch_None)
+; PINSRW is documented as using a reg32, but it's really using only 16 bit
+; -- accept either, but be truthful in disassembly
+mmxreg,reg16,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
+mmxreg,reg32,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2,ND
+mmxreg,mem,imm \301\2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
+mmxreg,mem16,imm \301\2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2,ND
+xmmreg,reg16,imm \3\x66\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2
+xmmreg,reg32,imm \3\x66\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2,ND
+xmmreg,mem,imm \301\3\x66\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2
+xmmreg,mem16,imm \301\3\x66\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2,ND
+
+[PMAXSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xEE\110 KATMAI,MMX
+mmxreg,mem \301\2\x0F\xEE\110 KATMAI,MMX,SM
+xmmreg,xmmreg \3\x66\x0F\xEE\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xEE\110 WILLAMETTE,SSE2,SM
+
+[PMAXUB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xDE\110 KATMAI,MMX
+mmxreg,mem \301\2\x0F\xDE\110 KATMAI,MMX,SM
+xmmreg,xmmreg \3\x66\x0F\xDE\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xDE\110 WILLAMETTE,SSE2,SM
+
+[PMINSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xEA\110 KATMAI,MMX
+mmxreg,mem \301\2\x0F\xEA\110 KATMAI,MMX,SM
+xmmreg,xmmreg \3\x66\x0F\xEA\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xEA\110 WILLAMETTE,SSE2,SM
+
+[PMINUB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xDA\110 KATMAI,MMX
+mmxreg,mem \301\2\x0F\xDA\110 KATMAI,MMX,SM
+xmmreg,xmmreg \3\x66\x0F\xDA\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xDA\110 WILLAMETTE,SSE2,SM
+
+[PMOVMSKB]
+(Ch_All, Ch_None, Ch_None)
+reg32,mmxreg \2\x0F\xD7\110 KATMAI,MMX
+reg32,xmmreg \3\x66\x0F\xD7\110 WILLAMETTE,SSE2
+
+[PMULHUW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xE4\110 KATMAI,MMX
+mmxreg,mem \301\2\x0F\xE4\110 KATMAI,MMX,SM
+xmmreg,xmmreg \3\x66\x0F\xE4\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xE4\110 WILLAMETTE,SSE2,SM
+
+[PSADBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xF6\110 KATMAI,MMX
+mmxreg,mem \301\2\x0F\xF6\110 KATMAI,MMX,SM
+xmmreg,xmmreg \3\x66\x0F\xF6\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xF6\110 WILLAMETTE,SSE2,SM
+
+[PSHUFW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg,imm \2\x0F\x70\110\22 KATMAI,MMX,SB,AR2
+mmxreg,mem,imm \301\2\x0F\x70\110\22 KATMAI,MMX,SM2,SB,AR2
+
+;
+; New Athlon Instructions
+;
+
+[PFNACC]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x8A PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x8A PENT,3DNOW
+
+[PFPNACC]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x8E PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x8E PENT,3DNOW
+
+[PI2FW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x0C PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x0C PENT,3DNOW
+
+[PF2IW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\x1C PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\x1C PENT,3DNOW
+
+[PSWAPD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \301\2\x0F\x0F\110\01\xBB PENT,3DNOW,SM
+mmxreg,mmxreg \2\x0F\x0F\110\01\xBB PENT,3DNOW,SM
+
+[FFREEP]
+(Ch_All, Ch_None, Ch_None)
+fpureg \1\xDF\10\xC0 PENT,3DNOW,FPU
+
+; Willamette SSE2 Cacheability Instructions
+[MASKMOVDQU]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\xF7\110 WILLAMETTE,SSE2
+
+; CLFLUSH needs its own feature flag implemented one day
+[CLFLUSH]
+(Ch_All, Ch_None, Ch_None)
+mem \300\2\x0F\xAE\207 WILLAMETTE,SSE2
+
+[MOVNTDQ]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \300\3\x66\x0F\xE7\101 WILLAMETTE,SSE2,SM
+
+[MOVNTI]
+(Ch_All, Ch_None, Ch_None)
+mem,reg32 \300\2\x0F\xC3\101 WILLAMETTE,SSE2,SM
+
+[MOVNTPD]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \300\3\x66\x0F\x2B\101 WILLAMETTE,SSE2,SM
+
+[PAUSE]
+(Ch_All, Ch_None, Ch_None)
+void \333\1\x90 WILLAMETTE,SSE2
+
+[LFENCE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\xAE\xE8 WILLAMETTE,SSE2
+
+[MFENCE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\xAE\xF0 WILLAMETTE,SSE2
+
+;
+; Willamette MMX instructions (SSE2 SIMD Integer Instructions)
+;
+[MOVDQA]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x6F\110 WILLAMETTE,SSE2
+mem,xmmreg \300\3\x66\x0F\x7F\101 WILLAMETTE,SSE2,SM
+xmmreg,mem \301\3\x66\x0F\x6F\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\x7F\110 WILLAMETTE,SSE2
+
+[MOVDQU]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \333\2\x0F\x6F\110 WILLAMETTE,SSE2
+mem,xmmreg \333\300\2\x0F\x7F\101 WILLAMETTE,SSE2,SM
+xmmreg,mem \301\333\2\x0F\x6F\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \333\2\x0F\x7F\110 WILLAMETTE,SSE2
+
+[MOVDQ2Q]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,xmmreg \3\xF2\x0F\xD6\110 WILLAMETTE,SSE2
+
+[MOVQ2DQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mmxreg \333\2\x0F\xD6\110 WILLAMETTE,SSE2
+
+[PADDQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xD4\110 WILLAMETTE,SSE2
+mmxreg,mem \301\2\x0F\xD4\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xD4\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xD4\110 WILLAMETTE,SSE2,SM
+
+[PMULUDQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xF4\110 WILLAMETTE,SSE2
+mmxreg,mem \301\2\x0F\xF4\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xF4\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xF4\110 WILLAMETTE,SSE2,SM
+
+[PSHUFD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg,imm \3\x66\x0F\x70\110\22 WILLAMETTE,SSE2,SB,AR2
+xmmreg,mem,imm \301\3\x66\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[PSHUFHW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg,imm \333\2\x0F\x70\110\22 WILLAMETTE,SSE2,SB,AR2
+xmmreg,mem,imm \301\333\2\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[PSHUFLW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg,imm \3\xF2\x0F\x70\110\22 WILLAMETTE,SSE2,SB,AR2
+xmmreg,mem,imm \301\3\xF2\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[PSRLDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,imm \3\x66\x0F\x73\203\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSUBQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xFB\110 WILLAMETTE,SSE2
+mmxreg,mem \301\2\x0F\xFB\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\xFB\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xFB\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKHQDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x6D\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x6D\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKLQDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x6C\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x6C\110 WILLAMETTE,SSE2,SM
+
+;
+; Willamette Streaming SIMD instructions (SSE2)
+;
+[ADDPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \331\3\x66\x0F\x58\110 WILLAMETTE,SSE2
+xmmreg,mem \301\331\3\x66\x0F\x58\110 WILLAMETTE,SSE2,SM
+
+[ADDSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \331\3\xF2\x0F\x58\110 WILLAMETTE,SSE2
+xmmreg,mem \301\331\3\xF2\x0F\x58\110 WILLAMETTE,SSE2
+
+[ANDNPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \331\3\x66\x0F\x55\110 WILLAMETTE,SSE2
+xmmreg,mem \301\331\3\x66\x0F\x55\110 WILLAMETTE,SSE2,SM
+
+[ANDPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \331\3\x66\x0F\x54\110 WILLAMETTE,SSE2
+xmmreg,mem \301\331\3\x66\x0F\x54\110 WILLAMETTE,SSE2,SM
+
+[CMPEQPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x00 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x00 WILLAMETTE,SSE2
+
+[CMPEQSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x00 WILLAMETTE,SSE2
+xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x00 WILLAMETTE,SSE2
+
+[CMPLEPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x02 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x02 WILLAMETTE,SSE2
+
+[CMPLESD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x02 WILLAMETTE,SSE2
+xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x02 WILLAMETTE,SSE2
+
+[CMPLTPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x01 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x01 WILLAMETTE,SSE2
+
+[CMPLTSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x01 WILLAMETTE,SSE2
+xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x01 WILLAMETTE,SSE2
+
+[CMPNEQPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x04 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x04 WILLAMETTE,SSE2
+xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x04 WILLAMETTE,SSE2
+xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x04 WILLAMETTE,SSE2
+
+[CMPNLEPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x06 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x06 WILLAMETTE,SSE2
+
+[CMPNLESD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x06 WILLAMETTE,SSE2
+xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x06 WILLAMETTE,SSE2
+
+[CMPNLTPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x05 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x05 WILLAMETTE,SSE2
+
+[CMPNLTSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x05 WILLAMETTE,SSE2
+xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x05 WILLAMETTE,SSE2
+
+[CMPORDPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x07 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x07 WILLAMETTE,SSE2
+
+[CMPORDSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x07 WILLAMETTE,SSE2
+xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x07 WILLAMETTE,SSE2
+
+[CMPUNORDPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x03 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x03 WILLAMETTE,SSE2
+
+[CMPUNORDSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x03 WILLAMETTE,SSE2
+xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x03 WILLAMETTE,SSE2
+
+; CMPPD/CMPSD must come after the specific ops; that way the disassembler will find the
+; specific ops first and only disassemble illegal ones as cmppd/cmpsd.
+[CMPPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg,imm \331\3\x66\x0F\xC2\110\26 WILLAMETTE,SSE2,SB,AR2
+xmmreg,mem,imm \301\331\3\x66\x0F\xC2\110\26 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[COMISD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \331\3\x66\x0F\x2F\110 WILLAMETTE,SSE2
+xmmreg,mem \301\331\3\x66\x0F\x2F\110 WILLAMETTE,SSE2
+
+[CVTDQ2PD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \333\2\x0F\xE6\110 WILLAMETTE,SSE2
+xmmreg,mem \301\333\2\x0F\xE6\110 WILLAMETTE,SSE2
+
+[CVTDQ2PS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \2\x0F\x5B\110 WILLAMETTE,SSE2
+xmmreg,mem \301\2\x0F\x5B\110 WILLAMETTE,SSE2,SM
+
+[CVTPD2DQ]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\xF2\x0F\xE6\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\xE6\110 WILLAMETTE,SSE2,SM
+
+[CVTPD2PI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mmxreg,xmmreg \3\x66\x0F\x2D\110 WILLAMETTE,SSE2
+mmxreg,mem \301\3\x66\x0F\x2D\110 WILLAMETTE,SSE2
+
+[CVTPD2PS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x5A\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x5A\110 WILLAMETTE,SSE2,SM
+
+[CVTPI2PD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,mmxreg \3\x66\x0F\x2A\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x2A\110 WILLAMETTE,SSE2
+
+[CVTPS2DQ]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x5B\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x5B\110 WILLAMETTE,SSE2,SM
+
+[CVTPS2PD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \2\x0F\x5A\110 WILLAMETTE,SSE2
+xmmreg,mem \301\2\x0F\x5A\110 WILLAMETTE,SSE2
+
+[CVTSD2SI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32,xmmreg \3\xF2\x0F\x2D\110 WILLAMETTE,SSE2
+reg32,mem \301\3\xF2\x0F\x2D\110 WILLAMETTE,SSE2
+
+[CVTSD2SS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\xF2\x0F\x5A\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x5A\110 WILLAMETTE,SSE2
+
+[CVTSI2SD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,reg32 \3\xF2\x0F\x2A\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x2A\110 WILLAMETTE,SSE2
+
+[CVTSS2SD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \333\2\x0F\x5A\110 WILLAMETTE,SSE2
+xmmreg,mem \301\333\2\x0F\x5A\110 WILLAMETTE,SSE2
+
+[CVTTPD2PI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mmxreg,xmmreg \3\x66\x0F\x2C\110 WILLAMETTE,SSE2
+mmxreg,mem \301\3\x66\x0F\x2C\110 WILLAMETTE,SSE2
+
+[CVTTPD2DQ]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\xE6\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\xE6\110 WILLAMETTE,SSE2,SM
+
+[CVTTPS2DQ]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \333\2\x0F\x5B\110 WILLAMETTE,SSE2
+xmmreg,mem \301\333\2\x0F\x5B\110 WILLAMETTE,SSE2,SM
+
+[CVTTSD2SI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32,xmmreg \3\xF2\x0F\x2C\110 WILLAMETTE,SSE2
+reg32,mem \301\3\xF2\x0F\x2C\110 WILLAMETTE,SSE2
+
+[DIVPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x5E\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x5E\110 WILLAMETTE,SSE2,SM
+
+[DIVSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\xF2\x0F\x5E\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x5E\110 WILLAMETTE,SSE2
+
+[MAXPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x5F\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x5F\110 WILLAMETTE,SSE2,SM
+
+[MAXSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\xF2\x0F\x5F\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x5F\110 WILLAMETTE,SSE2
+
+[MINPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x5D\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x5D\110 WILLAMETTE,SSE2,SM
+
+[MINSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\xF2\x0F\x5D\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x5D\110 WILLAMETTE,SSE2
+
+[MOVAPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x28\110 WILLAMETTE,SSE2
+xmmreg,xmmreg \3\x66\x0F\x29\110 WILLAMETTE,SSE2
+mem,xmmreg \300\3\x66\x0F\x29\101 WILLAMETTE,SSE2,SM
+xmmreg,mem \301\3\x66\x0F\x28\110 WILLAMETTE,SSE2,SM
+
+[MOVHPD]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \300\3\x66\x0F\x17\101 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x16\110 WILLAMETTE,SSE2
+
+[MOVLPD]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \300\3\x66\x0F\x13\101 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x12\110 WILLAMETTE,SSE2
+
+[MOVMSKPD]
+(Ch_All, Ch_None, Ch_None)
+reg32,xmmreg \3\x66\x0F\x50\110 WILLAMETTE,SSE2
+
+[MOVUPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x10\110 WILLAMETTE,SSE2
+xmmreg,xmmreg \3\x66\x0F\x11\110 WILLAMETTE,SSE2
+mem,xmmreg \300\3\x66\x0F\x11\101 WILLAMETTE,SSE2,SM
+xmmreg,mem \301\3\x66\x0F\x10\110 WILLAMETTE,SSE2,SM
+
+[MULPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x59\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x59\110 WILLAMETTE,SSE2,SM
+
+[MULSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\xF2\x0F\x59\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x59\110 WILLAMETTE,SSE2
+
+[ORPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,mem \301\3\x66\x0F\x56\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmreg \3\x66\x0F\x56\110 WILLAMETTE,SSE2
+
+[SHUFPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg,imm \3\x66\x0F\xC6\110\26 WILLAMETTE,SSE2,SB,AR2
+xmmreg,mem,imm \301\3\x66\x0F\xC6\110\26 WILLAMETTE,SSE2,SM,SB,AR2
+
+[SQRTPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x51\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x51\110 WILLAMETTE,SSE2,SM
+
+[SQRTSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\xF2\x0F\x51\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x51\110 WILLAMETTE,SSE2
+
+[SUBPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x5C\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x5C\110 WILLAMETTE,SSE2,SM
+
+[SUBSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\xF2\x0F\x5C\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\xF2\x0F\x5C\110 WILLAMETTE,SSE2
+
+[UCOMISD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x2E\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x2E\110 WILLAMETTE,SSE2
+
+[UNPCKHPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x15\110 WILLAMETTE,SSE2
+mem,xmmreg \300\3\x66\x0F\x15\110 WILLAMETTE,SSE2,SM
+
+[UNPCKLPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x14\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x14\110 WILLAMETTE,SSE2,SM
+
+[XORPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmreg \3\x66\x0F\x57\110 WILLAMETTE,SSE2
+xmmreg,mem \301\3\x66\x0F\x57\110 WILLAMETTE,SSE2,SM
+
+;
+; Prescott New Instructions (SSE3)
+;
+[ADDSUBPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\x66\x0F\xD0\110 PRESCOTT,SSE3,SM
+xmmreg,xmmreg \3\x66\x0F\xD0\110 PRESCOTT,SSE3
+
+[ADDSUBPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\xF2\x0F\xD0\110 PRESCOTT,SSE3,SM
+xmmreg,xmmreg \3\xF2\x0F\xD0\110 PRESCOTT,SSE3
+
+[HADDPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\x66\x0F\x7C\110 PRESCOTT,SSE3,SM
+xmmreg,xmmreg \3\x66\x0F\x7C\110 PRESCOTT,SSE3
+
+[HADDPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\xF2\x0F\x7C\110 PRESCOTT,SSE3,SM
+xmmreg,xmmreg \3\xF2\x0F\x7C\110 PRESCOTT,SSE3
+
+[HSUBPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\x66\x0F\x7D\110 PRESCOTT,SSE3,SM
+xmmreg,xmmreg \3\x66\x0F\x7D\110 PRESCOTT,SSE3
+
+[HSUBPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\xF2\x0F\x7D\110 PRESCOTT,SSE3,SM
+xmmreg,xmmreg \3\xF2\x0F\x7D\110 PRESCOTT,SSE3
+
+[LDDQU]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \3\xF2\x0F\xF0\110 PRESCOTT,SSE3
+
+[MOVDDUP]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\xF2\x0F\x12\110 PRESCOTT,SSE3
+xmmreg,xmmreg \3\xF2\x0F\x12\110 PRESCOTT,SSE3
+
+[MOVSHDUP]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\xF3\x0F\x16\110 PRESCOTT,SSE3
+xmmreg,xmmreg \3\xF3\x0F\x16\110 PRESCOTT,SSE3
+
+[MOVSLDUP]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \301\3\xF3\x0F\x12\110 PRESCOTT,SSE3
+xmmreg,xmmreg \3\xF3\x0F\x12\110 PRESCOTT,SSE3
+
+;
+; GAS specific x86-64 instructions
+;
+[MOVABS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32,imm \321\10\xB8\41 X86_64
+
+[MOVSXD,movslq]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg64,mem \321\301\1\x63\110 X86_64
+reg64,reg32 \321\301\1\x63\110 X86_64
+
+[CQO,cqto]
+(Ch_MRAX, Ch_WRDX, Ch_None)
+void \321\1\x99 X86_64
diff --git a/compiler/x86/x86reg.dat b/compiler/x86/x86reg.dat
new file mode 100644
index 0000000000..38d8fcff95
--- /dev/null
+++ b/compiler/x86/x86reg.dat
@@ -0,0 +1,140 @@
+;
+; x86 registers
+;
+; layout
+; <name>,<value>,<stdname>,<attname>,<masmname>,<nasmname>,<stabidx>,<dwarf32idx>,<dwarf64idx>,<ot value>,<opcode value>,[AMD64 specific]
+;
+; For stab/dwarf numbers see gdb/i386-tdep.c and gdb/amd64-tdep.c
+;
+NR_NO,$00000000,INVALID,INVALID,INVALID,INVALID,-1,-1,-1,OT_NONE,0
+NR_AL,$01010000,al,%al,al,al,0,0,0,OT_REG_AL,0
+NR_AH,$01020000,ah,%ah,ah,ah,0,0,0,OT_REG8,4
+NR_AX,$01030000,ax,%ax,ax,ax,0,0,0,OT_REG_AX,0
+NR_EAX,$01040000,eax,%eax,eax,eax,0,0,0,OT_REG_EAX,0
+NR_RAX,$01050000,rax,%rax,rax,rax,0,0,0,OT_REG_RAX,0,64
+NR_CL,$01010001,cl,%cl,cl,cl,1,1,2,OT_REG_CL,1
+NR_CH,$01020001,ch,%ch,ch,ch,1,1,2,OT_REG8,5
+NR_CX,$01030001,cx,%cx,cx,cx,1,1,2,OT_REG_CX,1
+NR_ECX,$01040001,ecx,%ecx,ecx,ecx,1,1,2,OT_REG_ECX,1
+NR_RCX,$01050001,rcx,%rcx,rcx,rcx,1,1,2,OT_REG_RCX,1,64
+NR_DL,$01010002,dl,%dl,dl,dl,2,2,1,OT_REG8,2
+NR_DH,$01020002,dh,%dh,dh,dh,2,2,1,OT_REG8,6
+NR_DX,$01030002,dx,%dx,dx,dx,2,2,1,OT_REG_DX,2
+NR_EDX,$01040002,edx,%edx,edx,edx,2,2,1,OT_REG32,2
+NR_RDX,$01050002,rdx,%rdx,rdx,rdx,2,2,1,OT_REG64,2,64
+NR_BL,$01010003,bl,%bl,bl,bl,3,3,3,OT_REG8,3
+NR_BH,$01020003,bh,%bh,bh,bh,3,3,3,OT_REG8,7
+NR_BX,$01030003,bx,%bx,bx,bx,3,3,3,OT_REG16,3
+NR_EBX,$01040003,ebx,%ebx,ebx,ebx,3,3,3,OT_REG32,3
+NR_RBX,$01050003,rbx,%rbx,rbx,rbx,3,3,3,OT_REG64,3,64
+NR_SIL,$01010004,sil,%sil,sil,sil,6,6,4,OT_REG8,6,64
+NR_SI,$01030004,si,%si,si,si,6,6,4,OT_REG16,6
+NR_ESI,$01040004,esi,%esi,esi,esi,6,6,4,OT_REG32,6
+NR_RSI,$01050004,rsi,%rsi,rsi,rsi,6,6,4,OT_REG64,6,64
+NR_DIL,$01010005,dil,%dil,dil,dil,7,7,5,OT_REG8,7,64
+NR_DI,$01030005,di,%di,di,di,7,7,5,OT_REG16,7
+NR_EDI,$01040005,edi,%edi,edi,edi,7,7,5,OT_REG32,7
+NR_RDI,$01050005,rdi,%rdi,rdi,rdi,7,7,5,OT_REG64,7,64
+NR_BPL,$01010006,bpl,%bpl,bpl,bpl,5,5,6,OT_REG8,5,64
+NR_BP,$01030006,bp,%bp,bp,bp,5,5,6,OT_REG16,5
+NR_EBP,$01040006,ebp,%ebp,ebp,ebp,5,5,6,OT_REG32,5
+NR_RBP,$01050006,rbp,%rbp,rbp,rbp,5,5,6,OT_REG64,5,64
+NR_SPL,$01010007,spl,%spl,spl,spl,4,4,7,OT_REG8,4,64
+NR_SP,$01030007,sp,%sp,sp,sp,4,4,7,OT_REG16,4
+NR_ESP,$01040007,esp,%esp,esp,esp,4,4,7,OT_REG32,4
+NR_RSP,$01050007,rsp,%rsp,rsp,rsp,4,4,7,OT_REG64,4,64
+NR_R8,$01050008,r8,%r8,r8,r8,-1,-1,8,OT_REG64,0,64
+NR_R8L,$01010008,r8b,%r8b,r8b,r8b,-1,-1,8,OT_REG8,0,64
+NR_R8W,$01030008,r8w,%r8w,r8w,r8w,-1,-1,8,OT_REG16,0,64
+NR_R8D,$01040008,r8d,%r8d,r8d,r8d,-1,-1,8,OT_REG32,0,64
+NR_R9,$01050009,r9,%r9,r9,r9,-1,-1,9,OT_REG64,0,64
+NR_R9L,$01010009,r9b,%r9b,r9b,r9b,-1,-1,9,OT_REG8,0,64
+NR_R9W,$01030009,r9w,%r9w,r9w,r9w,-1,-1,9,OT_REG16,0,64
+NR_R9D,$01040009,r9d,%r9d,r9d,r9d,-1,-1,9,OT_REG32,0,64
+NR_R10,$0105000a,r10,%r10,r10,r10,-1,-1,10,OT_REG64,0,64
+NR_R10L,$0101000a,r10b,%r10b,r10b,r10b,-1,-1,10,OT_REG8,0,64
+NR_R10W,$0103000a,r10w,%r10w,r10w,r10w,-1,-1,10,OT_REG16,0,64
+NR_R10D,$0104000a,r10d,%r10d,r10d,r10d,-1,-1,10,OT_REG32,0,64
+NR_R11,$0105000b,r11,%r11,r11,r11,-1,-1,11,OT_REG64,0,64
+NR_R11L,$0101000b,r11b,%r11b,r11b,r11b,-1,-1,11,OT_REG8,0,64
+NR_R11W,$0103000b,r11w,%r11w,r11w,r11w,-1,-1,11,OT_REG16,0,64
+NR_R11D,$0104000b,r11d,%r11d,r11d,r11d,-1,-1,11,OT_REG32,0,64
+NR_R12,$0105000c,r12,%r12,r12,r12,-1,-1,12,OT_REG64,0,64
+NR_R12L,$0101000c,r12b,%r12b,r12b,r12b,-1,-1,12,OT_REG8,0,64
+NR_R12W,$0103000c,r12w,%r12w,r12w,r12w,-1,-1,12,OT_REG16,0,64
+NR_R12D,$0104000c,r12d,%r12d,r12d,r12d,-1,-1,12,OT_REG32,0,64
+NR_R13,$0105000d,r13,%r13,r13,r13,-1,-1,13,OT_REG64,0,64
+NR_R13L,$0101000d,r13b,%r13b,r13b,r13b,-1,-1,13,OT_REG8,0,64
+NR_R13W,$0103000d,r13w,%r13w,r13w,r13w,-1,-1,13,OT_REG16,0,64
+NR_R13D,$0104000d,r13d,%r13d,r13d,r13d,-1,-1,13,OT_REG32,0,64
+NR_R14,$0105000e,r14,%r14,r14,r14,-1,-1,14,OT_REG64,0,64
+NR_R14L,$0101000e,r14b,%r14b,r14b,r14b,-1,-1,14,OT_REG8,0,64
+NR_R14W,$0103000e,r14w,%r14w,r14w,r14w,-1,-1,14,OT_REG16,0,64
+NR_R14D,$0104000e,r14d,%r14d,r14d,r14d,-1,-1,14,OT_REG32,0,64
+NR_R15,$0105000f,r15,%r15,r15,r15,-1,-1,15,OT_REG64,0,64
+NR_R15L,$0101000f,r15b,%r15b,r15b,r15b,-1,-1,15,OT_REG8,0,64
+NR_R15W,$0103000f,r15w,%r15w,r15w,r15w,-1,-1,15,OT_REG16,0,64
+NR_R15D,$0104000f,r15d,%r15d,r15d,r15d,-1,-1,15,OT_REG32,0,64
+
+; EIP is needed for DWARF call frame info return address (RA)
+NR_RIP,$05000000,rip,%rip,rip,rip,-1,8,16,OT_NONE,0,64
+NR_EIP,$05000000,eip,%eip,eip,eip,-1,8,16,OT_NONE,0
+NR_CS,$05000001,cs,%cs,cs,cs,-1,-1,-1,OT_REG_CS,1
+NR_DS,$05000002,ds,%ds,ds,ds,-1,-1,-1,OT_REG_DESS,3
+NR_ES,$05000003,es,%es,es,es,-1,-1,-1,OT_REG_DESS,0
+NR_SS,$05000004,ss,%ss,ss,ss,-1,-1,-1,OT_REG_DESS,2
+NR_FS,$05000005,fs,%fs,fs,fs,-1,-1,-1,OT_REG_FSGS,4
+NR_GS,$05000006,gs,%gs,gs,gs,-1,-1,-1,OT_REG_FSGS,5
+
+NR_DR0,$05000007,dr0,%dr0,dr0,dr0,-1,-1,-1,OT_REG_DREG,0
+NR_DR1,$05000008,dr1,%dr1,dr1,dr1,-1,-1,-1,OT_REG_DREG,1
+NR_DR2,$05000009,dr2,%dr2,dr2,dr2,-1,-1,-1,OT_REG_DREG,2
+NR_DR3,$0500000a,dr3,%dr3,dr3,dr3,-1,-1,-1,OT_REG_DREG,3
+NR_DR6,$0500000b,dr6,%dr6,dr6,dr6,-1,-1,-1,OT_REG_DREG,6
+NR_DR7,$0500000c,dr7,%dr7,dr7,dr7,-1,-1,-1,OT_REG_DREG,7
+NR_CR0,$0500000d,cr0,%cr0,cr0,cr0,-1,-1,-1,OT_REG_CREG,0
+NR_CR2,$0500000e,cr2,%cr2,cr2,cr2,-1,-1,-1,OT_REG_CREG,2
+NR_CR3,$0500000f,cr3,%cr3,cr3,cr3,-1,-1,-1,OT_REG_CREG,3
+NR_CR4,$05000010,cr4,%cr4,cr4,cr4,-1,-1,-1,OT_REG_CR4,4
+NR_TR3,$05000011,tr3,%tr3,tr3,tr3,-1,-1,-1,OT_REG_TREG,3
+NR_TR4,$05000012,tr4,%tr4,tr4,tr4,-1,-1,-1,OT_REG_TREG,4
+NR_TR5,$05000013,tr5,%tr5,tr5,tr5,-1,-1,-1,OT_REG_TREG,5
+NR_TR6,$05000014,tr6,%tr6,tr6,tr6,-1,-1,-1,OT_REG_TREG,6
+NR_TR7,$05000015,tr7,%tr7,tr7,tr7,-1,-1,-1,OT_REG_TREG,7
+
+NR_ST0,$02000000,st(0),%st(0),st(0),st0,12,11,33,OT_FPU0,0
+NR_ST1,$02000001,st(1),%st(1),st(1),st1,13,12,34,OT_FPUREG,1
+NR_ST2,$02000002,st(2),%st(2),st(2),st2,14,13,35,OT_FPUREG,2
+NR_ST3,$02000003,st(3),%st(3),st(3),st3,15,14,36,OT_FPUREG,3
+NR_ST4,$02000004,st(4),%st(4),st(4),st4,16,15,37,OT_FPUREG,4
+NR_ST5,$02000005,st(5),%st(5),st(5),st5,17,16,38,OT_FPUREG,5
+NR_ST6,$02000006,st(6),%st(6),st(6),st6,18,17,39,OT_FPUREG,6
+NR_ST7,$02000007,st(7),%st(7),st(7),st7,19,18,40,OT_FPUREG,7
+; Special code to that will map to %st(0)
+NR_ST,$02000008,st,%st,st,st0,12,11,33,OT_FPU0,0
+
+NR_MM0,$03000000,mm0,%mm0,mm0,mm0,29,29,41,OT_MMXREG,0
+NR_MM1,$03000001,mm1,%mm1,mm1,mm1,30,30,42,OT_MMXREG,1
+NR_MM2,$03000002,mm2,%mm2,mm2,mm2,31,31,43,OT_MMXREG,2
+NR_MM3,$03000003,mm3,%mm3,mm3,mm3,32,32,44,OT_MMXREG,3
+NR_MM4,$03000004,mm4,%mm4,mm4,mm4,33,33,45,OT_MMXREG,4
+NR_MM5,$03000005,mm5,%mm5,mm5,mm5,34,34,46,OT_MMXREG,5
+NR_MM6,$03000006,mm6,%mm6,mm6,mm6,35,35,47,OT_MMXREG,6
+NR_MM7,$03000007,mm7,%mm7,mm7,mm7,36,36,48,OT_MMXREG,7
+
+NR_XMM0,$04000000,xmm0,%xmm0,xmm0,xmm0,21,21,17,OT_XMMREG,0
+NR_XMM1,$04000001,xmm1,%xmm1,xmm1,xmm1,22,22,18,OT_XMMREG,1
+NR_XMM2,$04000002,xmm2,%xmm2,xmm2,xmm2,23,23,19,OT_XMMREG,2
+NR_XMM3,$04000003,xmm3,%xmm3,xmm3,xmm3,24,24,20,OT_XMMREG,3
+NR_XMM4,$04000004,xmm4,%xmm4,xmm4,xmm4,25,25,21,OT_XMMREG,4
+NR_XMM5,$04000005,xmm5,%xmm5,xmm5,xmm5,26,26,22,OT_XMMREG,5
+NR_XMM6,$04000006,xmm6,%xmm6,xmm6,xmm6,27,27,23,OT_XMMREG,6
+NR_XMM7,$04000007,xmm7,%xmm7,xmm7,xmm7,28,28,24,OT_XMMREG,7
+NR_XMM8,$04000008,xmm8,%xmm8,xmm8,xmm8,-1,-1,25,OT_XMMREG,0,64
+NR_XMM9,$04000009,xmm9,%xmm9,xmm9,xmm9,-1,-1,26,OT_XMMREG,1,64
+NR_XMM10,$0400000a,xmm10,%xmm10,xmm10,xmm10,-1,-1,27,OT_XMMREG,2,64
+NR_XMM11,$0400000b,xmm11,%xmm11,xmm11,xmm11,-1,-1,28,OT_XMMREG,3,64
+NR_XMM12,$0400000c,xmm12,%xmm12,xmm12,xmm12,-1,-1,29,OT_XMMREG,4,64
+NR_XMM13,$0400000d,xmm13,%xmm13,xmm13,xmm13,-1,-1,30,OT_XMMREG,5,64
+NR_XMM14,$0400000e,xmm14,%xmm14,xmm14,xmm14,-1,-1,31,OT_XMMREG,6,64
+NR_XMM15,$0400000f,xmm15,%xmm15,xmm15,xmm15,-1,-1,32,OT_XMMREG,7,64
diff --git a/compiler/x86_64/aoptcpu.pas b/compiler/x86_64/aoptcpu.pas
new file mode 100644
index 0000000000..cb656af36e
--- /dev/null
+++ b/compiler/x86_64/aoptcpu.pas
@@ -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.
diff --git a/compiler/x86_64/aoptcpub.pas b/compiler/x86_64/aoptcpub.pas
new file mode 100644
index 0000000000..de9031add3
--- /dev/null
+++ b/compiler/x86_64/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the sparc 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_JMP;
+ aopt_condjmp = A_Jcc;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/compiler/x86_64/aoptcpud.pas b/compiler/x86_64/aoptcpud.pas
new file mode 100644
index 0000000000..cb8c5d319f
--- /dev/null
+++ b/compiler/x86_64/aoptcpud.pas
@@ -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.
diff --git a/compiler/x86_64/cgcpu.pas b/compiler/x86_64/cgcpu.pas
new file mode 100644
index 0000000000..bf3116b9cc
--- /dev/null
+++ b/compiler/x86_64/cgcpu.pas
@@ -0,0 +1,139 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit implements the code generator for the x86-64.
+
+ 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 cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase,cgobj,cgx86,
+ aasmbase,aasmtai,aasmcpu,
+ cpubase,cpuinfo,cpupara,parabase,
+ symdef,
+ node,symconst,rgx86,procinfo;
+
+ type
+ tcgx86_64 = class(tcgx86)
+ procedure init_register_allocators;override;
+ procedure g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);override;
+ procedure g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ end;
+
+
+ implementation
+
+ uses
+ globtype,globals,verbose,systems,cutils,
+ symsym,defutil,paramgr,fmodule,cgutils,
+ rgobj,tgobj,rgcpu;
+
+
+ procedure Tcgx86_64.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_RAX,RS_RDX,RS_RCX,RS_RBX,RS_RSI,RS_RDI,
+ RS_R8,RS_R9,RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15],first_int_imreg,[RS_RBP]);
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBWHOLE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7,
+ RS_XMM8,RS_XMM9,RS_XMM10,RS_XMM11,RS_XMM12,RS_XMM13,RS_XMM14,RS_XMM15],first_mm_imreg,[]);
+ rgfpu:=Trgx86fpu.create;
+ end;
+
+
+ procedure tcgx86_64.g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);
+ var
+ stacksize : longint;
+ begin
+ { Release PIC register }
+ if cs_create_pic in aktmoduleswitches then
+ list.concat(tai_regalloc.dealloc(NR_PIC_OFFSET_REG,nil));
+
+ { remove stackframe }
+ if not nostackframe then
+ begin
+ if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+ begin
+ stacksize:=current_procinfo.calc_stackframe_size;
+ if (stacksize<>0) then
+ cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
+ end
+ else
+ list.concat(Taicpu.op_none(A_LEAVE,S_NO));
+ list.concat(tai_regalloc.dealloc(NR_FRAME_POINTER_REG,nil));
+ end;
+
+ list.concat(Taicpu.Op_none(A_RET,S_NO));
+ end;
+
+
+ procedure tcgx86_64.g_intf_wrapper(list: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);
+ var
+ make_global : boolean;
+ href : treference;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef._class) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>objectsymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ if po_virtualmethod in procdef.procoptions then
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { mov 0(%rdi),%rax ; load vmt}
+ reference_reset_base(href,NR_RDI,0);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_RAX);
+ { jmp *vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_RAX,procdef._class.vmtmethodoffset(procdef.extnumber));
+ list.concat(taicpu.op_ref_reg(A_MOV,S_Q,href,NR_RAX));
+ list.concat(taicpu.op_reg(A_JMP,S_Q,NR_RAX));
+ end
+ else
+ list.concat(taicpu.op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+
+begin
+ cg:=tcgx86_64.create;
+{$ifndef cpu64bit}
+ cg64:=tcg64f64.create;
+{$endif cpu64bit}
+end.
diff --git a/compiler/x86_64/cpubase.inc b/compiler/x86_64/cpubase.inc
new file mode 100644
index 0000000000..dfaffb98c6
--- /dev/null
+++ b/compiler/x86_64/cpubase.inc
@@ -0,0 +1,148 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
+
+ Contains the basic declarations for the x86-64 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.
+
+ ****************************************************************************
+}
+{ This include file contains the basic declarations for the x86-64 architecture.
+}
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_Q,S_BW,S_BL,S_WL,S_BQ,S_WQ,S_LQ,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_FV,S_FXX,
+ S_MD,
+ S_NEAR,S_FAR,S_SHORT,
+ S_T,
+ S_XMM
+ );
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+const
+ { Standard opcode string table (for each tasmop enumeration). The
+ opcode strings should conform to the names as defined by the
+ processor manufacturer.
+ }
+ std_op2str:op2strtable={$i x8664int.inc}
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ c_countusableregsint = 4;
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from i386.c (dbx_register_map) and i386.h
+ (FIXED_REGISTERS) from GCC 3.x source code
+
+ }
+ stab_regindex : array[tregisterindex] of shortint = (
+ {$i r8664stab.inc}
+ );
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_64;
+ { the natural int size for a processor, }
+ OS_INT = OS_64;
+ OS_SINT = OS_S64;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F80;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M64;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ RS_STACK_POINTER_REG = RS_RSP;
+ NR_STACK_POINTER_REG = NR_RSP;
+ {# Frame pointer register }
+ RS_FRAME_POINTER_REG = RS_RBP;
+ NR_FRAME_POINTER_REG = NR_RBP;
+ { Return address for DWARF }
+ NR_RETURN_ADDRESS_REG = NR_EIP;
+ { Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+ NR_PIC_OFFSET_REG = NR_RBX;
+ { Results are returned in this register (both 32 and 64 bits }
+ NR_FUNCTION_RETURN_REG = NR_RAX;
+ RS_FUNCTION_RETURN_REG = RS_RAX;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+
+ { WARNING: don't change to R_ST0!! See comments above implementation of }
+ { a_loadfpu* methods in rgcpu (JM) }
+ NR_FPU_RESULT_REG = NR_ST;
+ NR_MM_RESULT_REG = NR_XMM0;
+
+ { Offset where the parent framepointer is pushed }
+ PARENT_FRAMEPOINTER_OFFSET = 16;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..4] of tsuperregister = (RS_EBX,RS_R12,RS_R13,RS_R14,RS_R15);
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_xmm_registers : array[0..4] of tsuperregister = (RS_EBX,RS_R12,RS_R13,RS_R14,RS_R15);
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 8;
+
diff --git a/compiler/x86_64/cpuinfo.pas b/compiler/x86_64/cpuinfo.pas
new file mode 100644
index 0000000000..1100387c80
--- /dev/null
+++ b/compiler/x86_64/cpuinfo.pas
@@ -0,0 +1,84 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ Basic Processor information
+
+ 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 cpuinfo;
+
+{$i fpcdefs.inc}
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = type extended;
+
+ pbestreal=^bestreal;
+
+ tprocessors =
+ (no_processor,
+ ClassAthlon64
+ );
+
+ tfputype =
+ (no_fpuprocessor,
+ fpu_sse64
+ );
+
+Const
+ { Size of native extended type }
+ extended_size = 10;
+ { Size of a multimedia register }
+ mmreg_size = 16;
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'x86_64';
+
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+{ pocall_compilerproc,
+ pocall_inline,}
+ pocall_register,
+ pocall_safecall,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl
+ ];
+
+ processorsstr : array[tprocessors] of string[10] = ('',
+ 'ATHLON64'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'SSE64'
+ );
+
+ sse_singlescalar : set of tfputype = [fpu_sse64];
+ sse_doublescalar : set of tfputype = [fpu_sse64];
+
+Implementation
+
+end.
diff --git a/compiler/x86_64/cpunode.pas b/compiler/x86_64/cpunode.pas
new file mode 100644
index 0000000000..a22ba4eee2
--- /dev/null
+++ b/compiler/x86_64/cpunode.pas
@@ -0,0 +1,58 @@
+{
+ Copyright (c) 2000 by Florian Klaempfl
+
+ Includes the x86-64 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.
+
+ ****************************************************************************
+}
+{ This is a helper unit to include the necessary code generator units
+ for the x86-64 processor.
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,
+ ncgld,
+ ncgflw,
+ ncgcnv,
+ ncgmem,
+ ncgmat,
+ ncgcon,
+ ncgcal,
+ ncgset,
+ ncgopt,
+ // n386con,n386flw,n386mat,n386mem,
+ // n386set,n386inl,n386opt,
+ { the cpu specific node units must be used after the generic ones to
+ get the correct class pointer }
+ nx86set,
+ nx86con,
+ nx64add,
+ nx64cal,
+ nx64cnv,
+ nx64mat,
+ nx64inl
+ ;
+
+end.
diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas
new file mode 100644
index 0000000000..7d818c4dc2
--- /dev/null
+++ b/compiler/x86_64/cpupara.pas
@@ -0,0 +1,493 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generates the argument location information for x86-64 target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published bymethodpointer
+ 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 cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cpubase,cgbase,
+ symconst,symtype,symsym,symdef,
+ aasmtai,
+ parabase,paramgr;
+
+ type
+ tx86_64paramanager = class(tparamanager)
+ private
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var intparareg,mmparareg,parasize:longint);
+ public
+ function param_use_paraloc(const cgpara:tcgpara):boolean;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ end;
+
+ implementation
+
+ uses
+ cutils,verbose,
+ systems,
+ defutil,
+ cgutils;
+
+ const
+ paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
+ parammsupregs : array[0..7] of tsuperregister = (RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7);
+
+ procedure getvalueparaloc(p : tdef;var loc1,loc2:tcgloc);
+ begin
+ loc1:=LOC_INVALID;
+ loc2:=LOC_INVALID;
+ case p.deftype of
+ orddef:
+ begin
+ loc1:=LOC_REGISTER;
+ {$warning TODO 128bit also needs lochigh}
+ end;
+ floatdef:
+ begin
+ case tfloatdef(p).typ of
+ s80real:
+ loc1:=LOC_REFERENCE;
+ s32real,
+ s64real :
+ loc1:=LOC_MMREGISTER;
+ s64currency,
+ s64comp :
+ loc1:=LOC_REGISTER;
+ s128real:
+ begin
+ loc1:=LOC_MMREGISTER;
+ loc2:=LOC_MMREGISTER;
+ {$warning TODO float 128bit needs SSEUP lochigh}
+ end;
+ end;
+ end;
+ recorddef:
+ begin
+ if p.size<=16 then
+ begin
+ {$warning TODO location depends on the fields}
+ loc1:=LOC_REFERENCE;
+ end
+ else
+ loc1:=LOC_REFERENCE;
+ end;
+ objectdef:
+ begin
+ if is_object(p) then
+ loc1:=LOC_REFERENCE
+ else
+ loc1:=LOC_REGISTER;
+ end;
+ arraydef:
+ begin
+ loc1:=LOC_REFERENCE;
+ end;
+ variantdef:
+ loc1:=LOC_REFERENCE;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ loc1:=LOC_REFERENCE
+ else
+ loc1:=LOC_REGISTER;
+ setdef:
+ if is_smallset(p) then
+ loc1:=LOC_REGISTER
+ else
+ loc1:=LOC_REFERENCE;
+ procvardef:
+ begin
+ { This is a record < 16 bytes }
+ if (po_methodpointer in tprocvardef(p).procoptions) then
+ begin
+ loc1:=LOC_REGISTER;
+ loc2:=LOC_REGISTER;
+ end
+ else
+ loc1:=LOC_REGISTER;
+ end;
+ else
+ begin
+ { default for pointers,enums,etc }
+ loc1:=LOC_REGISTER;
+ end;
+ end;
+ end;
+
+
+ function tx86_64paramanager.param_use_paraloc(const cgpara:tcgpara):boolean;
+ var
+ paraloc : pcgparalocation;
+ begin
+ if not assigned(cgpara.location) then
+ internalerror(200410102);
+ result:=true;
+ { All locations are LOC_REFERENCE }
+ paraloc:=cgpara.location;
+ while assigned(paraloc) do
+ begin
+ if (paraloc^.loc<>LOC_REFERENCE) then
+ begin
+ result:=false;
+ exit;
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ { true if a parameter is too large to copy and only the address is pushed }
+ function tx86_64paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out always require address }
+ if varspez in [vs_var,vs_out] then
+ begin
+ result:=true;
+ exit;
+ end;
+ { Only vs_const, vs_value here }
+ case def.deftype of
+ variantdef,
+ formaldef :
+ result:=true;
+ recorddef :
+ result:=(def.size>sizeof(aint));
+ arraydef :
+ begin
+ result:=not(
+ { cdecl array of const need to be ignored and therefor be puhsed
+ as value parameter with length 0 }
+ (calloption in [pocall_cdecl,pocall_cppdecl]) and
+ (is_array_of_const(def) or
+ is_dynamic_array(def))
+ );
+ end;
+ objectdef :
+ result:=is_object(def);
+ stringdef :
+ result:=(tstringdef(def).string_typ in [st_shortstring,st_longstring]);
+ procvardef :
+ result:=(po_methodpointer in tprocvardef(def).procoptions);
+ setdef :
+ result:=(tsetdef(def).settype<>smallset);
+ end;
+ end;
+
+
+ function tx86_64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[RS_RAX,RS_RCX,RS_RDX,RS_RSI,RS_RDI,RS_R8,RS_R9,RS_R10,RS_R11];
+ end;
+
+
+ function tx86_64paramanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[RS_XMM0..RS_XMM15];
+ end;
+
+
+ function tx86_64paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[RS_ST0..RS_ST7];
+ end;
+
+
+ procedure tx86_64paramanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.intsize:=tcgsize2size[OS_INT];
+ cgpara.alignment:=get_para_align(calloption);
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ if nr<1 then
+ internalerror(200304303)
+ else if nr<=high(paraintsupregs)+1 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],R_SUBWHOLE);
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=(nr-6)*sizeof(aint);
+ end;
+ end;
+ end;
+
+
+ procedure tx86_64paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ var
+ retcgsize : tcgsize;
+ begin
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ retcgsize:=OS_ADDR
+ else
+ retcgsize:=def_cgsize(p.rettype.def);
+
+ location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
+ { void has no location }
+ if is_void(p.rettype.def) then
+ begin
+ location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
+ exit;
+ end;
+ { Return in FPU register? }
+ if p.rettype.def.deftype=floatdef then
+ begin
+ case tfloatdef(p.rettype.def).typ of
+ s32real,s64real:
+ begin
+ p.funcretloc[side].loc:=LOC_MMREGISTER;
+ p.funcretloc[side].register:=NR_MM_RESULT_REG;
+ p.funcretloc[side].size:=retcgsize;
+ end;
+ s64currency,
+ s64comp,
+ s80real:
+ begin
+ p.funcretloc[side].loc:=LOC_FPUREGISTER;
+ p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+ p.funcretloc[side].size:=retcgsize;
+ end;
+ else
+ internalerror(200405034);
+ end;
+ end
+ else
+ { Return in register? }
+ if not ret_in_param(p.rettype.def,p.proccalloption) then
+ begin
+ p.funcretloc[side].loc:=LOC_REGISTER;
+ p.funcretloc[side].size:=retcgsize;
+ if side=callerside then
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
+ else
+ p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
+ end
+ else
+ begin
+ p.funcretloc[side].loc:=LOC_REFERENCE;
+ p.funcretloc[side].size:=retcgsize;
+ end;
+ end;
+
+
+ procedure tx86_64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var intparareg,mmparareg,parasize:longint);
+ var
+ hp : tparavarsym;
+ paraloc : pcgparalocation;
+ subreg : tsubregister;
+ pushaddr : boolean;
+ paracgsize : tcgsize;
+ loc : array[1..2] of tcgloc;
+ paralen,
+ locidx,
+ l,i,
+ varalign,
+ paraalign : longint;
+ begin
+ paraalign:=get_para_align(p.proccalloption);
+ { Register parameters are assigned from left to right }
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ pushaddr:=push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption);
+ if pushaddr then
+ begin
+ loc[1]:=LOC_REGISTER;
+ loc[2]:=LOC_INVALID;
+ paracgsize:=OS_ADDR;
+ paralen:=sizeof(aint);
+ end
+ else
+ begin
+ getvalueparaloc(hp.vartype.def,loc[1],loc[2]);
+ paralen:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
+ paracgsize:=def_cgsize(hp.vartype.def);
+ end;
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].Alignment:=paraalign;
+ if paralen>0 then
+ begin
+ locidx:=1;
+ while (paralen>0) do
+ begin
+ if locidx>2 then
+ internalerror(200501283);
+ { Enough registers free? }
+ case loc[locidx] of
+ LOC_REGISTER :
+ begin
+ if (intparareg>high(paraintsupregs)) then
+ loc[locidx]:=LOC_REFERENCE;
+ end;
+ LOC_MMREGISTER :
+ begin
+ if (mmparareg>high(parammsupregs)) then
+ loc[locidx]:=LOC_REFERENCE;
+ end;
+ end;
+ { Allocate }
+ case loc[locidx] of
+ LOC_REGISTER :
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if (paracgsize=OS_NO) or (loc[2]<>LOC_INVALID) then
+ begin
+ paraloc^.size:=OS_INT;
+ subreg:=R_SUBWHOLE;
+ end
+ else
+ begin
+ paraloc^.size:=paracgsize;
+ { s64comp is pushed in an int register }
+ if paraloc^.size=OS_C64 then
+ paraloc^.size:=OS_64;
+ subreg:=cgsize2subreg(paraloc^.size);
+ end;
+ paraloc^.register:=newreg(R_INTREGISTER,paraintsupregs[intparareg],subreg);
+ inc(intparareg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ LOC_MMREGISTER :
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_MMREGISTER;
+ paraloc^.register:=newreg(R_MMREGISTER,parammsupregs[mmparareg],R_SUBNONE);
+ if paracgsize=OS_F128 then
+ paraloc^.size:=OS_F64
+ else
+ paraloc^.size:=paracgsize;
+ inc(mmparareg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ LOC_REFERENCE :
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ { Extended needs a single location }
+ if (paracgsize=OS_F80) then
+ begin
+ paraloc^.size:=paracgsize;
+ l:=paralen;
+ end
+ else
+ begin
+ l:=paralen;
+ paraloc^.size:=int_cgsize(l);
+ end;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(l),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ parasize:=align(parasize+l,varalign);
+ dec(paralen,l);
+ end;
+ end;
+ if (locidx<2) and
+ (loc[locidx+1]<>LOC_INVALID) then
+ inc(locidx);
+ end;
+ end
+ else
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_VOID;
+ end;
+ end;
+ { Register parameters are assigned from left-to-right, but the
+ offsets on the stack are right-to-left. There is no need
+ to reverse the offset, only adapt the calleeside with the
+ start offset of the first param on the stack }
+ if side=calleeside then
+ begin
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ with hp.paraloc[side].location^ do
+ if (loc=LOC_REFERENCE) then
+ inc(reference.offset,target_info.first_parm_offset);
+ end;
+ end;
+ end;
+
+
+ function tx86_64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ intparareg,mmparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ mmparareg:=0;
+ parasize:=0;
+ { calculate the registers for the normal parameters }
+ create_paraloc_info_intern(p,callerside,p.paras,intparareg,mmparareg,parasize);
+ { append the varargs }
+ create_paraloc_info_intern(p,callerside,varargspara,intparareg,mmparareg,parasize);
+ { store used no. of SSE registers, that needs to be passed in %AL }
+ varargspara.mmregsused:=mmparareg;
+ result:=parasize;
+ end;
+
+
+ function tx86_64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ intparareg,mmparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ mmparareg:=0;
+ parasize:=0;
+ create_paraloc_info_intern(p,side,p.paras,intparareg,mmparareg,parasize);
+ { Create Function result paraloc }
+ create_funcretloc_info(p,side);
+ { We need to return the size allocated on the stack }
+ result:=parasize;
+ end;
+
+
+begin
+ paramanager:=tx86_64paramanager.create;
+end.
diff --git a/compiler/x86_64/cpupi.pas b/compiler/x86_64/cpupi.pas
new file mode 100644
index 0000000000..c9eb0ffd8b
--- /dev/null
+++ b/compiler/x86_64/cpupi.pas
@@ -0,0 +1,64 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ 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 contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ psub,procinfo;
+
+ type
+ tx86_64procinfo = class(tcgprocinfo)
+ function calc_stackframe_size:longint;override;
+ procedure allocate_push_parasize(size:longint);override;
+ end;
+
+
+implementation
+
+ uses
+ globals,
+ cutils,
+ tgobj;
+
+
+ procedure tx86_64procinfo.allocate_push_parasize(size:longint);
+ begin
+ if size>maxpushedparasize then
+ maxpushedparasize:=size;
+ end;
+
+
+ function tx86_64procinfo.calc_stackframe_size:longint;
+ begin
+ maxpushedparasize:=align(maxpushedparasize,max(aktalignment.localalignmin,16));
+ { RSP should be aligned on 16 bytes }
+ result:=Align(tg.direction*tg.lasttemp,16)+maxpushedparasize;
+ end;
+
+begin
+ cprocinfo:=tx86_64procinfo;
+end.
diff --git a/compiler/x86_64/cpuswtch.pas b/compiler/x86_64/cpuswtch.pas
new file mode 100644
index 0000000000..c306ea8b0a
--- /dev/null
+++ b/compiler/x86_64/cpuswtch.pas
@@ -0,0 +1,97 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ interprets the commandline options which are i386 specific
+
+ 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 cpuswtch;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ options;
+
+type
+ toptionx86_64=class(toption)
+ procedure interpret_proc_specific_options(const opt:string);override;
+ end;
+
+implementation
+
+uses
+ cutils,globtype,systems,globals;
+
+procedure toptionx86_64.interpret_proc_specific_options(const opt:string);
+var
+ j : longint;
+ More : string;
+begin
+ More:=Upper(copy(opt,3,length(opt)-2));
+ case opt[2] of
+ 'O' : Begin
+ j := 3;
+ While (j <= Length(Opt)) Do
+ Begin
+ case opt[j] of
+ '-' :
+ begin
+ initglobalswitches:=initglobalswitches-[cs_optimize,cs_fastoptimize,cs_slowoptimize,cs_littlesize,
+ cs_regvars,cs_uncertainopts];
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+ end;
+ 'a' :
+ begin
+ UpdateAlignmentStr(Copy(Opt,j+1,255),ParaAlignment);
+ j:=length(Opt);
+ end;
+ 'g' : initglobalswitches:=initglobalswitches+[cs_littlesize];
+ 'G' : initglobalswitches:=initglobalswitches-[cs_littlesize];
+ 'r' :
+ begin
+ initglobalswitches:=initglobalswitches+[cs_regvars];
+ Simplify_ppu:=false;
+ end;
+ 'u' : initglobalswitches:=initglobalswitches+[cs_uncertainopts];
+ '1' : initglobalswitches:=initglobalswitches-[cs_fastoptimize,cs_slowoptimize]+[cs_optimize];
+ '2' : initglobalswitches:=initglobalswitches-[cs_slowoptimize]+[cs_optimize,cs_fastoptimize];
+ '3' : initglobalswitches:=initglobalswitches+[cs_optimize,cs_fastoptimize,cs_slowoptimize];
+ else IllegalPara(opt);
+ End;
+ Inc(j)
+ end;
+ end;
+ 'R' : begin
+ if More='ATT' then
+ initasmmode:=asmmode_i386_att
+ else
+ if More='INTEL' then
+ initasmmode:=asmmode_i386_intel
+ else
+ IllegalPara(opt);
+ end;
+ else
+ IllegalPara(opt);
+ end;
+end;
+
+
+initialization
+ coption:=toptionx86_64;
+end.
diff --git a/compiler/x86_64/cputarg.pas b/compiler/x86_64/cputarg.pas
new file mode 100644
index 0000000000..6e9c515386
--- /dev/null
+++ b/compiler/x86_64/cputarg.pas
@@ -0,0 +1,84 @@
+{
+ Copyright (c) 2001 by Peter Vreman
+
+ Includes the x86-64 dependent target units
+
+ 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 includes the x86-64 dependent target units. }
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETFREEBSD}
+ ,t_bsd
+ {$endif}
+ {$ifndef NOTARGETWIN}
+ ,t_win
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGX86_64INT}
+ ,agx86int
+ {$endif}
+ {$ifndef NOAGX86_64ATT}
+ ,agx86att
+ {$endif}
+
+ ,ogcoff
+ ,ogelf
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRax64att}
+ ,rax64att
+ {$endif NoRax64att}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+ ;
+
+end.
diff --git a/compiler/x86_64/nx64add.pas b/compiler/x86_64/nx64add.pas
new file mode 100644
index 0000000000..aff2a4ad6a
--- /dev/null
+++ b/compiler/x86_64/nx64add.pas
@@ -0,0 +1,87 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Code generation for add nodes on the x86-64
+
+ 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 nx64add;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,cpubase,nx86add;
+
+ type
+ tx8664addnode = class(tx86addnode)
+ procedure second_mul;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,globals,
+ aasmbase,aasmtai,
+ cgbase,cgutils,cga,cgobj,
+ tgobj;
+
+{*****************************************************************************
+ MUL
+*****************************************************************************}
+
+ procedure tx8664addnode.second_mul;
+
+ var r:Tregister;
+ hl4 : tasmlabel;
+
+ begin
+ { The location.register will be filled in later (JM) }
+ location_reset(location,LOC_REGISTER,OS_INT);
+ { Get a temp register and load the left value into it
+ and free the location. }
+ r:=cg.getintregister(exprasmlist,OS_INT);
+ cg.a_load_loc_reg(exprasmlist,OS_INT,left.location,r);
+ { Allocate RAX. }
+ cg.getcpuregister(exprasmlist,NR_RAX);
+ { Load the right value. }
+ cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,NR_RAX);
+ { Also allocate RDX, since it is also modified by a mul (JM). }
+ cg.getcpuregister(exprasmlist,NR_RDX);
+ emit_reg(A_MUL,S_Q,r);
+ if cs_check_overflow in aktlocalswitches then
+ begin
+ objectlibrary.getjumplabel(hl4);
+ cg.a_jmp_flags(exprasmlist,F_AE,hl4);
+ cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
+ cg.a_label(exprasmlist,hl4);
+ end;
+ { Free RDX,RAX }
+ cg.ungetcpuregister(exprasmlist,NR_RDX);
+ cg.ungetcpuregister(exprasmlist,NR_RAX);
+ { Allocate a new register and store the result in RAX in it. }
+ location.register:=cg.getintregister(exprasmlist,OS_INT);
+ emit_reg_reg(A_MOV,S_Q,NR_RAX,location.register);
+ location_freetemp(exprasmlist,left.location);
+ location_freetemp(exprasmlist,right.location);
+ end;
+
+
+begin
+ caddnode:=tx8664addnode;
+end.
diff --git a/compiler/x86_64/nx64cal.pas b/compiler/x86_64/nx64cal.pas
new file mode 100644
index 0000000000..7ba31e5740
--- /dev/null
+++ b/compiler/x86_64/nx64cal.pas
@@ -0,0 +1,62 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the x86-64 specific part of call 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 bymethodpointer
+ 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 nx64cal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ ncal,ncgcal;
+
+ type
+ tx8664callnode = class(tcgcallnode)
+ procedure extra_call_code;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,
+ cpubase,
+ aasmtai,aasmcpu;
+
+ procedure tx8664callnode.extra_call_code;
+ var
+ mmregs : aint;
+ begin
+ { x86_64 requires %al to contain the no. SSE regs passed }
+ if cnf_uses_varargs in callnodeflags then
+ begin
+ if assigned(varargsparas) then
+ mmregs:=varargsparas.mmregsused
+ else
+ mmregs:=0;
+ exprasmlist.concat(taicpu.op_const_reg(A_MOV,S_Q,mmregs,NR_RAX))
+ end;
+ end;
+
+
+begin
+ ccallnode:=tx8664callnode;
+end.
diff --git a/compiler/x86_64/nx64cnv.pas b/compiler/x86_64/nx64cnv.pas
new file mode 100644
index 0000000000..06960eacaa
--- /dev/null
+++ b/compiler/x86_64/nx64cnv.pas
@@ -0,0 +1,66 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86-64 assembler for type converting 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 nx64cnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgcnv,defutil,defcmp,
+ nx86cnv;
+
+ type
+ tx8664typeconvnode = class(tx86typeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ { function first_int_to_real: tnode; override; }
+ { procedure second_int_to_real;override; }
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ { procedure second_int_to_bool;override; }
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+
+implementation
+
+ uses
+ ncnv;
+
+
+begin
+ ctypeconvnode:=tx8664typeconvnode;
+end.
diff --git a/compiler/x86_64/nx64inl.pas b/compiler/x86_64/nx64inl.pas
new file mode 100644
index 0000000000..2c322f897c
--- /dev/null
+++ b/compiler/x86_64/nx64inl.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86-64 inline 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 nx64inl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ nx86inl;
+
+ type
+ tx8664inlinenode = class(tx86inlinenode)
+ end;
+
+implementation
+
+ uses
+ ninl;
+
+begin
+ cinlinenode:=tx8664inlinenode;
+end.
diff --git a/compiler/x86_64/nx64mat.pas b/compiler/x86_64/nx64mat.pas
new file mode 100644
index 0000000000..4f0333fff8
--- /dev/null
+++ b/compiler/x86_64/nx64mat.pas
@@ -0,0 +1,204 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86-64 assembler for math 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 nx64mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat,nx86mat;
+
+ type
+ tx8664moddivnode = class(tmoddivnode)
+ procedure pass_2;override;
+ end;
+
+ tx8664shlshrnode = class(tshlshrnode)
+ procedure pass_2;override;
+ end;
+
+ tx8664unaryminusnode = class(tx86unaryminusnode)
+ end;
+
+ tx8664notnode = class(tx86notnode)
+ end;
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,aasmbase,aasmtai,defutil,
+ pass_1,pass_2,
+ ncon,
+ cpubase,cpuinfo,
+ cgbase,cgutils,cga,cgobj,cgx86,
+ ncgutil;
+
+{*****************************************************************************
+ TX8664MODDIVNODE
+*****************************************************************************}
+
+ procedure tx8664moddivnode.pass_2;
+ var
+ hreg1,hreg2:Tregister;
+ power:longint;
+ op:Tasmop;
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ secondpass(right);
+ if codegenerror then
+ exit;
+
+ { put numerator in register }
+ location_reset(location,LOC_REGISTER,OS_INT);
+ location_force_reg(exprasmlist,left.location,OS_INT,false);
+ hreg1:=left.location.register;
+
+ if (nodetype=divn) and (right.nodetype=ordconstn) and
+ ispowerof2(int64(tordconstnode(right).value),power) then
+ begin
+ { for signed numbers, the numerator must be adjusted before the
+ shift instruction, but not wih unsigned numbers! Otherwise,
+ "Cardinal($ffffffff) div 16" overflows! (JM) }
+ if is_signed(left.resulttype.def) Then
+ begin
+ { use a sequence without jumps, saw this in
+ comp.compilers (JM) }
+ { no jumps, but more operations }
+ hreg2:=cg.getintregister(exprasmlist,OS_INT);
+ emit_reg_reg(A_MOV,S_Q,hreg1,hreg2);
+ {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
+ emit_const_reg(A_SAR,S_Q,63,hreg2);
+ {If signed, hreg2=right value-1, otherwise 0.}
+ emit_const_reg(A_AND,S_Q,tordconstnode(right).value-1,hreg2);
+ { add to the left value }
+ emit_reg_reg(A_ADD,S_Q,hreg2,hreg1);
+ { do the shift }
+ emit_const_reg(A_SAR,S_Q,power,hreg1);
+ end
+ else
+ emit_const_reg(A_SHR,S_Q,power,hreg1);
+ location.register:=hreg1;
+ end
+ else
+ begin
+ {Bring denominator to a register.}
+ cg.getcpuregister(exprasmlist,NR_RAX);
+ emit_reg_reg(A_MOV,S_Q,hreg1,NR_RAX);
+ cg.getcpuregister(exprasmlist,NR_RDX);
+ {Sign extension depends on the left type.}
+ if torddef(left.resulttype.def).typ=u64bit then
+ emit_reg_reg(A_XOR,S_Q,NR_RDX,NR_RDX)
+ else
+ emit_none(A_CQO,S_NO);
+
+ {Division depends on the right type.}
+ if Torddef(right.resulttype.def).typ=u64bit then
+ op:=A_DIV
+ else
+ op:=A_IDIV;
+
+ if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ emit_ref(op,S_Q,right.location.reference)
+ else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ emit_reg(op,S_Q,right.location.register)
+ else
+ begin
+ hreg1:=cg.getintregister(exprasmlist,right.location.size);
+ cg.a_load_loc_reg(exprasmlist,OS_64,right.location,hreg1);
+ emit_reg(op,S_Q,hreg1);
+ end;
+
+ { Copy the result into a new register. Release RAX & RDX.}
+ cg.ungetcpuregister(exprasmlist,NR_RDX);
+ cg.ungetcpuregister(exprasmlist,NR_RAX);
+ location.register:=cg.getintregister(exprasmlist,OS_INT);
+ if nodetype=divn then
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,NR_RAX,location.register)
+ else
+ cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,NR_RDX,location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TX8664SHLRSHRNODE
+*****************************************************************************}
+
+
+ procedure tx8664shlshrnode.pass_2;
+ var
+ op : Tasmop;
+ opsize : tcgsize;
+ mask : aint;
+ begin
+ secondpass(left);
+ secondpass(right);
+
+ { determine operator }
+ if nodetype=shln then
+ op:=A_SHL
+ else
+ op:=A_SHR;
+
+ { special treatment of 32bit values for backwards compatibility }
+ if left.resulttype.def.size<=4 then
+ begin
+ opsize:=OS_32;
+ mask:=31;
+ end
+ else
+ begin
+ opsize:=OS_64;
+ mask:=63;
+ end;
+
+ { load left operators in a register }
+ location_copy(location,left.location);
+ location_force_reg(exprasmlist,location,opsize,false);
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ emit_const_reg(op,tcgsize2opsize[opsize],tordconstnode(right).value and mask,location.register)
+ else
+ begin
+ { load right operators in a RCX }
+ cg.getcpuregister(exprasmlist,NR_RCX);
+ cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,NR_RCX);
+
+ { right operand is in ECX }
+ cg.ungetcpuregister(exprasmlist,NR_RCX);
+ emit_reg_reg(op,tcgsize2opsize[opsize],NR_CL,location.register);
+ end;
+ end;
+
+
+begin
+ cunaryminusnode:=tx8664unaryminusnode;
+ cmoddivnode:=tx8664moddivnode;
+ cshlshrnode:=tx8664shlshrnode;
+ cnotnode:=tx8664notnode;
+end.
diff --git a/compiler/x86_64/r8664ari.inc b/compiler/x86_64/r8664ari.inc
new file mode 100644
index 0000000000..bdce69ce50
--- /dev/null
+++ b/compiler/x86_64/r8664ari.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+2,
+1,
+3,
+17,
+16,
+30,
+29,
+18,
+7,
+6,
+83,
+84,
+85,
+86,
+71,
+8,
+12,
+26,
+25,
+11,
+77,
+78,
+79,
+80,
+81,
+82,
+72,
+13,
+4,
+31,
+19,
+9,
+27,
+14,
+70,
+73,
+23,
+35,
+75,
+76,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+45,
+46,
+48,
+47,
+49,
+50,
+52,
+51,
+53,
+54,
+56,
+55,
+57,
+58,
+60,
+59,
+61,
+62,
+64,
+63,
+65,
+66,
+68,
+67,
+37,
+38,
+40,
+39,
+41,
+42,
+44,
+43,
+5,
+32,
+20,
+10,
+28,
+15,
+69,
+24,
+36,
+22,
+21,
+34,
+33,
+74,
+100,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+87,
+88,
+89,
+90,
+91,
+109,
+110,
+119,
+120,
+121,
+122,
+123,
+124,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118,
+0
diff --git a/compiler/x86_64/r8664att.inc b/compiler/x86_64/r8664att.inc
new file mode 100644
index 0000000000..f9539b56f8
--- /dev/null
+++ b/compiler/x86_64/r8664att.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'%al',
+'%ah',
+'%ax',
+'%eax',
+'%rax',
+'%cl',
+'%ch',
+'%cx',
+'%ecx',
+'%rcx',
+'%dl',
+'%dh',
+'%dx',
+'%edx',
+'%rdx',
+'%bl',
+'%bh',
+'%bx',
+'%ebx',
+'%rbx',
+'%sil',
+'%si',
+'%esi',
+'%rsi',
+'%dil',
+'%di',
+'%edi',
+'%rdi',
+'%bpl',
+'%bp',
+'%ebp',
+'%rbp',
+'%spl',
+'%sp',
+'%esp',
+'%rsp',
+'%r8',
+'%r8b',
+'%r8w',
+'%r8d',
+'%r9',
+'%r9b',
+'%r9w',
+'%r9d',
+'%r10',
+'%r10b',
+'%r10w',
+'%r10d',
+'%r11',
+'%r11b',
+'%r11w',
+'%r11d',
+'%r12',
+'%r12b',
+'%r12w',
+'%r12d',
+'%r13',
+'%r13b',
+'%r13w',
+'%r13d',
+'%r14',
+'%r14b',
+'%r14w',
+'%r14d',
+'%r15',
+'%r15b',
+'%r15w',
+'%r15d',
+'%rip',
+'%eip',
+'%cs',
+'%ds',
+'%es',
+'%ss',
+'%fs',
+'%gs',
+'%dr0',
+'%dr1',
+'%dr2',
+'%dr3',
+'%dr6',
+'%dr7',
+'%cr0',
+'%cr2',
+'%cr3',
+'%cr4',
+'%tr3',
+'%tr4',
+'%tr5',
+'%tr6',
+'%tr7',
+'%st(0)',
+'%st(1)',
+'%st(2)',
+'%st(3)',
+'%st(4)',
+'%st(5)',
+'%st(6)',
+'%st(7)',
+'%st',
+'%mm0',
+'%mm1',
+'%mm2',
+'%mm3',
+'%mm4',
+'%mm5',
+'%mm6',
+'%mm7',
+'%xmm0',
+'%xmm1',
+'%xmm2',
+'%xmm3',
+'%xmm4',
+'%xmm5',
+'%xmm6',
+'%xmm7',
+'%xmm8',
+'%xmm9',
+'%xmm10',
+'%xmm11',
+'%xmm12',
+'%xmm13',
+'%xmm14',
+'%xmm15'
diff --git a/compiler/x86_64/r8664con.inc b/compiler/x86_64/r8664con.inc
new file mode 100644
index 0000000000..ae6a0d28e3
--- /dev/null
+++ b/compiler/x86_64/r8664con.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+NR_NO = tregister($00000000);
+NR_AL = tregister($01010000);
+NR_AH = tregister($01020000);
+NR_AX = tregister($01030000);
+NR_EAX = tregister($01040000);
+NR_RAX = tregister($01050000);
+NR_CL = tregister($01010001);
+NR_CH = tregister($01020001);
+NR_CX = tregister($01030001);
+NR_ECX = tregister($01040001);
+NR_RCX = tregister($01050001);
+NR_DL = tregister($01010002);
+NR_DH = tregister($01020002);
+NR_DX = tregister($01030002);
+NR_EDX = tregister($01040002);
+NR_RDX = tregister($01050002);
+NR_BL = tregister($01010003);
+NR_BH = tregister($01020003);
+NR_BX = tregister($01030003);
+NR_EBX = tregister($01040003);
+NR_RBX = tregister($01050003);
+NR_SIL = tregister($01010004);
+NR_SI = tregister($01030004);
+NR_ESI = tregister($01040004);
+NR_RSI = tregister($01050004);
+NR_DIL = tregister($01010005);
+NR_DI = tregister($01030005);
+NR_EDI = tregister($01040005);
+NR_RDI = tregister($01050005);
+NR_BPL = tregister($01010006);
+NR_BP = tregister($01030006);
+NR_EBP = tregister($01040006);
+NR_RBP = tregister($01050006);
+NR_SPL = tregister($01010007);
+NR_SP = tregister($01030007);
+NR_ESP = tregister($01040007);
+NR_RSP = tregister($01050007);
+NR_R8 = tregister($01050008);
+NR_R8L = tregister($01010008);
+NR_R8W = tregister($01030008);
+NR_R8D = tregister($01040008);
+NR_R9 = tregister($01050009);
+NR_R9L = tregister($01010009);
+NR_R9W = tregister($01030009);
+NR_R9D = tregister($01040009);
+NR_R10 = tregister($0105000a);
+NR_R10L = tregister($0101000a);
+NR_R10W = tregister($0103000a);
+NR_R10D = tregister($0104000a);
+NR_R11 = tregister($0105000b);
+NR_R11L = tregister($0101000b);
+NR_R11W = tregister($0103000b);
+NR_R11D = tregister($0104000b);
+NR_R12 = tregister($0105000c);
+NR_R12L = tregister($0101000c);
+NR_R12W = tregister($0103000c);
+NR_R12D = tregister($0104000c);
+NR_R13 = tregister($0105000d);
+NR_R13L = tregister($0101000d);
+NR_R13W = tregister($0103000d);
+NR_R13D = tregister($0104000d);
+NR_R14 = tregister($0105000e);
+NR_R14L = tregister($0101000e);
+NR_R14W = tregister($0103000e);
+NR_R14D = tregister($0104000e);
+NR_R15 = tregister($0105000f);
+NR_R15L = tregister($0101000f);
+NR_R15W = tregister($0103000f);
+NR_R15D = tregister($0104000f);
+NR_RIP = tregister($05000000);
+NR_EIP = tregister($05000000);
+NR_CS = tregister($05000001);
+NR_DS = tregister($05000002);
+NR_ES = tregister($05000003);
+NR_SS = tregister($05000004);
+NR_FS = tregister($05000005);
+NR_GS = tregister($05000006);
+NR_DR0 = tregister($05000007);
+NR_DR1 = tregister($05000008);
+NR_DR2 = tregister($05000009);
+NR_DR3 = tregister($0500000a);
+NR_DR6 = tregister($0500000b);
+NR_DR7 = tregister($0500000c);
+NR_CR0 = tregister($0500000d);
+NR_CR2 = tregister($0500000e);
+NR_CR3 = tregister($0500000f);
+NR_CR4 = tregister($05000010);
+NR_TR3 = tregister($05000011);
+NR_TR4 = tregister($05000012);
+NR_TR5 = tregister($05000013);
+NR_TR6 = tregister($05000014);
+NR_TR7 = tregister($05000015);
+NR_ST0 = tregister($02000000);
+NR_ST1 = tregister($02000001);
+NR_ST2 = tregister($02000002);
+NR_ST3 = tregister($02000003);
+NR_ST4 = tregister($02000004);
+NR_ST5 = tregister($02000005);
+NR_ST6 = tregister($02000006);
+NR_ST7 = tregister($02000007);
+NR_ST = tregister($02000008);
+NR_MM0 = tregister($03000000);
+NR_MM1 = tregister($03000001);
+NR_MM2 = tregister($03000002);
+NR_MM3 = tregister($03000003);
+NR_MM4 = tregister($03000004);
+NR_MM5 = tregister($03000005);
+NR_MM6 = tregister($03000006);
+NR_MM7 = tregister($03000007);
+NR_XMM0 = tregister($04000000);
+NR_XMM1 = tregister($04000001);
+NR_XMM2 = tregister($04000002);
+NR_XMM3 = tregister($04000003);
+NR_XMM4 = tregister($04000004);
+NR_XMM5 = tregister($04000005);
+NR_XMM6 = tregister($04000006);
+NR_XMM7 = tregister($04000007);
+NR_XMM8 = tregister($04000008);
+NR_XMM9 = tregister($04000009);
+NR_XMM10 = tregister($0400000a);
+NR_XMM11 = tregister($0400000b);
+NR_XMM12 = tregister($0400000c);
+NR_XMM13 = tregister($0400000d);
+NR_XMM14 = tregister($0400000e);
+NR_XMM15 = tregister($0400000f);
diff --git a/compiler/x86_64/r8664dwrf.inc b/compiler/x86_64/r8664dwrf.inc
new file mode 100644
index 0000000000..27f736cb5c
--- /dev/null
+++ b/compiler/x86_64/r8664dwrf.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+-1,
+0,
+0,
+0,
+0,
+0,
+2,
+2,
+2,
+2,
+2,
+1,
+1,
+1,
+1,
+1,
+3,
+3,
+3,
+3,
+3,
+4,
+4,
+4,
+4,
+5,
+5,
+5,
+5,
+6,
+6,
+6,
+6,
+7,
+7,
+7,
+7,
+8,
+8,
+8,
+8,
+9,
+9,
+9,
+9,
+10,
+10,
+10,
+10,
+11,
+11,
+11,
+11,
+12,
+12,
+12,
+12,
+13,
+13,
+13,
+13,
+14,
+14,
+14,
+14,
+15,
+15,
+15,
+15,
+16,
+16,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+33,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32
diff --git a/compiler/x86_64/r8664int.inc b/compiler/x86_64/r8664int.inc
new file mode 100644
index 0000000000..55ea578074
--- /dev/null
+++ b/compiler/x86_64/r8664int.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'rax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'rcx',
+'dl',
+'dh',
+'dx',
+'edx',
+'rdx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'rbx',
+'sil',
+'si',
+'esi',
+'rsi',
+'dil',
+'di',
+'edi',
+'rdi',
+'bpl',
+'bp',
+'ebp',
+'rbp',
+'spl',
+'sp',
+'esp',
+'rsp',
+'r8',
+'r8b',
+'r8w',
+'r8d',
+'r9',
+'r9b',
+'r9w',
+'r9d',
+'r10',
+'r10b',
+'r10w',
+'r10d',
+'r11',
+'r11b',
+'r11w',
+'r11d',
+'r12',
+'r12b',
+'r12w',
+'r12d',
+'r13',
+'r13b',
+'r13w',
+'r13d',
+'r14',
+'r14b',
+'r14w',
+'r14d',
+'r15',
+'r15b',
+'r15w',
+'r15d',
+'rip',
+'eip',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st(0)',
+'st(1)',
+'st(2)',
+'st(3)',
+'st(4)',
+'st(5)',
+'st(6)',
+'st(7)',
+'st',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7',
+'xmm8',
+'xmm9',
+'xmm10',
+'xmm11',
+'xmm12',
+'xmm13',
+'xmm14',
+'xmm15'
diff --git a/compiler/x86_64/r8664iri.inc b/compiler/x86_64/r8664iri.inc
new file mode 100644
index 0000000000..2050f990fd
--- /dev/null
+++ b/compiler/x86_64/r8664iri.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
diff --git a/compiler/x86_64/r8664nor.inc b/compiler/x86_64/r8664nor.inc
new file mode 100644
index 0000000000..7b3502fb2e
--- /dev/null
+++ b/compiler/x86_64/r8664nor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from x86reg.dat }
+125
diff --git a/compiler/x86_64/r8664num.inc b/compiler/x86_64/r8664num.inc
new file mode 100644
index 0000000000..01e0b0dfa7
--- /dev/null
+++ b/compiler/x86_64/r8664num.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+tregister($00000000),
+tregister($01010000),
+tregister($01020000),
+tregister($01030000),
+tregister($01040000),
+tregister($01050000),
+tregister($01010001),
+tregister($01020001),
+tregister($01030001),
+tregister($01040001),
+tregister($01050001),
+tregister($01010002),
+tregister($01020002),
+tregister($01030002),
+tregister($01040002),
+tregister($01050002),
+tregister($01010003),
+tregister($01020003),
+tregister($01030003),
+tregister($01040003),
+tregister($01050003),
+tregister($01010004),
+tregister($01030004),
+tregister($01040004),
+tregister($01050004),
+tregister($01010005),
+tregister($01030005),
+tregister($01040005),
+tregister($01050005),
+tregister($01010006),
+tregister($01030006),
+tregister($01040006),
+tregister($01050006),
+tregister($01010007),
+tregister($01030007),
+tregister($01040007),
+tregister($01050007),
+tregister($01050008),
+tregister($01010008),
+tregister($01030008),
+tregister($01040008),
+tregister($01050009),
+tregister($01010009),
+tregister($01030009),
+tregister($01040009),
+tregister($0105000a),
+tregister($0101000a),
+tregister($0103000a),
+tregister($0104000a),
+tregister($0105000b),
+tregister($0101000b),
+tregister($0103000b),
+tregister($0104000b),
+tregister($0105000c),
+tregister($0101000c),
+tregister($0103000c),
+tregister($0104000c),
+tregister($0105000d),
+tregister($0101000d),
+tregister($0103000d),
+tregister($0104000d),
+tregister($0105000e),
+tregister($0101000e),
+tregister($0103000e),
+tregister($0104000e),
+tregister($0105000f),
+tregister($0101000f),
+tregister($0103000f),
+tregister($0104000f),
+tregister($05000000),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c),
+tregister($0500000d),
+tregister($0500000e),
+tregister($0500000f),
+tregister($05000010),
+tregister($05000011),
+tregister($05000012),
+tregister($05000013),
+tregister($05000014),
+tregister($05000015),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($04000000),
+tregister($04000001),
+tregister($04000002),
+tregister($04000003),
+tregister($04000004),
+tregister($04000005),
+tregister($04000006),
+tregister($04000007),
+tregister($04000008),
+tregister($04000009),
+tregister($0400000a),
+tregister($0400000b),
+tregister($0400000c),
+tregister($0400000d),
+tregister($0400000e),
+tregister($0400000f)
diff --git a/compiler/x86_64/r8664op.inc b/compiler/x86_64/r8664op.inc
new file mode 100644
index 0000000000..61f5df7ba9
--- /dev/null
+++ b/compiler/x86_64/r8664op.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+0,
+4,
+0,
+0,
+0,
+1,
+5,
+1,
+1,
+1,
+2,
+6,
+2,
+2,
+2,
+3,
+7,
+3,
+3,
+3,
+6,
+6,
+6,
+6,
+7,
+7,
+7,
+7,
+5,
+5,
+5,
+5,
+4,
+4,
+4,
+4,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+1,
+3,
+0,
+2,
+4,
+5,
+0,
+1,
+2,
+3,
+6,
+7,
+0,
+2,
+3,
+4,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7
diff --git a/compiler/x86_64/r8664ot.inc b/compiler/x86_64/r8664ot.inc
new file mode 100644
index 0000000000..7db67465fe
--- /dev/null
+++ b/compiler/x86_64/r8664ot.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+OT_NONE,
+OT_REG_AL,
+OT_REG8,
+OT_REG_AX,
+OT_REG_EAX,
+OT_REG_RAX,
+OT_REG_CL,
+OT_REG8,
+OT_REG_CX,
+OT_REG_ECX,
+OT_REG_RCX,
+OT_REG8,
+OT_REG8,
+OT_REG_DX,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_NONE,
+OT_NONE,
+OT_REG_CS,
+OT_REG_DESS,
+OT_REG_DESS,
+OT_REG_DESS,
+OT_REG_FSGS,
+OT_REG_FSGS,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_CREG,
+OT_REG_CREG,
+OT_REG_CREG,
+OT_REG_CR4,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_FPU0,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPU0,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG
diff --git a/compiler/x86_64/r8664rni.inc b/compiler/x86_64/r8664rni.inc
new file mode 100644
index 0000000000..3ab0a735ab
--- /dev/null
+++ b/compiler/x86_64/r8664rni.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+1,
+6,
+11,
+16,
+21,
+25,
+29,
+33,
+38,
+42,
+46,
+50,
+54,
+58,
+62,
+66,
+2,
+7,
+12,
+17,
+3,
+8,
+13,
+18,
+22,
+26,
+30,
+34,
+39,
+43,
+47,
+51,
+55,
+59,
+63,
+67,
+4,
+9,
+14,
+19,
+23,
+27,
+31,
+35,
+40,
+44,
+48,
+52,
+56,
+60,
+64,
+68,
+5,
+10,
+15,
+20,
+24,
+28,
+32,
+36,
+37,
+41,
+45,
+49,
+53,
+57,
+61,
+65,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+109,
+110,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118,
+119,
+120,
+121,
+122,
+123,
+124,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90,
+91
diff --git a/compiler/x86_64/r8664sri.inc b/compiler/x86_64/r8664sri.inc
new file mode 100644
index 0000000000..67d9df19f9
--- /dev/null
+++ b/compiler/x86_64/r8664sri.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+2,
+1,
+3,
+17,
+16,
+30,
+29,
+18,
+7,
+6,
+83,
+84,
+85,
+86,
+71,
+8,
+12,
+26,
+25,
+11,
+77,
+78,
+79,
+80,
+81,
+82,
+72,
+13,
+4,
+31,
+19,
+9,
+27,
+14,
+70,
+73,
+23,
+35,
+75,
+76,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+45,
+46,
+48,
+47,
+49,
+50,
+52,
+51,
+53,
+54,
+56,
+55,
+57,
+58,
+60,
+59,
+61,
+62,
+64,
+63,
+65,
+66,
+68,
+67,
+37,
+38,
+40,
+39,
+41,
+42,
+44,
+43,
+5,
+32,
+20,
+10,
+28,
+15,
+69,
+24,
+36,
+22,
+21,
+34,
+33,
+74,
+100,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+87,
+88,
+89,
+90,
+91,
+109,
+110,
+119,
+120,
+121,
+122,
+123,
+124,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118
diff --git a/compiler/x86_64/r8664stab.inc b/compiler/x86_64/r8664stab.inc
new file mode 100644
index 0000000000..d487a36364
--- /dev/null
+++ b/compiler/x86_64/r8664stab.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+-1,
+0,
+0,
+0,
+0,
+0,
+1,
+1,
+1,
+1,
+1,
+2,
+2,
+2,
+2,
+2,
+3,
+3,
+3,
+3,
+3,
+6,
+6,
+6,
+6,
+7,
+7,
+7,
+7,
+5,
+5,
+5,
+5,
+4,
+4,
+4,
+4,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+12,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1
diff --git a/compiler/x86_64/r8664std.inc b/compiler/x86_64/r8664std.inc
new file mode 100644
index 0000000000..55ea578074
--- /dev/null
+++ b/compiler/x86_64/r8664std.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'rax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'rcx',
+'dl',
+'dh',
+'dx',
+'edx',
+'rdx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'rbx',
+'sil',
+'si',
+'esi',
+'rsi',
+'dil',
+'di',
+'edi',
+'rdi',
+'bpl',
+'bp',
+'ebp',
+'rbp',
+'spl',
+'sp',
+'esp',
+'rsp',
+'r8',
+'r8b',
+'r8w',
+'r8d',
+'r9',
+'r9b',
+'r9w',
+'r9d',
+'r10',
+'r10b',
+'r10w',
+'r10d',
+'r11',
+'r11b',
+'r11w',
+'r11d',
+'r12',
+'r12b',
+'r12w',
+'r12d',
+'r13',
+'r13b',
+'r13w',
+'r13d',
+'r14',
+'r14b',
+'r14w',
+'r14d',
+'r15',
+'r15b',
+'r15w',
+'r15d',
+'rip',
+'eip',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st(0)',
+'st(1)',
+'st(2)',
+'st(3)',
+'st(4)',
+'st(5)',
+'st(6)',
+'st(7)',
+'st',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7',
+'xmm8',
+'xmm9',
+'xmm10',
+'xmm11',
+'xmm12',
+'xmm13',
+'xmm14',
+'xmm15'
diff --git a/compiler/x86_64/rax64att.pas b/compiler/x86_64/rax64att.pas
new file mode 100644
index 0000000000..93247e0bd8
--- /dev/null
+++ b/compiler/x86_64/rax64att.pas
@@ -0,0 +1,69 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the i386 GNU AS styled inline assembler.
+
+ 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 rax64att;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ rax86att;
+
+ type
+ tx8664attreader = class(tx86attreader)
+ procedure handleopcode;override;
+ end;
+
+
+ implementation
+
+ uses
+ rabase,systems,rax86,aasmcpu;
+
+ procedure tx8664attreader.handleopcode;
+ var
+ instr : Tx86Instruction;
+ begin
+ instr:=Tx86Instruction.Create(Tx86Operand);
+ instr.OpOrder:=op_att;
+ BuildOpcode(instr);
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ {
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+
+const
+ asmmode_x86_64_gas_info : tasmmodeinfo =
+ (
+ id : asmmode_x86_64_gas;
+ idtxt : 'GAS';
+ casmreader : tx8664attreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_x86_64_gas_info);
+end.
diff --git a/compiler/x86_64/rgcpu.pas b/compiler/x86_64/rgcpu.pas
new file mode 100644
index 0000000000..2198759ecb
--- /dev/null
+++ b/compiler/x86_64/rgcpu.pas
@@ -0,0 +1,53 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the x86-64 specific class for the register
+ allocator
+
+ 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 rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase,rgx86;
+
+ type
+ trgcpu = class(trgx86)
+ procedure add_constraints(reg:Tregister);
+ end;
+
+ implementation
+
+ uses
+ cpubase;
+
+ procedure trgcpu.add_constraints(reg:Tregister);
+ var
+ supreg : tsuperregister;
+ begin
+ supreg:=getsupreg(reg);
+ { All registers conflict with rsp/rbp }
+ add_edge(supreg,RS_RSP);
+ add_edge(supreg,RS_RBP);
+ end;
+
+end.
diff --git a/compiler/x86_64/x8664ats.inc b/compiler/x86_64/x8664ats.inc
new file mode 100644
index 0000000000..b6584499f8
--- /dev/null
+++ b/compiler/x86_64/x8664ats.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufNONE,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufFPU,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufINT,
+attsufNONE,
+attsufFPU,
+attsufINT,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE
+);
diff --git a/compiler/x86_64/x8664att.inc b/compiler/x86_64/x8664att.inc
new file mode 100644
index 0000000000..895be5db74
--- /dev/null
+++ b/compiler/x86_64/x8664att.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+'none',
+'aaa',
+'aad',
+'aam',
+'aas',
+'adc',
+'add',
+'and',
+'arpl',
+'bound',
+'bsf',
+'bsr',
+'bswap',
+'bt',
+'btc',
+'btr',
+'bts',
+'call',
+'cbtw',
+'cltd',
+'clc',
+'cld',
+'cli',
+'clts',
+'cmc',
+'cmp',
+'cmpsb',
+'cmpsl',
+'cmpsw',
+'cmpxchg',
+'cmpxchg486',
+'cmpxchg8b',
+'cpuid',
+'cwd',
+'cwtl',
+'daa',
+'das',
+'dec',
+'div',
+'emms',
+'enter',
+'f2xm1',
+'fabs',
+'fadd',
+'faddp',
+'fbld',
+'fbstp',
+'fchs',
+'fclex',
+'fcmovb',
+'fcmovbe',
+'fcmove',
+'fcmovnb',
+'fcmovnbe',
+'fcmovne',
+'fcmovnu',
+'fcmovu',
+'fcom',
+'fcomi',
+'fcomip',
+'fcomp',
+'fcompp',
+'fcos',
+'fdecstp',
+'fdisi',
+'fdiv',
+'fdivp',
+'fdivr',
+'fdivrp',
+'femms',
+'feni',
+'ffree',
+'fiadd',
+'ficom',
+'ficomp',
+'fidiv',
+'fidivr',
+'fild',
+'fimul',
+'fincstp',
+'finit',
+'fist',
+'fistp',
+'fisttp',
+'fisub',
+'fisubr',
+'fld',
+'fld1',
+'fldcw',
+'fldenv',
+'fldl2e',
+'fldl2t',
+'fldlg2',
+'fldln2',
+'fldpi',
+'fldz',
+'fmul',
+'fmulp',
+'fnclex',
+'fndisi',
+'fneni',
+'fninit',
+'fnop',
+'fnsave',
+'fnstcw',
+'fnstenv',
+'fnstsw',
+'fpatan',
+'fprem',
+'fprem1',
+'fptan',
+'frndint',
+'frstor',
+'fsave',
+'fscale',
+'fsetpm',
+'fsin',
+'fsincos',
+'fsqrt',
+'fst',
+'fstcw',
+'fstenv',
+'fstp',
+'fstsw',
+'fsub',
+'fsubp',
+'fsubr',
+'fsubrp',
+'ftst',
+'fucom',
+'fucomi',
+'fucomip',
+'fucomp',
+'fucompp',
+'fwait',
+'fxam',
+'fxch',
+'fxtract',
+'fyl2x',
+'fyl2xp1',
+'hlt',
+'ibts',
+'icebp',
+'idiv',
+'imul',
+'in',
+'inc',
+'insb',
+'insl',
+'insw',
+'int',
+'int01',
+'int1',
+'int03',
+'int3',
+'into',
+'invd',
+'invlpg',
+'iret',
+'iret',
+'iretw',
+'jcxz',
+'jecxz',
+'jmp',
+'lahf',
+'lar',
+'lcall',
+'lds',
+'lea',
+'leave',
+'les',
+'lfs',
+'lgdt',
+'lgs',
+'lidt',
+'ljmp',
+'lldt',
+'lmsw',
+'loadall',
+'loadall286',
+'lock',
+'lodsb',
+'lodsl',
+'lodsw',
+'loop',
+'loope',
+'loopne',
+'loopnz',
+'loopz',
+'lsl',
+'lss',
+'ltr',
+'monitor',
+'mov',
+'movd',
+'movq',
+'movsb',
+'movsl',
+'movsq',
+'movsw',
+'movs',
+'movz',
+'mul',
+'mwait',
+'neg',
+'nop',
+'not',
+'or',
+'out',
+'outsb',
+'outsl',
+'outsw',
+'packssdw',
+'packsswb',
+'packuswb',
+'paddb',
+'paddd',
+'paddsb',
+'paddsiw',
+'paddsw',
+'paddusb',
+'paddusw',
+'paddw',
+'pand',
+'pandn',
+'paveb',
+'pavgusb',
+'pcmpeqb',
+'pcmpeqd',
+'pcmpeqw',
+'pcmpgtb',
+'pcmpgtd',
+'pcmpgtw',
+'pdistib',
+'pf2id',
+'pfacc',
+'pfadd',
+'pfcmpeq',
+'pfcmpge',
+'pfcmpgt',
+'pfmax',
+'pfmin',
+'pfmul',
+'pfrcp',
+'pfrcpit1',
+'pfrcpit2',
+'pfrsqit1',
+'pfrsqrt',
+'pfsub',
+'pfsubr',
+'pi2fd',
+'pmachriw',
+'pmaddwd',
+'pmagw',
+'pmulhriw',
+'pmulhrwa',
+'pmulhrwc',
+'pmulhw',
+'pmullw',
+'pmvgezb',
+'pmvlzb',
+'pmvnzb',
+'pmvzb',
+'pop',
+'popa',
+'popal',
+'popaw',
+'popf',
+'popfl',
+'popfw',
+'por',
+'prefetch',
+'prefetchw',
+'pslld',
+'pslldq',
+'psllq',
+'psllw',
+'psrad',
+'psraw',
+'psrld',
+'psrlq',
+'psrlw',
+'psubb',
+'psubd',
+'psubsb',
+'psubsiw',
+'psubsw',
+'psubusb',
+'psubusw',
+'psubw',
+'punpckhbw',
+'punpckhdq',
+'punpckhwd',
+'punpcklbw',
+'punpckldq',
+'punpcklwd',
+'push',
+'pusha',
+'pushal',
+'pushaw',
+'pushf',
+'pushfl',
+'pushfw',
+'pxor',
+'rcl',
+'rcr',
+'rdshr',
+'rdmsr',
+'rdpmc',
+'rdtsc',
+'rep',
+'repe',
+'repne',
+'repnz',
+'repz',
+'ret',
+'lret',
+'ret',
+'rol',
+'ror',
+'rsdc',
+'rsldt',
+'rsm',
+'sahf',
+'sal',
+'salc',
+'sar',
+'sbb',
+'scasb',
+'scasl',
+'scasw',
+'cs',
+'ds',
+'es',
+'fs',
+'gs',
+'ss',
+'sgdt',
+'shl',
+'shld',
+'shr',
+'shrd',
+'sidt',
+'sldt',
+'smi',
+'smint',
+'smintold',
+'smsw',
+'stc',
+'std',
+'sti',
+'stosb',
+'stosl',
+'stosw',
+'str',
+'sub',
+'svdc',
+'svldt',
+'svts',
+'syscall',
+'sysenter',
+'sysexit',
+'sysret',
+'test',
+'ud1',
+'ud2',
+'umov',
+'verr',
+'verw',
+'wait',
+'wbinvd',
+'wrshr',
+'wrmsr',
+'xadd',
+'xbts',
+'xchg',
+'xlat',
+'xlatb',
+'xor',
+'xstore',
+'cmov',
+'j',
+'set',
+'addps',
+'addss',
+'andnps',
+'andps',
+'cmpeqps',
+'cmpeqss',
+'cmpleps',
+'cmpless',
+'cmpltps',
+'cmpltss',
+'cmpneqps',
+'cmpneqss',
+'cmpnleps',
+'cmpnless',
+'cmpnltps',
+'cmpnltss',
+'cmpordps',
+'cmpordss',
+'cmpunordps',
+'cmpunordss',
+'cmpps',
+'cmpss',
+'comiss',
+'cvtpi2ps',
+'cvtps2pi',
+'cvtsi2ss',
+'cvtss2si',
+'cvttps2pi',
+'cvttss2si',
+'divps',
+'divss',
+'ldmxcsr',
+'maxps',
+'maxss',
+'minps',
+'minss',
+'movaps',
+'movhps',
+'movlhps',
+'movlps',
+'movhlps',
+'movmskps',
+'movntps',
+'movss',
+'movups',
+'mulps',
+'mulss',
+'orps',
+'rcpps',
+'rcpss',
+'rsqrtps',
+'rsqrtss',
+'shufps',
+'sqrtps',
+'sqrtss',
+'stmxcsr',
+'subps',
+'subss',
+'ucomiss',
+'unpckhps',
+'unpcklps',
+'xorps',
+'fxrstor',
+'fxsave',
+'prefetchnta',
+'prefetcht0',
+'prefetcht1',
+'prefetcht2',
+'sfence',
+'maskmovq',
+'movntq',
+'pavgb',
+'pavgw',
+'pextrw',
+'pinsrw',
+'pmaxsw',
+'pmaxub',
+'pminsw',
+'pminub',
+'pmovmskb',
+'pmulhuw',
+'psadbw',
+'pshufw',
+'pfnacc',
+'pfpnacc',
+'pi2fw',
+'pf2iw',
+'pswapd',
+'ffreep',
+'maskmovdqu',
+'clflush',
+'movntdq',
+'movnti',
+'movntpd',
+'pause',
+'lfence',
+'mfence',
+'movdqa',
+'movdqu',
+'movdq2q',
+'movq2dq',
+'paddq',
+'pmuludq',
+'pshufd',
+'pshufhw',
+'pshuflw',
+'psrldq',
+'psubq',
+'punpckhqdq',
+'punpcklqdq',
+'addpd',
+'addsd',
+'andnpd',
+'andpd',
+'cmpeqpd',
+'cmpeqsd',
+'cmplepd',
+'cmplesd',
+'cmpltpd',
+'cmpltsd',
+'cmpneqpd',
+'cmpnlepd',
+'cmpnlesd',
+'cmpnltpd',
+'cmpnltsd',
+'cmpordpd',
+'cmpordsd',
+'cmpunordpd',
+'cmpunordsd',
+'cmppd',
+'comisd',
+'cvtdq2pd',
+'cvtdq2ps',
+'cvtpd2dq',
+'cvtpd2pi',
+'cvtpd2ps',
+'cvtpi2pd',
+'cvtps2dq',
+'cvtps2pd',
+'cvtsd2si',
+'cvtsd2ss',
+'cvtsi2sd',
+'cvtss2sd',
+'cvttpd2pi',
+'cvttpd2dq',
+'cvttps2dq',
+'cvttsd2si',
+'divpd',
+'divsd',
+'maxpd',
+'maxsd',
+'minpd',
+'minsd',
+'movapd',
+'movhpd',
+'movlpd',
+'movmskpd',
+'movupd',
+'mulpd',
+'mulsd',
+'orpd',
+'shufpd',
+'sqrtpd',
+'sqrtsd',
+'subpd',
+'subsd',
+'ucomisd',
+'unpckhpd',
+'unpcklpd',
+'xorpd',
+'addsubpd',
+'addsubps',
+'haddpd',
+'haddps',
+'hsubpd',
+'hsubps',
+'lddqu',
+'movddup',
+'movshdup',
+'movsldup',
+'movabs',
+'movslq',
+'cqto'
+);
diff --git a/compiler/x86_64/x8664int.inc b/compiler/x86_64/x8664int.inc
new file mode 100644
index 0000000000..428a64f8cf
--- /dev/null
+++ b/compiler/x86_64/x8664int.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+'none',
+'aaa',
+'aad',
+'aam',
+'aas',
+'adc',
+'add',
+'and',
+'arpl',
+'bound',
+'bsf',
+'bsr',
+'bswap',
+'bt',
+'btc',
+'btr',
+'bts',
+'call',
+'cbw',
+'cdq',
+'clc',
+'cld',
+'cli',
+'clts',
+'cmc',
+'cmp',
+'cmpsb',
+'cmpsd',
+'cmpsw',
+'cmpxchg',
+'cmpxchg486',
+'cmpxchg8b',
+'cpuid',
+'cwd',
+'cwde',
+'daa',
+'das',
+'dec',
+'div',
+'emms',
+'enter',
+'f2xm1',
+'fabs',
+'fadd',
+'faddp',
+'fbld',
+'fbstp',
+'fchs',
+'fclex',
+'fcmovb',
+'fcmovbe',
+'fcmove',
+'fcmovnb',
+'fcmovnbe',
+'fcmovne',
+'fcmovnu',
+'fcmovu',
+'fcom',
+'fcomi',
+'fcomip',
+'fcomp',
+'fcompp',
+'fcos',
+'fdecstp',
+'fdisi',
+'fdiv',
+'fdivp',
+'fdivr',
+'fdivrp',
+'femms',
+'feni',
+'ffree',
+'fiadd',
+'ficom',
+'ficomp',
+'fidiv',
+'fidivr',
+'fild',
+'fimul',
+'fincstp',
+'finit',
+'fist',
+'fistp',
+'fisttp',
+'fisub',
+'fisubr',
+'fld',
+'fld1',
+'fldcw',
+'fldenv',
+'fldl2e',
+'fldl2t',
+'fldlg2',
+'fldln2',
+'fldpi',
+'fldz',
+'fmul',
+'fmulp',
+'fnclex',
+'fndisi',
+'fneni',
+'fninit',
+'fnop',
+'fnsave',
+'fnstcw',
+'fnstenv',
+'fnstsw',
+'fpatan',
+'fprem',
+'fprem1',
+'fptan',
+'frndint',
+'frstor',
+'fsave',
+'fscale',
+'fsetpm',
+'fsin',
+'fsincos',
+'fsqrt',
+'fst',
+'fstcw',
+'fstenv',
+'fstp',
+'fstsw',
+'fsub',
+'fsubp',
+'fsubr',
+'fsubrp',
+'ftst',
+'fucom',
+'fucomi',
+'fucomip',
+'fucomp',
+'fucompp',
+'fwait',
+'fxam',
+'fxch',
+'fxtract',
+'fyl2x',
+'fyl2xp1',
+'hlt',
+'ibts',
+'icebp',
+'idiv',
+'imul',
+'in',
+'inc',
+'insb',
+'insd',
+'insw',
+'int',
+'int01',
+'int1',
+'int03',
+'int3',
+'into',
+'invd',
+'invlpg',
+'iret',
+'iretd',
+'iretw',
+'jcxz',
+'jecxz',
+'jmp',
+'lahf',
+'lar',
+'lcall',
+'lds',
+'lea',
+'leave',
+'les',
+'lfs',
+'lgdt',
+'lgs',
+'lidt',
+'ljmp',
+'lldt',
+'lmsw',
+'loadall',
+'loadall286',
+'lock',
+'lodsb',
+'lodsd',
+'lodsw',
+'loop',
+'loope',
+'loopne',
+'loopnz',
+'loopz',
+'lsl',
+'lss',
+'ltr',
+'monitor',
+'mov',
+'movd',
+'movq',
+'movsb',
+'movsd',
+'movsq',
+'movsw',
+'movsx',
+'movzx',
+'mul',
+'mwait',
+'neg',
+'nop',
+'not',
+'or',
+'out',
+'outsb',
+'outsd',
+'outsw',
+'packssdw',
+'packsswb',
+'packuswb',
+'paddb',
+'paddd',
+'paddsb',
+'paddsiw',
+'paddsw',
+'paddusb',
+'paddusw',
+'paddw',
+'pand',
+'pandn',
+'paveb',
+'pavgusb',
+'pcmpeqb',
+'pcmpeqd',
+'pcmpeqw',
+'pcmpgtb',
+'pcmpgtd',
+'pcmpgtw',
+'pdistib',
+'pf2id',
+'pfacc',
+'pfadd',
+'pfcmpeq',
+'pfcmpge',
+'pfcmpgt',
+'pfmax',
+'pfmin',
+'pfmul',
+'pfrcp',
+'pfrcpit1',
+'pfrcpit2',
+'pfrsqit1',
+'pfrsqrt',
+'pfsub',
+'pfsubr',
+'pi2fd',
+'pmachriw',
+'pmaddwd',
+'pmagw',
+'pmulhriw',
+'pmulhrwa',
+'pmulhrwc',
+'pmulhw',
+'pmullw',
+'pmvgezb',
+'pmvlzb',
+'pmvnzb',
+'pmvzb',
+'pop',
+'popa',
+'popad',
+'popaw',
+'popf',
+'popfd',
+'popfw',
+'por',
+'prefetch',
+'prefetchw',
+'pslld',
+'pslldq',
+'psllq',
+'psllw',
+'psrad',
+'psraw',
+'psrld',
+'psrlq',
+'psrlw',
+'psubb',
+'psubd',
+'psubsb',
+'psubsiw',
+'psubsw',
+'psubusb',
+'psubusw',
+'psubw',
+'punpckhbw',
+'punpckhdq',
+'punpckhwd',
+'punpcklbw',
+'punpckldq',
+'punpcklwd',
+'push',
+'pusha',
+'pushad',
+'pushaw',
+'pushf',
+'pushfd',
+'pushfw',
+'pxor',
+'rcl',
+'rcr',
+'rdshr',
+'rdmsr',
+'rdpmc',
+'rdtsc',
+'rep',
+'repe',
+'repne',
+'repnz',
+'repz',
+'ret',
+'retf',
+'retn',
+'rol',
+'ror',
+'rsdc',
+'rsldt',
+'rsm',
+'sahf',
+'sal',
+'salc',
+'sar',
+'sbb',
+'scasb',
+'scasd',
+'scasw',
+'segcs',
+'segds',
+'seges',
+'segfs',
+'seggs',
+'segss',
+'sgdt',
+'shl',
+'shld',
+'shr',
+'shrd',
+'sidt',
+'sldt',
+'smi',
+'smint',
+'smintold',
+'smsw',
+'stc',
+'std',
+'sti',
+'stosb',
+'stosd',
+'stosw',
+'str',
+'sub',
+'svdc',
+'svldt',
+'svts',
+'syscall',
+'sysenter',
+'sysexit',
+'sysret',
+'test',
+'ud1',
+'ud2',
+'umov',
+'verr',
+'verw',
+'wait',
+'wbinvd',
+'wrshr',
+'wrmsr',
+'xadd',
+'xbts',
+'xchg',
+'xlat',
+'xlatb',
+'xor',
+'xstore',
+'cmov',
+'j',
+'set',
+'addps',
+'addss',
+'andnps',
+'andps',
+'cmpeqps',
+'cmpeqss',
+'cmpleps',
+'cmpless',
+'cmpltps',
+'cmpltss',
+'cmpneqps',
+'cmpneqss',
+'cmpnleps',
+'cmpnless',
+'cmpnltps',
+'cmpnltss',
+'cmpordps',
+'cmpordss',
+'cmpunordps',
+'cmpunordss',
+'cmpps',
+'cmpss',
+'comiss',
+'cvtpi2ps',
+'cvtps2pi',
+'cvtsi2ss',
+'cvtss2si',
+'cvttps2pi',
+'cvttss2si',
+'divps',
+'divss',
+'ldmxcsr',
+'maxps',
+'maxss',
+'minps',
+'minss',
+'movaps',
+'movhps',
+'movlhps',
+'movlps',
+'movhlps',
+'movmskps',
+'movntps',
+'movss',
+'movups',
+'mulps',
+'mulss',
+'orps',
+'rcpps',
+'rcpss',
+'rsqrtps',
+'rsqrtss',
+'shufps',
+'sqrtps',
+'sqrtss',
+'stmxcsr',
+'subps',
+'subss',
+'ucomiss',
+'unpckhps',
+'unpcklps',
+'xorps',
+'fxrstor',
+'fxsave',
+'prefetchnta',
+'prefetcht0',
+'prefetcht1',
+'prefetcht2',
+'sfence',
+'maskmovq',
+'movntq',
+'pavgb',
+'pavgw',
+'pextrw',
+'pinsrw',
+'pmaxsw',
+'pmaxub',
+'pminsw',
+'pminub',
+'pmovmskb',
+'pmulhuw',
+'psadbw',
+'pshufw',
+'pfnacc',
+'pfpnacc',
+'pi2fw',
+'pf2iw',
+'pswapd',
+'ffreep',
+'maskmovdqu',
+'clflush',
+'movntdq',
+'movnti',
+'movntpd',
+'pause',
+'lfence',
+'mfence',
+'movdqa',
+'movdqu',
+'movdq2q',
+'movq2dq',
+'paddq',
+'pmuludq',
+'pshufd',
+'pshufhw',
+'pshuflw',
+'psrldq',
+'psubq',
+'punpckhqdq',
+'punpcklqdq',
+'addpd',
+'addsd',
+'andnpd',
+'andpd',
+'cmpeqpd',
+'cmpeqsd',
+'cmplepd',
+'cmplesd',
+'cmpltpd',
+'cmpltsd',
+'cmpneqpd',
+'cmpnlepd',
+'cmpnlesd',
+'cmpnltpd',
+'cmpnltsd',
+'cmpordpd',
+'cmpordsd',
+'cmpunordpd',
+'cmpunordsd',
+'cmppd',
+'comisd',
+'cvtdq2pd',
+'cvtdq2ps',
+'cvtpd2dq',
+'cvtpd2pi',
+'cvtpd2ps',
+'cvtpi2pd',
+'cvtps2dq',
+'cvtps2pd',
+'cvtsd2si',
+'cvtsd2ss',
+'cvtsi2sd',
+'cvtss2sd',
+'cvttpd2pi',
+'cvttpd2dq',
+'cvttps2dq',
+'cvttsd2si',
+'divpd',
+'divsd',
+'maxpd',
+'maxsd',
+'minpd',
+'minsd',
+'movapd',
+'movhpd',
+'movlpd',
+'movmskpd',
+'movupd',
+'mulpd',
+'mulsd',
+'orpd',
+'shufpd',
+'sqrtpd',
+'sqrtsd',
+'subpd',
+'subsd',
+'ucomisd',
+'unpckhpd',
+'unpcklpd',
+'xorpd',
+'addsubpd',
+'addsubps',
+'haddpd',
+'haddps',
+'hsubpd',
+'hsubps',
+'lddqu',
+'movddup',
+'movshdup',
+'movsldup',
+'movabs',
+'movsxd',
+'cqo'
+);
diff --git a/compiler/x86_64/x8664nop.inc b/compiler/x86_64/x8664nop.inc
new file mode 100644
index 0000000000..abfe89b2fb
--- /dev/null
+++ b/compiler/x86_64/x8664nop.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from x86ins.dat }
+1640;
diff --git a/compiler/x86_64/x8664op.inc b/compiler/x86_64/x8664op.inc
new file mode 100644
index 0000000000..4c011681b0
--- /dev/null
+++ b/compiler/x86_64/x8664op.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+A_NONE,
+A_AAA,
+A_AAD,
+A_AAM,
+A_AAS,
+A_ADC,
+A_ADD,
+A_AND,
+A_ARPL,
+A_BOUND,
+A_BSF,
+A_BSR,
+A_BSWAP,
+A_BT,
+A_BTC,
+A_BTR,
+A_BTS,
+A_CALL,
+A_CBW,
+A_CDQ,
+A_CLC,
+A_CLD,
+A_CLI,
+A_CLTS,
+A_CMC,
+A_CMP,
+A_CMPSB,
+A_CMPSD,
+A_CMPSW,
+A_CMPXCHG,
+A_CMPXCHG486,
+A_CMPXCHG8B,
+A_CPUID,
+A_CWD,
+A_CWDE,
+A_DAA,
+A_DAS,
+A_DEC,
+A_DIV,
+A_EMMS,
+A_ENTER,
+A_F2XM1,
+A_FABS,
+A_FADD,
+A_FADDP,
+A_FBLD,
+A_FBSTP,
+A_FCHS,
+A_FCLEX,
+A_FCMOVB,
+A_FCMOVBE,
+A_FCMOVE,
+A_FCMOVNB,
+A_FCMOVNBE,
+A_FCMOVNE,
+A_FCMOVNU,
+A_FCMOVU,
+A_FCOM,
+A_FCOMI,
+A_FCOMIP,
+A_FCOMP,
+A_FCOMPP,
+A_FCOS,
+A_FDECSTP,
+A_FDISI,
+A_FDIV,
+A_FDIVP,
+A_FDIVR,
+A_FDIVRP,
+A_FEMMS,
+A_FENI,
+A_FFREE,
+A_FIADD,
+A_FICOM,
+A_FICOMP,
+A_FIDIV,
+A_FIDIVR,
+A_FILD,
+A_FIMUL,
+A_FINCSTP,
+A_FINIT,
+A_FIST,
+A_FISTP,
+A_FISTTP,
+A_FISUB,
+A_FISUBR,
+A_FLD,
+A_FLD1,
+A_FLDCW,
+A_FLDENV,
+A_FLDL2E,
+A_FLDL2T,
+A_FLDLG2,
+A_FLDLN2,
+A_FLDPI,
+A_FLDZ,
+A_FMUL,
+A_FMULP,
+A_FNCLEX,
+A_FNDISI,
+A_FNENI,
+A_FNINIT,
+A_FNOP,
+A_FNSAVE,
+A_FNSTCW,
+A_FNSTENV,
+A_FNSTSW,
+A_FPATAN,
+A_FPREM,
+A_FPREM1,
+A_FPTAN,
+A_FRNDINT,
+A_FRSTOR,
+A_FSAVE,
+A_FSCALE,
+A_FSETPM,
+A_FSIN,
+A_FSINCOS,
+A_FSQRT,
+A_FST,
+A_FSTCW,
+A_FSTENV,
+A_FSTP,
+A_FSTSW,
+A_FSUB,
+A_FSUBP,
+A_FSUBR,
+A_FSUBRP,
+A_FTST,
+A_FUCOM,
+A_FUCOMI,
+A_FUCOMIP,
+A_FUCOMP,
+A_FUCOMPP,
+A_FWAIT,
+A_FXAM,
+A_FXCH,
+A_FXTRACT,
+A_FYL2X,
+A_FYL2XP1,
+A_HLT,
+A_IBTS,
+A_ICEBP,
+A_IDIV,
+A_IMUL,
+A_IN,
+A_INC,
+A_INSB,
+A_INSD,
+A_INSW,
+A_INT,
+A_INT01,
+A_INT1,
+A_INT03,
+A_INT3,
+A_INTO,
+A_INVD,
+A_INVLPG,
+A_IRET,
+A_IRETD,
+A_IRETW,
+A_JCXZ,
+A_JECXZ,
+A_JMP,
+A_LAHF,
+A_LAR,
+A_LCALL,
+A_LDS,
+A_LEA,
+A_LEAVE,
+A_LES,
+A_LFS,
+A_LGDT,
+A_LGS,
+A_LIDT,
+A_LJMP,
+A_LLDT,
+A_LMSW,
+A_LOADALL,
+A_LOADALL286,
+A_LOCK,
+A_LODSB,
+A_LODSD,
+A_LODSW,
+A_LOOP,
+A_LOOPE,
+A_LOOPNE,
+A_LOOPNZ,
+A_LOOPZ,
+A_LSL,
+A_LSS,
+A_LTR,
+A_MONITOR,
+A_MOV,
+A_MOVD,
+A_MOVQ,
+A_MOVSB,
+A_MOVSD,
+A_MOVSQ,
+A_MOVSW,
+A_MOVSX,
+A_MOVZX,
+A_MUL,
+A_MWAIT,
+A_NEG,
+A_NOP,
+A_NOT,
+A_OR,
+A_OUT,
+A_OUTSB,
+A_OUTSD,
+A_OUTSW,
+A_PACKSSDW,
+A_PACKSSWB,
+A_PACKUSWB,
+A_PADDB,
+A_PADDD,
+A_PADDSB,
+A_PADDSIW,
+A_PADDSW,
+A_PADDUSB,
+A_PADDUSW,
+A_PADDW,
+A_PAND,
+A_PANDN,
+A_PAVEB,
+A_PAVGUSB,
+A_PCMPEQB,
+A_PCMPEQD,
+A_PCMPEQW,
+A_PCMPGTB,
+A_PCMPGTD,
+A_PCMPGTW,
+A_PDISTIB,
+A_PF2ID,
+A_PFACC,
+A_PFADD,
+A_PFCMPEQ,
+A_PFCMPGE,
+A_PFCMPGT,
+A_PFMAX,
+A_PFMIN,
+A_PFMUL,
+A_PFRCP,
+A_PFRCPIT1,
+A_PFRCPIT2,
+A_PFRSQIT1,
+A_PFRSQRT,
+A_PFSUB,
+A_PFSUBR,
+A_PI2FD,
+A_PMACHRIW,
+A_PMADDWD,
+A_PMAGW,
+A_PMULHRIW,
+A_PMULHRWA,
+A_PMULHRWC,
+A_PMULHW,
+A_PMULLW,
+A_PMVGEZB,
+A_PMVLZB,
+A_PMVNZB,
+A_PMVZB,
+A_POP,
+A_POPA,
+A_POPAD,
+A_POPAW,
+A_POPF,
+A_POPFD,
+A_POPFW,
+A_POR,
+A_PREFETCH,
+A_PREFETCHW,
+A_PSLLD,
+A_PSLLDQ,
+A_PSLLQ,
+A_PSLLW,
+A_PSRAD,
+A_PSRAW,
+A_PSRLD,
+A_PSRLQ,
+A_PSRLW,
+A_PSUBB,
+A_PSUBD,
+A_PSUBSB,
+A_PSUBSIW,
+A_PSUBSW,
+A_PSUBUSB,
+A_PSUBUSW,
+A_PSUBW,
+A_PUNPCKHBW,
+A_PUNPCKHDQ,
+A_PUNPCKHWD,
+A_PUNPCKLBW,
+A_PUNPCKLDQ,
+A_PUNPCKLWD,
+A_PUSH,
+A_PUSHA,
+A_PUSHAD,
+A_PUSHAW,
+A_PUSHF,
+A_PUSHFD,
+A_PUSHFW,
+A_PXOR,
+A_RCL,
+A_RCR,
+A_RDSHR,
+A_RDMSR,
+A_RDPMC,
+A_RDTSC,
+A_REP,
+A_REPE,
+A_REPNE,
+A_REPNZ,
+A_REPZ,
+A_RET,
+A_RETF,
+A_RETN,
+A_ROL,
+A_ROR,
+A_RSDC,
+A_RSLDT,
+A_RSM,
+A_SAHF,
+A_SAL,
+A_SALC,
+A_SAR,
+A_SBB,
+A_SCASB,
+A_SCASD,
+A_SCASW,
+A_SEGCS,
+A_SEGDS,
+A_SEGES,
+A_SEGFS,
+A_SEGGS,
+A_SEGSS,
+A_SGDT,
+A_SHL,
+A_SHLD,
+A_SHR,
+A_SHRD,
+A_SIDT,
+A_SLDT,
+A_SMI,
+A_SMINT,
+A_SMINTOLD,
+A_SMSW,
+A_STC,
+A_STD,
+A_STI,
+A_STOSB,
+A_STOSD,
+A_STOSW,
+A_STR,
+A_SUB,
+A_SVDC,
+A_SVLDT,
+A_SVTS,
+A_SYSCALL,
+A_SYSENTER,
+A_SYSEXIT,
+A_SYSRET,
+A_TEST,
+A_UD1,
+A_UD2,
+A_UMOV,
+A_VERR,
+A_VERW,
+A_WAIT,
+A_WBINVD,
+A_WRSHR,
+A_WRMSR,
+A_XADD,
+A_XBTS,
+A_XCHG,
+A_XLAT,
+A_XLATB,
+A_XOR,
+A_XSTORE,
+A_CMOVcc,
+A_Jcc,
+A_SETcc,
+A_ADDPS,
+A_ADDSS,
+A_ANDNPS,
+A_ANDPS,
+A_CMPEQPS,
+A_CMPEQSS,
+A_CMPLEPS,
+A_CMPLESS,
+A_CMPLTPS,
+A_CMPLTSS,
+A_CMPNEQPS,
+A_CMPNEQSS,
+A_CMPNLEPS,
+A_CMPNLESS,
+A_CMPNLTPS,
+A_CMPNLTSS,
+A_CMPORDPS,
+A_CMPORDSS,
+A_CMPUNORDPS,
+A_CMPUNORDSS,
+A_CMPPS,
+A_CMPSS,
+A_COMISS,
+A_CVTPI2PS,
+A_CVTPS2PI,
+A_CVTSI2SS,
+A_CVTSS2SI,
+A_CVTTPS2PI,
+A_CVTTSS2SI,
+A_DIVPS,
+A_DIVSS,
+A_LDMXCSR,
+A_MAXPS,
+A_MAXSS,
+A_MINPS,
+A_MINSS,
+A_MOVAPS,
+A_MOVHPS,
+A_MOVLHPS,
+A_MOVLPS,
+A_MOVHLPS,
+A_MOVMSKPS,
+A_MOVNTPS,
+A_MOVSS,
+A_MOVUPS,
+A_MULPS,
+A_MULSS,
+A_ORPS,
+A_RCPPS,
+A_RCPSS,
+A_RSQRTPS,
+A_RSQRTSS,
+A_SHUFPS,
+A_SQRTPS,
+A_SQRTSS,
+A_STMXCSR,
+A_SUBPS,
+A_SUBSS,
+A_UCOMISS,
+A_UNPCKHPS,
+A_UNPCKLPS,
+A_XORPS,
+A_FXRSTOR,
+A_FXSAVE,
+A_PREFETCHNTA,
+A_PREFETCHT0,
+A_PREFETCHT1,
+A_PREFETCHT2,
+A_SFENCE,
+A_MASKMOVQ,
+A_MOVNTQ,
+A_PAVGB,
+A_PAVGW,
+A_PEXTRW,
+A_PINSRW,
+A_PMAXSW,
+A_PMAXUB,
+A_PMINSW,
+A_PMINUB,
+A_PMOVMSKB,
+A_PMULHUW,
+A_PSADBW,
+A_PSHUFW,
+A_PFNACC,
+A_PFPNACC,
+A_PI2FW,
+A_PF2IW,
+A_PSWAPD,
+A_FFREEP,
+A_MASKMOVDQU,
+A_CLFLUSH,
+A_MOVNTDQ,
+A_MOVNTI,
+A_MOVNTPD,
+A_PAUSE,
+A_LFENCE,
+A_MFENCE,
+A_MOVDQA,
+A_MOVDQU,
+A_MOVDQ2Q,
+A_MOVQ2DQ,
+A_PADDQ,
+A_PMULUDQ,
+A_PSHUFD,
+A_PSHUFHW,
+A_PSHUFLW,
+A_PSRLDQ,
+A_PSUBQ,
+A_PUNPCKHQDQ,
+A_PUNPCKLQDQ,
+A_ADDPD,
+A_ADDSD,
+A_ANDNPD,
+A_ANDPD,
+A_CMPEQPD,
+A_CMPEQSD,
+A_CMPLEPD,
+A_CMPLESD,
+A_CMPLTPD,
+A_CMPLTSD,
+A_CMPNEQPD,
+A_CMPNLEPD,
+A_CMPNLESD,
+A_CMPNLTPD,
+A_CMPNLTSD,
+A_CMPORDPD,
+A_CMPORDSD,
+A_CMPUNORDPD,
+A_CMPUNORDSD,
+A_CMPPD,
+A_COMISD,
+A_CVTDQ2PD,
+A_CVTDQ2PS,
+A_CVTPD2DQ,
+A_CVTPD2PI,
+A_CVTPD2PS,
+A_CVTPI2PD,
+A_CVTPS2DQ,
+A_CVTPS2PD,
+A_CVTSD2SI,
+A_CVTSD2SS,
+A_CVTSI2SD,
+A_CVTSS2SD,
+A_CVTTPD2PI,
+A_CVTTPD2DQ,
+A_CVTTPS2DQ,
+A_CVTTSD2SI,
+A_DIVPD,
+A_DIVSD,
+A_MAXPD,
+A_MAXSD,
+A_MINPD,
+A_MINSD,
+A_MOVAPD,
+A_MOVHPD,
+A_MOVLPD,
+A_MOVMSKPD,
+A_MOVUPD,
+A_MULPD,
+A_MULSD,
+A_ORPD,
+A_SHUFPD,
+A_SQRTPD,
+A_SQRTSD,
+A_SUBPD,
+A_SUBSD,
+A_UCOMISD,
+A_UNPCKHPD,
+A_UNPCKLPD,
+A_XORPD,
+A_ADDSUBPD,
+A_ADDSUBPS,
+A_HADDPD,
+A_HADDPS,
+A_HSUBPD,
+A_HSUBPS,
+A_LDDQU,
+A_MOVDDUP,
+A_MOVSHDUP,
+A_MOVSLDUP,
+A_MOVABS,
+A_MOVSXD,
+A_CQO
+);
diff --git a/compiler/x86_64/x8664pro.inc b/compiler/x86_64/x8664pro.inc
new file mode 100644
index 0000000000..df064ad42e
--- /dev/null
+++ b/compiler/x86_64/x8664pro.inc
@@ -0,0 +1,569 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_MOp1, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_ROp1, Ch_All, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_CDirFlag, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_ROp2, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_none)),
+(Ch: (Ch_MEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_Wop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_WFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WEBP, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_RWECX, Ch_None, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_ROP1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_RWESP, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_RWESP, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFLAGS, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFLAGS, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_REAX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_WEAX, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_MOp3, Ch_RWFlags, Ch_Rop2)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_MOp3, Ch_RWFlags, Ch_Rop2)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_SDirFlag, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWop1, Ch_RWop2, Ch_None)),
+(Ch: (Ch_WEAX, Ch_REBX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_REBX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_WOp2, Ch_RFLAGS)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_RFLAGS, Ch_WOp1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_MRAX, Ch_WRDX, Ch_None))
+);
diff --git a/compiler/x86_64/x8664tab.inc b/compiler/x86_64/x8664tab.inc
new file mode 100644
index 0000000000..11fcae0ac9
--- /dev/null
+++ b/compiler/x86_64/x8664tab.inc
@@ -0,0 +1,11483 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+ (
+ opcode : A_NONE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #0;
+ flags : if_none
+ ),
+ (
+ opcode : A_AAA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#55;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#213#10;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AAD;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#213#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_AAM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#212#10;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AAM;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#212#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_AAS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#63;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#16#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#16#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#17#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#17#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#17#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#17#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#18#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#18#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#19#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#19#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#19#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#19#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#130#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#130#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#20#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#21#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#21#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#130#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#130#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#130#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#130#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#130#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#130#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#15#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#15#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#1#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#1#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#1#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#1#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#2#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#2#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#3#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#3#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#3#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#3#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#128#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#128#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#4#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#5#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#5#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#32#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#32#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#33#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#33#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#33#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#33#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#34#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#34#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#35#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#35#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#35#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#35#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#132#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#132#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#36#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#37#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#37#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#132#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#132#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#132#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#132#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#132#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#132#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ARPL;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #192#1#99#65;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_ARPL;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #192#1#99#65;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_BOUND;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#98#72;
+ flags : if_186
+ ),
+ (
+ opcode : A_BOUND;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#98#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#188#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#188#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#188#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#188#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#189#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#189#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#189#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#189#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_BSWAP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#1#15#8#200;
+ flags : if_486
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#163#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#163#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#163#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#163#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#2#15#186#132#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#2#15#186#132#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#187#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#187#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#187#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#187#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#2#15#186#135#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#2#15#186#135#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#179#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#179#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#179#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#179#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#2#15#186#134#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#2#15#186#134#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#171#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#171#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#171#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#171#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#2#15#186#133#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#2#15#186#133#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #211#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none);
+ code : #211#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_far,ot_none,ot_none);
+ code : #211#1#154#28#31;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #208#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#1#154#28#31;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #209#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#1#154#28#31;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none);
+ code : #211#1#154#29#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate or ot_bits16,ot_immediate,ot_none);
+ code : #208#1#154#25#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits16,ot_none);
+ code : #208#1#154#25#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate or ot_bits32,ot_immediate,ot_none);
+ code : #209#1#154#33#24;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits32,ot_none);
+ code : #209#1#154#33#24;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none);
+ code : #211#192#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#192#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#192#1#255#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none);
+ code : #211#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #211#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_CBW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#152;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CDQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#153;
+ flags : if_386
+ ),
+ (
+ opcode : A_CLC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#248;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#252;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#250;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLTS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#6;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_CMC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#245;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#56#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#56#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#57#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#57#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#57#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#57#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#58#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#58#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#59#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#59#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#59#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#59#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#135#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#135#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#60#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#61#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#61#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#135#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#135#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#135#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#135#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#135#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#135#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMPSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#1#166;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#209#1#167;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #217#3#242#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#217#3#242#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#208#1#167;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#2#15#176#65;
+ flags : if_pent or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#2#15#176#65;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#177#65;
+ flags : if_pent or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#177#65;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#177#65;
+ flags : if_pent or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#177#65;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#2#15#166#65;
+ flags : if_486 or if_sm or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#2#15#166#65;
+ flags : if_486 or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#167#65;
+ flags : if_486 or if_sm or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#167#65;
+ flags : if_486 or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#167#65;
+ flags : if_486 or if_sm or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#167#65;
+ flags : if_486 or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG8B;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#199#129;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CPUID;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#162;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CWD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#153;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CWDE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#152;
+ flags : if_386
+ ),
+ (
+ opcode : A_DAA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#39;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DAS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#47;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#8#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#8#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#254#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#129;
+ flags : if_386
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#134;
+ flags : if_386
+ ),
+ (
+ opcode : A_EMMS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#119;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_ENTER;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none);
+ code : #1#200#24#21;
+ flags : if_186
+ ),
+ (
+ opcode : A_F2XM1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FABS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#193;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#193;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#1#223#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBLD;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#223#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#1#223#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBSTP;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#223#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCHS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCLEX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#219#226;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#193;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#218#8#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#218#9#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#209;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#218#8#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#218#9#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#201;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#218#8#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#218#9#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#193;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#209;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#201;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#217;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#217;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#218#8#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#218#9#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#216#209;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#241;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#223#241;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#223#8#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#223#9#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#216#217;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMPP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#217;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#255;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FDECSTP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#246;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDISI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#219#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FEMMS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none or ot_signed);
+ code : #2#15#14;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_FENI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#219#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FFREE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#219#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#223#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#223#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FINCSTP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#247;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#219#227;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#219#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#223#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#219#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#223#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#223#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#221#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#219#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#223#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#222#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#218#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#217#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#221#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#1#219#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#217#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#217#133;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FLDENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#217#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDL2E;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#234;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDL2T;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDLG2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#236;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDLN2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#237;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDPI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#235;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#238;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNCLEX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#226;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNDISI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNENI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#227;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#221#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSTCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#217#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FNSTENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#217#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSTSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#221#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FNSTSW;
+ ops : 1;
+ optypes : (ot_reg_ax,ot_none,ot_none);
+ code : #2#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FPATAN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#243;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FPREM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FPREM1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#245;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FPTAN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#242;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FRNDINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#252;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FRSTOR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#221#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#155#221#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSCALE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#253;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSETPM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#228;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSIN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#254;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FSINCOS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#251;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FSQRT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#250;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#217#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#221#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#155#217#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FSTENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#155#217#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#217#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#221#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#1#219#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#155#221#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#155#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 1;
+ optypes : (ot_reg_ax,ot_none,ot_none);
+ code : #3#155#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #192#1#216#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none);
+ code : #192#1#220#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#220#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none);
+ code : #1#220#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#220#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#216#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#216#9#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#222#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#222#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#222#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FTST;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#228;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#221#225;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#224;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#221#9#224;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#219#233;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#219#8#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#219#9#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#223#233;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#223#8#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#223#9#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#221#233;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#221#8#232;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#221#9#232;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMPP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#218#233;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FWAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#155;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXAM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#229;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#217#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none);
+ code : #1#217#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none);
+ code : #1#217#9#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXTRACT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#244;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FYL2X;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FYL2XP1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#217#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_HLT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#244;
+ flags : if_8086 or if_priv
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#167#65;
+ flags : if_386 or if_sw or if_undoc
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#167#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#167#65;
+ flags : if_386 or if_sd or if_undoc
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#167#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_ICEBP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#135;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#175#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#175#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#175#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#175#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_memory,ot_immediate or ot_bits8 or ot_signed);
+ code : #208#193#1#107#72#14;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_immediate or ot_bits8 or ot_signed);
+ code : #208#193#1#107#72#14;
+ flags : if_286
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_memory,ot_immediate);
+ code : #208#193#1#105#72#26;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_immediate);
+ code : #208#193#1#105#72#26;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_memory,ot_immediate or ot_bits8 or ot_signed);
+ code : #209#193#1#107#72#14;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits8 or ot_signed);
+ code : #209#193#1#107#72#14;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_memory,ot_immediate);
+ code : #209#193#1#105#72#34;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate);
+ code : #209#193#1#105#72#34;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#1#107#64#13;
+ flags : if_286
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate,ot_none);
+ code : #208#1#105#64#25;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#1#107#64#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none);
+ code : #209#1#105#64#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#228#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#229#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#229#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_al,ot_reg_dx,ot_none);
+ code : #1#236;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_reg_dx,ot_none);
+ code : #208#1#237;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg_dx,ot_none);
+ code : #209#1#237;
+ flags : if_386
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#8#64;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#8#64;
+ flags : if_386
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#254#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_INSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#108;
+ flags : if_186
+ ),
+ (
+ opcode : A_INSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#109;
+ flags : if_386
+ ),
+ (
+ opcode : A_INSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#109;
+ flags : if_186
+ ),
+ (
+ opcode : A_INT;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#205#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_INT01;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_INT1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_INT03;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#204;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INT3;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#204;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INTO;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#206;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INVD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#8;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_INVLPG;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#135;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_IRET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#207;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IRETD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#207;
+ flags : if_386
+ ),
+ (
+ opcode : A_IRETW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#207;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JCXZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #208#1#227#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JECXZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #209#1#227#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_short,ot_none,ot_none);
+ code : #1#235#40;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #211#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none);
+ code : #211#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_far,ot_none,ot_none);
+ code : #211#1#234#28#31;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #208#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#1#234#28#31;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #209#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#1#234#28#31;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none);
+ code : #211#1#234#29#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits16,ot_none);
+ code : #208#1#234#25#24;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits32,ot_none);
+ code : #209#1#234#33#24;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none);
+ code : #211#192#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#192#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#192#1#255#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none);
+ code : #211#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #211#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_LAHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#159;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#2#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#2#72;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#2#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#2#72;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none);
+ code : #211#192#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#192#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#192#1#255#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none);
+ code : #211#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #211#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_LDS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#197#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LDS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#197#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#141#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#141#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #209#193#1#141#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEAVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#201;
+ flags : if_186
+ ),
+ (
+ opcode : A_LES;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#196#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LES;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#196#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LFS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#180#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LFS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#180#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LGDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#130;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LGS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#181#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LGS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#181#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LIDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#131;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none);
+ code : #211#192#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_far,ot_none,ot_none);
+ code : #208#192#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_far,ot_none,ot_none);
+ code : #209#192#1#255#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none);
+ code : #211#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #211#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#255#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_LLDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#130;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#130;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LLDT;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#1#15#15#130;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LMSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#134;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LMSW;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#2#15#1#134;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LMSW;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#2#15#1#134;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LOADALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#7;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_LOADALL286;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#5;
+ flags : if_286 or if_undoc
+ ),
+ (
+ opcode : A_LOCK;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#240;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_LODSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#172;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LODSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#173;
+ flags : if_386
+ ),
+ (
+ opcode : A_LODSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#173;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#226#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#226#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#226#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#225#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#224#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#224#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #202#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none);
+ code : #200#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx,ot_none);
+ code : #201#1#225#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#3#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#3#72;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#3#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#3#72;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_LSS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#178#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LSS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#178#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LTR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#131;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LTR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#131;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LTR;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#1#15#15#131;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_MONITOR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#1#200;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MONITOR;
+ ops : 3;
+ optypes : (ot_reg_eax,ot_reg_ecx,ot_reg_edx);
+ code : #3#15#1#200;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg_cs,ot_none);
+ code : #208#192#1#140#129;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg_dess,ot_none);
+ code : #208#192#1#140#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg_fsgs,ot_none);
+ code : #208#192#1#140#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_cs,ot_none);
+ code : #208#192#1#140#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_dess,ot_none);
+ code : #208#192#1#140#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_fsgs,ot_none);
+ code : #208#192#1#140#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cs,ot_none);
+ code : #209#192#1#140#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_dess,ot_none);
+ code : #209#192#1#140#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_fsgs,ot_none);
+ code : #209#192#1#140#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dess,ot_memory,ot_none);
+ code : #208#193#1#142#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_fsgs,ot_memory,ot_none);
+ code : #208#193#1#142#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dess,ot_reg16,ot_none);
+ code : #208#193#1#142#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_fsgs,ot_reg16,ot_none);
+ code : #208#193#1#142#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dess,ot_regmem or ot_bits32,ot_none);
+ code : #209#193#1#142#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_fsgs,ot_regmem or ot_bits32,ot_none);
+ code : #209#193#1#142#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_cr4,ot_none);
+ code : #2#15#32#132;
+ flags : if_pent or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_creg,ot_none);
+ code : #2#15#32#65;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_dreg,ot_none);
+ code : #2#15#33#65;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_treg,ot_none);
+ code : #2#15#36#65;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_cr4,ot_reg32,ot_none);
+ code : #2#15#34#140;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_creg,ot_reg32,ot_none);
+ code : #2#15#34#72;
+ flags : if_386 or if_priv
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dreg,ot_reg32,ot_none);
+ code : #2#15#35#72;
+ flags : if_386 or if_priv
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_treg,ot_reg32,ot_none);
+ code : #2#15#38#72;
+ flags : if_386 or if_priv
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#136#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#136#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#137#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#137#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#137#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#137#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#138#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#138#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#139#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#139#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#139#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#139#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_immediate,ot_none);
+ code : #8#176#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate,ot_none);
+ code : #208#8#184#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none);
+ code : #209#8#184#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#198#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#199#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#199#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#198#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#199#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#199#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#110#72;
+ flags : if_pent or if_mmx or if_sd
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_reg32,ot_none);
+ code : #2#15#110#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_memory,ot_mmxreg,ot_none);
+ code : #192#2#15#126#65;
+ flags : if_pent or if_mmx or if_sd
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_reg32,ot_mmxreg,ot_none);
+ code : #2#15#126#65;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32,ot_none);
+ code : #3#102#15#110#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#102#15#126#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#126#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#110#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#111#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#111#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_memory,ot_mmxreg,ot_none);
+ code : #192#2#15#127#65;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#127#65;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#126#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#214#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#126#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#164;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#165;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#16#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#17#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#242#15#17#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#16#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #210#1#165;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_MOVSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#165;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#190#72;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg8,ot_none);
+ code : #208#193#2#15#190#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regmem or ot_bits8,ot_none);
+ code : #209#193#2#15#190#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regmem or ot_bits16,ot_none);
+ code : #209#193#2#15#191#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg64,ot_regmem or ot_bits16,ot_none);
+ code : #209#193#2#15#191#72;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#182#72;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg8,ot_none);
+ code : #208#193#2#15#182#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regmem or ot_bits8,ot_none);
+ code : #209#193#2#15#182#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regmem or ot_bits16,ot_none);
+ code : #209#193#2#15#183#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_MWAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#1#201;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MWAIT;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg_ecx,ot_none);
+ code : #3#15#1#201;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_NOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits8,ot_none,ot_none);
+ code : #192#1#246#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#247#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#247#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#8#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#8#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#9#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#9#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#9#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#9#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#10#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#10#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#11#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#11#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#11#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#11#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#129#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#129#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#12#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#13#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#13#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#129#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#129#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#129#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#129#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#129#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#129#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_al,ot_none);
+ code : #1#230#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ax,ot_none);
+ code : #208#1#231#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_eax,ot_none);
+ code : #209#1#231#20;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_al,ot_none);
+ code : #1#238;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_ax,ot_none);
+ code : #208#1#239;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_eax,ot_none);
+ code : #209#1#239;
+ flags : if_386
+ ),
+ (
+ opcode : A_OUTSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#110;
+ flags : if_186
+ ),
+ (
+ opcode : A_OUTSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#111;
+ flags : if_386
+ ),
+ (
+ opcode : A_OUTSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#111;
+ flags : if_186
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#107#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#107#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#107#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#107#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#99#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#99#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#99#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#99#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#103#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#103#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#103#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#103#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#252#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#252#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#252#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#252#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#254#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#254#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#254#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#254#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#236#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#236#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#236#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#236#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#81#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PADDSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#81#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#237#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#237#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#237#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#237#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#220#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#220#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#220#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#220#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#221#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#221#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#221#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#221#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#253#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#253#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#253#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#253#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#219#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#219#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#219#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#219#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#223#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#223#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#223#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#223#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAVEB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#80#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PAVEB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#80#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PAVGUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#191;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PAVGUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#191;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#116#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#116#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#116#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#116#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#118#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#118#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#118#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#118#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#117#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#117#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#117#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#117#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#100#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#100#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#100#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#100#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#102#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#102#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#102#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#102#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#101#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#101#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#101#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#101#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PDISTIB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#84#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PF2ID;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#29;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PF2ID;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#29;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#174;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#174;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFADD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#158;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFADD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#158;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFCMPEQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#176;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPEQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#176;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFCMPGE;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#144;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPGE;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#144;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFCMPGT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#160;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPGT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#160;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFMAX;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#164;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMAX;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#164;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFMIN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#148;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMIN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#148;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFMUL;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#180;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMUL;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#180;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRCP;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#150;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCP;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#150;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRCPIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#166;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCPIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#166;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRCPIT2;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#182;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCPIT2;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#182;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRSQIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#167;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRSQIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#167;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFRSQRT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#151;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRSQRT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#151;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFSUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#154;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFSUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#154;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFSUBR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#170;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFSUBR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#170;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PI2FD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#13;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PI2FD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#13;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PMACHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#94#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#245#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#245#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#245#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#245#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMAGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#82#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMAGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#82#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#93#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#93#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRWA;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#183;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PMULHRWA;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#183;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PMULHRWC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#89#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRWC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#89#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#229#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#229#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#229#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#229#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#213#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#213#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#213#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#213#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMVGEZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#92#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVLZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#91#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVNZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#90#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#88#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#8#88;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#8#88;
+ flags : if_386
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits16,ot_none,ot_none);
+ code : #208#192#1#143#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_regmem or ot_bits32,ot_none,ot_none);
+ code : #209#192#1#143#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_cs,ot_none,ot_none);
+ code : #1#15;
+ flags : if_8086 or if_undoc
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_dess,ot_none,ot_none);
+ code : #4;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_fsgs,ot_none,ot_none);
+ code : #1#15#5;
+ flags : if_386
+ ),
+ (
+ opcode : A_POPA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#97;
+ flags : if_186
+ ),
+ (
+ opcode : A_POPAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#97;
+ flags : if_386
+ ),
+ (
+ opcode : A_POPAW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#97;
+ flags : if_186
+ ),
+ (
+ opcode : A_POPF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#157;
+ flags : if_186
+ ),
+ (
+ opcode : A_POPFD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#157;
+ flags : if_386
+ ),
+ (
+ opcode : A_POPFW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#157;
+ flags : if_186
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#235#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#235#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#235#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#235#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PREFETCH;
+ ops : 1;
+ optypes : (ot_memory,ot_none or ot_signed,ot_none);
+ code : #2#15#13#128;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PREFETCHW;
+ ops : 1;
+ optypes : (ot_memory,ot_none or ot_signed,ot_none);
+ code : #2#15#13#129;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#242#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#242#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#114#134#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#242#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#242#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#114#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#115#135#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#243#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#243#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#115#134#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#243#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#243#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#115#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#241#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#241#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#113#134#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#241#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#241#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#113#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#226#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#226#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#114#132#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#226#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#226#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#114#132#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#225#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#225#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#113#132#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#225#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#225#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#113#132#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#210#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#210#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#114#130#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#210#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#210#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#114#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#211#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#211#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#115#130#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#211#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#211#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#115#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#209#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#209#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#113#130#21;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#209#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#209#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#113#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#248#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#248#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#248#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#248#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#250#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#250#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#250#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#250#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#232#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#232#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#232#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#232#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#85#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PSUBSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#85#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#233#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#233#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#233#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#233#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#216#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#216#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#216#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#216#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#217#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#217#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#217#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#217#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#249#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#249#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#249#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#249#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#104#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#104#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#104#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#104#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#106#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#106#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#106#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#106#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#105#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#105#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#105#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#105#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#96#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#96#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#96#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#96#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#98#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#98#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#98#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#98#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#97#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#97#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#97#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#97#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUSHA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#96;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#96;
+ flags : if_386
+ ),
+ (
+ opcode : A_PUSHAW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#96;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #211#1#156;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHFD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#156;
+ flags : if_386
+ ),
+ (
+ opcode : A_PUSHFW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#156;
+ flags : if_186
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#239#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#239#72;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#239#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#239#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#130#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#130#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#130;
+ flags : if_386
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#130#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#131#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#131#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#131;
+ flags : if_386
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#131#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_RDSHR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#54;
+ flags : if_p6 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RDMSR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#50;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_RDPMC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#51;
+ flags : if_p6
+ ),
+ (
+ opcode : A_RDTSC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#49;
+ flags : if_pent
+ ),
+ (
+ opcode : A_REP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPNE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#242;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPNZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#242;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_RET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#195;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RET;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#194#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_RETF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#203;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RETF;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#202#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_RETN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#195;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RETN;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #1#194#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#128#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#128#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#128#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#129#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#129#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#129;
+ flags : if_386
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#129;
+ flags : if_386
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#129#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_RSDC;
+ ops : 2;
+ optypes : (ot_reg_sreg,ot_memory or ot_bits80,ot_none);
+ code : #193#2#15#121#65;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RSLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#2#15#123#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RSM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#170;
+ flags : if_pent or if_smm
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#132#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_SALC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#214;
+ flags : if_8086 or if_undoc
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#135#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#135#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#135;
+ flags : if_386
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#135;
+ flags : if_386
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#135#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#24#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#24#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#25#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#25#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#25#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#25#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#26#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#26#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#27#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#27#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#27#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#27#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#131#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#131#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#28#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#29#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#29#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#131#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#131#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#131#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#131#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#131#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#131#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SCASB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#1#174;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SCASD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#209#1#175;
+ flags : if_386
+ ),
+ (
+ opcode : A_SCASW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #218#208#1#175;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SEGCS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#46;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGDS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#62;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGES;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#38;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGFS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#100;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGGS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#101;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGSS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#54;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SGDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#132#21;
+ flags : if_186 or if_sw
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#132#21;
+ flags : if_386 or if_sd
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg16,ot_immediate);
+ code : #192#208#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_immediate);
+ code : #192#208#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg32,ot_immediate);
+ code : #192#209#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate);
+ code : #192#209#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg16,ot_reg_cl);
+ code : #192#208#2#15#165#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_reg_cl);
+ code : #192#208#2#15#165#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg32,ot_reg_cl);
+ code : #192#209#2#15#165#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg_cl);
+ code : #192#209#2#15#165#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_unity,ot_none);
+ code : #192#1#208#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_reg_cl,ot_none);
+ code : #192#1#210#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#192#133#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_unity,ot_none);
+ code : #208#192#1#209#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_reg_cl,ot_none);
+ code : #208#192#1#211#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#193#133#21;
+ flags : if_186 or if_sw
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_unity,ot_none);
+ code : #209#192#1#209#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_reg_cl,ot_none);
+ code : #209#192#1#211#133;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#193#133#21;
+ flags : if_386 or if_sd
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg16,ot_immediate);
+ code : #192#208#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_immediate);
+ code : #192#208#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg32,ot_immediate);
+ code : #192#209#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate);
+ code : #192#209#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg16,ot_reg_cl);
+ code : #192#208#2#15#173#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_reg16,ot_reg16,ot_reg_cl);
+ code : #192#208#2#15#173#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_memory,ot_reg32,ot_reg_cl);
+ code : #192#209#2#15#173#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg_cl);
+ code : #192#209#2#15#173#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SIDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#129;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#1#15#15#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#1#15#15#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_SMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_SMINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#56;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_SMINTOLD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#126;
+ flags : if_486 or if_cyrix
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#1#132;
+ flags : if_286
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#2#15#1#132;
+ flags : if_286
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#2#15#1#132;
+ flags : if_286
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#2#15#1#132;
+ flags : if_386
+ ),
+ (
+ opcode : A_STC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#249;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#253;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#251;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STOSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#170;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STOSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#171;
+ flags : if_386
+ ),
+ (
+ opcode : A_STOSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #208#1#171;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #208#1#15#15#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none);
+ code : #209#1#15#15#129;
+ flags : if_386 or if_prot
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#40#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#40#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#41#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#41#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#41#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#41#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#42#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#42#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#43#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#43#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#43#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#43#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#133#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#133#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#44#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#45#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#45#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#133#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#133#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#133#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#133#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#133#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#133#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SVDC;
+ ops : 2;
+ optypes : (ot_memory or ot_bits80,ot_reg_sreg,ot_none);
+ code : #192#2#15#120#65;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SVLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#2#15#122#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SVTS;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none);
+ code : #192#2#15#124#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SYSCALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#5;
+ flags : if_p6 or if_amd
+ ),
+ (
+ opcode : A_SYSENTER;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#52;
+ flags : if_p6
+ ),
+ (
+ opcode : A_SYSEXIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#53;
+ flags : if_p6 or if_priv
+ ),
+ (
+ opcode : A_SYSRET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#7;
+ flags : if_p6 or if_priv or if_amd
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#132#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#132#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#133#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#133#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#133#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#133#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#132#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#133#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#133#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#168#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#169#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#169#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#246#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#247#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#247#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#246#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#247#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#247#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_UD1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#185;
+ flags : if_286 or if_undoc
+ ),
+ (
+ opcode : A_UD2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#11;
+ flags : if_286
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#2#15#16#65;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#2#15#16#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#17#65;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#17#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#17#65;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#17#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#2#15#18#72;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#2#15#18#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#19#72;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#19#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#19#72;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#19#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#1#15#15#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#15#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none);
+ code : #192#1#15#15#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none);
+ code : #192#1#15#15#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_WAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#155;
+ flags : if_8086
+ ),
+ (
+ opcode : A_WBINVD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#9;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_WRSHR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#55;
+ flags : if_p6 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_WRMSR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #2#15#48;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#2#15#192#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#2#15#192#65;
+ flags : if_486
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#2#15#193#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#2#15#193#65;
+ flags : if_486
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#2#15#193#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#2#15#193#65;
+ flags : if_486
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#2#15#166#72;
+ flags : if_386 or if_sw or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#2#15#166#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#2#15#166#72;
+ flags : if_386 or if_sd or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#2#15#166#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_reg16,ot_none);
+ code : #208#9#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg32,ot_none);
+ code : #209#9#144;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_ax,ot_none);
+ code : #208#8#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_eax,ot_none);
+ code : #209#8#144;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#134#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#134#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#135#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#135#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#135#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#135#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#134#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#134#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#135#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#135#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#135#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#135#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_XLAT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#215;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XLATB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #1#215;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg8,ot_none);
+ code : #192#1#48#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #192#1#48#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none);
+ code : #208#192#1#49#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#192#1#49#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #209#192#1#49#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#192#1#49#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg8,ot_memory,ot_none);
+ code : #193#1#50#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none);
+ code : #193#1#50#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#51#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#51#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#51#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#51#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#192#1#131#134#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #209#192#1#131#134#13;
+ flags : if_386
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none);
+ code : #1#52#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none);
+ code : #208#1#53#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none);
+ code : #209#1#53#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits8,ot_immediate,ot_none);
+ code : #192#1#128#134#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits16,ot_immediate,ot_none);
+ code : #208#192#1#129#134#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_regmem or ot_bits32,ot_immediate,ot_none);
+ code : #209#192#1#129#134#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none);
+ code : #192#1#128#134#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none);
+ code : #208#192#1#129#134#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none);
+ code : #209#192#1#129#134#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XSTORE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#167#192;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none);
+ code : #208#193#1#15#216#64#72;
+ flags : if_p6 or if_sm
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none);
+ code : #208#193#1#15#216#64#72;
+ flags : if_p6
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #209#193#1#15#216#64#72;
+ flags : if_p6 or if_sm
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none);
+ code : #209#193#1#15#216#64#72;
+ flags : if_p6
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none);
+ code : #211#1#15#216#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_near,ot_none,ot_none);
+ code : #208#1#15#216#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32 or ot_near,ot_none,ot_none);
+ code : #209#1#15#216#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none);
+ code : #216#112#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_short,ot_none,ot_none);
+ code : #216#112#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SETcc;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#1#15#216#144#128;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_SETcc;
+ ops : 1;
+ optypes : (ot_reg8,ot_none,ot_none);
+ code : #192#1#15#216#144#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ADDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ADDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDNPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#85#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDNPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#85#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#84#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#84#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#217#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #217#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#219#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #219#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_COMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#47#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_COMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#47#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTPI2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#42#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPI2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none);
+ code : #217#2#15#42#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#217#2#15#45#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #217#2#15#45#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTSI2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#42#72;
+ flags : if_katmai or if_sse or if_sd or if_ar1
+ ),
+ (
+ opcode : A_CVTSI2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32,ot_none);
+ code : #219#2#15#42#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #193#219#2#15#45#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #219#2#15#45#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#217#2#15#44#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #217#2#15#44#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #193#219#2#15#44#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #219#2#15#44#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_LDMXCSR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#130;
+ flags : if_katmai or if_sse or if_sd
+ ),
+ (
+ opcode : A_MAXPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MAXPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MAXSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MAXSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#40#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#2#15#41#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#40#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#41#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#22#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#2#15#23#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#22#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#18#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#2#15#19#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#18#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVMSKPS;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #2#15#80#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVNTPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #2#15#43#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#219#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#217#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#86#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#86#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SHUFPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#2#15#198#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHUFPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #2#15#198#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_STMXCSR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#131;
+ flags : if_katmai or if_sse or if_sd
+ ),
+ (
+ opcode : A_SUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SUBSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SUBSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UCOMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#46#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UCOMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#46#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#21#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#21#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#20#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#20#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_XORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#87#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_XORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#87#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_FXRSTOR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#129;
+ flags : if_p6 or if_sse or if_fpu
+ ),
+ (
+ opcode : A_FXSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#128;
+ flags : if_p6 or if_sse or if_fpu
+ ),
+ (
+ opcode : A_PREFETCHNTA;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#24#128;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT0;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#24#129;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT1;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#24#130;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT2;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#24#131;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_SFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#174#248;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_MASKMOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#247#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_MOVNTQ;
+ ops : 2;
+ optypes : (ot_memory,ot_mmxreg,ot_none);
+ code : #2#15#231#65;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#224#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#224#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#224#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#224#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#227#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#227#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#227#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#227#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_reg32,ot_mmxreg,ot_immediate);
+ code : #2#15#197#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_reg32,ot_xmmreg,ot_immediate);
+ code : #3#102#15#197#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_reg16,ot_immediate);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_reg32,ot_immediate);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory,ot_immediate);
+ code : #193#2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory or ot_bits16,ot_immediate);
+ code : #193#2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg16,ot_immediate);
+ code : #3#102#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg32,ot_immediate);
+ code : #3#102#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#3#102#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits16,ot_immediate);
+ code : #193#3#102#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#238#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#238#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#238#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#238#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#222#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#222#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#222#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#222#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#234#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#234#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#234#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#234#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#218#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#218#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#218#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#218#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMOVMSKB;
+ ops : 2;
+ optypes : (ot_reg32,ot_mmxreg,ot_none);
+ code : #2#15#215#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMOVMSKB;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#102#15#215#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#228#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#228#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#228#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#228#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#246#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#246#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#246#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#246#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSHUFW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_immediate);
+ code : #2#15#112#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory,ot_immediate);
+ code : #193#2#15#112#72#18;
+ flags : if_katmai or if_mmx or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PFNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#138;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#138;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PFPNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#142;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFPNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#142;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PI2FW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#12;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PI2FW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#12;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PF2IW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#28;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PF2IW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#28;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_PSWAPD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#15#72#1#187;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PSWAPD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#15#72#1#187;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_FFREEP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none);
+ code : #1#223#8#192;
+ flags : if_pent or if_3dnow or if_fpu
+ ),
+ (
+ opcode : A_MASKMOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#247#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CLFLUSH;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none);
+ code : #192#2#15#174#135;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVNTDQ;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#231#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVNTI;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none);
+ code : #192#2#15#195#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVNTPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#43#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAUSE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #219#1#144;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_LFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#174#232;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #3#15#174#240;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#111#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#127#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#111#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#127#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#111#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #219#192#2#15#127#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#111#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#127#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQ2Q;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #3#242#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none);
+ code : #219#2#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#212#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#212#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#212#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#212#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#244#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#244#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#244#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#244#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSHUFD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #3#102#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#3#102#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFHW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #219#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFHW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#219#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFLW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #3#242#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFLW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#3#242#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSRLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none);
+ code : #3#102#15#115#131#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none);
+ code : #2#15#251#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#2#15#251#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#251#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#251#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#109#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKHQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#109#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#108#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PUNPCKLQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#108#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#88#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#88#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#88#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ADDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#88#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ANDNPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#85#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ANDNPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#85#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ANDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#84#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ANDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#84#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#0;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#0;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPEQSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#0;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPEQSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#0;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#2;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#2;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#2;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#2;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#1;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#1;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#1;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#1;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#4;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#4;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#4;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#4;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#6;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#6;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#6;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#6;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#5;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#5;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#5;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#5;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#7;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#7;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#7;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#7;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPUNORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#194#72#1#3;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPUNORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#194#72#1#3;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPUNORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#242#15#194#72#1#3;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPUNORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#242#15#194#72#1#3;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #217#3#102#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#217#3#102#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_COMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #217#3#102#15#47#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_COMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#217#3#102#15#47#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#91#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#230#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #3#102#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#3#102#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#90#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPI2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none);
+ code : #3#102#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPI2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#91#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPS2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPS2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#242#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #193#3#242#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSI2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32,ot_none);
+ code : #3#242#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSI2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSS2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSS2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none);
+ code : #3#102#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none);
+ code : #193#3#102#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#230#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #219#2#15#91#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#219#2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#242#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none);
+ code : #193#3#242#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_DIVPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#94#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_DIVPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#94#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_DIVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#94#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_DIVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#94#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MAXPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#95#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MAXPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#95#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MAXSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#95#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MAXSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#95#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MINPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#93#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MINPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#93#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MINSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#93#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MINSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#93#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#40#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#41#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#41#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#40#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVHPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#23#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVHPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#22#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVLPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#19#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#18#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVMSKPD;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none);
+ code : #3#102#15#80#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#16#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#17#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#17#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#16#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MULPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#89#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MULPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#89#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MULSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#89#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MULSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#89#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#86#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#86#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SHUFPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate);
+ code : #3#102#15#198#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHUFPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate);
+ code : #193#3#102#15#198#72#22;
+ flags : if_willamette or if_sse2 or if_sm or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SQRTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#81#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SQRTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#81#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SQRTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#81#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SQRTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#81#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#92#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#92#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SUBSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#92#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SUBSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#92#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UCOMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#46#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UCOMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#46#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UNPCKHPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#21#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UNPCKHPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none);
+ code : #192#3#102#15#21#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_UNPCKLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#20#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UNPCKLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#20#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_XORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#87#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_XORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#87#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#208#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#208#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_ADDSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#208#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#208#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_HADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#124#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#124#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_HADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#124#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#124#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_HSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#102#15#125#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#102#15#125#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_HSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#125#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#125#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_LDDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #3#242#15#240#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVDDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#242#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVDDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#242#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSHDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#243#15#22#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSHDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#243#15#22#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSLDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none);
+ code : #193#3#243#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSLDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none);
+ code : #3#243#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVABS;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none);
+ code : #209#8#184#33;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_MOVSXD;
+ ops : 2;
+ optypes : (ot_reg64,ot_memory,ot_none);
+ code : #209#193#1#99#72;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_MOVSXD;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg32,ot_none);
+ code : #209#193#1#99#72;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_CQO;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none);
+ code : #209#1#153;
+ flags : if_x86_64
+ )
+);